Inform 7 Concepts and Strategies

By Allison Parrish

(Draft version, some parts still unfinished!)

Inform is a programming language for creating interactive fiction (in the classic Infocom-esque parser-based format). It was created by Graham Nelson, and has a number of characteristics that make it different from other programming languages, and uniquely suited to the task of writing interactive fiction. Inform 7 is the most recent iteration of the language, and differs dramatically from previous versions, which is why you’ll see so many tutorials and documents specifically referencing “Inform 7.”

Inform: What and why

Inform is freely available for download, with IDEs for multiple programming languages. At points, this tutorial assumes that you’re working with the macOS IDE, but the general principles apply regardless of the version you’re using.

The goal of this tutorial is to show you some of the basic concepts that underlie how Inform works, along with some simple examples, so that you can quickly jump into the task of making your own interactive fiction works. But this tutorial is not comprehensive! It’s just a whirlwind tour of features that I think are important and interesting. See the Inform website’s “Learn” page for more resources, including the manuals, which give in-depth descriptions of the language along with helpful copy-and-paste-able snippets.

Natural-ish language-like

The most notable thing about Inform is its resemblance to “natural language.” One of the design goals of the project was to make a language that is easy for people without a programming background to read and write, and one tack taken to achieve this goal was to make the language “read” more like natural language, and, when writing code, allow for phrasings that (when everything is working the way it should) closely resemble idiomatic assertions and descriptions of what the programmer wants.

It would be reasonable, after looking at some Inform code, to reach the conclusion that “programming” in Inform consists of simply opening up the IDE and typing out what you want to happen. But don’t be fooled! Although it looks very different from other programming languages, Inform still has strict syntax and strong expectations about how your code is written and arranged.

See the manual chapter on punctuation for dramatic examples of how Inform bends over backwards to retain the quality and conventions of printed text in its source code. You end up with programs that are beautiful and clear to read. But writing the programs, or figuring out exactly what a program does without digging through the manual, can sometimes be a challenge.

The basic loop

A typical Inform program has more or less the following logic as its core “loop”:

  1. The user types in a command, usually consisting of a short imperative sentence (“open the wardrobe”).
  2. Inform’s parser translates what the user typed into an action, and attempts to match that action against actions defined in the source code. (There is a many-to-one relationship between what the user types and the actions thereby matched. For example, as we’ll see below, dance, jitterbug, and boogie might all be commands that map to the dance action.)
  3. Rules associated with each action can make changes to the state of the game. For example, an open action might update the state of a cupboard from being “closed” to “open”; an eat action might increment a variable associated with the player’s hunger level. The objects and values that form the game’s state are defined in the source code along with the actions and the rules.
  4. In addition to updating the game state, the rules cause a representation of the game’s state to be displayed to the user. (I.e., after typing in a command, the game will show you the results of that command.) The programmer makes decisions about what information gets displayed and how it’s displayed.
  5. Repeat from 1.

In most (imperative) programming languages, the main work of the programmer is to write a list of instructions that the computer carries out from beginning to end. In an Inform program, however, most of the programmer’s work goes into defining things: what the objects are like, what actions operate on them, and what should happen when those actions are triggered, either directly by user input, or indirectly from rules activating other rules. It’s a very different style of programming.

Interactive fiction and narrative structure

