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