A common question for many new Twine authors is creating an inventory system. There are many different ways to create inventory, but for this story, you’re going to start easy and later, scale up to advanced.
In this story, players need to collect certain items. First, they need to find Bernie’s chili recipe to turn it over to the authorities. Next they need to find pickup keys and the gasoline to escape. Optionally, they can try to find a flashlight to pass through a dark area in the campground.
On easy mode, the objects start in the same location every time. On hard mode, the locations are randomized. You’ll get started by adding objects in easy mode.
Note: This is part of an ongoing series of free tutorials on Twine. You can catch up over here.
Your Basic Basic Inventory System
The easiest way to create an inventory system is to simply create a variable for each object in the story. For example:
(set: $hasFlashlight to false)
Later, you can check if the user has the flashlight and then branch your story based on that value. You’ll learn about branching stories in the next tutorial.
This inventory method works well for small stories that contain only a few items, but as you add more items, this approach becomes tedious and error-prone.
A better approach is to create a container and put items in it. You can assign this container to the player and even create containers for each passage. One such container is an array.
Meet the Array (for your inventory)
An array is a container that holds things. You can have it hold numbers, text, and even other arrays! The best example of an array is a pill container.
The pill container contains pills for each day of the week. An array is just like a pill container except it can only contain one item. Instead of labeling each slot by the day, the array labels each slot by number.
When a player picks up an item, you’ll put that item into the array.
If the player drops an item, you’ll remove that item from the array.
If you wanted rooms to contain items, you could remove the object from the player’s inventory and put it in the room’s inventory. You won’t be implementing dropping behavior but consider it a personal challenge once you complete the tutorial series.
Implementing an Array
To get started, you’ll define a new story-wide variable. Open the Startup passage. Create a new variable $inventory and create an array, using the (a:) macro.
(set: $inventory to (a:))
The Starter passage should look like the following:
This creates an empty array but by declaring this in the Startup passage, every passage has access to the array.
Now to add your first object. You’ll add a set of keys. Open the Camp Entrance passage and at the bottom of the passage, add the following:
On the ground, you see a set of [[keys]].
The passage should look like the following:
This creates a new Keys passage. This is going to be a temporary passage which you’ll delete in a later tutorial.
Open the Keys passage and add the following:
These looks like Bernie's keys to his pickup. [[Pick them up->pickup]] or [[leave them->Camp Entrance]]
It should look like the following:
If the player leaves the keys, they’ll be sent to the Camp Entrance. If they decide to pick up the keys, they’ll be sent to the Pickup passage. You’ll notice this approach causes some problems.
First, the keys are “hard coded” to the Camp Entrance. This means the keys will always be located in the Camp Entrance. Remember, on hard difficulty, object placement is supposed to be randomized.
The next issue is you are going to do this for every object in the story which is going to get old pretty fast.
Adding to an Array
Arrays in Harlowe are somewhat confusing coming from another language. Typically, you directly set an item in an array. With Harlowe, you need to create another array, then combine the two arrays together.
Can you guess which macro you’ll use? If you guessed (set:), give yourself a prize.
Open the Pickup passage and add the following:
(set: $inventory to $inventory + (a: "keys"))
It should look like the following:
Uggh – that little bit of code that isn’t exactly obvious. This is a common pain point of Harlowe. As you add logic, your code will look like gobbly gook.
I’ve written lots of code in my time, including Objective-C which is a notorious ugly coding language. For me, Harlowe takes the ugly prize. Especially when you do complex things like writing your own macros (which won’t be covered)
Now to break down your code. Start on the right side. You’ll see the following code:
This creates a new array that contains the string, “keys”. You can also add other strings by separating them with commas.
(a: "keys", "flashlight", "recipe")
That creates an array containing three different text items. Now check out this code:
$inventory + (a: "keys")
The $inventory variable is an empty array and you are adding an existing array, so this combines the keys to the empty $inventory array. If you had existing items in the array, it would combine all those elements.
(set: $inventory to $inventory + (a: "keys"))
This code simply takes the combined $inventory and sets it to the old $inventory array. Now redirect the user. Add the following:
(go-to: "Camp Entrance")
The entire passage should look like the following:
Now run your story. If you select Easy mode and pickup the keys, you’ll be redirected back to the Camp Entrance like nothing happened.
Something did happen! You picked up the keys. You just don’t know it yet.
Printing from the Array
This is where things start to get fun. You have two tasks to complete but unfortunately, you’ll only be able to complete one of them. First, you have to show the inventory.
Next, once the user picks up the keys, you need to hide the keys from the passage’s description. Unfortunately, you won’t learn that in this tutorial. Don’t worry, it’s coming up in the next tutorial! For now, think of it as a bug.
To print out the inventory, add the following to the bottom of the Camp Entrance:
You are carrying:
Now to write the code to get the first item in the array. Remember, array’s contain items so you want to get the first item. Add the following:
You are carrying: (print: $inventory's 1st)
That’s all it takes. Your code should look like the following:
You are printing out the first element. If you wanted the second, you’d write: (print: $inventory’s 2nd) and so forth. This is a weird syntax, especially if you are coming from another programming language.
Run your story. Select easy mode and right away, you’ll run into an error.
This is an error message. You are trying to print out the first item in an inventory, but the inventory is empty. Harlowe doesn’t know what to do, so it prints an error message to let you know.
You’ll also notice a white rectangle in the lower right corner of the screen.
This is known as a “debug panel”. It helps troubleshoot your story when you run into errors. Right now, it shows you all your variables and it will update with any changes.
Now with the story still running, go ahead and pickup the keys. When you return back to the Camp Entrance, the error message is gone. In it’s place is your first inventory item.
You’ll also notice the debug panel has updated as well.
Congratulations! You’ve implemented a very rudimentary inventory system.
Where to Go From Here
Some of you may be scratching your head. Why did you have to write such complex code to get a basic inventory system? Why didn’t Twine come with such a system out of the box?
Twine is an interactive fiction engine. Even though many people use it to create games, Twine is not a game engine. It’s designed for create branching narratives like Choose Your Own Adventure stories.
There are other systems like Inform or TADS that have game concepts built into them from the ground up since they build interactive fiction games. For example, Inform allows you to create objects in one sentence. These objects can be carried by the player, dropped and manipulated.
Twine has a much broader scope. It’s meant to tell interactive stories and lots of those stories don’t have concepts of inventories or hit points. Thankfully, with some code, you can add your own.
You have your basic inventory in place but there’s a lot to do to build on it. In the next tutorial, you’ll clear up all those bugs and add new objects with a very helpful macro that poses a simple question: if.
See you then!