Suppose that we want to change the reporting of "take" so that the player is always told something like "You take the book from the shelf." or "You pick up the toy from the ground." In order to generate these reports, we will need to know where the object started, even though by the time we are printing the output, the object will have moved.
"Removal"
The Pharmacy is a room. A desk and a trash can are in the Pharmacy. The pill-counter, a prescription, and a computer are on the desk. The computer is fixed in place. The pill-counter contains some Vicodin. The trash can contains an empty box.
The taking action has an object called previous locale (matched as "from").
The previous locale could in theory be either a thing or a room, so we make it "an object" -- that is, the most generic possible kind, to which both things and rooms belong. Now we record what the previous locale is at the beginning of each taking action:
Setting action variables for taking:
now previous locale is the holder of the noun.
Report taking something from the location:
say "You pick up [the noun] from the ground." instead.
Report taking something:
say "You take [the noun] from [the previous locale]." instead.
Test me with "get all".
We begin with the location and its fittings, and we create a kind of value which names the different internal positions we will allow.
"Further Reasons Why All Poets Are Liars"
Nook Obscure is a room. "Above the College kitchens, which make a humming sound, less tuneable than bees, but hardly less industrious, with shrill notes of sharp command and scolding intermixed: and below Trinity's loquacious clock, who never lets the quarters, night or day, slip by him unproclaimed, and tells the hours twice over with a male and female voice. In short, the kind of rubbish room they give to a northern villager. But you get a bed and a high shelf all of your own. And you long to find some Romantic way to look out of the window."
The window, the shelf and the bed are scenery in the Nook Obscure. The shelf and the bed are supporters. The bed is enterable.
Internal position is a kind of value. The internal positions are nowhere at all, over by the window, under the shelf and near the bed.
The box is an enterable supporter in Nook Obscure. The current box position is an internal position that varies. The current box position is near the bed. "Your packing case, stamped W. WORDSWORTH (KENDAL), is [current box position]." Instead of taking the box, say "It is filled with your peerless rock collection and too heavy to lift, but could be pushed." Instead of opening the box, say "It is securely nailed shut."
We create an action, "pushing it over to", for pushing a box around on the floor of a single location. (Calling this "pushing it over to" prevents clashes with the existing "pushing it to" action, which is for pushing things from one room to another.) Almost half of the text which defines the action is concerned with the two action variables, but they make the implementation of everything else so much easier that we end up writing less than if we hadn't used them.
Understand "push [box]" as a mistake ("You can push the box to the window, the bed or the shelf.").
Understand "push [something] to [something]" as pushing it over to. Pushing it over to is an action applying to two things.
The pushing it over to action has an internal position called the old position.
The pushing it over to action has an internal position called the new position.
Setting action variables for pushing something over to something:
now the old position is the current box position;
now the new position is nowhere at all;
if the second noun is the window, now the new position is over by the window;
if the second noun is the bed, now the new position is near the bed;
if the second noun is the shelf, now the new position is under the shelf.
Check pushing it over to:
if the noun is not the box, say "That's not something you can push." instead;
if the player is on the bed, say "You can't reach from here." instead;
if the player is on the noun, say "Not while you are standing on [the noun]." instead;
if the new position is nowhere at all, say "You can only push [the noun] to the window, the bed or the shelf." instead;
if the new position is the old position, say "The [noun] is already [new position]." instead.
Carry out pushing it over to:
now the current box position is the new position.
Report pushing it over to:
say "With some effort, you shove [the noun] from [old position] to [new position]."
Everything which remains simply provides a couple of puzzles to test this arrangement.
Euclid's Elements is on the shelf. Understand "euclid" or "book" as the Elements.
Instead of taking something (called the item) which is on the shelf:
if the player is on the box and the current box position is under the shelf, continue the action;
say "You cannot reach [the item], which is up on the shelf."
Instead of examining the window:
say "This window opens rather unpromisingly onto the chapel wall opposite, so even granted the moonlight it is dark in here. Still, surely there's a poem here somewhere?"
Instead of examining the window when the player is on the bed:
say "Just a blank patch of chapel wall."
Instead of examining the window when the player is on the box:
if the current box position is near the bed:
say "Tantalisingly, you are not quite able to spy the statue.";
otherwise if the current box position is under the shelf:
say "All you can see is the antechapel wall, and the dull silver gleam of the pealing organ.";
otherwise:
say "At last! You can just, standing on tiptoes on the box right up at the window, make out the top of the statue! Of such epiphanies are Poesy born. Let's see now... oh yes...[paragraph break]And from my pillow, looking forth by light[line break]Of moon or favouring stars, I could behold[line break]The antechapel where the statue stood[line break]Of Newton with his prism and silent face,[line break]The marble index of a mind for ever[line break]Voyaging through strange seas of Thought, alone.";
end the story finally.
Test me with "get on bed / x window / get off / x window /get elements / get on box / x window / get elements / push box to shelf / get off / push box to shelf / get on box / get elements / x window / get off / push box to window / get on box / x window".
Text in this example is drawn from Will Crowther's original 1976 FORTRAN implementation of ADVENTURE, the founding work of the genre, whose source code was rediscovered by Dennis G. Jerz in 2007. Note the capitals: the program ran on an early computer without lower case lettering. They look a little mimsy now, but picture them glowing green on an old-style cathode ray tube monitor in a darkened room late at night.
The problem alluded to is that the player is forbidden to walk between two dark rooms, so that he must always have light to see by from at least one end of any movement. Writing source text to achieve this is tricky to get right in every case, because the determination of light is hard to do. Here we interleave the necessary rules into the existing "going" action, using a new action variable to record the number of ends which are dark as experienced by the player, which might be 0, 1 or 2:
"THE SECOND OLDEST PROBLEM"
The going action has a number called the dark terminus count.
Setting action variables for going:
now the dark terminus count is 0;
if in darkness, increment the dark terminus count.
The last carry out going rule:
if in darkness, increment the dark terminus count;
if the dark terminus count is 2, end the story saying "YOU FELL INTO A PIT AND BROKE EVERY BONE IN YOUR BODY!" instead.
And now three early rooms to try this out.
COBBLE CRAWL is a room. "YOU ARE CRAWLING OVER COBBLES IN A LOW PASSAGE. THERE IS A DIM LIGHT AT THE EAST END OF THE PASSAGE."
DEBRIS ROOM is west of COBBLE CRAWL. "YOU ARE IN A DEBRIS ROOM, FILLED WITH STUFF WASHED IN FROM THE SURFACE. A LOW WIDE PASSAGE WITH COBBLES BECOMES PLUGGED WITH MUD AND DEBRIS HERE,BUT AN AWKWARD CANYON LEADS UPWARD AND WEST."
AWKWARD CANYON is west of DEBRIS ROOM. "YOU ARE IN AN AWKWARD SLOPING EAST/WEST CANYON."
DEBRIS ROOM and AWKWARD CANYON are dark.
Rule for printing the name of a dark room: say "DARKNESS" instead.
Rule for printing the description of a dark room: say "IT IS NOW PITCH BLACK. IF YOU PROCEED YOU WILL LIKELY FALL INTO A PIT." instead.
Test me with "w / e / w / w".
This is only the second oldest problem in the IF literature: the earliest puzzle is unlocking the steel grate which bars entrance to the cave.
Suppose we want to let the player kill characters, leaving behind corpses.
"Puff of Orange Smoke"
Paraguay is a room. Bolivia is north of Paraguay. Lydia is a woman in Paraguay. "Lydia is, as usual, here." The description of Lydia is "Long, long legs and a sarcastic attitude." Instead of touching Lydia: say "'Watch it, sailor,' she snaps."
A body is a kind of thing. A body is a part of every person. Instead of touching a body: say "[The noun] is grotesquely inert."
The description of Lydia's body is "Long, long legs and no attitude at all." The initial appearance of Lydia's body is "Lydia's corpse is sprawled at your feet."
Using our "part of every person..." line, we've conveniently assigned one body per person. Since we're going to separate people from their bodies when the bodies die, though, we also want a more permanent relation that will help us keep track of which bodies used to belong to which people:
Spirit-possession relates one person to one body. The verb to be owner of means the spirit-possession relation.
When play begins:
repeat with victim running through people:
let the corpse be a random body which is part of the victim;
now the victim is owner of the corpse.
When Lydia is alive, we want >TOUCH LYDIA'S BODY to mean the same thing as >TOUCH LYDIA, so we use the setting action variables rules as a convenient point at which to reassign the action:
Setting action variables when the noun is a body which is part of a person (called owner):
now the noun is the owner.
Setting action variables when the second noun is a body which is part of a person (called owner):
now the second noun is the owner.
This doesn't change Inform's idea about what action is being performed; just about the object it's being performed on. The rest of the action will now proceed as if the player had typed >TOUCH LYDIA.
Along similar lines, once Lydia is dead, we want >MOVE LYDIA to mean >MOVE LYDIA'S BODY if the body is in view:
Setting action variables when the noun is a dead person and the noun is owner of a visible body (called the mortal remains):
now the noun is the mortal remains.
The trick is, though, that >MOVE LYDIA will only be understood if there is something called Lydia that the player can see and refer to, even after she's dead. There are various ways to do this, but the least painful here will be to make the deceased Lydia permanently visible, by putting her in an always-accessible backdrop. The backdrop itself will never be mentioned in the game, and we should make its name something that the player is unlikely to type casually; we don't want the player to interact with it directly. So:
The worldview is a privately-named backdrop. It is everywhere. The spirit-world is a privately-named transparent closed unopenable container. It is part of the worldview.
Definition: a person is dead if he is in the spirit-world.
It's also possible that the player will type something like >X LYDIA when Lydia's corpse is not in view, so we should have an appropriate answer to that as well:
Before doing something to a dead person:
say "[The noun] is dead; or had you blocked that out?" instead.
Because the before rules happen after the setting action variables rules, this will only ever happen if the corpse is not visible.
Now we define the attack itself, which should discard the body, move the spirit to its eternal resting place, and describe the event to the player:
Instead of attacking someone:
let the corpse be a random body which is part of the noun;
move the corpse to the location;
move the noun to the spirit-world;
say "With a single blow, you rid the world of [the noun]."
And finally a trick borrowed from the chapter on understanding, so that we can refer to "Lydia's body" while Lydia is alive, but "Lydia's corpse" only after Lydia has died:
Understand "corpse" as a body when the item described is not part of a person.
Test me with "x body / x lydia's body / touch lydia's body / x corpse / kill lydia / look / x lydia's body / x lydia's corpse / x corpse / x lydia / touch lydia / lydia, hello / n / x lydia / touch lydia / lydia, hello".
Suppose that we have a design in which the player spends lots of time on enterable supporters, and in which we want to report certain actions -- dropping things onto those supporters, or leaping from one to another -- in a new way. We might begin by adding some action variables to help us keep track of the situation:
"Croft"
The dropping action has an object called the container dropped into (matched as "into").
The dropping action has an object called the supporter dropped onto (matched as "onto").
Rule for setting action variables for dropping:
if the actor is in a container (called C), now the container dropped into is C;
if the actor is on a supporter (called C), now the supporter dropped onto is C.
Report dropping a heavy thing onto a metallic thing:
say "You drop [the noun], and [the supporter dropped onto] clangs protestingly." instead.
Report someone dropping a heavy thing onto a metallic thing:
say "[The actor] drops [the noun] onto [the supporter dropped onto], which clangs protestingly." instead.
A thing can be heavy or light. A thing can be metallic or ordinary. A thing is usually ordinary. A thing is usually light.
The Ancient Cambodian Temple is a room. "A vast space built for ancient and forgotten rituals. The stone floor crawls with vermin. Well above the floor, and separated by some feet, are twin platforms built into the wall: the one carved of jointed wood, the other of sheets of graven bronze."
A platform is a kind of supporter. A platform is always enterable. A platform is usually scenery.
The bronze platform is a metallic platform in the Temple. Lara is a woman. She is on the bronze platform. She wears safari pants and a tank top. She carries a gun and a map. The gun is heavy.
The wood platform is an ordinary platform in the Temple. The player is on the wood platform. The player carries a rope, an Ancient Cambodian/English Phrasebook, a pickaxe, and a precious idol. The idol and the pickaxe are heavy.
Persuasion rule: persuasion succeeds.
The entering action has an object called the place left (matched as "from").
Check entering a platform from a platform:
if actor is the player, say "You leap into midair to cross the distance...";
otherwise say "[The actor] leaps gracefully across the distance...";
move the actor to the holder of the noun, without printing a room description.
Because this rule occurs before the "implicitly pass through other barriers rule", that rule will not occur when we move from platform to platform; we'll use our own custom rule instead.
Rule for setting action variables for entering:
now the place left is the holder of the actor.
Report entering a platform from a platform:
say "You land in a cat-like crouch on [the noun]." instead.
Report Lara entering a platform from a platform:
say "Lara lands soundlessly on [the noun][if the noun supports the player] beside you[end if]." instead.
Report entering a platform from the location:
say "You jump, catch the edge of [the noun] in your hands, and -- exerting considerable upper-body strength -- pull yourself up onto it." instead.
Report Lara entering a platform from a location:
say "Lara jumps, catches the edge of [the noun], and is standing upright on it, all in less time than it takes to tell."
Instead of examining a person who is not the player:
say "[The noun] carries [list of things carried by the noun] and wears [list of things worn by the noun]."
Instead of climbing a platform, try entering the noun.
Test me with "Lara, drop map / lara, drop gun / drop idol / enter bronze platform / drop pickaxe / get off / climb wood".