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