Harlowe: Various outputs for certain array checks

Sorry for the strange title, it’s hard to pin down exactly what I’m requiring help for in a succint sentance. I’m using Twine 2, and the latest harlowe version (3.2.1)

For context, I’m stuck in a particularly difficult passage. In said passage, I am picking random names from an array, for the purposes of a dynamic scene with random characters. The characters are set as such:

(set:$Targets to (a: "Character 1", "Character 2", "Character 3", "Character 4"))
(set:$ET1 to $Targets's (random:1,$Targets's length))

On top of this, there is a boolean variable check for whether you’ve met the character in question initially or not. I’m trying to find a more efficient way for it to check for the array’s chosen character. Because the chosen variable for the character is always random, my initial thought is to have to do an (if:) check for every available character, but I’m hoping there’s a cleaner way. It’s hard to explain, but what I have so far is the following:

(if:$ET1 is "Character 1")[
(if:$MetC1 is false)[ ]
(elseif:$MetC1 is true)[ ]
(elseif:$ET1 is "Character 2")[
(if:$MetC2 is false)[ ]
(elseif:$MetC2 is true)[ ]

You get the idea. Whilst this works for the purposes of what I need, I can realise from a distance that it’s messy, perhaps overdone code. I’m not a complete expert in harlowe yet so whilstI can come to solutions such as these on my own, they’re simply not efficient and can take up a lot of space in a passage that can inevitably be difficult for me to follow when editing it later.

I’ve considered datamaps but I’d be using this code in several other passages for more dynamic options. I’m just really stumped. I’ve been sifting through the documentation to find what I’m looking for but nothing is really clicking.

If anyone has done something similar in the past I’d love to hear your method. Thanks for reading!

You can use the (either:) macro combined with the Spread operator ... (three full-stops) to randomly select an element of an Array…

(set: $Targets to (a: "Character 1", "Character 2", "Character 3", "Character 4"))
(set: $ET1 to (either: ...$Targets))

…and if you don’t want the same Character to be randomly selected again then you could delete the selected name from the Array.

(set: $Targets to it - (a: $ET1))

You could use an Array to track which Characters have been ‘met’ so far…

(set: $met to (a:))

…and then add each ‘met’ Character to that array when the meeting occurs.

(set: $met to it + (a: $ET1))

You can then use the Array contains operator to determine if a specific character has been ‘met’ or not…

(if: $met contains $ET1)[You have met this Character previously]

Thanks for the response, Greyelf, this is some pretty helpful insight! I really appreciate it.

So let’s say for example that I wanted to write parts of a passage containing the random selected character $ET1. Would I have to go through if statements one by one like this:

(if:$ET1 is "Character 1")[Character 1 says this, and does a handstand, etc.](elseif:$ET1 is "Character 2")[Character 2 says this and does a flip, etc.]

…and such, or is there a more efficient way to do it? My example ‘text’ would be drastically different for each potential $ET1 so I wouldn’t be able to simply supplement sections of the prose for if statements, but rather have to potentially do whole chunks, unless there’s a better way.

There are techniques you can use to associated data with specific key values, but for the use-case you described using a combination of (if:) and (else-if:) macros is likely to be the most efficient means to achieve the result your want.

note: Harlowe uses its own custom object implementation of Array and (data)Map, and those implementations aren’t that efficient when it comes to actions like dynamically adding/subtracting elements and looping through the elements. Which is why I’m not suggesting any technique where specific Character associated data is stored within such objects.

Alright, thanks Greyelf! I’ve been reading your solutions to problems since the old days of the past Q&A so I 100% trust your judgement-- I will continue forwards with it this way.


I don’t mean to revive an old thread, but for anyone looking for a solution to a similar problem, I recommend looking into the Conditional (cond:) Macro. It’s Harlowe’s ternary command, sometimes known as a switch-case. This is a command designed for a long list of if…else statements.

I think Harlowe’s documentation can sometimes be confusing, so it helped me to see the logic in a more vertical format. This is the logic:

case1: do x
otherwise, case 2: do y
otherwise, case 3: do z
otherwise, case 4: do a
otherwise do default