Talking about the state of the world is much easier than listening to the player's intentions for it. Despite this, the business of description takes up a fair part of this chapter since the designer of a really complex game will eventually need to know almost every rule involved. (Whereas nobody would want to know everything about the parser.)
The simplest description of an object is its “short name”. For instance,
print (a) brass_lamp;
may result in “an old brass lamp” being
printed. There are four such forms of print
:
print (the) obj |
Print the object with its definite article |
print (The) obj |
The same, but capitalised |
print (a) obj |
Print the object with indefinite article |
print (name) obj |
Print the object's short name alone |
and these can be freely mixed into lists of things
to print
or print_ret
, as for example:
"The ogre declines to eat ", (the) noun, ".";
•
EXERCISE 62
When referring to animate
objects, you sometimes need to
use pronouns such as “him”. Define new printing routines
so that print "You throw the book at ", (PronounAcc) obj,
"!";
will insert the right accusative pronouns.
▲▲
There is also a special syntax print (object)
for printing
object names, but do not use it without good reason: it
doesn't understand some of the features below and is not protected
against crashing if you mistakenly try to print the name for an object
that doesn't exist.
· · · · ·
Inform tries to work out the right indefinite article
for any object automatically. In English-language games, it uses ‘an’
when the short name starts with a vowel and ‘a’ when
it does not (unless the name is plural, when ‘some’ is used
in either case). You can override this by setting article
yourself, either to some text or a routine to print some. Here are
some possibilities, arranged as “article / name”:
“a / platinum bar”, “an
/ orange balloon”, “your / Aunt Jemima”,
“some bundles of / reeds”, “far too many / marbles”,
“The / London Planetarium”
If the object is given the attribute proper
then
its name is treated as a proper noun taking no article, so the value
of article is ignored. Objects representing named people usually have
proper
, and so might a book like “Whitaker's
Almanac”.
Definite articles are always “the”, except
for proper
nouns. Thus
“the / platinum bar”, “Benjamin Franklin”, “Elbereth”
are all printed by print (the) ...
, the
latter two objects being proper
.
A single object whose name is plural, such as
“grapes” or “marble pillars”, should
be given the attribute pluralname
. As a result the library
might say, e.g., “You can't open those” instead of “You
can't open that”. As mentioned above, the indefinite article
becomes “some”, and the player can use the pronoun
“them” to refer to the object, so for instance “take
them” to pick up the grapes-object.
▲
You can give animate
objects the attributes male
,
female
or neuter
to help the parser understand
pronouns properly. animate
objects are assumed to be
male if you set neither alternative.
▲ There's usually no need to worry about definite and indefinite articles for room objects, as the standard Inform rules never print them.
· · · · ·
The short name of an object is normally the text given
in double-quotes at the head of its definition. This is very inconvenient
to change during play when, for example, “blue liquid”
becomes “purple liquid” as a result of a chemical reaction.
A more flexible way to specify an object's short name is with the
short_name
property. To print the name of such an object,
Inform does the following:
short_name
is a string, it's printed and
that's all.true
, that's all.For example, the dye might be defined with:
short_name [; switch(self.colour) { 1: print "blue "; 2: print "purple "; 3: print "horrid sludge"; rtrue; } ],
with "liquid"
as the
short name in its header. According to whether its colour
property is 1, 2 or 3, the printed result is “blue liquid”,
“purple liquid” or “horrid sludge”.
▲
Alternatively, define the dye with short_name "blue liquid"
and then simply execute dye.short_name = "purple liquid";
when the time comes.
•
EXERCISE 63
Design a chessboard of sixty-four locations with a map corresponding to
an eight-by-eight grid, so that White advances north towards Black, with
pieces placed on the board according to a game position. Hint: using
flexible routines for short_name
, this can be done with
just two objects, one representing all sixty-four squares, the other
representing all thirty-two pieces.
· · · · ·
For many objects the indefinite article and short name will most often be seen in inventory lists, such as:
>inventory
You are carrying:
a leaf of mint
a peculiar book
your satchel (which is open)
a green cube
Some objects, though, ought to have fuller entries
in an inventory: a wine bottle should say how much wine is left,
for instance. The invent
property is designed for this.
The simplest way to use invent
is as a string. For
instance, declaring a peculiar book with
invent "that harmless old book of Geoffrey's",
will make this the inventory line for the book. In the light of events, it could later be changed with a statement like:
book.invent = "that lethal old book of Geoffrey's";
▲
Note that this string becomes the whole inventory entry: if the object
were an open container, its contents wouldn't be listed, which might
be unfortunate. In such circumstances it's better to write an invent
routine, and that's also the way to append text like “(half-empty)”.
▲ Each line of an inventory is produced in two stages. First, the basic line:
inventory_stage
is set to 1.invent
routine is called (if there is one).
If it returns true, stop here.Second, little informative messages like “(which is open)" are printed, and inventories are given for the contents of open containers:
inventory_stage
is set
to 2.invent
routine is called (if there is one).
If it returns true, stop here.open container
, or a supporter
,
or is transparent
, then its contents are inventoried.After each line is printed, linking text such as a new-line or a comma is printed, according to the current “list style”.
For example, here is the invent
routine
used by the matchbook in ‘Toyshop’:
invent [ i; if (inventory_stage == 2) { i = self.number; if (i == 0) print " (empty)"; if (i == 1) print " (1 match left)"; if (i > 1) print " (", i, " matches left)"; } ],
•▲▲
EXERCISE 64
Suppose you want to change the whole inventory line for an ornate box
but you can't use an invent
string, or return true from
stage 1, because you still want stage 2d to happen properly (so that
its contents will be listed). How can you achieve this?
· · · · ·
The largest and most complicated messages the Inform
library ever prints on its own initiative are room descriptions, printed
when the Look
action is carried out (for instance, when
the statement <Look>;
triggers a room description).
What happens is: the room's short name is printed, usually emphasised
in bold-face, then the description
, followed by a list of
the objects residing there which aren't concealed
or
scenery
.
Chapter III mentioned many
different properties – initial
, when_on
,
when_off
and so on – giving descriptions of what
an object looks like when in the same room as the player: some apply
to doors, others to switchable objects and so on. All of them can be
routines to print text, instead of being strings to print. The precise
rules are given below.
But the whole system can be bypassed using the
describe
property. If an object gives a describe
routine then this takes priority over everything: if it returns
true
, the library assumes that the object has already been
described, and prints nothing further. For example:
describe [; "^The platinum pyramid catches the light beautifully."; ],
Unlike an initial
description, this is
still seen even if the pyramid has moved, i.e., been held by the
player at some stage.
▲
Note the initial ^
(new-line) character. The library doesn't
print a skipped line itself before calling describe
because
it doesn't know yet whether the routine will want to say anything.
A describe
routine which prints nothing and returns true
makes an object invisible, as if it were concealed
.
▲▲
Here is exactly how a room description is printed. Recall from
§21 that location
holds the
player's location if there is light, and thedark
if not,
and see §21 for the definition of
“visibility ceiling”, which roughly means the outermost
thing the player can see: normally the location, but possibly a closed
opaque container which the player is inside. First the top line:
supporter
, then
“ (on ‹something›)” is printed;
if inside something (other than the visibility ceiling), then
“ (in ‹something›)”.ChangePlayer
: for instance, “ (as a werewolf)”.
(See §21 for details of ChangePlayer
.)Now the long description. This step is sometimes
skipped, depending on which “look mode” the player has
chosen: in the normal mode, it is skipped if the player has just moved
by a Go
action into a location already visited; in “superbrief”
mode it is always skipped, while in “verbose” mode it is
never skipped.
enterable
objects containing
the player, a long description is printed, as follows:
location
,
that is, the current room or else thedark
, then: if
location
provides describe
then the message
location.describe()
is sent. If not, then
location.description()
is sent. Every room is required
to provide one or the other. (This is now redundant. In earlier
Informs, description
could only be a string, so
describe
was there in case a routine was needed.)E
.
If E
provides it, the message E.inside_description()
is sent.The library has now finished, but your game gets a chance to add a postscript by means of an entry point routine:
LookRoutine
is called.▲▲
Besides printing room descriptions, the Look
action has
side-effects: it can award the player some points, or mark a room
with the attribute visited
. For these rules in full,
see §21.
▲▲
The visited
attribute is only given to a room after its
description has been printed for the first time. This is convenient
for making the description different after the first time.
▲▲
When “listing objects” (as in 3a and 3b above) some objects
are given a paragraph to themselves, while others are lumped together
in a list at the end. The following objects are not mentioned at all:
the player; what the player is in or on (if anything), because this
has been taken care of in the short or long description already; and
anything which has the attributes scenery
or concealed
.
The remaining objects are looked through, eldest first, as follows:
describe
routine, run it. If
it returns true
, stop here and don't mention the object
at all.container
, this is when_open
or when_closed
;switchable
object this is
when_on
or when_off
;when_open
or
when_closed
;initial
.moved
and the property isn't when_off
or when_closed
then the object will be listed
at the end, not given a paragraph of its own.▲
Note that although a supporter
which is scenery
won't be mentioned, anything on top of it may well be. If this
is undesirable, set these objects on top to be concealed
.
▲ Objects which have just been pushed into a new room are not listed in that room's description on the turn in question. This is not because of any rule about room descriptions, but because the pushed object is moved into the new room only after the room description is made. This means that when a wheelbarrow is pushed for a long distance, the player does not have to keep reading “You can see a wheelbarrow here.” every move, as though that were a surprise.
▲
You can use a library routine called Locale
to perform
object listing. See §A3 for details,
but suffice to say here that the process above is equivalent to
executing
if (Locale(location, "You can see", "You can also see")) print " here.^";
Locale
is useful for describing areas
of a room which are sub-divided off while remaining part of the same
location, such as the stage of a theatre.
•▲▲
EXERCISE 65
As mentioned above, the library implements “superbrief” and
“verbose” modes for room description (one always omits
long room descriptions, the other never does). How can verbose mode
automatically print room descriptions every turn? (Some of the later
Infocom games did this.)
•
REFERENCES
‘Balances’ often uses short_name
, especially
for the white cubes (whose names change) and lottery tickets (whose
numbers are chosen by the player). ‘Adventureland’ uses
short_name
in simpler ways: see the bear and the bottle,
for instance.
•The scroll class of ‘Balances’
uses invent
.
•See the ScottRoom
class of ‘Adventureland’ for a radically different way
to describe rooms (in pidgin English, like telegraphese, owing to
an extreme shortage of memory to store text – Scott Adams was
obliged to write for machines with under 16K of free memory).