Twine 2 Tutorial: Coding with Twine Variables

Here it comes. The part of this tutorial series that some of you have been dreading: coding.

This is the part where we type obscure symbols that only a few select people can ever understand. Or so, some people tend to think. Believe it or not, coding isn’t that hard. You will get started on this journey by creating some Twine variables.

We use code all the time. Some code is made up on the fly while other code is rooted in technical documentation. As a parent, I remember employing a simple code to hide my intent from my then toddler.

“Lizzie, after we put Fiora to bed, do you want to have I-C-E-C-R-E-A-M”.

To my young daughter, I had just spoken some bizarre incantation, but my wife knew exactly what I meant. I was speaking in code.

You can write Twine code no problem. Heck, by reading this, you already show an amazing aptitude for deciphering code. Language is a far more complex code (by orders of magnitude) than anything written for a computer. After all, a computer language may dozens of words whereas a language has thousands and thousands of them.

In this tutorial, you’re going to be doing some Twine coding. You’ll also:

  • Learn about variables
  • Add a difficulty selection to your story
  • Create a global variable

This sounds difficult, but trust me, you’re going to be a pro. Time to get started.

Understanding Variables

Before you start writing code, you should have a good idea about variables because you’ll be using LOTS of variables in your stories.

Variables are small parcels of information that you pass around in your story. They are called variables because the containing value may change. That is, the information may vary.

Here’s an example of variables in action:

cats = 5
dogs = 10
pandemonium = cats + dogs

Can you guess the value of pandemonium? Take all the cats and add all the dogs, and then you get the number 15.

Now, whenever you refer to pandemonium, you’ll be referring to the value of 15.

If you were to say:

I had pandemonium sodas last night.

You would mean:

I had 15 sodas last night.

If you wanted to be tricky, you could say:

I had cats + dogs sodas last night.

The meaning is the same; ten sodas or otherwise a terrible hyperallergic sugar crash.

Twine Variable Types and Names

With Twine, we get lots of variable types. In the previous example, you saw number variables. You can also use decimal:

totalCats = 3.5

You can have true and false values:

isHungry = true

Or you can use text:

myQuote = "this space for rent."

All text-based variables (otherwise known as strings) must be put in quotes. You always must have two quotes; a start quote and an end quote. Missing a quote causes an error.

The following will cause an error being it is missing the end quote:

myQuote = "this space for rent.

Now, you may have noticed something amiss in the previous examples. I’m not talking about the half of a cat (the .5 refers to a kitten, you monster), but rather the variable names. Instead of one word, I used two. I lowercased the first letter of the first word and uppercased the first letter of each subsequent word. This is a standard programming practice when naming variables with multiple words.

Here are more examples:

numberOfDaysInMarch = 31
morningTemperature = 16.4
totalHitPoints = 54

This “camel case” makes it easier to decipher multiple words. You see, our variable name must be one word. So this is not valid:

total cats = 3.5

You must combine them into one word like the following:

totalCats = 3.5

Mind you, you can also use an underscore to separate words:

total_cats = 3.5

For these tutorials, I’ll be using camel-case, but when it comes to your own stories, use a naming convention that works best for you. Just make sure you are consistent with it.

Using the Correct Story Format

Okay, at this point, you are ready to start coding. We will be coding with the Harlowe story format. At the time of publication, this is the default story format included with Twine.

Open up your story when you last worked on it, or download the starter story found below:

Each story format provides its own coding style. This means code written for Harlowe won’t work in SugarCube and vice versa. You’ll learn more about story formats later in this series.

First make sure that you are using the correct story format. With your story open in Twine, click Bernie’s Revenge and then click the Change Story Format option.

Screenshot showing the options to select.

Make sure you have the latest version of Harlowe selected. This tutorial was written using Harlowe 3.2.1.

A screenhot showing the various story formats.

Nice job! You’re are all set to start coding!

Creating a “Difficulty Select”

In this story, players must escape the campground before being caught by Bernie. They need to collect gas for a pickup as well as the keys. They also must find Bernie’s recipe so they can turn it into authorities.

This story is going to have two difficulty modes. The easy mode has items in their same locations during each play through. On hard, item locations are randomized.

To get started, create a new passage. Name it: Introduction. Add the following to the description:

Welcome to the Wraith of Bernie. In this game, you play a lone boy scout, trapped in a campground while the camp cook seeks you out to try his new chili recipe. Seeing as the recipe sent all the other campers to the hospital, you must escape.

To win the game, you must escape with the evidence of the crime. Mind you, Bernie is out there, searching for one last victim. Can you survive?

This game has two modes: Easy and Hard. On easy, all the objects can be found in the same place. On hard, object locations are randomized.

[[Play Easy Mode|Easy]]
[[Play Hard Mode|Hard]]

