This chapter introduces five fundamentals of Inform: how to construct games; messages, classes and actions; and how to debug games. Chapter III then makes a systematic exploration of the model world available to Inform games. Throughout both chapters, examples gradually build up a modest game called ‘Ruins’, a tale of Central American archaeology in the 1930s. Here is its first state:
Constant Story "RUINS"; Constant Headline "^An Interactive Worked Example^ Copyright (c) 1999 by Angela M. Horns.^"; Include "Parser"; Include "VerbLib"; Object Forest "~Great Plaza~" with description "Or so your notes call this low escarpment of limestone, but the rainforest has claimed it back. Dark olive trees crowd in on all sides, the air steams with the mist of a warm recent rain, midges hang in the air. ~Structure 10~ is a shambles of masonry which might once have been a burial pyramid, and little survives except stone-cut steps leading down into darkness below.", has light; [ Initialise; location = Forest; "^^^Days of searching, days of thirsty hacking through the briars of the forest, but at last your patience was rewarded. A discovery!^"; ]; Include "Grammar";
If you can compile this tiny beginning successfully,
Inform is probably set up and working properly on your computer.
Compilation may take a few seconds, because although you have only
written twenty lines or so, the Include
directives paste
in another seven and a half thousand. This is “the
Library”, a computer program which acts as umpire during play.
The library is divided into three parts:
Parser
which decodes what the player types;
VerbLib
how actions, like “take” or
“go north”, work;
Grammar
the verbs and phrases which the game
understands.
It does matter what order the three lines beginning
with Include
come in, and it sometimes matters where
your own code goes with respect to them: objects shouldn't be declared
until after the inclusion of the parser, for instance. For now,
follow the structure above, with everything interesting placed between
the inclusions of VerbLib
and Grammar
.
▲
Chapter I above said that every Inform program
had to contain a routine called Main
. Games like ‘Ruins’
are no exception, but their Main
routine is part of
the library, so that game designers do not need to write a Main
.
· · · · ·
The two constants at the beginning are text giving
the game's name and copyright message, which the library needs in
order to print out the “banner” announcing the game.
Similarly, the library expects to find a routine named Initialise
somewhere in your source code. This routine is called when the game
starts up, and is expected to carry out any last setting-up operations
before play begins. In most games, it also prints up a ‘welcome’
message, but the one thing it has to do is to set the location
variable to the place where the player begins. And this means that every
game has to declare at least one object, too: the room where the player
begins.
▲
In this book places are often called “rooms” even when
outdoors (like Forest
) or underground. This goes back
at least to Stephen Bishop's 1842 map of the Mammoth and Flint Ridge
cave system of Kentucky, which was the setting of the first adventure
game, ‘Advent’, also called ‘Colossal Cave’
(c.1975). The author, Will Crowther, was a
caver and used the word
“room” in its caving sense. Don Woods, who recast the game
in 1976–7, confused the word further with its everyday sense.
Players of adventure games continue to call locations “rooms”
to this day.
· · · · ·
‘Ruins’ is at this stage an exceedingly dull game:
Days of searching, days of thirsty hacking through the briars of the forest, but at last your patience was rewarded. A discovery!
RUINS
An Interactive Worked Example
Copyright (c) 1998 by Angela M. Horns.
Release 1 / Serial number 990220 / Inform v6.20 Library 6/8
“Great Plaza”
Or so your notes call this low escarpment of limestone, but the
rainforest has claimed it back. Dark olive trees crowd in on all
sides, the air steams with the mist of a warm recent rain, midges
hang in the air. “Structure 10” is a shambles of masonry
which might once have been a burial pyramid, and little survives
except stone-cut steps leading down into darkness below.
>inventory
You are carrying nothing.
>north
You can't go that way.
>wait
Time passes.
>quit
Are you sure you want to quit? yes
· · · · ·
In an Inform game, objects are used to simulate
everything: rooms and items to be picked up, scenery, the player,
intangible things like mist and even some abstract ideas, like
the direction “north” or the idea of “darkness”.
The library itself is present as an object, called InformLibrary
,
though like the concept of “north” it cannot be picked
up or visited during play. All told, ‘Ruins’ already
contains twenty-four objects.
It is time to add something tangible, by writing
the following just after the definition of Forest
:
Object -> mushroom "speckled mushroom" with name 'speckled' 'mushroom' 'fungus' 'toadstool';
The arrow ->
means that the mushroom
begins inside the previous object, which is to say, the Forest
.
If the game is recompiled, the mushroom is now in play: the player
can call it “speckled mushroom”, “mushroom”,
“toadstool” and so on. It can be taken, dropped, looked
at, looked under and so on. However, it only adds the rather plain
line “There is a speckled mushroom here.” to the
Forest's description. Here is a more decorative species:
Object -> mushroom "speckled mushroom" with name 'speckled' 'mushroom' 'fungus' 'toadstool', initial "A speckled mushroom grows out of the sodden earth, on a long stalk.";
The initial
message is used to tell the player
about the mushroom when the Forest is described.
(Once the mushroom has been picked or moved, the message is no longer
used: hence the name ‘initial’.) The mushroom is, however,
still “nothing special” when the player asks to “look
at” or “examine” it. To provide a more interesting
close-up view, we must give the mushroom its own description
:
Object -> mushroom "speckled mushroom" with name 'speckled' 'mushroom' 'fungus' 'toadstool', initial "A speckled mushroom grows out of the sodden earth, on a long stalk.", description "The mushroom is capped with blotches, and you aren't at all sure it's not a toadstool.", has edible;
Now if we examine the mushroom, as is always wise, we get a cautionary hint. But the edible notation means that it can be eaten, so that for the first time the player can change the game state irrevocably: from a game with a forest and a mushroom into a game with just a forest.
The mushroom shows the two kinds of feature something
can have: a “property” with some definite value or list
of values and an “attribute”, which is either present
or not but has no particular value. name
, initial
and description
are all properties, while light
and edible
are attributes. The current state of these
properties changes during play: for instance, it can be changed
by code like the following.
mushroom.description = "You're sure it's a toadstool now."; give mushroom light; if (mushroom has edible) print "It's definitely edible.^";
light
is the attribute for “giving
off light”. The Forest
was defined as having light
on account of daylight, so it doesn't much matter whether or not the
mushroom has light
, but for the sake of botanical
verisimilitude it won't have light
in the final game.
· · · · ·
Declaring objects has so far been a matter of filling
in forms: fill some text into the box marked description
,
and so on. We could go much further like this, but for the sake of
example it's time to add some rules:
after [; Take: "You pick the mushroom, neatly cleaving its thin stalk."; Drop: "The mushroom drops to the ground, battered slightly."; ],
The property after
doesn't just have
a string for a value: it has a routine of its own. What happens is
that after something happens to the mushroom, the library asks
the mushroom if it would like to react in some way. In this case,
it reacts only to Take
and Drop
, and
the only effect is that the usual messages (“Taken.”
“Dropped.”) are replaced by new ones. (It doesn't react
to Eat
, so nothing out of the ordinary happens when
it's eaten.) ‘Ruins’ can now manage a briefly plausible
dialogue:
“Great Plaza”
Or so your notes call this low escarpment of limestone, but the rainforest
has claimed it back. Dark olive trees crowd in on all sides, the air
steams with the mist of a warm recent rain, midges hang in the air.
“Structure 10” is a shambles of masonry which might once
have been a burial pyramid, and little survives except stone-cut
steps leading down into darkness below.
A speckled mushroom grows out of the sodden earth, on a long stalk.
>get mushroom
You pick the mushroom, neatly cleaving its thin stalk.
>look at it
The mushroom is capped with blotches, and you aren't at all sure
it's not a toadstool.
>drop it
The mushroom drops to the ground, battered slightly.
▲ Gareth Rees persuasively advocates writing this sort of transcript, of an ideal sequence of play, first, and worrying about how to code up the design afterwards. Other designers prefer to build from the bottom up, crafting the objects one at a time and finally bringing them together into the narrative.
· · · · ·
The mushroom is a little more convincing now, but still does nothing. Here is a more substantial new rule:
before [; Eat: if (random(100) <= 30) { deadflag = true; "The tiniest nibble is enough. It was a toadstool, and a poisoned one at that!"; } "You nibble at one corner, but the curious taste repels you."; ],
The library consults before
just before
the player's intended action would take place. So when the player
tries typing, say, “eat the mushroom", what happens is:
in 30% of cases, death by toadstool poisoning; and in the other 70%,
a nibble of a corner of fungus, without consuming it completely.
Like location
, deadflag
is
a variable belonging to the library. It's normally false
,
meaning that the player is still alive and playing. Setting it to
true
thus kills the player. (Setting it to 2 causes the
player to win the game and there are other uses: see
§21.)
If the “tiniest nibble” text is printed,
the rule ends there, and does not flow on into the second “You
nibble at” text. So one and only one message is printed.
Here is how this is achieved: although it's not obvious from the look
of the program, the before
routine is being asked the
question “Do you want to interfere with the usual rules?”.
It must reply, that is, return, either true
or
false
meaning yes or no. Because this question is asked
and answered many times in a large Inform game, there are several
abbreviations for how to reply. For example,
return true;
and
rtrue;
both do the same thing. Moreover,
print_ret "The tiniest nibble... ...at that!";
performs three useful tasks: prints the message, then
prints a carriage return, and then returns true
. And this
is so useful that a bare string
"The tiniest nibble... ...at that!";
is understood to mean the same thing. To print the text
without returning, the statement print
has to be written
out in full. Here is an example:
before [; Taste: print "You extend your tongue nervously.^"; rfalse; ];
In this rule, the text is printed, but the answer
to “Do you want to interfere?” is no, so the game will
then go on to print something anodyne like “You taste nothing
unexpected.” (In fact the rfalse
was unnecessary,
because if a rule like this never makes any decision, then the answer
is assumed to be false.)
•
EXERCISE 1
The present after
routine for the mushroom is
misleading, because it says the mushroom has been picked every time
it's taken (which will be odd if it's taken, dropped then taken again).
Correct this.
· · · · ·
The following example of “form-filling”
is typical of the way that the library provides for several standard
kinds of object. This one is a kind of door, which will be gone into
properly in §13, but for now suffice to
say that a door doesn't literally have to be a door: it can be any
object which comes in between where the player is and where the
player can go. Because the object is also marked as scenery
(see §8), it isn't given any special paragraph
of description when the Forest is described. Finally, it is marked
as static
to prevent the player from being able to pick
it up and walk off with it.
Object -> steps "stone-cut steps" with name 'steps' 'stone' 'stairs' 'stone-cut' 'pyramid' 'burial' 'structure' 'ten' '10', description "The cracked and worn steps descend into a dim chamber. Yours might be the first feet to tread them for five hundred years.", door_to Square_Chamber, door_dir d_to has scenery static door open;
We also need to add a new line to the Forest's definition to tell it that the way down is by these steps:
Object Forest "~Great Plaza~" ... d_to steps,
Now “examine structure 10”, “enter stone-cut pyramid” and so forth will all work.
•
EXERCISE 2
Except of course that now ‘Ruins’ won't compile, because
Inform expects to find a room called Square_Chamber
which the steps lead to. Design one.