Requiring a password/answer in Sugarcube (1.0.35)

Hi. I Iove the idea of having a player use a password to progress in a game as described here: https://twinery.org/forum/discussion/2171/how-to-require-a-specific-answer-to-continue-game

This is the strand of code I WANT to use in my game, more or less:

<<set $password to "the password is Bacon">>
<<set $password to $password.toLowerCase()>>

/% using indexOf function %/

<<if $password.indexOf('bacon') > -1>>You are correct.<<else>>You are wrong.<</if>>


/% or using the ES6 includes function %/

<<if $password.includes('bacon')>>You are correct.<<else>>You are wrong.<</if>>

However, this code does not seem to work in Sugarcube (1.0.35), though the example listed (through the link) for Harlowe does. Any ideas on how to fix the code so that it’ll operate in Sugarcube?

There are a few different things going on here as to why the seemingly same code does not work across story formats. The first is that the Harlowe is returning a value from the use of the prompt() call. Whatever the user enters is set to the value of $password. Then, the code is checked. The use of the (prompt:) code interrupts the code flow and does that immediately before continuing.

The second is that SugarCube 1.0.35 does not follow the same process. Instead, and as is the case for your code, it is being run from top to bottom. There is no user input and the value of $password is being checked to see if it contains “bacon” (and it does).

Assuming you want your user to enter something, check it, and then react, some different macros are needed.

The first is <<textbox>>. If you want to get short selections of text, this is the macro to use in SugarCube 1.0.35. (For longer selections, look at <<textarea>>.) This will allow the user to enter some text value and then save the value in a variable. Some example code might look like the following:

What's the password? <<textbox "$password" "">>

Next, the value of $password needs to be checked. To do that, your code will work fine. However, there is a problem: code flow. The code will get run before the user inputs anything. To slow that down, let’s add another macro, <<click>>. Creating a link to “confirm” the content of the <<textbox>> helps break up the code flow as the user entering a value and then clicking another button to confirm it. The code for that might look like the following:

<<click "Confirm Password">>
  <<set $password to $password.toLowerCase()>>
  <<if $password.indexOf('bacon') > -1>>
  <<else>>
  <</if>>
<</click>>

However, you should probably also signal to the user somehow that a password is invalid or correct. For that, the <<replace>> macro could be used.

Wrapping the <<textbox>> area in a <div> could help it be “replaced” if the answer is correct or not. The code for that would look like the following:

<div id="passwordArea">
What's the password? <<textbox "$password" "">>
</div>

<<click "Confirm Password">>

  <<set $password to $password.toLowerCase()>>

  <<if $password.indexOf('bacon') > -1>>
  	<<replace "#passwordArea">>Correct!<</replace>>
  <<else>>
  	<<replace "#passwordArea">>Try again!
	What's the password? <<textbox "$password" "">><</replace>>
  <</if>>

<</click>>

Now, if it is the wrong password, the content is replaced with the addition of a message to the user. If the password is correct, the input is replaced entirely.

It’s a pretty common issue to run into when working with Twine, but keep in mind that if the user needs to input something, there should be some type of reaction or additional UI element to trigger. Otherwise, the code will run from top to bottom and end before the user gets a chance to do anything. (The name for this unwanted behavior in programming is a race condition.)

1 Like

Thank you so much for the explanation! The way you explained the issue made so much sense.

1 Like