Your passage should look like the following:

This creates two empty passages. Move them out of the way of the other passages.

At this point, you want to create a variable to keep track of the selected difficulty. You could have 0 mean easy and 1 mean hard, but that’s too abstract. Instead, you’ll use text instead.

Open the Easy passage. The name of the variable will be difficulty. In Harlowe, all variables must start with dollar sign. Your difficulty variable must be written as such:


This is weird but required. You’ll see why this is important in a moment.

Now in Easy passage, add the following:

$difficulty = "easy"

It should look like the following:

A screenshot showing the difficulty variable being set.

Now to run your story except you need to select a new starting point. Mouse over the Introduction passage. Click the three dots. Then click the Start Story Here option.

A screenshot showing how to set a passage as the starter passage

You’ll see the green rocket ship in the corner indicating the story start.

A screenshot showing the starter passage icon (a green circle with a white rocket in the center)

Now run your story. And select Easy. You should see something like the following:

A bug that reads: 0 = true

Umm … what the heck?

Before you read any further, let me pose a question to you: what did you expect to happen?

Think about it for a moment. You were setting data to a variable. That’s it. There was no other text so you should have encountered a black screen. Instead you got some gobbly-gook.

This, my friend, is a bug. That is an error in your program.

Welcome to the game!

Using Macros

When it comes to anything in Harlowe, you use macros. Macros are pre-built bits of code that you can leverage in your story and there are TONS of them. You can think of a macro like a singular word which you can use to create complex sentences.

Harlowe uses the Set macro to store data in a variable. The Set macro takes in the variable name and the value.

In your Easy passage, replace your previous code with the following:

(set: $difficulty to "easy")

It should look like the following:

A screenshot showing the set macro in use.

Now this looks really weird and codey. But try reading it out loud. It says, “set difficulty to easy”. You can see, it looks codey but speaks fine in English.

Macros follow the same pattern. First, they open with a parenthesis followed by the macro’s name. After the macro’s name is a colon where your provide your arguments. Here are some macro names:

(set: )
(print: )
(current-date: )
(link: )

Don’t worry if you don’t understand or even grasp the concept of macros. Go with the flow. Embrace the uncertainty. Just follow along. As you use more and more macros, it will all click but it takes both patience and practice.

Now play your story and select Easy. This time, you get a plain black screen.

An empty story

This is as expected. All you are doing is setting a variable and nothing else. Granted, this isn’t exactly a compelling experience. You need to move the player into the main story.

There is actually another macro that. Update the Easy passage to add the following code:

(go-to: "Camp Entrance")

Your passage should look like the following:

A screenshot showing the added code.

The Goto macro sends the player to the Camp Entrance passage. This is case sensitive so Camp Entrance is different than camp entrance is different from CaMp EnTrAnCe.

Now run your story. Select Easy and you’ll be sent to the Camp Entrance.

A screenshot showing the camp entrance passage.

One thing you’ll notice is that using the Goto passage DID NOT create a transition in your Twine editor.

A screenshot showing Twine passages without any new transitions.

The Go-to macro creates a dynamic transition while your story running. This means it can possibly send the player to any passage so it doesn’t annotate the transition.

Now that you set the difficulty, it’s time to access the value. This is where the Print macro comes into play.

Open the Camp Entrance and add the following to the top of the passage:

You have selected (print: $difficulty) mode.

It should look like the following:

A screenshot showing the new code added to the Camp Entrance passage.

Now play your story. Make sure to select the Easy difficulty. You will see the following:

A screenshot showing easy mode selected.

Look at that! Your variable is in action and printed out like normal text. Now you used the Print macro but there’s even an easier method.

Open the Camp Entrance and change the code to the following:

You have selected $difficulty mode.

It should look like such:

A screenshot which shows using $difficulty instead of the Set macro.

Now play your game and choose easy. You’ll discover it works just like before. You can just write your variables directly into the page.

Now the $ makes sense. It lets you (and Twine) know the difference between a regular word versus a variable.

One thing to note – you may need to reference currency in your story such as $1.99. Twine will show the currency without issue. This means, your variable names CANNOT start with a number.

For example, this is an invalid variable name:


Instead, write it out:


Defining Variables

At this point, you’ve set up the $difficulty variable for easy mode. Now it’s time for hard mode. Except, in this case, you’re not going to do that. It’s time to throw a wrench in the machine and see what happens.

I know some of you may be scratching your head. In development, we strive to make things work, not to make things fail. Yet, those failures are teachable moments as cheesy as it sounds.

When writing code, you’re going to run into a lot of weird errors so it’s best to experience them. That way, you’ll know what went wrong and how you might be able to fix it.

To get started, open the Hard passage and add the following code:

