7 | *S was a sailor, and spent all he got;*
8 | *T was a tinker, and mended a pot.*
12 .. image:: /images/picS.png
19 imple though they are, our two games have covered most of the basic
20 functionality of Inform, providing enough solid ground underfoot
21 for you to start creating simple stories. Even if some of what you've
22 encountered doesn't make sense yet, you should be able to browse a
23 game's source code and form a general understanding of what is going on.
25 We'll now design a third game, to show you a few additional features and
26 give you some more sample code to analyse. In "Heidi" we tried to make
27 progress step by step, explaining every bit of code that went into the
28 game as we laid the objects sequentially; in "William Tell" you'll have
29 noticed that we took a few necessary explanatory detours, as the
30 concepts grew more interesting and complicated. Here we'll organise the
31 information in logical didactic chunks, defining some of the objects
32 minimally at first and then adding complexity as need arises. Again,
33 this means that you won't be able to compile for testing purposes after
34 the addition of every code snippet, so, if you're typing in the game as
35 you read, you’ll need to check the advice in "Compile-as-you-go" on page
38 A lot of what goes into this game we have already seen; you may deduce
39 from this that the game design business is fairly repetitious and that
40 most games are, when you reach the programming bottom line, another
41 remake of the same old theme. Well, yes and no: you've got a camera and
42 have seen some short home videos in the making, but it’s a long way from
43 here to Casablanca. To stick with the analogy, we'll now construct the
44 opening sequence of an indie B-movie, a tribute to the style of
45 super-hero made famous by a childhood of comic books:
49 "Impersonating mild mannered John Covarth, assistant help boy at
50 an Impersonating insignificant drugstore, you suddenly STOP
51 when your acute hearing deciphers a stray radio call from the
52 POLICE. There’s some MADMAN attacking the population in Granary
53 Park! You must change into your Captain FATE costume fast...!"
55 which won't be so easy to do. In this short example, players will win
56 when they manage to change into their super-hero costume and fly away to
57 meet the foe. The confrontation will -- perhaps -- take place in some
58 other game, where we can but hope that Captain Fate will vanquish the
59 forces of evil, thanks to his mysterious (and here unspecified)
62 Fade up on: a nondescript city street
63 =====================================
65 The game starts with meek John Covarth walking down the street. We set
68 .. code-block:: inform
71 !============================================================================
72 Constant Story "Captain Fate";
74 "^A simple Inform example
75 ^by Roger Firth and Sonja Kesserich.^";
76 Release 3; Serial "040804"; ! for keeping track of public releases
78 Constant MANUAL_PRONOUNS;
80 Constant OBJECT_SCORE 1;
81 Constant ROOM_SCORE 1;
86 !============================================================================
90 with description "UNDER CONSTRUCTION",
95 Take,Pull,Push,PushDir:
96 "Even though your SCULPTED adamantine muscles are up to the task,
97 you don't favour property damage.";
101 !============================================================================
104 Room street "On the street"
105 with name 'city' 'buildings' 'skyscrapers' 'shops' 'apartments' 'cars',
107 "On one side -- which your HEIGHTENED sense of direction
108 indicates is NORTH -- there's an open cafe now serving
109 lunch. To the south, you can see a phone booth.";
111 !============================================================================
112 ! The player's possessions
114 !============================================================================
115 ! Entry point routines
120 "^^Impersonating mild mannered John Covarth, assistant help boy at an
121 insignificant drugstore, you suddenly STOP when your acute hearing
122 deciphers a stray radio call from the POLICE. There's some MADMAN
123 attacking the population in Granary Park! You must change into your
124 Captain FATE costume fast...!^^";
127 !============================================================================
128 ! Standard and extended grammar
131 !============================================================================
133 Almost everything is familar, apart from a few details:
135 .. code-block:: inform
137 Constant MANUAL_PRONOUNS;
138 Constant MAX_SCORE 2;
139 Constant OBJECT_SCORE 1;
140 Constant ROOM_SCORE 1;
142 By default, Inform uses a system of automatic pronouns: as the player
143 character moves into a room, the library assigns pronouns like IT and
144 HIM to likely objects (if you play "Heidi" or "William Tell" and type
145 PRONOUNS, you can see how the settings change). There is another option.
146 If we declare the ``MANUAL_PRONOUNS`` onstant, we force the library to
147 assign pronouns to objects only as the player mentions them (that is, IT
148 will be unassigned until the player types, say, EXAMINE TREE, at which
149 point, IT becomes the TREE ). The behaviour of pronoun assignment is a
150 matter of personal taste; no system is objectively perfect.
152 Apart from the constant ``MAX_SCORE`` that we have seen in "William
153 Tell", which defines the maximum number of points to be scored, we now
154 see two more constants: ``OBJECT_SCORE`` and ``ROOM_SCORE``. There are
155 several scoring systems predefined in Inform. In "William Tell" we've
156 seen how you can manually add (or subtract) points by changing the value
157 of the variable ``score``. Another approach is to award points to
158 players on the first occasion that they (a) enter a particular room, or
159 (b) pick up a particular object. To define that a room or object is
160 indeed “particular”, all you have to do is give it the attribute
161 ``scored``; the library take cares of the rest. The predefined scores
162 are five points for finally reached rooms and four points for wondrous
163 acquisition of objects. With the constants ``OBJECT_SCORE`` and
164 ``ROOM_SCORE`` we can change those defaults; for the sake of example,
165 we've decided to modestly award one point for each. By the way, the use
166 of an equals sign ``=`` is optional with ``Constant``; these two lines
167 have identical effect:
169 .. code-block:: inform
171 Constant ROOM_SCORE 1;
173 Constant ROOM_SCORE = 1;
175 Another difference has to do with a special short-hand method that
176 Inform provides for displaying strings of text. Until now, we have shown
179 .. code-block:: inform
181 print "And now for something completely different...^"; return true;
183 print_ret "And now for something completely different...";
185 Both lines do the same thing: they display the quoted string, output a
186 newline character, and return true. As you have seen in the previous
187 example games, this happens quite a lot, so there is a yet shorter way
188 of achieving the same result:
190 .. code-block:: inform
192 "And now for something completely different...";
194 That is, *in a routine* (where the compiler is expecting to find a
195 collection of statements each terminated by a semicolon), a string in
196 double quotes by itself, without the need for any explicit keywords,
197 works exactly as if there were a ``print_ret`` in front of it. Remember
198 that this way of displaying text implies a ``return true`` at the end
199 (which therefore exits from the routine immediately). This detail
200 becomes important if we *don't* want to return true after the string
201 has been displayed on the screen -- we should use the explicit ``print``
204 You'll notice that -- unusually for a room -- our ``street`` object has
207 .. code-block:: inform
209 Room street "On the street"
210 with name 'city' 'buildings' 'skyscrapers' 'shops' 'apartments' 'cars',
213 Rooms aren't normally referenced by name, so this may seem odd. In fact,
214 we're illustrating a feature of Inform: the ability to define dictionary
215 words as "known but irrelevant" in this location. If the player types
216 EXAMINE CITY here, the interpreter will reply "That's not something you
217 need to refer to in order to SAVE the day", rather than the misleading
218 "You can't see any such thing". We mostly prefer to deal with such
219 scenic words using classes like ``Prop`` and ``Furniture``, but
220 sometimes a room's ``name`` property is a quick and convenient solution.
222 In this game, we provide a class named ``Appliance`` to take care of
223 furniture and unmovable objects. You’ll notice that the starting room we
224 have defined has no connections yet. The description mentions a phone
225 booth and a café, so we might want to code those. While the café will be
226 a normal room, it would seem logical that the phone booth is actually a
227 big box on the sidewalk; therefore we define a ``container`` set in the
228 street, which players may enter:
230 .. code-block:: inform
232 Appliance booth "phone booth" street
233 with name 'old' 'red' 'picturesque' 'phone' 'booth' 'cabin'
236 "It's one of the old picturesque models, a red cabin with room
240 "The booth is already open.";
242 "There's no way to close this booth.";
246 "With implausible celerity, you dive inside the phone booth.";
248 has enterable container open;
250 What's interesting are the attributes at the end of the definition.
251 You'll recall from Heidi's ``nest`` object that a ``container`` is an
252 object capable of having other objects placed in it. If we make
253 something ``enterable``, players count as one of those objects, so that
254 they may squeeze inside. Finally, ``containers`` are, by default,
255 supposed to be closed. You can make them ``openable`` if you wish
256 players to be able to OPEN and CLOSE them at will, but this doesn't seem
257 appropriate behaviour for a public cabin -- it would become tedious to
258 have to type OPEN BOOTH and CLOSE BOOTH when these actions provide
259 nothing special -- so we add instead the attribute ``open`` (as we did
260 with the nest), telling the interpreter that the container is open from
261 the word go. Players aren't aware of our design, of course; they may
262 indeed try to OPEN and CLOSE the booth, so we trap those actions in a
263 ``before`` property which just tells them that these are not relevant
264 options. The ``after`` property gives a customised message to override
265 the library’s default for commands like ENTER BOOTH or GO INSIDE BOOTH.
267 Since in the street's description we have told players that the phone
268 booth is to the south, they might also try typing SOUTH. We must
269 intercept this attempt and redirect it (while we're at it, we add a
270 connection to the as-yet-undefined café room and a default message for
271 the movement which is not allowed):
273 .. code-block:: inform
275 Room street "On the street"
276 with name city' 'buildings' 'skyscrapers' 'shops' 'apartments' 'cars',
278 "On one side -- which your HEIGHTENED sense of direction
279 indicates is NORTH -- there's an open cafe now serving
280 lunch. To the south, you can see a phone booth.",
282 s_to [; <<Enter booth>>; ],
284 "No time now for exploring! You'll move much faster in your
285 Captain FATE costume.";
287 That takes care of entering the booth. But what about leaving it?
288 Players may type EXIT or OUT while they are inside an enterable
289 container and the interpreter will oblige but, again, they might type
290 NORTH. This is a problem, since we are actually in the street (albeit
291 inside the booth) and to the north we have the café. We may provide for
292 this condition in the room's ``before`` property:
294 .. code-block:: inform
298 if (player in booth && noun == n_obj) <<Exit booth>>;
301 Since we are outdoors and the booth provides a shelter, it's not
302 impossible that a player may try just IN, which is a perfectly valid
303 connection. However, that would be an ambiguous command, for it could
304 also refer to the café, so we express our bafflement and force the
305 player to try something else:
307 .. code-block:: inform
310 s_to [; <<Enter booth>>; ],
311 in_to "But which way?",
313 Now everything seems to be fine, except for a tiny detail. We've said
314 that, while in the booth, the player character’s location is still the
315 ``street`` room, regardless of being inside a ``container``; if players
316 chanced to type LOOK, they'd get:
318 .. code-block:: transcript
320 On the street (in the phone booth)
321 On one side -- which your HEIGHTENED sense of direction indicates is NORTH --
322 there's an open cafe now serving lunch. To the south, you can see a
325 Hardly an adequate description while *inside* the booth. There are
326 several ways to fix the problem, depending on the result you wish to
327 achieve. The library provides a property called ``inside_description``
328 which you can utilise with enterable containers. It works pretty much
329 like the normal ``description`` property, but it gets printed only when
330 the player is inside the container. The library makes use of this
331 property in a very clever way, because for every LOOK action it checks
332 whether we can see outside the container: if the container has the
333 ``transparent`` attribute set, or if it happens to be ``open``, the
334 library displays the normal ``description`` of the room first and then
335 the ``inside_description`` of the container. If the library decides we
336 can’t see outside the container, only the inside_description is
337 displayed. Take for instance the following (simplified) example:
339 .. code-block:: inform
341 Room stage "On stage"
343 "The stage is filled with David Copperfield's
344 magical contraptions.",
347 Object magic_box "magic box" stage
349 "A big elongated box decorated with silver stars, where
350 scantily clad ladies make a disappearing act.",
352 "The inside panels of the magic box are covered with black
353 velvet. There is a tiny switch by your right foot.",
355 has container openable enterable light;
357 Now, the player would be able to OPEN BOX and ENTER BOX. A player who
358 tried a LOOK would get:
360 .. code-block:: transcript
362 On stage (in the magic box)
363 The stage is filled with David Copperfield's magical contraptions.
365 The inside panels of the magic box are covered with black velvet. There is a
366 tiny switch by your right foot.
368 If now the player closes the box and LOOKs:
370 .. code-block:: transcript
372 On stage (in the magic box)
373 The inside panels of the magic box are covered with black velvet. There is a
374 tiny switch by your right foot.
376 In our case, however, we don't wish the description of the street to be
377 displayed at all (even if a caller is supposedly able to see the street
378 while inside a booth). The problem is that we have made the booth an
379 ``open`` container, so the street's description would be displayed every
380 time. There is another solution. We can make the ``description``
381 property of the ``street`` room a bit more complex, and change its
382 value: instead of a string, we write an embedded routine. Here's the
383 (almost) finished room:
385 .. code-block:: inform
387 Room street "On the street"
388 with name 'city' 'buildings' 'skyscrapers' 'shops' 'apartments' 'cars',
391 "From this VANTAGE point, you are rewarded with a broad view
392 of the sidewalk and the entrance to Benny's cafe.";
394 "On one side -- which your HEIGHTENED sense of direction
395 indicates is NORTH -- there's an open cafe now serving
396 lunch. To the south, you can see a phone booth.";
400 if (player in booth && noun == n_obj) <<Exit booth>>;
403 s_to [; <<Enter booth>>; ],
404 in_to "But which way?",
406 "No time now for exploring! You'll move much faster in your
407 Captain FATE costume.";
409 The description while inside the booth mentions the sidewalk, which
410 might invite the player to EXAMINE it. No problem:
412 .. code-block:: inform
414 Appliance "sidewalk" street
415 with name sidewalk' 'pavement' 'street',
418 "You make a quick surveillance of the sidewalk and discover much
419 to your surprise that it looks JUST like any other sidewalk in
422 Unfortunately, both descriptions also mention the café, which will be a
423 room and therefore not, from the outside, an examinable object. The
424 player may enter it and will get whatever description we code as the
425 result of a LOOK action (which will have to do with the way the café
426 looks from the *inside*); but while we are on the street we need
427 something else to describe it:
429 .. code-block:: inform
431 Appliance outside_of_cafe "Benny's cafe" street
432 with name 'benny^s' 'cafe' 'entrance',
434 "The town's favourite for a quick snack, Benny's cafe has a 50's
438 print "With an impressive mixture of hurry and nonchalance
439 you step into the open cafe.^";
443 has enterable proper;
447 although the text of our guide calls Benny's establishment a "café"
448 -- note the acute "e" -- the game itself simplifies this to "cafe".
449 We do this for clarity, not because Inform doesn't support accented
450 characters. The *Inform Designer's Manual* explains in detail how to
451 display these characters in "§1.11 *How text is printed*" and
452 provides the whole Z-machine character set in Table 2. In our case,
453 we could have displayed this::
455 The town's favourite for a quick snack, Benny's café has a 50's ROCKETSHIP look.
457 by defining the ``description`` property as any of these:
459 .. code-block:: inform
462 "The town's favourite for a quick snack, Benny's caf@'e has a 50's
466 "The town's favourite for a quick snack, Benny's caf@@170 has a 50's
470 "The town's favourite for a quick snack, Benny's caf@{E9} has a 50's
473 However, all three forms are harder to read than the vanilla "cafe", so
474 we've opted for the simple life.
476 Unlike the sidewalk object, we offer more than a mere description. Since
477 the player may try ENTER CAFE as a reasonable way of access -- which
478 would have confused the interpreter immensely -- we take the opportunity
479 of making this object also ``enterable``, and we cheat a little. The
480 attribute ``enterable`` has permitted the verb ENTER to be applied to
481 this object, but this is not a ``container``; we want the player to be
482 sent into the *real* café room instead. The ``before`` property handles
483 this, intercepting the action, displaying a message and teleporting the
484 player into the café. We ``return true`` to inform the interpreter that
485 we have taken care of the ``Enter`` action ourselves, so it can stop
488 As a final detail, note that we now have two ways of going into the
489 café: the ``n_to`` property of the ``street`` room and the ``Enter``
490 action of the ``outside_of_cafe`` object. A perfectionist might point
491 out that it would be neater to handle the actual movement of the player
492 in just one place of our code, because this helps clarity. To achieve
493 this, we redirect the street's ``n_to`` property thus:
495 .. code-block:: inform
497 n_to [; <<Enter outside_of_cafe>>; ],
499 You may think that this is unnecessary madness, but a word to the wise:
500 in a large game, you want action handling going on just in one place
501 when possible, because it will help you to keep track of where things
502 are a-happening if something goes *ploof* (as, believe us, it will; see
503 "Debugging your game" on page 197). You don't need to be a
504 perfectionist, just cautious.
506 A booth in this kind of situation is an open invitation for the player
507 to step inside and try to change into Captain Fate's costume. We won't
508 let this happen -- the player isn't Clark Kent, after all; later we'll
509 explain how we forbid this action -- and that will force the player to
510 go inside the café, looking for a discreet place to disrobe; but first,
511 let''s freeze John Covarth outside Benny''s and reflect about a
514 A hero is not an ordinary person
515 ================================
517 Which is to say, normal actions won't be the same for him.
519 As you have probably inferred from the previous chapters, some of the
520 library’s standard defined actions are less important than others in
521 making the game advance towards one of its conclusions. The library
522 defines PRAY and SING, for instance, which are of little consequence in
523 a normal gaming situation; each displays an all-purpose message,
524 sufficiently non-committal, and that's it. Of course, if your game
525 includes a magic portal that will reveal itself only if the player lets
526 rip with a snatch of Wagner, you may intercept the ``Sing`` action in a
527 ``before`` property and alter its default, pretty useless behaviour. If
528 not, it's "Your singing is abominable" for you.
530 All actions, useful or not, have a stock of messages associated with
531 them (the messages are held in the ``english.h`` library file and listed
532 in Appendix 4 of the *Inform Designer's Manual*). We have already seen
533 one way of altering the player character's description -- "As good
534 looking as ever" -- in "William Tell", but the other defaults may also
535 be redefined to suit your tastes and circumstantial needs.
537 John Covarth, aka Captain Fate, could happily settle for most of these
538 default messages, but we deem it worthwhile to give him some customised
539 responses. If nothing else, this adds to the general atmosphere, a
540 nicety that many players regard as important. For this mission, we make
541 use of the ``LibraryMessages`` object.
543 .. code-block:: inform
547 Object LibraryMessages ! must be defined between Parser and VerbLib
549 Buy: "Petty commerce interests you only on COUNTED occasions.";
550 Dig: "Your keen senses detect NOTHING underground worth your
551 immediate attention.";
552 Pray: "You won't need to bother almighty DIVINITIES to save
554 Sing: "Alas! That is not one of your many superpowers.";
555 Sleep: "A hero is ALWAYS on the watch.";
556 Strong: "An unlikely vocabulary for a HERO like you.";
557 Swim: "You quickly turn all your ATTENTION towards locating a
558 suitable place to EXERCISE your superior strokes,
559 but alas! you find none.";
562 if (clothes has worn)
563 "In your secret identity's outfit, you manage most
564 efficaciously to look like a two-cent loser, a
565 good-for-nothing wimp.";
567 "Now that you are wearing your costume, you project
568 the image of power UNBOUND, of ballooned,
569 multicoloured MUSCLE, of DASHING yet MODEST chic.";
571 "That's not a verb you need to SUCCESSFULLY save the day.";
573 "That's not something you need to refer to in order to
579 If you provide it, the ``LibraryMessages`` object must be defined
580 *between* the inclusion of ``Parser`` and ``VerbLib`` (it won't work
581 otherwise and you’ll get a compiler error). The object contains a single
582 property -- ``before`` -- which intercepts display of the default
583 messages that you want to change. An attempt to SING, for example, will
584 now result in "Alas! That is not one of your many superpowers" being
587 In addition to such verb-specific responses, the library defines other
588 messages not directly associated with an action, like the default
589 response when a verb is unrecognised, or if you refer to an object which
590 is not in scope, or indeed many other things. Most of these messages can
591 be accessed through the ``Miscellany entry``, which has a numbered list
592 of responses. The variable ``lm_n`` holds the current value of the
593 number of the message to be displayed, so you can change the default
594 with a test like this:
596 .. code-block:: inform
599 "That's not something you need to refer to in order to SAVE the day.";
601 where 39 is the number for the standard message "That's not something
602 you need to refer to in the course of this game" -- displayed when the
603 player mentions a noun which is listed in a room's name property, as we
604 did for the ``street``.
608 Remember that when we are testing for different values of the
609 same variable, we can also use the switch statement. For the
610 Miscellany entry, the following code would work just as nicely:
612 .. code-block:: inform
618 if (clothes has worn)
619 "In your secret identity's outfit, you manage most
620 efficaciously to look like a two-cent loser, a
621 good-for-nothing wimp.";
623 "Now that you are wearing your costume, you project
624 the image of power UNBOUND, of ballooned,
625 multicoloured MUSCLE, of DASHING yet MODEST chic.";
627 "That's not a verb you need to SUCCESSFULLY save the day.";
629 "That's not something you need to refer to in order to SAVE the day.";
632 Not surprisingly, the default message for self-examination: "As good
633 looking as ever" is a ``Miscellany`` entry -- it's number 19 -- so we
634 can change it through the ``LibraryMessages`` object instead of, as
635 before, assigning a new string to the ``player.description property``.
636 In our game, the description of the player character has two states:
637 with street clothes as John Covarth and with the super-hero outfit as
638 Captain Fate; hence the ``if (clothes has worn)`` clause.
640 This discussion of changing our hero's appearance shows that there are
641 different ways of achieving the same result, which is a common situation
642 while designing a game. Problems may be approached from different
643 angles; why use one technique and not another? Usually, the context tips
644 the balance in favour of one solution, though it might happen that you
645 opt for the not-so-hot approach for some overriding reason. Don't feel
646 discouraged; choices like this become more common (and easier) as your
651 That "whatever new look" below needs to be italicized and bolded for LaTeX
655 going back to our example, an alternative approach would be to set
656 the variable ``player.description`` in the ``Initialise`` routine (as we
657 did with "William Tell") to the "ordinary clothes" string, and then
658 later change it as the need arises. It is a variable, after all, and you
659 can alter its value with another statement like ``player.description =``
660 *whatever new look* anywhere in your code. This alternative solution
661 might be better if we intended changing the description of the player
662 many times through the game. Since we plan to have only two states, the
663 ``LibraryMessages`` approach will do just fine.
665 A final warning: as we explained when extending the standard verb
666 grammars, you *could* edit the appropriate library file and change all
667 the default messages, but that wouldn't be a sound practice, because
668 your library file will probably not be right for the next game. Use of
669 the ``LibraryMessages`` object is strongly advised.
671 If you're typing in the game, you'll probably want to read the brief
672 section on "Compile-as-you-go" on page 255 prior to performing a test
673 compile. Once everything's correct, it’s time that our hero entered that