I’ve been playing around with Twine for a number of years and the number one question I get from new story authors is, “how do I get the player’s name?”

In older versions of Harlowe, you needed to write some Javascript that created a browser input box. It was a rough solution that wasn’t very mobile-friendly. My advice to the question was always, “just don’t do it”.

Thankfully, Leon Arnott (the author of the Harlowe story format) provided a solution but in order to understand how to use it, you need to dive deeper into macros.

Understanding Macros

Macros enable you to add interactivity to your story. They enable dynamism to both passages and text. In short, they are bits of functionality that will drive your entire narrative.

There are two types of macros. The first type is a command macro. This macro does some bit of work on your behalf.

For example, in the last tutorial, you sent the player to another passage by way of the (go-to:) macro. You also set variables with the (set:) macro. You ran a command, and Twine performed that command on your behalf.

The other type of macro is known as a data macro. Like a command macro, a data macro will do some work on your behalf only this time, it will return a value.

For example, the (random:) macro takes in two different numbers and returns a random number between the two ranges.

Sometimes, macros return other types of objects such as macros! This means you can effectively set macros into variables, and then call those macros on demand. This is an advanced feature that you’ll learn later in this series.

The big question: how do you use values returned by macros? The answer is simple. You pass them into other macros!

To demonstrate this, you’ll pose a question to the player.

Asking a Question

In Harlowe, asking a question is quite easy. To do so, you use the (prompt:) macro. Open your story in progress, or feel free to download the starter story:

Open the Beginning passage. At the top of the passage, add the following code:

(prompt: "What is your name?", "Vegetarian Zombie")

It should look like the following:

A screenshot showing the code added to the passage.

This macro takes two different strings (remember, strings mean text). The first string is the question that you are asking. The second string is the default value.

If the player doesn’t provide a name, they’ll be assigned the name of my YouTube channel: Vegetarian Zombie.

Now run your story. When the story starts, you’ll see the following:

A screenshot that shows a dialog presented to the user

Click OK. Now you’ll notice something different. The name you selected is printed above the starting passage.

A screenshot that shows the entered text above the passage text.

The reason for that message is that once the prompt obtains the user’s name, it doesn’t know what to do with it. You need to store it in a variable like any other piece of data. Can you guess where I’m going here?

Macros in Macros in Macros

One of the awesome things about macros is that you can “nest” them a la Russian dolls. If a macro returns a value, you can pass it to another macro that returns a value. You can keep doing this until you call a command macro which ends the whole dance.

For example, let’s say you wanted to repeat a person’s name in all caps.

You first call the (prompt:) macro.

(prompt: "Name?", "Player 1")

It returns text, so you pass the results of the (prompt:) macro into the (uppercase:) macro.

(uppercase: 
  (prompt: "Name?", "Player 1")
)

After which, you pass the results of the (uppercase:) macro into the (str-repeated:) macro to repeat the name. The (str-repeated:) repeats the string (text) as many times as indicated by the number passed into it.

(str-repeated: 3,
  (uppercase: 
    (prompt: "Name?", "Player 1")
  )
)

Finally, you end the chain by using the (set:) macro.

(set: $name to 
  (str-repeated: 3,
    (uppercase: 
      (prompt: "Name?", "Player 1")
    )
  )
)

All you are doing is wrapping macros around each other. You could do this in one giant line, but with spacing and alignment, you can decipher the logic at glance.

Now take a moment to appreciate that last example. That’s code. That’s code you didn’t understand not too long ago.

Take this time to give yourself a pat on the back. You are seeing structure in something that looks nonsensical.

Now to put it to use. Open the Beginning passage and update it to the following:

(set: $name to 
  (prompt: "What is your name?", "Vegetarian Zombie")
)

Hello $name, welcome to the Wraith of Bernie ...

And that’s it.

A screenshot showing the code in the beginning of the passage.

Run your story. You’ll be greeted with a prompt. You’ll notice that the $name variable isn’t set.

The text reads: "Hello, welcome to the Wraith of Bernie"

Now provide your name. You’ll see the passage text update with your name.

A screenshot showing the player name in the story.

Well done!

Where to Go from Here?

Congratulations on making it this far in the tutorial series. You’ve created a simple story, added some logic to it and in the process, you’ve learned a lot about Twine (and Harlowe) in the process.

But you are just getting started. In the next part of this series, you’ll dive even deeper into the coding world, creating your own inventory system, adding branching logic and even creating some in game object.

So take a break, get a nice cool beverage and meet me in the next tutorial.