(go-to: "Camp Entrance")

All you are doing is redirecting the user to the Camp Entrance. You aren’t setting the $difficulty variable. Take a moment, and think how the story is going to behave. Now run your story. Make sure to select the hard mode.

The story says: You have selected 0 mode.

That’s an interesting result. You didn’t select easy or hard mode. You selected 0 mode.

According to the Camp Entrance passage, you didn’t create a $difficulty variable even though you defined it in the Easy passage. The user didn’t select easy mode, thus the variable wasn’t created.

Yet you are trying to access a variable that doesn’t exist. What’s Twine to do? The answer is simple. Default it to zero.

If you want to passages to share the same variable, you must define the variable in a parent passage. Open the Introduction passage and add the following code at the top of the passage:

(set: $difficulty to "hard")

Now any subsequent passages will have be able to read the $difficulty variable. In fact, you added a default value to it. Run your story.

Now select hard mode. And this time, it works as expected.

The story says: you have selected hard mode.

Believe it or not, you accidentally introduced a bug in your story. Run your story and check out the first paragraph. You’ll see that you gained an extra line break.

A screenshot showing the story with an extra space above it.

Harlowe (the story format) does its best to infer whitespace but it will replace your code with whitespace. There is a fix. You provide braces, ie {}, around your text and code. This will remove any whitespace.

In the Introduction passage, update it to the following:

(set: $difficulty to "hard")
Welcome to the Wraith of Bernie. In this game, you play a lone boy scout, trapped in a campground while the camp cook seeks you out to try his new Goulash recipe. Seeing as the recipe sent all the other campers to the hospital, you must escape. }

Now run your story. Voila! Your extra space is gone!

A screenshot showing that the extra space is now gone.

Well done!

Creating Global Variables

You saw in the last section that you must define a variable before you use it, otherwise, the variable will set to a zero. A best practice with Twine is to define your variable before you use it.

This poses a problem. Twine stories are non-linear. How do you define your variable before it is being used when you don’t know when that will happen? After all, you can’t predict behavior.

Instead, you’ll designate a passage as a startup passage. This is a special kind of passage that is run just once at the story start. This allows you to set variables that can be accessed anywhere in your story. In programming, these variables are known as global variables.

Create a new passage. Next, in the Tag field, click the + button.

A screenshot showing the location of the +Tag button.

Tags are a powerful part of Twine. You’ll see later in this series how you combine tags with code to some amazing results.

For the tag, give it the name startup. Remember, casing and spelling matter. Once done, click the add button.

A screenshot showing the startup tag added and the location of the Add button.

Next, in the passage, add the following to set the $difficulty variable.

(set: $difficulty to "hard")

Now open the Introduction passage and delete the code and braces. Run your story. Select hard mode. It works just like before, instead you are using global variables.

A screenshot shows the start of the game.

Nice work!

Where to Go from Here?

Congratulations on surviving your first coding encounter. As you can see, it wasn’t too bad. The Harlowe story format is designed for people new to coding. It’s quite easy to get up to speed and soon you’ll be creating some elaborate interactive stories.

In the next tutorial, you’ll build on your macro knowledge. You’ll learn how to retrieve values from macros and in the process, ask the player for their name.

See you in the next tutorial!

By Brian Moakley

Brian Douglas Moakley is a writer and technologist who lives amongst the quiet hills in New England. When not reading tales of high adventure, he is often telling such stories to all who will listen.

Related Post

4 thoughts on “Twine 2 Tutorial: Coding with Twine Variables”
  1. Hi, loving your tutorials! Little question to ask you. In the above tutorial you introduce global variables and get us to (set $difficulty to “hard”) in the Startup passage. With the result that I can run the game and choose between the hard and easy modes. In the corresponding YouTube tutorial you set each variable in their corresponding passages. I don’t understand the change and if I set $difficulty to “easy” in the start up passage I only get easy mode as a result in the game. I hope I have explained my confusion clearly. many thanks for all your work. Nick

    1. HI! Just running through you’re awesome tutorial here – and I’m curious about the same comment from nikikinz… How do Globar Variables work on a deeper level? Why can’t “easy” and “hard” variables be set in the Startup passage? Or how would one do that? (ignore if this is answered in the following lessons).

      1. Hi Zachary, that’s a good question. The difficulty variable can only contain one value. If you first set it to easy, and then set it to hard, the variable will hold the last value in it. That is, hard. Instead, we set it to easy and leave it alone. That’s the default value of the story. If the user selects easy mode, we don’t need to change it. But, if the user selects hard mode, we do need to change it to reflect the user’s choice.

        If that wasn’t clear enough or I misunderstood your question, please let me know. In any case, I’m glad you are enjoying the series.

Leave a Reply

Discover more from Jezner Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading