Keeping track of things in Twine
Today we’re going to learn about all the ways that your Twine game can be responsive to the choices of your reader, including “remembering” information from one passage to the next, and making the shape of your text contingent on what choices the reader has made.
We’re going to talk about macros, variables, and functions.
Macros and variables
A “macro” is a bit of pre-defined code that you get for free with Twine. Among other things, macros allow you to keep extra information in your game behind the scenes, and then change the way your story is displayed based on that information.
Macros are written like so:
<<something>>
… i.e., two angle brackets surrounding something, where something
is the
name of the macro you want to use. (Some macros have other information between
the brackets, as we’ll see below.) Note that macros are not HTML tags! They
only work in Twine, not in any old web page.
Macros: textinput and print
The first macro we’ll talk about is <<textinput>>
, which allows you to
prompt your reader to type in something. You can then take whatever they
typed in and use it in another passage. Here’s a little toy Twine game I
made to illustrate:
And here’s what it looks like when you play:
As you can see, the text I typed in on the first passage ends up embedded in
the second passage! Pretty cool. But how does it work? Well, take a look
at the source code for the Start
passage. It contains the following:
<<textinput $player_name [[Greetings]]>>
This looks complicated, so let’s break it down. The word textinput
indicates
to Twine that we want to use the textinput
macro, which causes a text input
box to appear on the screen. The textinput
macro needs a little bit more
information to do its job, though.
First off, the reader’s going to input some text, and we want to use that text
later. We need to give that text some kind of handle or name so we can refer to
it later. The name by which a value is known in Twine is called a “variable
name.” In this case, $player_name
is the variable name. (We could have chosen
whatever name we wanted—it just has to start with a $
and only contain
letters, numbers and underscores.)
Secondly, the reader needs to go to a different passage when they click the button next to the text field. The name of the passage to link to is contained inside the square brackets. And yes, it does look just like a Twine link! You can even change the text on the button using the pipe syntax, just like with a link. For example, this code would change the text on the button from “Greetings” to “Click me!”
<<textinput $player_name [[Click me!|Greetings]]>>
Altogether, you can read the macro as saying: “Hey, Twine! Make a text input box. Whatever the reader types in, remember it in a variable named $player_name
. Oh, and when the reader clicks on the button, send them to a passage with the name Greetings
. Thanks!”
Displaying the value of a variable
Of course, just putting what the player typed into a variable isn’t going to do much. We need to actually do something with that variable. Twine has a number of macros for manipulating variables and changing what the game does based on the value of a variable. The simplest of these is <<print>>
, which you use like so:
<<print $variable_name>>
… replacing $variable_name
with the name of the variable you’d like to display. In the example above, we told the the <<textinput>>
macro to use the
variable name $player_name
, which is why we put
<<print $player_name>>
… in the Greetings
passage. This causes whatever value we stored in the
variable $player_name
earlier to be included in the text of the passage.
EXERCISE: Make a Twine game that asks the reader multiple questions about themselves, one after another. (E.g., “what’s your name”, “what’s your hair color”, “think of a number from one to fifteen”, etc.) In the final passage, display all of the information that the reader typed in.
Read more about the <<textinput>>
macro here and about the <<print>>
macro here.
Setting variables
The <<textinput>>
macro is just one of many ways to get variables into our
games. Sometimes we want to make our own variables and set their values to
something of our own imagining, not that of the reader. We can do this with
the <<set>>
macro. The syntax of the <<set>>
macro looks like this:
<<set $variable_name to value>>
… where $variable_name
(again) is a name that we choose for the variable,
and value
is some kind of value, usually either a number (like 5
) or a
string of text (like "Mother said there'd be days like these"
). (More about
different kinds of values below.)
Here’s a screenshot of a simple Twine game that makes use of the <<set>>
macro.
This game is a simple personality quiz. Based on which color you prefer, the
game sets the variable $personality
to one of two things, then displays
the result in the final passage. Here’s a sample playthrough:
You can see here the use of <<set>>
to manually set a variable to
a particular value, in this case either "trustworthy"
or "flirtatious"
.
The <<set>>
happens when the reader clicks on the passage in which it
occurs; the variable stays set for the entire playthrough.
Different kinds of values
The <<set>>
macro allows you to set variables to different kinds of values.
In the above example, the value we set for $personality
to a kind of
value called a string. Strings contain “strings” of characters, and are
what you want to use for any textual information you want to store. When you
make a string value, you have to surround the value in double quotes "like
this"
.
The <<set>>
macro can also set numerical values, like 5
or 19.42
.
When you’re writing a number, you don’t have to include quotes.
The difference between these two kinds of values—strings and numbers—will become more apparent later on, when we talk about expressions. For now, just file away the idea that they’re two different things.
EXERCISE: Create a Twine game that
<<set>>
s a$score
variable for a reader, based on which of several passages they choose in the game. Have all passages lead to a “Game Over” passage that displays the$score
variable.
Changing a variable’s value
You can change a variable to a new value once you’ve set the value initially.
You can use this capability to track the reader’s progress through your story
over time. To change the value of a variable, simply use the <<set>>
macro again. In one passage, you might set the variable at first like so:
<<set $favorite_color to "red">>
… and then in another passage:
<<set $favorite_color to "blue">>
The variable $favorite_color
will now be "blue"
until the end of the
story (or until your story changes its value again!). Here’s an example game
that changes a variable that tracks the reader’s hunger level in response to
the choices that they make.
And here’s what it looks like when you play it:
As you play through this game, your “hunger level” will change, based on how
much of the cake you choose to eat. How does this work? We first set the
variable $hunger_level
to "famished"
in the Start
passage. In the
The Food Room
passage, we display the $hunger_level
with the <<print>>
macro, and then link to several new passages. Each of these passages then
links to another passage; these passages use <<set>>
to change the
value of the variable. When the reader returns to the The Food Room
passage, it reflects the new value assigned in the other passages.
Changing a variable’s value based on its current state
It’s common to want to change a variable’s value based on what the value currently is—say, for example, you’re keeping track of a player’s score. You might want to increase (or decrease) the user’s score by some amount, without having to set the value to some exact number.
There’s an easy way to do this in Twine using expressions. An “expression” is
some combination of values, variables and operators that the computer examines
and evaluates, producing a single value. We’ll talk more about expressions
below (what they are, how they work, and the rules for putting them together).
But for now, here’s how to write an expression that makes the <<set>>
macro
increase a variable by one.
Say you start in one passage with this code:
<<set $score to 0>>
If you want to increase the value in $score
by 1, you might put this macro
in another passage:
<<set $score to $score + 1>>
The $score + 1
in the above code is the “expression” in question:
essentially, it’s an instruction to the computer to figure out what the
value of the $score
variable is, with 1
added to it.
Here’s an example Twine game that increases the number of “widgets” in the player’s possession every time they visit a particular passage.
The $widget_count
variable gets set to 0
in the Start
passage. Whenever
the player clicks on the Take widget
passage, the following macro is run:
<<set $widget_count to $widget_count + 1>>
This macro causes the value in $widget_count
to increment by one. When the
variable is <<print>>
ed in the Showroom
passage, you can see that the
variable has been changed.
Here’s what it looks like in action:
You can replace +
in the expression below with -
if you want the value
to decrease by one instead of increasing. You can also change the number:
if you put 20
instead of 1
, the value will increase by twenty instead of
one. Give it a try!
Making decisions with <<if>>
At this point, we know how to set variables, print variables, and how to change the value of a variable after it’s been set. Now we’re going to learn how to make our Twine stories do different things based on the value of a variable.
The <<if>>/<<endif>>
macro checks to see if the value in a variable meets
certain criteria. If it does, then the text (and other markup) between the
<<if>>
and <<endif>>
gets displayed. If it does not, then nothing
happens.
The simplest way to use <<if>>/<<endif>>
is with a variable name after
the if
:
<<if $player_has_key>>You've got the key!<<endif>>
For example, the following code would display “You’ve got the key!”
only if the variable $player_has_key
has been set to a value with the
<<set>>
macro previously. (Technically, it happens if the variable has been
set to a value that isn’t 0
or an empty string ""
; full details here.)
Here’s a Twine game that makes use of <<if>>/<<endif>>
macro to show a
stretch of text in a passage only if the player has visited another passage:
Here you can see that the belongings
passage <<set>>
s the
$wearing_crystal_specs
variable to 1
when the reader visits the passage.
When the player returns to Start
, the previously hidden stretch of text
(linking to the cat
) appears, allowing the reader to complete the story.
Here’s an animation showing how it happens:
<<else>>
In the example above, the phrasing is a little awkward: the reader is
invited to go through their possessions to look for the crystal spectacles
even if they’re already wearing them! That’s not quite right. Ideally, we’d
like to have a way to say something like: “If the $wearing_crystal_specs
variable has been set, then do this. Otherwise, do something else.”
Twine provides a macro for doing just such a thing, and it’s called <<else>>
.
Here’s how it’s used:
<<if $player_has_key>>You've got the key!<<else>>You need a key. :(<<endif>>
The code above would display the text You've got the key!
if the variable
$player_has_key
is set. If not, it displays You need a key. :(
.
Here’s a modified version of the Start
passage from the example in the
previous section that uses the <<else>>
to only invite the reader to inspect
their belongings when they’re not already wearing the crystal spectacles:
And here’s how the playthrough looks (notice how the passage in Start
seems to change!)
More sophisticated expressions with operators
Okay, now we’re cooking with gas. But let’s take it one step further. Say we want to make a story where the reader starts with five coins, and then spends the coins one by one. At that point, we want the game to stop and display a different passage, informing the player that they’ve spent all of their coins.
A reasonable request! We’ll just have a variable called $coin_count
, which
we’ll <<set>>
to 5
in the Start
passage, and then have another passage
in which we <<set>>
the variable to one fewer than its current value.
Then, we’ll check to see if that value has reached zero with an <<if>>
statement. Simple! Except…
We can’t quite accomplish this with just the tools we’ve used so far, however.
We need to check not just if the $coin_count
variable has been set, but if
it contains a specific value. For this, we need to learn about a new thing:
operators.
The operators we’ll look at in this section allow us to perform a test by comparing two values in relation to one another—for example, checking to see if two values or equal, or if one value is greater than the other. We say that the expression “succeeds” or “returns true” if the test describes the actual state of things, and that it “fails” or “returns false” otherwise.
Such operators involve two values: one written to the operator’s left and one to its right. (By “value” here I mean either a variable that contains a value, or a value that you type in directly without assigning it to a variable.)
The way it works is this: you put the operator and both values right after
if
in the <<if>>
macro. The <<if>>
macro will display its text if
the comparison “succeeds.”
The operator you’ll use the most is probably is
, which checks to see if two
values are equal to one another. Here’s what it looks like in an <<if>>
macro:
<<if $coin_count is 0>>You're out of coins!<<endif>>
The above code will display the text You're out of coins!
if the value of
$coin_count
is 0
.
So let’s write the story!
Here are the important parts:
- In
Start
, we initialize$coin_count
to5
. - All of the links in
Flea Market
lead toBuy
. InBuy
, we do two important things:- First, we check to see if the reader has any coins left with
<<if $coin_count is 0>>
. If the count is zero, we know that the reader has spent all their coins, and display the “game over” message. - Then, in the
<<else>>
, we use<<set>>
to decrease the number of coins in the reader’s possession:<<set $coin_count to $coin_count - 1>>
.
- First, we check to see if the reader has any coins left with
- In
Flea Market
, we display the number of coins the player has left with<<print>>
.
EXERCISE: There’s another
<<if>>
macro inFlea Market
that controls whether or not thes
gets displayed after the wordcoin
. Describe in prose how this macro does its job.
More about expressions
The operator is
checks to ensure that the value to the left of the operator
is the same as the value to the right. But there are a number of other
operators that we can use as well! Learning how to use these operators will
open up new possibilities for interesting rules and procedures in your stories. Here’s a list:
is
: true if the left value is equal to the right value.neq
: true if the left value is NOT equal to the right value (neq
is short fornot equal
).>
: true if the left value is greater than the right value.<
: true if the left value is less than the right value.>=
: true if the left value is greater than or equal to the right value.<=
: true if the left value is less than or equal to the right value.
So, for example, to check whether a variable $player_name
has some value
other than Josephine, you might put the following macro in your code:
<<if $player_name neq "Josephine">>
This madeleine is only for Josephine! Go away!
<<endif>>
You can also combine expressions using the operators and
and or
. The
and
operator takes two expressions, one on its left, and the other on its
right, and counts as “true” if both expressions are true. The or
operator
similarly takes two expressions, and counts as “true” if either the left-hand
expression is true, or the right-hand expression is true (or both). The
expressions on either side of and
and or
should be surrounded by
parentheses.
So, for example, to make some text appear only if the reader has five coins AND that their name is “Robert”:
<<if ($player_name is "Robert") and ($coin_count >= 5)>>
You are Robert, and you have enough coins to purchase this magnificent
and magical sword.
<<endif>>
To make some text appear if the player has either 0 points or 100 points:
<<if ($score is 0) or ($score is 100)>>
You are either really good at this game or really bad at this game.
<<endif>>
Finally, the operator not
takes an expression directly to the right, and
counts as “true” if the expression is “false,” and “false” if the expression
is “true.” You can use this to check to see if a certain condition does not
obtain:
<<if not ($score is 0)>>
You have more or fewer than zero points! Good job.
<<endif>>
Eliminating excess whitespace
You may have noticed that every time we use a macro, some weird extra
space appears in the rendered output. This happens because Twine counts the
new lines that are inside the macro (i.e., after the >>
) even if the
macro doesn’t display anything (e.g., if an <<if>>
condition isn’t true).
For example, the following code:
Here's some text before.
<<if $player_name is "Sandra">>
You are Sandra.
<<endif>>
And here's some text after.
…renders like this, if you put something other than Sandra
in as the value
of $player_name
:
What’s worse, even if the <<if>>
macro condition is true, we still have
extra whitespace!
This is pretty annoying from an aesthetic perspective. Thankfully, there are ways to fix it.
One way to fix this is simply by removing as many new lines as possible, nestling the <<if>>
macro up against the other text:
Here's some text before.<<if $player_name is "Sandra">>
You are Sandra.<<endif>>
And here's some text after.
This is fine (try it out!) but it’s a little bit confusing, because the
<<if>>
macro is in a strange place. Ideally, we’d like to be able to retain
the whitespace in our code, as a means of keeping things clear, while still
avoiding the appearance of unwanted whitespace.
Another way to do this is with the \
character (backslash). If you put
this character at the end of a line, it instructs Twine to not display
a new line in the rendered output:
Here's some text before.
<<if $player_name is "Sandra">>\
You are Sandra.
<<endif>>\
And here's some text after.
If you have a number of macros that you want to include in your code without
introducing unwanted whitespace, you can use the <<nobr>>
tag. The
<<nobr>>
macro, which instructs Twine to ignore new lines up until it
encounters <<endnobr>>
. For example, to include a number of <<set>>
macros without making a huge amount of whitespace:
<<nobr>>
<<set $cheese to 1>>
<<set $room_title to "Vestibule">>
<<set $current_trouser_type to "Denim">>
<<endnobr>>
Read more about the nobr macro.
Setter links
We’ve spent a lot of time here creating passages that serve one purpose only:
to use the <<set>>
macro to set a variable to a particular value, then
continue to some other passage. It turns out that this is a very common thing
to want to do—so common, in fact, that Twine has a short-cut that allows
you to set a variable right inside a link! This technique is called a “setter
link” and it looks like this:
[[Text of link|PassageName][$variable = value]]
… where Text of link
is the text that the link should display,
PassageName
is the passage the link should go to, $variable
is the name of
the variable you want to set, and value
is the value you want to set the
variable to.
Using setter links, we can reduce our Personality Quiz Twine to just two passages:
The value
you set the variable to can itself be an expression. Here’s a
single-passage Twine story that lets you click and click to increase a number,
without ever needing a second passage. Notice the syntax in the setter link:
Read more about setter links.
Functions
Twine has still another way for you to introduce interesting behavior into your stories: functions. A “function” is a little piece of code, defined by Twine behind the scenes, that you can use in your Twine code as if it were a value or an expression. We’ll talk about a few of these below.
either()
The either()
function takes a series of comma-separated values inside its
parentheses. When you play your story, Twine will randomly choose one of these
values. You can use this to add a bit of color to your games:
Rain is falling from the <<print either("slate", "stone", "somber")>>
sky.
… or to make something random happen:
<<set $player_fate to either("death", "happiness", "fondue")>>
<<if $player_fate is "death">>
You die, finally and painfully.
<<else if $player_fate is "happiness">>
You live happily ever after.
<<else if $player_fate is "fondue">>
You have a fondue party with all of your closest friends.
<<endif>>
visited()
The visited()
function can tell you how many times the reader has visited
a particular passage in the game. Just put the name of the passage that
you want to check inside the parentheses (and inside quotation marks):
You have visited the cheese shop <<print visited("Cheeseshop")>> time(s).
You can also use this function in <<if>>
macros to make decisions based on
whether the reader has visited a particular passage:
<<if visited("University") > 0>>
You've been to the university, so you know everything you need to know
about interactive text.
<<endif>>
previous()
The previous()
function evaluates to the name of the last passage the
reader visited. You can use this to easily make a link that goes to the
previous page:
Dead end. [[Try another passage|previous()]]
You could also use the value from previous()
to check to see which passage
the reader just came from, if a passage has more than one entry point:
You are successful in your career, even though <<if previous() is
"University">>you start with no real-world experience<<else if previous() is
"Training">>you have no formal education<<endif>>.
Read more about functions.
Embedding other passages
With <<display>>