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