Why learn how to make interactive fiction games as part of a course about computational approaches to narrative? The first reason is simply that many works of interactive fiction are themselves well-known and useful examples of computational narrative, and learning how to make games in that style will help you understand how those games work and how they successfully produce the effects that they produce. (Examples of interactive fiction works that might be considered in the “canon” of new media art and literature include Zork, Trinity.

Another reason is the particular parts of narrative that the medium of interactive fiction draws its authors toward. Hypertext works concern themselves primarily with how snippets of narrative discourse related to one another, and usually don’t have a formal model of setting, objects or character, aside from what emerges in the text of the narration. Interactive fiction, on the other hand, starts with formal definitions of setting, objects and character, and the narration emerges from the rules associated with those models.

As a (traditionally) entirely text-based medium, interactive fiction serves both as a testbed for generating textual narrative discourse from abstract representations of events, and as a potential prototyping environment for simulation-oriented computational storytelling in other media.

Actions, verbs, properties, kinds and relations

The purpose of this section is to show you how to make it so you can make a program that accepts a command from the user, changes the state of the game in response, and displays a response to the user.

Let’s get started. The following is a very minimal Inform program. The first line is a header that gives the title of the work along with the name of its author. Anything between square brackets ([, ]) is a comment (unless the square brackets are inside of double quotes; see below). The last line creates two objects, one called “Studio” and another called “piano.” Note that definitions of this kind end with periods (.). For now, don’t worry about what a room is, or what it means for the piano to be in the room. We’ll talk about those later.

Note on how this tutorial works: You’ll find Inform 7 code samples above a box with a button labelled “Play.” The “play” button will activate an in-browser Inform interpreter allowing you to interact with the program whose source code is listed. If you want to make modifications to the code, copy and paste it into the Inform IDE and hit the “Go!” button in the IDE.

"The Studio" by Allison Parrish

[This is a comment.]
The Studio is a room. A piano is in the studio.

When you start an Inform program, Inform automatically creates a player object and puts it into the room mentioned. Right now this game doesn’t do much. If you try to type a command, like sing, or play the piano, you’ll get something like this:

>sing
That's not a verb I recognise.

>play the piano
That's not a verb I recognise.

The game is telling you that it doesn’t have any actions associated with the commands you’ve typed. You’ll have to define those actions yourself. (If you’ve played interactive fiction before, you might know about some commands that every Inform game already supports, like examine or take. We’ll talk about those later, but for now we’re going to focus on writing code to implement our own verbs and actions.)

Your first verbs

Making an action. Report rule. Say command.

To make the game do something in response to the user typing a command like, say, dance, you need to do the following things:

  1. Define the action
  2. Define the text that causes the action to happen
  3. Define a rule that specifies what should happen when the action is triggered

For now, we’ll focus on verbs that don’t take a direct object.

In Inform, an action (with no direct object) is defined with the following syntax:

Verbing is an action applying to nothing.

The is an action applying to nothing part is the actual Inform syntax. You need to replace Verbing with the -ing form of the verb of your choice (e.g., dancing, coughing, sighing, etc.).

An action definition on its own doesn’t do anything. If you want the player’s input to trigger this action, you need to include a line that looks like this:

Understand "verb" as verbing.

(Keeping the quotes intact.) Replace verb with the command you want the user to be able to type, and verbing with the same verb that you used to define the action above. This creates a “verb” command that triggers the corresponding action.

The following example creates an action dancing and associates it with the command dance. Try typing dance at the prompt.

"Dancing in the studio" by Allison Parrish

The Studio is a room. A piano is in the studio.

Dancing is an action applying to nothing. Understand "dance" as dancing.

Report dancing:
    say "You dance a spritely jig."

The last two lines of this program create a rule that specifies what should happen after the dancing action is activated. In this case, the only thing that happens is a call to say, which is an Inform construct that simply displays the text between the quotation marks to the screen.

The understand construction can take multiple “synonyms” or alternative commands that will all trigger the same action:

"More dancing in the studio" by Allison Parrish

The Studio is a room. A piano is in the studio.

Dancing is an action applying to nothing. Understand "dance" or "boogie" or "jitterbug" as dancing.

Report dancing:
    say "You dance a spritely jig."

Now all of the following will report a jig being danced:

>dance
You dance a spritely jig.

>boogie
You dance a spritely jig.

>jitterbug
You dance a spritely jig.

It’s important to distinguish between the work that is an action applying to does, and the work that Understand … as … does. The former defines the action; the latter defines what the user has to type to create the action. (In some works of IF, there are actions that are never triggered directly by the user, but only by other actions. Those actions don’t need an Understand … as … construction.)

Verbs with direct objects

To make a command that allows the user to take action on something in the world, there’s another version of the is an action applying to syntax. It looks like this:

Verbing is an action applying to one touchable thing.

Again, replace Verbing with the verb of your choice. The one touchable thing notation is a little bit weird; you can ignore it for now, except to say that Inform keeps track of which objects can be “touched” by the player (i.e., are in the same place, aren’t inside a closed container). Specifying touchable here here guarantees that the action won’t apply to (e.g.) something in a distant place. More on touchable and its alternatives.

In this case, the Understand … as … construction needs a pair of square brackets between the double quotes defining the command, to tell Inform where it should look for the name of the direct object of the verb. Something like:

Understand "verb [something]" as verbing.

Where (again) verb is what you want the user to type and verbing matches what you called the action in the is an action applying to construction.

The following example creates a verb play, which takes a direct object:

"Piano lessons" by Allison Parrish

The Studio is a room. A piano is in the studio.

Playing is an action applying to one touchable thing. Understand "play [something]" as playing.

Report playing:
    say "You play a tune on [the noun]. It sounds lovely."

Note that Inform takes care of the particulars for you, and shows an error if the user attempts to play something that isn’t there:

>play piano
You play a tune on the piano. It sounds lovely.

>play marimba
You can't see any such thing.

The Report rule works as in the previous example, but with a twist: inside the double quotes of say, you can type [the noun], which Inform will replace with the direct object of the noun that was played. Handy!

Boolean properties

The actions we implemented above aren’t very interesting, because they don’t actually change anything in the game state. That’s partially because we haven’t defined anything in the game state yet that can be changed.

So let’s do just that. Inform allows you to define properties on objects. For simplicity, we’ll focus on Boolean properties in this tutorial, but properties can have other types of value as well. A Boolean property has two different values, only one of which can be assigned to the property at any one time. (Like “heads” and “tails,” or “true” and “false,” except you can give other names to them.)

To define a Boolean property, use the following construction:

X can be either Y or Z. X is usually Y.

The … can be either … or … and is usually are the actual Inform syntax for defining a property. Replace X with the object whose property you’re defining, and Y and Z with the name of the properties. The is usually construction specifies the value of the property when the game begins.

This can look a little bit tricky. Let’s break down the example from the code below.

The piano can be either in tune or out of tune. The piano is out of tune.

Pick out … can be either … or … from the code above. The things in each of the “slots” of the command are: The piano (the object whose properties we’re defining), in tune (first possible property) and out of tune (second possible property). This will look really strange to programmers familiar with other languages: the names of the properties have multiple words but aren’t separated from the rest of the code with quotes, or joined by underscores, or whatever! And yes, it’s true: in Inform, any identifier can have spaces in it, whether properties or actions or names of objects. (It’s doubly confusing because it feels like the in in in tune should have some syntactic purpose. But no, in this case, it’s just a word that is a part of the name of the property.)

Here’s an example, showing a piano that is out of tune:

"Just awful" by Allison Parrish

The Studio is a room. A piano is in the studio.

The piano can be either in tune or out of tune. The piano is out of tune.

Playing is an action applying to one touchable thing. Understand "play [something]" as playing.

Report playing:
    say "You play a tune on [the noun]. It sounds [if in tune]lovely[else]awful[end if]."

This example has another new bit of syntax: [if property]text A[else]text B[end if] between the double quotes. This syntax (only usable inside of double quotes) is replaced with text A if property is the current value of the given property for the direct object of the verb, and text B otherwise. Handy for modifying what the program displays based on the current state of the object.

Changing a property

We’ve assigned a property to the piano at this point, and specified what should happen if the piano has one or the other value for that property. But we haven’t actually made a way to change that property.

To do this, we need to add a few more tools to our toolkit. In the following example, we define a new action and command, tune (“tune [something]”). The idea of this verb is that user can type it to change the boolean property we defined on the piano from out of tune to in tune.

For play and dance above, we only used a rule called Report …:, which Inform triggers after the action has taken place. For this rule, we need to use two new rules: Check …:, which is triggered before the action takes place, and Carry out… which should contain the actual instructions of how to update the game state based on the action of the verb.

Here’s how it works. Try playing the game and typing tune piano. (Then try typing it again.) The example also includes the play command; try playing the piano before and after you tune it:

"Tuning the piano" by Allison Parrish

The Studio is a room. A piano is in the studio.

A piano can be either in tune or out of tune. The piano is out of tune.

Tuning is an action applying to one touchable thing. Understand "tune [something]" as tuning.

Check tuning:
    if the noun is in tune, say "It's already perfectly in tune." instead.

Carry out tuning:
    now the noun is in tune.

Report tuning:
    say "You meticulously tune [the noun]."

Playing is an action applying to one touchable thing. Understand "play [something]" as playing.

Report playing:
    say "You play a tune on [the noun]. It sounds [if in tune]lovely[else]awful[end if]."

There are two other new bits of syntax to discuss here. In the Check tuning: rule, there’s a construction that looks like this:

if the noun is in tune, say "It's already perfectly in tune." instead.

This line checks to see if the thing being tuned is (already) in tune, and if so, it stops the Carry out… and Report… rules from firing. Schematically, you can think of this line as:

if the noun is property, say "some text" instead.

… where the actual Inform syntax is if the noun is ..., say "..." instead. and you can replace property with the property you’re checking for, and some text with what you want to be displayed. (Of course, you can put other types of descriptions after the if, and other kinds of phrases after the comma. But the simple schema given above is good enough for our current purpose.)

The second new bit of syntax is now the noun is in tune. The now phrase updates the state of the object, setting the Boolean property to the given value (in tune).

New kinds of things

So far so good. It would be reasonable at this point to think about more than just pianos: maybe we want to add other kinds of instruments to our studio. At this point, however, if you wanted to add another instrument, you’d also have to add the can be either in tune or out of tune property to each additional instrument, which would be inconvenient.

To address this potential inconvenience, Inform provides the ability to define kinds of thing. A kind is essentially a class of objects that share the same property definitions. Once you do this, you can create new objects of that kind that will automatically have all of the properties from that kind associated with them.

The syntax for making a new kind looks like this:

X is a kind of thing.

You can pick X, and like any other identifier, it can consist of multiple words. (You can actually swap out thing for any other kind, and thing itself is actually a kind that Inform itself defines. But let’s leave that aside for now.)

Once you’ve defined the kind, you can associate properties with it, using a syntax similar to the syntax you used for associating properties with an individual object:

X is a kind of thing.

X can be either Y or Z. Xs are usually Y.

The main difference here is the use of the word usually: this sets a default value for the property. Any object of this kind will have this boolean property set to this value when it’s created. (But you can write an action to change it later.)

Finally, creating an object of a particular kind looks like this:

A is a X.

Where A is the name of the object, and X is the kind of thing you want it to be.

The example below creates a new kind, musical instrument, which has the ability to be in tune or out of tune (a Boolean property). The tuning action changes the property from out of tune to in tune for any musical instrument. Otherwise, the code in the example is exactly the same as the previous example.

"Tuning anything" by Allison Parrish

The Studio is a room.

A musical instrument is a kind of thing.

A musical instrument can be either in tune or out of tune. Musical instruments are usually out of tune.

The piano is a musical instrument. The piano is in the studio. The french horn is a musical instrument. The french horn is in the studio.

Tuning is an action applying to one touchable thing. Understand "tune [something]" as tuning.

Check tuning:
    if the noun is in tune, say "It's already perfectly in tune." instead.

Carry out tuning:
    now the noun is in tune.

Report tuning:
    say "You meticulously tune [the noun]."

Playing is an action applying to one touchable thing. Understand "play [something]" as playing.

Report playing:
    say "You play a tune on [the noun]. It sounds [if in tune]lovely[else]awful[end if]."

Relations

Relations are an important part of Inform, but most other programming languages don’t have a construction that is similar. A relation is a way of keeping track of how two (or more) items of different kinds are related to one another.

An example of an everyday situation that could be modeled with relations is people wearing clothes. “Wearing” is something that requires two different things: a person and a piece of clothing. When a person puts on a piece of clothing, that person is then said to be wearing it, and the piece of clothing is said to be being worn by the person. A person can wear multiple pieces of clothing, but (usually) a piece of clothing can only be worn by one person at a time.

You could keep track of these relationships using a two-dimensional table, where people are rows and piece of clothing columns:

  scarf trousers skirt top hat sweater oxford shirt
Allison 1 0 1 0 1 0
Horatio 0 1 0 1 0 1
Fido 0 0 0 0 0 0

This table shows a hypothetical relation between people and clothes. Where there’s a 1 in a cell, it means that the person in the corresponding row is wearing the piece of clothing in the corresponding column. Relations in Inform are a way of defining these tables, keeping track of the data in them, and changing that data. (In fact, Inform’s built-in verbs “put on” and “take off” make use of a relation very similar to the one I just described.)

A relation holds between two objects; you define a relationship as being between two kinds. Defining a relation looks like this:

X relates one Y to one Z. The verb to V means the X relation.

… where X is an identifier that names the relation, Y is a kind of thing, Z is a kind of thing, and V is a verb that will be used to write code about the relation later in the program. Typing one … one creates a one-to-one relationship and one … various a one-to-many relationship.

Inside of a rule (like Carry out …), you can use the phrase now A Vs B to associate object A with object B using the relation you associated the verb V with (using the present-tense third person singular form of the verb).

The following example shows a relation called skill, which relates people (like the player) to musical instruments. A new command, learn, causes the player and the specified musical instrument to be related by this relation.

This is a minimal example; relations can be much more sophisticated (and useful!) than this. See sections 13.3+ in the Inform manual for more explanations about relations.

"Learn to play" by Allison Parrish

The Studio is a room.

A musical instrument is a kind of thing.

A piano is a musical instrument in the studio. A french horn is a musical instrument in the studio.

Skill relates one person to various musical instruments. The verb to be skilled in means the skill relation.

Learning is an action applying to one touchable thing. Understand "learn [something]" as learning.

Check learning:
    if the actor is skilled in the noun, say "There is such a thing as too much practice." instead.

Carry out learning:
    now the actor is skilled in the noun.

Report learning:
    say "It takes mere hours to master [the noun]."

Playing is an action applying to one touchable thing. Understand "play [something]" as playing.

Report playing:
    say "You play a tune on [the noun]. It sounds [if player is skilled in the noun]lovely[else]awful[end if]."

Try typing relations; it’s a built-in command that gives you a list of all relations that hold between objects in your game (except for built-in relations, which we’ll talk more about below).

Exercise: Add a verb “forget [something]” that removes the relation between the player and the instrument. (Hint: you can ask if the relation does not hold with “if the actor is not skilled with the noun” and unset the relation with “now the actor is not skilled in the noun.”

Graham’s goodies

In the previous section, I showed you how to define your own commands and have them operate (via actions and rules) on objects whose properties and relations you defined yourself. But part of what makes Inform an ideal language for writing interactive fiction is the rich library of commands, objects, kinds, and relations that come standard with the library. These include relations for giving textual descriptions to objects, putting objects in rooms, putting rooms in spatial relations with each other, picking up objects, dropping objects, etc.

In fact, everything we’ve made so far has been using some of these “freebies” from the Inform standard library. For example, try typing take piano in any of the examples above; you’ll find that the game already knows how to let the player take things! (And, somewhat absurdly, that the game will allow the player to pick up a piano and carry it with them. More on how to prevent this below.)

So show me

The showme command is a way to see the properties and relations defined for objects in your story, including those that come for free with the Inform standard library. On its own, showme displays rooms and their contents; used with the name of an object, it shows that object’s type, properties, and relations. For example, showme piano, if typed in the example story above, displays the following:

>showme piano
piano - musical instrument
location: in the Studio
singular-named, improper-named; unlit, inedible, portable
list grouping key: none
printed name: "piano"
printed plural name: "musical instruments"
indefinite article: none
description: none
initial appearance: none

The musical instrument part is something we created, but the rest of these are properties and relations added to objects automatically on creation, in order to make them play more nicely with the rest of the standard library. (It’s important to remember, though, that a property like portable, however evocative its name, is no different in principle from the in tune/out of tune property we programmed above. It’s just something that Graham Nelson defined in the standard library that goes along with rules and actions that modify the game state in response to user input. Likewise, the location relation, even though it’s so central to how a work of interactive fiction functions, is defined in a way very similar to the way we defined the “skill” relation above!)

The index

Another indispensible way to see all of the goodies that the standard library gives you (along with an overview of what you yourself have defined) is the Index. You can reach this in the Inform IDE with the tab labelled “Index” on the side of either of the editing panels. Here are some highlights from the Index:

  • The “Actions” tab shows all of the actions that are defined; selecting “Commands” in the header shows what the user can type to trigger those actions.
  • The “Kinds” tab shows the kinds of things that have been defined in a hierarchical view. Scrolling down a bit shows the description of those kinds along with their properties and default (“usually”) values.
  • In the “Phrases” tab, selecting “Relations” shows all of the defined relations (along with the kinds that they relate to), and the “Verbs” tab shows the verbs that enact those relations. (Note how these are distinct from commands and actions!)
  • The “World” tab shows you a map of the rooms you’ve added to the game.

In any of the Index tabs, items that you’ve defined (as opposed to items that are defined as part of the standard library) have an orange arrow next to them.

The remainder of this section will explore and explain some of the most common kinds, actions, verbs, relations and properties from the standard library that you’re likely to use when making things with Inform.

Descriptions

An object’s description property is displayed in response to the examine command. You can set the value of description using the syntax

The description of X is "..."

… where X is the object whose description you want to supply, and ... is the text of the description (making sure to retain the quotes). If a description is applied to a room, that description is displayed when the player first enters the room, or when the player issues the command look (with no direct object). In the following example, the Studio’s description of the room is displayed immediately, and the piano’s description is shown if you type examine piano.

"The Studio, described" by Allison Parrish

The Studio is a room. The description of the Studio is "The studio is a well-appointed, spacious chamber for learning all manner of expressive performing arts."

A piano is in the Studio. The description of the piano is "A baby grand with a shiny finish."

A string that follows directly the construction that brings an object into existence (i.e., “X is a Y”) are displayed in the room description. In the example below, You see the Studio's trusty piano is displayed in the room description (and when the player types look). For rooms, a string written this way is simply treated as the room’s description. For more information on how to customize room descriptions to your need, see section 3.1 in the Inform Recipe Book on Room Descriptions.

"The Studio, described, with shortcuts" by Allison Parrish

The Studio is a room. "The studio is a well-appointed, spacious chamber for learning all manner of expressive performing arts."

A piano is here. "You see the Studio's trusty piano." The description is "A baby grand with a shiny finish."

One other new thing in the example above: stating that X is here is equivalent to typing X is in Y, where Y is the room whose definition is closest and also earlier (i.e., above).

Decorating the set, possessions, getting dressed

The “is on” relation. inventory, taking things, taking things off, putting things on things. Openable.

"The Studio, with more stuff" by Allison Parrish

The Studio is a room. "The studio is a well-appointed, spacious chamber for learning all manner of expressive performing arts. There are beautifully worn hardwood floors."

The floor is here. The floor is scenery. "Oak floors, lovingly worn by years of use."

A piano is here. "You see the Studio's trusty piano." The description is "A baby grand with a shiny finish."

A metronome is on the piano. The description is "A wind-up metronome, made from wood and steel."

The player is carrying a student ID card. The description of the student ID card is "Your student ID card, with an unflattering picture of you as a freshman."

The player is carrying an apple. The apple is edible. The description of the apple is "A Granny Smith apple from the bodega across the street."

The player is wearing tap shoes. The description of the tap shoes is "A new pair of patent leather tap shoes."

The mahogany wardrobe is here. The wardrobe is an openable container. "In the corner, you see a mahogany wardrobe." The wardrobe is fixed in place. The description of the wardrobe is "The doors are [if open]wide open[else]shut[end if]."

Inform 7 assumes that if X “is on” Y, then Y is a kind of thing called a supporter. Supporters are normally fixed in place.

Making a map

“is [DIR] of” relation, setting the player’s initial location. need to use “in” to enter time machine.

"The Studio and surrounding rooms" by Allison Parrish

The Studio is a room. "The studio is a well-appointed, spacious chamber for learning all manner of expressive performing arts. A door leads south to the Laboratory."

The Laboratory is south of the Studio. "The laboratory is full of mysterious devices. A time machine stands in the middle of the room, beckoning you to enter. A doorway north will take you to the Studio, and steps lead down to the basement." The devices is scenery. The description of the devices is "Blinking LEDs, scrolling LCDs, beakers and tubes full of fluorescent fluids. Bleeping, blooping, glorping, glooping." 

The Time Machine is inside from the Laboratory. "For such a sophisticated device, the interior of this time machine has a surprisingly clean design. You see no recognizable controls. You can step out back into the Laboratory."

The Basement is down from the Laboratory. "A dark room with low ceilings. Steps lead back up to the laboratory."

When play begins:
    now the player is in the Basement.

Interfering with Graham’s actions

instead of rule, after rule (names action plus noun)

"Tap shoe blues" by Allison Parrish

The Studio is a room. "The studio is a well-appointed, spacious chamber for learning all manner of expressive performing arts."

The player is wearing tap shoes. The description of the tap shoes is "A new pair of patent leather tap shoes."

The player is carrying an apple. The apple is edible. The description of the apple is "A Granny Smith apple from the bodega across the street."

Instead of taking off the tap shoes:
    say "But they're so comfortable! And besides, your class will start any minute."

After eating the apple:
    say "The tart flavor of the apple recalls the tart criticism of your dance instructor."

Winning the game

otherwise, continue the action, end the story finally.

"Time Machine of the Performing Arts" by Allison Parrish

The Studio is a room. "The studio is a well-appointed, spacious chamber for learning all manner of expressive performing arts. A door leads south to the Laboratory."

The mahogany wardrobe is here. The wardrobe is an openable container. "In the corner, you see a [if open]open[else]closed[end if] mahogany wardrobe." The wardrobe is fixed in place. The wardrobe is closed. The description of the wardrobe is "Seemingly ancient beyond imagining, covered in eldritch designs that resemble sigils of a forgotten civilization."

A pair of tap shoes are in the wardrobe. The description of the pair of tap shoes is "The shoes, made of an unidentifiable substance in a color you can't quite name, seem to glow and quiver of their own accord." The tap shoes are wearable.  

After wearing the shoes, say "You feel strangely powerful."

The Laboratory is south of the Studio. "The laboratory is full of mysterious devices. A time machine stands in the middle of the room, beckoning you to enter. A doorway north will take you to the Studio." The devices is scenery. The description of the devices is "Blinking LEDs, scrolling LCDs, beakers and tubes full of fluorescent fluids. Bleeping, blooping, glorping, glooping." 

[this makes it possible to type "enter time machine"]
The Time Machine is scenery in the Laboratory. Instead of entering the Time Machine, try going inside.

Time Machine Interior is inside from the Laboratory. "For such a sophisticated device, the interior of this time machine has a surprisingly clean design. You see no recognizable controls. You can step out back into the Laboratory."

Instead of going inside from the Laboratory:
	if the player is wearing the pair of tap shoes:
		say "As you enter the Time Machine, the strange tap shoes begin to hum.  The walls of the Time Machine fade to darkness and an infinite field of stars appears around you. You hear a voice: 'Where in time would you like to go, Tap Shoe Captain?'";
		end the story finally;
	otherwise:
		say "Your feet twitch, as though you've missed an opportunity.";
		continue the action.

Further reading