Moving through a random string of passages in Twine

Twine Version: 2.8.0
[Harlowe 3.3.7 (but open to other options)]

Hi all. Absolute beginner here, first post, probably doing everything wrong. Sorry. I promise I’ve searched all over and tried a bunch of things, but I can’t seem to find out how to do something I swear should be simple, and I don’t know enough to know if I’m just searching badly. Apologies if so.

Basically, want I want to do is:

  1. Start the player in an introductory passage with a link at the bottom saying “Begin”.
  2. Take them through a random selection of three passages from a total of nine (without seeing the same passage twice), clicking a link saying “Continue” each time to go from one to the next.
  3. When three random passages have been seen, have “Continue” take them to a final “Ending” passage.

I’ve tried various solutions, including things that use storylets (which I felt like I could figure out if I could only find some more entry-level instruction than what I’ve been able to track down), something using ‘pluck’ (I think that was in Sugarcube maybe?) and other things using arrays and various methods of randomly selecting things.

However, each time, I’m being hampered by my absolute beginnerness. I’d like to be able to understand what I’m seeing in terms of online instruction and resources, but it assumes a whole bunch of knowledge I just don’t have, and figuring out where to begin accumulating said knowledge just keeps sending me down search rabbitholes.

I even tried getting a couple of the big AIs to suggest solutions, but “confidently wrong” is an understatement. I’d like to also add “totally unapologetic when called out for being wrong” and “happy to shamelessly repeat suggestions that you already told it don’t work”. Lovely stuff.

Anyway, would really appreciate some help with this, even if it’s just pointing me in the direction of the right idiot-proof resource.

Thanks!

1 Like

I think the (either:) macro should help! One of the examples of its use is:

(go-to: (either: "Void 2", "Void 3", "Void 4")) will send the player to one of three random passages.

The (set:) and (a:) macros can be used to create a Variable that references an Array that contains the names of the 9 possible Passages.

(set: $passages to (a: "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"))

The (shufffled:) macro can be used to randomly sort that Array of Passage Names.

(set: $passages to (shuffled: ...$passages))

And the Array’s range based indexing can be used to reduce that random list of 9 Passage Names down to the first 3.

(set: $passages to $passages's 1stto3rd)

note: All of the above could be done in the project’s startup tagged Passage.

Now that the Variable only contains 3 Passage Names the (move:) macro can be used to extract the top most name from the list as needed, and the (link-goto:) macro can be used to create a link that transitions to that Passage.

Welcome to the project
{
	(move: $passages's 1st into _target)
	(link-goto: "Continue", _target)
}

The exact same (move:) and (link-goto:) macro combination can be used to transition to the next two random passages.

eg. if the above transitioned to a Passage named Nine…

Welcome to the Passage named Nine.
{
	(move: $passages's 1st into _target)
	(link-goto: "Continue", _target)
}

Amazing, Greyelf, thanks so, so much!

I now have my story set up as per your instructions, and it’s correctly running through the three randomly selected passages as intended.

When it gets to the end of the selection, it then throws an error, presumably because $passages is now empty.

So I guessed I needed to put some code at the bottom of each of my random passages that checks if $passages is empty, and if it is, produces a link to the ending passage instead, and added the following:

(if: $passages's length is 0)[[Ending]]

But this still displays the error when $passages is empty, I’m just also able to click the ‘Ending’ link to get away from it. My guess was that this means I need to make the following:

{
	(move: $passages's 1st into _target)
	(link-goto: "Continue", _target)
}

The subject of an (else:) statement below the (if:), but I’m struggling to figure out how to format it correctly. The closest I got was the following:

(if: $passages's length is 0)[[Ending]]

(else:[
	(move: $passages's 1st into _target)
	(link-goto: "Continue", _target)
]
)

But that and various other attempts (including preserving the {} brackets around the move/link-goto bit) produce the error “1 too many values were given to the (else:) macro.”

I’m guessing “else” is only supposed to encounter one instruction, but I’m hoping some bracketing method or other will get it to treat the following as a single instruction:

(move: $passages's 1st into _target)
	(link-goto: "Continue", _target)

But am I completely barking up the wrong tree here?

Sorry to rinse you for yet more knowledge!

You are on the right path, but there are two syntax issues with the above example:

1: As shown in the (if:) macro’s documentation, the syntax for using that macro is…

(if: condition)[ conditional content ]

eg. the macro is followed by its associated Hook.

2: The (else:) macro’s documentation shows that macro has a similar syntax.

(else:)[ conditional content ]

eg. this macro is also followed by its associated Hook.

If we review the syntax of the (if:) and (else:) macro calls in your example we see…

(if: condition) conditional content

…and…

(else: [ conditional content ] )

Do you see the differences between the syntax shown in the documentation and that of your example?

Thanks again, Greyelf! You’re a very patient legend.

So, I had previously been playing around trying to figure out where my brackets should be, but had discounted “[[[Results]]]” as a solution, since it very oddly creates a passage called “[Results” off to one side (tried to post a screenshot/link to screenshot, but seemingly that’s not possible).

However, I went ahead and tried that anyway based on your kind instruction, and it did turn out to be the solution (that and moving that closing bracket to where it should have been in the “else” bit).

So despite the rogue “[Results” passage, the following code results in the expected behaviour, and I’m now happily cycling through random selections of three games and finishing up at the end. Hooray!

(if: $passages's length is 0)[[[Results]]]
(else:)
[(move: $passages's 1st into _target)
(link-goto: "Continue", _target)]

Thank you very much indeed!

The “find all Markup based Links in the Passage” functionality used by the Twine 2.x application’s “Create Missing Passages” feature unfortunately gets confused when if finds something like [[[Results]]], even though that is valid Harlowe code.

The application basically can’t cope with an extra open [ square bracket being added to the start of any of the standard Markup based Links.

So to help the Twine 2.x application get things right you will need to add a SPACE character between the first [ and the double [[ that indicates the start of the Markup based link.

(if: $passages's length is 0)[ [[Results]]]

Ahhh, nice. Thanks so much for the tip!