Help needed. How do i set a temp variable with a random variable from a list

Twine Version: 2.8

Im an absolute beginner when it comes to programing and need help with some code for my game. Im wanting to have some random events happen at the end of game turn. I created a list with some event names “alpha, beta, delta and echo”

I want the code to select one of these at random and then go to the appropriate passage. Im not wanting to use a number field as I want to be able to add events based on conditions and choices elsewhere in the game.

Im using the following code on start

<<set $eventlist = [ "alpha", "bravo", "delta", "echo" ]>>

and then later

<<set _tempoccurlist to (either: $eventlist)>>

<<if $tempoccurlist.includesAny("alpha")>> <<goto alpha>>
<<if $tempoccurlist.includesAny("beta")>> <<goto beta>>
<<if $tempoccurlist.includesAny("delta")>> <<goto delta>>
<<if $tempoccurlist.includesAny("echo")>> <<goto echo>>

and it keeps only sending me to the passage delta and is not randomising it. Any idea why and how i fix it.


You need either($eventlist) rather than (either: $eventlist).

Did you switch from Harlowe to Sugarcube? If so, you should be aware that the macros aren’t interchangeable. It’s probably best to treat it like it’s a whole different authoring system.

To be honest ive been grabbing code from whereever I can find it and i dont know enough to tell the difference.

I’ve tried what you suggested and I’m still having the same problem. It always sends me to delta.

Okay, well, as long as you keep doing that you’re not going to be able to make anything functional. You either need to take some time to familiarize yourself with Sugarcube or at least only use markup that was clearly labeled as Sugarcube when posted. Usually people do specify.

Anyway, the random bit of Harlowe markup jumped out at me, but there are a number of other problems here.

One, for something like this you probably want to use the if/else structure instead of a bunch of independent if statements.

Two, you set the value of _tempoccurlist (a temporary variable), but then your if statements are trying to check $tempoccurlist (a permanent variable), which doesn’t exist.

Three, the value of _tempoccurlist will be a random entry from the array $eventlist, so it will be a string. .includesAny is an array method, so it’s not meant to be used on a string. (It would also be the wrong method for this purpose even if _tempoccurlist was an array, but that’s neither here nor there.) All you need here is good old is.

The following worked for me (I added the link to click on so that I could easily hit the back button to check that the value of _tempoccurlist was randomizing as expected):

<<set _tempoccurlist to either($eventlist)>>

<<link "Go to event">><<if _tempoccurlist is "alpha">>
	<<goto "alpha">>
<<elseif _tempoccurlist is "beta">>
	<<goto "beta">>
<<elseif _tempoccurlist is "delta">>
	<<goto "delta">>
<<elseif _tempoccurlist is "echo">>
	<<goto "echo">>
1 Like

Thanks for that. much appreciated

1 Like

Yeah, you really will need to understand the code eventually or you’ll keep running into problems because computers are picky like that.

But in this particular case… you should be able to skip the if block entirely and do:

<<set $eventlist = [ "alpha", "bravo", "delta", "echo" ]>>
<<set _event = either($eventlist)>>
<<link "Go to event" _event>><</link>>

You could also skip the temporary variable, but in that case, since <<link>> takes multiple arguments, you need backticks around the code argument, like so:

<<link "Go to event" `either($eventlist)`>><</link>>
1 Like

Y’know, I’ve used that in a couple of my games, so I don’t know why it didn’t occur to me to suggest it.

Thanks for that its very clean. I am learning sugarcube slowly but with my limited coding experience its slow going.

I have another question. Im trying to remove an option from the list once its happened but it just seems to get stuck on it instead. I have this at the end of the delta passage to remove it.

<<set $eventlist = $eventlist.delete("delta")>>

Am I using the wrong command for this?

The code seems correct. Do you get an error message?

You can also just do:
<<set $eventlist.delete("delta")>>

I dont get an error message but the event I deleted then shows up everytime I get to the end of turn.

You’re using the correct method, but using it incorrectly.

From its documentation: (emphasis on the relevant bit)

Removes all instances of the given members from the array and returns a new array containing the removed members.

The fact that it returns an array of the removed members is important here. What your code is doing is removing all delta string members and then assigning the returned array of removed members to the story variable $eventlist, overwriting it.

If you simply want to remove any delta string members, then you should not assign its return value to anything, let alone the $eventlist. For example:

<<run $eventlist.delete("delta")>>

Note that you could use <<set>> there instead—<<set>> and <<run>> are the same macro. I used <<run>> since no assignment is happening there, you’re simply running code.

If you want to remove any delta string members while also recording what was removed, then you may assign its return value to another variable—you still do not want to overwrite $eventlist. For example:

<<set _removed = $eventlist.delete("delta")>>

After that, the story variable $eventlist will no longer contain any delta string members while the temporary variable _removed will contain every member that was removed.