Text adventures were some of the earliest computer games. A generation of hackers cut their teeth on ones such as Infocom's Zork. Graphical games have long since taken over the commercial games market, but a vibrant independent community has kept text adventures, also known as interactive fiction, alive. For example, as many games were written for the 2005 Interactive Fiction Competition as Infocom wrote in ten years.
Want to write interactive fiction? You're in luck. A lot of work has gone into tools for doing so. Specialty programming languages such as TADS and Hugo are designed for the task, and are freely available. The most popular of these is Inform. The latest version of Inform, known as Inform 7 or I7, is designed to be easy for newcomers to use.
Let's find out if it really is easy to use. In this tutorial we'll use I7 to write a simple game. By the time we're done, you'll have the beginnings of your very own masterpiece.
I7 is a complete design system for interactive fiction. It's made up of a programming language and a front-end development environment. The programming language is based on English—if you're used to programming languages like C or Perl, be ready for a surprise. I7 uses logical rule-based programming to make things happen in the game world. You make a rule by defining when the rule should happen (like "when a player tries to pick up the porcupine") and what should happen (the player is told "Those quills are too pointy for you to do that!"). The development environment is set up like a book. On one page you write your game; on the opposing page you play it. The opposing page also includes a manual, a table of contents for your game, a list of every object in your game world, and more.
There's a lot more to I7 than that, but rather than wasting our time talking about I7, let's start writing our game. Before we begin, you'll need to grab a copy of Inform 7. It's available for Mac, Windows, and Linux.
For this tutorial, we'll create a simple game. Let's say that the player is on an intergalactic tour of various planets. We'll start the game on the player's spaceship-slash-cruise liner while it's en route to the first planet. Let's call the game "The Grand Tour".
Once you've installed Inform 7, start the program. Press "start a New Project". You'll need to fill in the name of your project ("The Grand Tour") and your name. Then press Start.
The Inform 7 manual is designed to introduce enough concepts early on that you can write a simple game after a few chapters, with additional chapters introducing additional features. It also has many worked examples to demonstrate how to code something. Read through the manual at your first opportunity.
On the left is where we'll write the code to our game, called the "source". At the top you'll see that I7 has already entered the game name and your name in a sentence. On the right is the manual. You'll want to read that later, but for now, just follow along with me. Just as the I7 development environment is modeled on a book, I7 in many ways treats your game as a book. The source is divided into paragraphs, with a blank line between each paragraph. You can add bibliographic data to your game to specify what year it was written, what its genre is, and more. Below the paragraph with the game's title and your name, add the following paragraph:
The release number is 1. The story creation year is 2006. The story headline is "A short I7 demonstration". The story genre is "Science Fiction". The story description is "A small example of how to write interactive fiction with Inform 7".
Games begin by printing out the game's title, author name, and story headline. Traditionally the headline gives additional information about the game. The story description is a short blurb about the game, suitable for excerpting on a web page listing many games.
When writing interactive fiction, you usually begin by defining the game's rooms. We'll start with just a few. To make our life easy, the player will be stuck in their stateroom, which will have a main room and a bathroom.
To make a room, you give it a name and a description. Whatever room you put first in the source is where the player will start. Let's begin with the stateroom's main room. Type the following paragraph below the game information paragraph.
The Stateroom is a room. "Staterooms aboard a spaceship, even one as luxurious as the Thaleia, are tight, cramped affairs, and this one is no exception. There is barely enough room for you and the furniture. The door to the hallway is locked tight for now. East is your bathroom."
Let's not wait any longer—try running it! Above your source is the green Go! button. Press it and the game compiles, then runs in the right pane. If instead you see a report that begins with Problem, then you've typed something wrong. Compare what you've typed with the above.
That one room isn't very exciting on its own, so let's go ahead and add the bathroom. We'll say what direction the bathroom is from the stateroom using compass directions. Start a new paragraph below the Stateroom paragraph.
The Bathroom is east of the Stateroom. The description is "Like your stateroom in smallness, only moreso. There is a mirror on one wall."
We now have two rooms connected to each other. Press the Go! button (or F5) to compile and run the game. Try going east and then west. It can be hard to keep track of where rooms are in relation to each other. The Index can help with that. On the right side of the I7 window, select the Index tab. If it's blank, hit F7 to compile your game. In the Index tab, select the World button. You should see the Stateroom and Bathroom listed with a line connecting them. You can also see that the player, listed as "yourself", starts in the Stateroom. The Index begins blank, but every time you compile your game, it's updated with new information.
Now that we have our game world mapped out, let's add stuff. The game doesn't automatically create the stuff we mention in room descriptions, like the mirror in the bathroom. It's up to us to define it ourselves.
I7 uses "kinds" to categorize stuff. We used a kind above when we said "The Stateroom is a room." That tells I7 that the object called the Stateroom is a kind of room. There can be more specific versions of any kind. For example, I7 knows about persons. It also knows that a man and a woman are more specific kinds of persons.
To see what kinds of objects I7 knows about, select the Index tab in the right side. Remember, if it's blank, press F7 to compile your game and fill in the Index's information. Under the Index tab, press the Kinds button. This page lists all the kinds that I7 knows about. They're grouped by what they're related to. At the top of the list is "object," the most fundamental kind of stuff in I7. A thing is a kind of object, so it's listed and indented under object. A person is a specific kind of thing, so it's listed and indented under object, about halfway down the list. A man is a specific kind of person, so it's listed and indented under person. Unless you say otherwise, I7 will usually assume that anything you create is a thing.
Now back to our game. The Stateroom is very bare. Let's add a promotional leaflet to the Stateroom extolling the virtues of our trip. Under the paragraph about the Stateroom, add the following paragraph.
The leaflet is in the Stateroom. The description is "It goes on and on about how wonderful the Thaleia is. Should you have trouble sleeping later, reading this could help."
"The description is" tells I7 what should be printed when you look at the leaflet. If you run the game now, you'll see a leaflet on the floor, which you can pick up and read.
While the leaflet makes the Stateroom less empty, the room doesn't even have a place for the player to sleep! Let's add a bed to the room.
The bed is in the Stateroom.
That's not bad. If you press F5 to compile and run the game, you'll see the bed in the Stateroom. However, try taking the bed. Whoops, it's portable. Even worse, try typing >ENTER BED. You can't get in it! To fix these problems, we need to give the bed some attributes, and possibly define it as a different "kind".
I7 keeps track of all of the commands you've ever typed while playing your game. They're stored in the Skein tab in the right-hand pane. The Skein is a tree view of the commands, branching every time you entered a different command than you did on a previous play-through. You can name branches of the tree for easy reference, and by double-clicking on a node you will play through the game using all the commands in the branches leading to that node. As your game gets more complex, use the Skein to test your game. This gives you more flexibility than the Replay button, since you can try different commands on a runthrough but go back to your standard runthrough later.
In the Index, select the Kinds button. We'll select a better kind for the bed than "thing". If you click on the grey magnifying glass icon next to any kind, you'll see a description of that kind. We need to make the bed a supporter, so that players can put things on it if they wish. If you click on the grey magnifying glass icon next to supporter, you'll see "Normally fixed in place not portable." In other words, supporters by default can't be taken, which is what we want for the bed. Change the paragraph about the bed to be:
The bed is a supporter in the Stateroom.
Now we can take the leaflet and put it on the bed, and we can't take the bed itself. However, we can't get in the bed. Play the game and type >GET IN BED to see. To be able to enter the bed, we need to change the definition of the bed.
The bed is an enterable supporter in the Stateroom.
We could now re-run the game by pressing F5. Instead, press the green button with the circular arrows, just to the right of the Go! button. That's the replay button, and it plays through the game using the exact same commands as last time. If you typed >GET IN BED last time, the Replay button will re-try that command, only this time it should work. Replay is useful for re-testing a game when you discover a bug, make a change to the code, and then want to make sure you fixed the bug.
Let's add one more refinement to the bed. In the room description, we mentioned the furniture. Right now the only furniture is the bed. It would be nice if the game allowed players to refer to the bed as furniture. To do so, we need to use an Understand sentence. Add the following sentence to the paragraph about the bed:
Inform 7's basis in English can lead you to write code that reads okay but that I7 doesn't understand. When that happens, I7 prints a Problem Message. In stating the Problem, I7 includes orange arrow icons to take you to the offending sentences.
Understand "furniture" as the bed.
"Understand" tells I7 that we want to be able to refer to a prop by a different name. By default I7 knows that, if a player types "bed", they're refering to the bed. By adding the above Understand sentence, we're telling I7 that if a player types "furniture", I7 should refer to the bed as well.
In describing the Bathroom, we mentioned that it has a mirror. Let's add that now, below the Bathroom paragraph.
The mirror is scenery in the Bathroom. The description is "You look tired after your long shuttle flight to the Thaleia."
"Scenery" is an attribute that most kinds can have. Props that are scenery are fixed in place, and aren't described separately from the room, the way the bed in the Stateroom is.
Finally, let's add a shower to the Bathroom. Add this paragraph somewhere under the Bathroom paragraph:
The shower is here. It is fixed in place. "Opposite the mirror is the shower, which is closed." The description of the shower is "When it's open, you get in it to take a shower. Right now it's closed, keeping you from using it."
There are three new ideas introduced in this paragraph. First, notice how we said that the shower is "here"? "Here" refers to the last room we defined. If we had put the shower paragraph under the Stateroom paragraph instead of the Bathroom paragraph, it would be in the Stateroom and not the Bathroom. Second, the shower is fixed in place so light-fingered players won't tuck it in their pockets. Third, the sentence in quotes is the paragraph of text that will be printed in the Bathroom. If we hadn't specified the shower's description in the room, then I7 would print, "You see a shower here."
We described the shower as being closed so we wouldn't have to deal with the player trying to use it. But what if the player tries to open it? If you run the game and try it yourself, you'll be told, "That's not something you can open." While strictly true, that message isn't very satisfying. We can do better by using a rule.
Rules define how the game world works. You specify when a rule applies and what happens when the rule is followed. I7 uses rules to define what happens normally. We can add our own rules to change I7's behavior. In this case, instead of I7 printing the default message when players try to open the shower, we want our game to say something else. Add the following sentence to the end of the shower paragraph:
Instead of opening or entering the shower, say "It is locked down until after the ship makes its jump to hyperspace."
This is an "Instead" rule. Instead rules bypass I7's normal rules and replace them with our own. In this case, we're telling I7 not to do what it normally does if the player tries to open or enter the shower. Instead, our game should explain that the shower is locked for now.
We can do something similar with a door in the Stateroom. The Stateroom's description says that the door to the hallway is locked tight. Let's add a door to the Stateroom that tells players that it's locked if the players try to open it.
The hallway door is scenery in the Stateroom. Instead of opening or entering the hallway door, say "The captain has locked all stateroom doors in preparation for jumping to hyperspace."
There are more types of rules than just Instead rules. As a demonstration of rules' other powers, let's fix an ongoing problem with our game. When you start The Grand Tour, you're dumped into the Stateroom with no explanation, and only a leaflet to give you some idea of what's going on. Let's start the game with the captain announcing the lockdown over the intercom. We can do that by writing a new rule that will be followed at the start of the game. Near the top of the source, add this rule:
When play begins: say "The intercom crackles to life. 'This is your captain speaking. We're jumping to hyperspace shortly, so for your protection, we've locked all stateroom doors. As soon as we've safely jumped, your doors will open and you will be free to move about the ship.'"
I7 will automatically turn the single quotes into double quotes. Try playing the game now, and you should see the above paragraph before the game's name is printed.
To round our our example game, let's add a person. In fact, let's add a robot butler for the player.
Robutler is a man in the Stateroom. "Robutler stands attentive to your needs." The description of Robutler is "Robutler has four arms, treads, and a shiny metal body." Understand "robot" and "butler" as Robutler.
I7 provides a way to organize code through headings. Headings are any single-sentence paragraphs that begin with "volume", "book", "part", "chapter", or "section". Headings let you organize your story as if it were a book. In addition, the Index keeps track of all of your headings under the "Contents" sub-tab, and lets you jump directly to them. For this game, I would use three headers. "Chapter 1 - The Game World" would be the Stateroom, the Bathroom, and all of the props besides Robutler. "Chapter 2 - Other Characters" would be Robutler and his "every turn" rule. "Chapter 3 - The Sleep Puzzle" would be all of the rules for the sleep puzzle.
It would be cool if Robutler, like an annoying solicitor, followed the player around wherever they went-which right now is just to the bathroom, but still. For this to occur, we need to check every turn to see if Robutler is still in the same room as the player. If not, we need to move Robutler to the player's room and say something about Robutler joining the player. Try adding the following to the game's source.
Every turn:
if Robutler is not visible begin;
move Robutler to the location of the player;
say "Robutler rattles into the room, following you.";
end if.
This is the most complex rule we've written so far. "Every turn:" means that the rule is followed every turn. The "if...begin" and "end if" statements surround several actions that occur only if Robutler isn't in the same room as the player. We determine whether or not Robutler and the player are together with the "is not visible" condition. "visible" means the player can see the object. Using "is not visible" prevents Robutler from following the player onto the bed, since the player can see Robutler from the bed. The two actions move Robutler to the player and announce his arrival. To see it in action, run your game and go east.
So far the game is static. Other than Robutler following players around, nothing happens. We can change that by adding a sleep puzzle. Early text adventures often had puzzles where players had to sleep or eat or else they'd die. These days sleep and hunger puzzles are considered too annoying to include in a game. However, for a demonstration game like this, a sleep puzzle will do just fine.
The sleep puzzle will be very simple. Every once in a while, players will be told that they're getting sleepier, and that they should get in bed. If they don't get in bed after enough time has gone by, they'll die. If they get into bed, they win the game.
The basic unit of time in interactive fiction is the turn. A turn consists of the player typing a command and the game responding. In I7 one turn takes one minute, and the game begins at 9 AM. We're not including a clock in the game, so the absolute time doesn't matter to us. What does matter is how long we want to wait between warning messages. Let's have three warning messages. The first will come after 10 turns-in other words, at 9:10 AM. The second will come at 9:20 AM. The third will come at 9:25 AM. At 9:27 AM players will fall down dead.
Down at the bottom of your source, add the following paragraph:
At 9:10 AM: say "You realize that you are becoming exhausted." At 9:20 AM: say "Your exhaustion is threatening to send you crashing to the floor, unable to move." At 9:25 AM: say "You are about to drop dead of exhaustion. You really should get in bed."
These rules occur at 9:10 AM, 9:20 AM, and 9:25 AM, just as we planned. If you run the game and wait long enough, either by repeatedly typing Z to wait a turn or by moving around and looking at things, then you'll see all three messages.
That takes care of the warning messages. What about killing the player? We do so by ending the game. We can end the game in victory, end the game in death, or end the game and say a particular message. In this case we want to end the game in death at 9:27 AM. Add the following paragraph to the end of your source:
At 9:27 AM:
say "You stumble to your knees and then collapse on the floor, quite surprised to find that the phrase 'drop dead of exhaustion' can be literally true.";
end the game in death.
If we now play the game and wait 27 turns, we will fall over dead and the game will end.
There's one more thing we need to do: let the player win if they get in bed. We'll use an Instead rule to make the game end in victory when the player gets in bed.
Instead of entering the bed:
say "You climb into the bed, exhaustion overtaking you. You are asleep before you can order Robutler to undress you.";
end the game in victory.
There we go: our very first puzzle, complete with a way to lose the game and a way to win it.
The Inform 7 website has example I7 games and more, while Baf's Guide to the IF Archive lists the best recent works of interactive fiction for you to play. For more advanced advice about writing a good game, turn to Dan Shiovitz's guide.
At this point we have a game, albeit a small and not very interesting one. The player can't go many places, there's only one puzzle, and that puzzle is a sleep puzzle. It would be nice if Robutler would take things from you for safekeeping and give them back to you if you wanted. The game doesn't understand the command >LIE ON THE BED. And at some point the ship should complete its hyperspace jump and let players leave the Stateroom.
While this short tutorial can't cover all of that, the manual that comes with I7 can and does. Now that you understand some of the basic concepts, read through the manual. Not only does it explain all of I7 in a straightforward manner, it's chock full of examples that you can steal. For example, in the documentation, open the "Alphabetical Index of Examples" and look for the example called "Lies". If you click on it, you'll see that the example shows not only how to handle >LIE DOWN ON THE BED but also >LIE DOWN NEAR THE BED and more. Once you've read through the manual and know more about I7's advanced features, you'll be ready to add to The Grand Tour or to write an entirely new game.