Add special RST roles for the Inform entities.
[ibg.git] / chapters / 13.rst
1 ===========================
2 Captain Fate: the final cut
3 ===========================
4
5 .. epigraph::
6
7    | |CENTER| *Y was a youth, that did not love school;*
8    | |CENTER| *Z was a zany, a poor harmless fool.*
9
10 .. only:: html
11
12    .. image:: /images/picY.png
13       :align: left
14
15 |Y|\ou'll probably be pleased to hear that Captain Fate has almost run his
16 allotted span. There are some minor objects still to be defined -- the
17 toilet, our hero’s clothes, the all-important costume -- but first we need
18 to decorate the café a little more.
19
20 Additional catering garnish
21 ===========================
22
23 We must not forget a couple of tiny details in the café room:
24
25 .. code-block:: inform
26
27   Object   food "Benny's snacks" cafe
28     with   name 'food' 'pastry' 'pastries' 'sandwich' 'sandwiches' 'snack'
29            before [; "There is no time for FOOD right now."; ],
30     has    scenery proper;
31
32   Object   menu "menu" cafe
33     with   name 'informative' 'menu' 'board' 'picture' 'writing',
34            description
35                "The menu board lists Benny's food and drinks, along with their
36                 prices. Too bad you've never learnt how to read, but luckily
37                 there is a picture of a big cup of coffee among the
38                 incomprehensible writing.",
39            before [;
40              Take:
41                "The board is mounted on the wall behind Benny. Besides, it's
42                 useless WRITING.";
43            ],
44     has    scenery;
45
46 And a not-so-trivial object:
47
48 .. code-block:: inform
49
50   Object  coffee "cup of coffee" benny
51     with  name 'cup' 'of' 'coffee' 'steaming' 'cappuccino'
52                'cappucino' 'capuccino' 'capucino',
53           description [;
54               if (self in benny)
55                   "The picture on the menu board SURE looks good.";
56               else
57                   "It smells delicious.";
58           ],
59           before [;
60             Take,Drink,Taste:
61               if (self in benny) "You should ask Benny for one first.";
62               else {
63                   move self to benny;
64                   print "You pick up the cup and swallow a mouthful. Benny's
65                          WORLDWIDE REPUTATION is well deserved. Just as you
66                          finish, Benny takes away the empty cup.";
67                   if (benny.coffee_not_paid == true)
68                       " ~That will be one quidbuck, sir.~";
69                   else
70                       "";
71               }
72             Buy:
73               if (coin in player) <<Give coin benny>>;
74               else                "You have no money.";
75             Smell:
76               "If your HYPERACTIVE pituitary glands are to be trusted,
77                it's Colombian.";
78           ];
79
80 There's nothing really new in this object (other than that the :prop:`name` 
81 property caters for orthographically challenged players), but notice how 
82 we don't ``remove`` it after the player drinks it. In an apparently 
83 absurd whim, the coffee returns to Benny magically (although this is not 
84 information that the player needs to know). Why? After you remove an 
85 object from the game, if the player attempts, say, to EXAMINE it, the 
86 interpreter will impertinently state that "You can't see any such 
87 thing". Moreover, if the player asks Benny for a second coffee, once the 
88 first one has been removed, Benny will complain "I don’t think that’s on 
89 the menu, sir" -- a blatant lie -- which was the default in Benny’s 
90 orders property. Since the removed coffee object does not belong to 
91 Benny, it's not a noun that the player can ASK Benny FOR. By making it a 
92 child of the barman (who has the :attr:`transparent` attribute set), the 
93 coffee is still an object that players can refer to. We ensure that they 
94 don't get more cups thanks to Benny's ``coffee_asked_for`` property, 
95 which will remain :const:`true` after the first time.
96
97 We also ensure that Benny doesn't ask for money from players who have 
98 already paid, by first printing a "You pick up the cup..." message and 
99 then testing Benny's ``coffee_not_paid`` property. If its value is 
100 :const:`true`, we can finish the message with the "quidbuck" print-and-return 
101 statement. If its value is :const:`false`, the player has previously paid, 
102 and so there's nothing else to say. However, we still need to terminate 
103 the incomplete message with a newline, and to return :const:`true` from the 
104 property routine; we *could* have used the statements ``{ print "^"; 
105 return true; }``, but an empty ``""`` statement does the same thing more 
106 neatly.
107
108
109 Toilet or dressing room?
110 ========================
111
112 Rather more of the latter, actually, since it's the only place away from 
113 curious eyes where our hero will be able to metamorphose from weakling 
114 into the bane of all evildoers. And we *really* don't want to become, 
115 erm, bogged down with details of the room's function or plumbing.
116
117 There's not a lot about the toilet room and its contents, though there 
118 will be some tricky side effects:
119
120 .. code-block:: inform
121
122   Room    toilet "Unisex toilet"
123     with  description
124               "A surprisingly CLEAN square room covered with glazed-ceramic
125                tiles, featuring little more than a lavatory and a light switch.
126                The only exit is south, through the door and into the cafe.",
127           s_to toilet_door,
128     has   ~light scored;
129
130   Appliance lavatory "lavatory" toilet
131     with name 'lavatory' 'wc' 'toilet' 'loo' 'bowl' 'can' 'john' 'bog',
132          before [;
133            Examine,Search,LookUnder:
134              if (coin in self) {
135                  move coin to parent(self);
136                  "The latest user CIVILLY flushed it after use, but failed to
137                   pick up the VALUABLE coin that fell from his pants.";
138              }
139            Receive:
140              "While any other MORTALS might unwittingly throw just about
141               ANYTHING into ", (the) self, ", you remember the WISE teachings
142               of your mentor, Duke ELEGANT, about elderly plumbing and rising
143               waters.";
144          ];
145
146   Object  coin "valuable coin" lavatory
147     with  name 'valuable' 'coin' 'silver' 'quidbuck',
148           description "It's a genuine SILVER QUIDBUCK.",
149           before [;
150             Drop:
151               if (self notin player) return false;
152               "Such a valuable coin? Har, har! This must be a demonstration of
153                your ULTRA-FLIPPANT jesting!";
154           ],
155           after [;
156             Take:
157               "You crouch into the SLEEPING DRAGON position and deftly, with
158                PARAMOUNT STEALTH, you pocket the lost coin.";
159           ],
160     has   scored;
161
162 We initially place the coin as a child of the lavatory (just so that we 
163 can easily make the ``if (coin in self)`` one-time test). Since the 
164 lavatory does not have the :attr:`transparent` attribute set, the coin will 
165 be invisible to players until they try to inspect the lavatory, an 
166 action that will move the coin into the toilet room. Once taken, the 
167 coin will remain in the inventory until the player gives it to Benny, 
168 because we trap any ``Drop`` actions to help the player to Do the Right 
169 Thing.
170
171 The lavatory object includes a load of helpful synonyms in its name 
172 property, including our favourite word ``'toilet'`` . That won't be a 
173 problem: the other objects here which may have TOILET in their names -- 
174 the key and the door -- both use the ``pname`` property to turn their 
175 use of ``'toilet'`` into a lower-priority adjective.
176
177 See that here we have the only two :attr:`scored` attributes of the game. 
178 The player will be awarded one point for entering the toilet room, and 
179 another for finding and picking up the coin.
180
181 You might have noticed that we are forcefully clearing the :attr:`light` 
182 attribute, inherited from the ``Room`` class. This will be a windowless 
183 space and, to add a touch of realism, we'll make the room a dark one, 
184 which will enable us to tell you about Inform's default behaviour when 
185 there's no light to see by. However, let's define first the light switch 
186 mentioned in the room's description to aid players in their dressing 
187 duties.
188
189 .. code-block:: inform
190
191   Appliance  light_switch "light switch" toilet
192     with     name 'light' 'switch',
193              description
194                  "A notorious ACHIEVEMENT of technological SCIENCE, elegant yet
195                   EASY to use.",
196              before [;
197                Push:
198                  if (self has on) <<SwitchOff self>>;
199                  else             <<SwitchOn  self>>;
200              ],
201              after [;
202                SwitchOn:
203                  give self light;
204                  "You turn on the light in the toilet.";
205                SwitchOff:
206                  give self ~light;
207                  "You turn off the light in the toilet.";
208              ],
209     has      switchable ~on;
210
211 Please notice the appearance of new attributes :attr:`switchable` and 
212 :attr:`on`. switchable enables the object to be turned on and off, and is 
213 typical of lanterns, computers, television sets, radios, and so on. The 
214 library automatically extends the description of these objects by 
215 indicating if they are currently on or off:
216
217 .. code-block:: transcript
218
219   > X LIGHT SWITCH
220   A notorious ACHIEVEMENT of technological SCIENCE, elegant yet EASY to use.
221   The light switch is currently switched on.
222
223 Two new actions are ready to use, ``SwitchOn`` and ``SwitchOff``. Left 
224 to themselves, they toggle the object's state between ON and OFF and 
225 display a message like:
226
227 .. code-block:: transcript
228
229   You switch the brass lantern on.
230
231 They also take care of checking if the player fumbled and tried to turn 
232 on (or off) an object which was already on (or off). How does the 
233 library know the state of the object? This is thanks to the :attr:`on` 
234 attribute, which is set or cleared automatically as needed. You can, of 
235 course, set or clear it manually like any other attribute, with the 
236 ``give`` statement:
237
238 .. code-block:: inform
239
240   give self on;
241
242   give self ~on;
243
244 and check if a :attr:`switchable` object is on or off with the test:
245
246 .. code-block:: inform
247
248   if (light_switch has on) ...
249
250   if (light_switch hasnt on) ...
251
252 A :attr:`switchable` object is OFF by default. However, you’ll notice that 
253 the has line of the object definition includes ``~on`` :
254
255 .. code-block:: inform
256
257   has    switchable ~on;
258
259 Surely that’s saying "not-on"? Surely that's what would have happened 
260 anyway if the line hadn't mentioned the attribute at all?
261
262 .. code-block:: inform
263
264   has    switchable;
265
266 Absolutely true. Adding that ``~on`` attribute has no effect whatsoever 
267 on the game -- but nevertheless it's a good idea. It's an aide-mémoire, 
268 a way of reminding ourselves that we start with the attribute clear, and 
269 that at some point we'll be setting it for some purpose. Trust us: it's 
270 worthwhile taking tiny opportunities like this to help yourself.
271
272 Let’s see how our light switch works. We trap the ``SwitchOn`` and 
273 ``SwitchOff`` actions in the :prop:`after` property (when the switching has 
274 successfully taken place) and use them to give :attr:`light` to the light 
275 switch.
276
277 Uh, wait. To the light switch? Why not to the toilet room? Well, there's 
278 a reason and we'll see it in a minute. For now, just remember that, in 
279 order for players to see their surroundings, you need only one object in 
280 a room with the :attr:`light` attribute set. It doesn't have to be the room 
281 itself (though this is usually convenient).
282
283 After setting the :attr:`light` attribute, we display a customised message, 
284 to avoid the default:
285
286 .. code-block:: transcript
287
288   You switch the light switch on.
289
290 which, given the name of the object, doesn't read very elegantly. We 
291 foresee that players might try to PUSH SWITCH, so we trap this attempt 
292 in a :prop:`before` property and redirect it to ``SwitchOn`` and 
293 ``SwitchOff`` actions, checking first which one is needed by testing the 
294 :attr:`on` attribute. Finally, we have made the switch a member of the class 
295 ``Appliance``, so that the player doesn't walk away with it.
296
297 .. note::
298
299   Remember what we said about class inheritance? No matter what you 
300   define in the class, the object’s definition has priority. The class 
301   ``Appliance`` defines a response for the ``Push`` action, but we 
302   override it here with a new behaviour.
303
304
305 And there was light
306 ===================
307
308 So the player walks into the toilet and
309
310 .. code-block:: transcript
311
312   Darkness
313   It is pitch dark, and you can't see a thing.
314
315 Oops! No toilet description, no mention of the light switch, nothing. It 
316 is reasonable to think that if we have opened the toilet door to access 
317 the toilet, some light coming from the café room will illuminate our 
318 surroundings -- at least until the player decides to close the door. So 
319 perhaps it would be a good idea to append a little code to the door 
320 object to account for this. A couple of lines in the after property will 
321 suffice:
322
323 .. code-block:: inform
324
325   after [ ks;
326     Unlock:
327       if (self has locked) return false;
328       print "You unlock ", (the) self, " and open it.^";
329       ks = keep_silent; keep_silent = true;
330       <Open self>; keep_silent = ks;
331       return true;
332     Open:
333       give toilet light;
334     Close:
335       give toilet ~light;
336
337   ],
338
339 And this is the reason why the light switch didn't set the :attr:`light` 
340 attribute of the toilet room, but did it to itself. We avoid running 
341 into trouble if we let the open/closed states of the door control the 
342 light of the room object, and the on/off states of the switch control 
343 the light of the switch. So it is one shiny light switch. Fortunately, 
344 players are never aware of this glowing artefact.
345
346 .. note::
347
348   Now, could they? Well, if players could TAKE the light switch (which
349   we have forbidden) and then did INVENTORY, the trick would be given
350   away, because all objects with the :attr:`light` attribute set are listed 
351   as ``(providing light)`` .
352
353 So the player walks into the toilet and
354
355 .. code-block:: transcript
356
357   Unisex toilet
358   A surprisingly CLEAN square room covered with glazed-ceramic tiles, featuring
359   little more than a lavatory and a light switch. The only exit is south, through
360   the door and into the cafe.
361
362   [Your score has just gone up by one point.]
363
364 Better. Now, suppose the player closes the door.
365
366 .. code-block:: transcript
367
368   >CLOSE DOOR
369   You close the door to the cafe.
370
371   It is now pitch dark in here!
372
373 The player might try then to LOOK:
374
375 Well, no problem. We have mentioned that there is a light switch. Surely 
376 the player will now try to:
377
378 .. code-block:: transcript
379
380   >TURN ON LIGHT SWITCH
381   You can't see any such thing.
382
383 Oops! Things are getting nasty here in the dark. It's probably time to 
384 leave this place and try another approach:
385
386 .. code-block:: transcript
387
388   >OPEN DOOR
389   You can't see any such thing.
390
391 And this illustrates one of the terrible things about darkness in a 
392 game. You can't see anything; you can do very little indeed. All objects 
393 except those in your inventory are out of scope, unreachable, as if 
394 non-existent. Worse, if you DROP one of the objects you are carrying, it 
395 will be swallowed by the dark, never to be found until there is light to 
396 see by.
397
398 The player, who is doubtless immersed in the fantasy of the game, will 
399 now be a little annoyed. "I am in a small bathroom and I can't even 
400 reach the door I have just closed?" The player's right, of 
401 course [#dark]_.  Darkened rooms are one cliché of traditional games. 
402 Usually you move in one direction while looking for treasure in some 
403 underground cave, and suddenly arrive at a pitch black place. It's good 
404 behaviour of the game to disallow exploration of unknown dark territory, 
405 and it's a convention to bar passage to players until they return with a 
406 light source. However, if the scenario of the game features, say, the 
407 player character's home, a little apartment with two rooms, and there’s 
408 no light in the kitchen, we could expect the owner of the house to know 
409 how to move around a little, perhaps groping for the light switch or 
410 even going to the refrigerator in the dark.
411
412 We are in a similar situation. The inner logic of the game demands that 
413 blind players should be able to open the door and probably operate the 
414 light switch they've just encountered. We have been telling you that an 
415 object is in scope when it’s in the same room as the player. Darkness 
416 changes that rule. All objects not directly carried by the player become 
417 out of scope.
418
419 One of the advantages of an advanced design system like Inform is the 
420 flexibility to change all default behaviours to suit your particular 
421 needs. Scope problems are no different. There is a set of routines and 
422 functions to tamper with what's in scope when. We'll see just a tiny 
423 example to fix our particular problem. In the section "``Entry point 
424 routines``" of our game -- after the ``Initialise`` routine, for 
425 instance -- include the following lines:
426
427 .. code-block:: inform
428
429   [ InScope person;
430       if (person == player && location == thedark && real_location == toilet) {
431           PlaceInScope(light_switch);
432           PlaceInScope(toilet_door);
433       }
434       return false;
435   ];
436
437 :samp:`InScope({actor_obj_id})` is an entry point routine that can tamper
438 with the scope rules for the given :samp:`{actor_obj_id}` (either the
439 player character or a NPC). We define it with one variable (which we name
440 as we please; it's also a good idea to name variables in an intuitive way
441 to remind us of what they represent), ``person`` , and then we make a
442 complex test to see if the player is actually in the toilet and in the
443 dark.
444
445 We have told you that the library variable :var:`location` holds the 
446 current 
447 room that the player is in. However, when there is no light, the 
448 variable location gets assigned to the value of the special library 
449 object thedark . It doesn't matter if we have ten dark rooms in our 
450 game; location will be equal to thedark in all of them. There is yet 
451 another variable, called :var:`real_location`, which holds the room the 
452 player is in *even when there is no light to see by*.
453
454 So the test:
455
456 .. code-block:: inform
457
458   if (person == player && location == thedark && real_location == toilet) ...
459
460 is stating: if the specified actor is the :var:`player` character *and* he 
461 finds himself in the dark *and* he actually happens to be in the 
462 toilet...
463
464 Then we make a call to one of the library routines,
465 :samp:`PlaceInScope({obj_id})`, which has a very descriptive name: it
466 places in scope the given object. In our case, we want both the door and
467 the light switch to be within reach of the player, hence both additional
468 lines. Finally, we must ``return false``, because we want the normal scope
469 rules for the defined actor -- the player -- to apply to the rest of the
470 objects of the game (if we returned :const:`true`, players would find that they
471 are able to interact with very little indeed). Now we get a friendlier and
472 more logical response:
473
474 .. code-block:: transcript
475
476   Darkness
477   It is pitch dark, and you can't see a thing.
478
479   >TURN ON SWITCH
480   You turn on the light in the toilet.
481
482   Unisex toilet
483   A surprisingly CLEAN square room covered with glazed-ceramic tiles, featuring
484   little more than a lavatory and a light switch. The only exit is south, through
485   the door and into the cafe.
486
487 And the same would happen with the door. Notice how the room description 
488 gets displayed after we pass from dark to light; this is the normal 
489 library behaviour.
490
491 There is still one final problem which, admittedly, might originate from 
492 an improbable course of action; however, it could be a nuisance. Suppose 
493 that the player enters the toilet, locks the door -- which is possible 
494 in the dark now that the door is in scope -- and then drops the key. 
495 There's no way to exit the toilet -- because the door is locked and the 
496 key has disappeared, engulfed by the darkness -- unless the player 
497 thinks to turn on the light switch, thereby placing the key in scope 
498 once more.
499
500 Why don't we add a :samp:`PlaceInScope({toilet_key})` to the above routine?
501 Well, for starters, the key can be moved around (as opposed to the door or
502 the light switch, which are fixed items in the toilet room). Suppose the
503 player opens the door of the toilet, but drops the key in the café, then
504 enters the toilet and closes the door. The condition is met and the key is
505 placed in scope, when it's in another room. Second, this is a simple game
506 with just a few objects, so you can define a rule for each of them; but in
507 any large game, you might like to be able to refer to objects in bunches,
508 and make general rules that apply to all (or some) of them.
509
510 We need to add code to the ``InScope`` routine, telling the game to 
511 place in scope all objects that we drop in the dark, so that we might 
512 recover them (maybe going on all fours and groping a little, but it’s a 
513 possible action). We don’t want the player to have other objects in 
514 scope (like the coin, for instance), so it might be good to have a way 
515 of testing if the objects have been touched and carried by the player. 
516 The attribute :attr:`moved` is perfect for this. The library sets it for 
517 every object that the player has picked up at one time in the game; 
518 :attr:`scenery` and :attr:`static` objects, and those we have not yet seen don't 
519 have :attr:`moved`. Here is the reworked ``InScope`` routine. There are a 
520 couple of new concepts to look at:
521
522 .. code-block:: inform
523
524   [ InScope person item;
525       if (person == player && location == thedark && real_location == toilet) {
526           PlaceInScope(light_switch);
527           PlaceInScope(toilet_door);
528       }
529       if (person == player && location == thedark)
530           objectloop (item in parent(player))
531               if (item has moved) PlaceInScope(item);
532       return false;
533   ];
534
535 We have added one more local variable to the routine, ``item`` -- again, 
536 this is a variable we have created and named on our own; it is not part 
537 of the library. We make now a new test: if the actor is the player and 
538 the location is any dark room, then perform a certain action. We don't 
539 need to specify the toilet, because we want this rule to apply to all 
540 dark rooms (well, the only dark room in the game *is* the toilet, but we 
541 are trying to provide a general rule).
542
543    :samp:`objectloop (variable) {statement};`
544
545 is a loop statement, one of the four defined in Inform. A loop statement is
546 a construct that allows you to run several times through a statement (or a
547 statement block). ``objectloop`` performs the :samp:`{statement}` once for
548 every object defined in the (:samp:`{variable}`) . If we were to code:
549
550    :samp:`objectloop (item) {statement};`
551
552 then the :samp:`{statement}` would be executed once for each object in the
553 game. However, we want to perform the statement only for those objects
554 whose parent object is the same as the player's parent object: that is, for
555 objects in the same room as the player, so we instead code:
556
557    :samp:`objectloop (item in parent(player)) {statement};`
558
559 What is the actual :samp:`{statement}` that we'll repeatedly execute?
560
561 .. code-block:: inform
562
563   if (item has moved)
564       PlaceInScope(item);
565
566 The test: ``if (item has moved)`` ensures that ``PlaceInScope(item)`` 
567 deals only with objects with the :attr:`moved` attribute set. So: if the 
568 player is in the dark, let’s go through the objects which are in the 
569 same room, one at a time. For each of them, check if it's an item that 
570 the player has at some time carried, in which case, place it in scope. 
571 All dropped objects within the room were carried at one time, so we let 
572 players recollect them even if they can’t see them.
573
574 As you see, darkness has its delicate side. If you plan to have dark 
575 rooms galore in your games, bear in mind that you are in for some 
576 elaborate code (unless you let the library carry on with default rules, 
577 in which case there won't be much for your players to do).
578
579
580 Amazing techicolour dreamcoats
581 ==============================
582
583 This leaves us the clothing items themselves, which will require a few 
584 tailored actions. Let's see first the ordinary garments of John Covarth:
585
586 .. code-block:: inform
587
588   Object  clothes "your clothes"
589     with  name 'ordinary' 'street' 'clothes' 'clothing',
590           description
591               "Perfectly ORDINARY-LOOKING street clothes for a NOBODY like
592                John Covarth.",
593           before [;
594             Wear:
595               if (self has worn)
596                   "You are already dressed as John Covarth.";
597               else
598                   "The town NEEDS the power of Captain FATE, not the anonymity
599                    of John Covarth.";
600             Change,Disrobe:
601               if (self hasnt worn)
602                  "Your KEEN eye detects that you're no longer wearing them.";
603               switch (location) {
604                 street:
605                   if (player in booth)
606                       "Lacking Superman's super-speed, you realise that it
607                        would be awkward to change in plain view of the passing
608                        pedestrians.";          
609                   else
610                       "In the middle of the street? That would be a PUBLIC
611                        SCANDAL, to say nothing of revealing your secret
612                        identity.";
613                 cafe:
614                       "Benny allows no monkey business in his establishment.";
615                 toilet:
616                   if (toilet_door has open)
617                       "The door to the bar stands OPEN at tens of curious eyes.
618                        You'd be forced to arrest yourself for LEWD conduct.";
619                   print "You quickly remove your street clothes and bundle them
620                          up together into an INFRA MINUSCULE pack ready for easy
621                          transportation. ";
622                   if (toilet_door has locked) {
623                       give clothes ~worn; give costume worn;
624                       "Then you unfold your INVULNERABLE-COTTON costume and
625                        turn into Captain FATE, defender of free will, adversary
626                        of tyranny!";
627                   }
628                   else {
629                       deadflag = 3;
630                       "Just as you are slipping into Captain FATE's costume,
631                        the door opens and a young woman enters. She looks at
632                        you and starts screaming, ~RAPIST! NAKED RAPIST IN THE
633                        TOILET!!!~^^
634                        Everybody in the cafe quickly comes to the rescue, only
635                        to find you ridiculously jumping on one leg while trying
636                        to get dressed. Their laughter brings a QUICK END to
637                        your crime-fighting career!";
638                   }
639                 thedark:
640                   "Last time you changed in the dark, you wore the suit inside
641                    out!";
642                 default:                  ! this _should_ never happen...
643                   "There must be better places to change your clothes!";
644               }
645           ],
646     clothing proper pluralname;
647
648 See how the object deals only with ``Wear``, ``Disrobe`` and ``Change``. 
649 ``Wear`` and ``Disrobe`` are standard library actions already defined in 
650 Inform, but we'll have to make a new verb to allow for CHANGE CLOTHES. 
651 In this game, ``Disrobe`` and ``Change`` are considered synonymous for 
652 all purposes; we'll deal with them first.
653
654 The goal of the game is for players to change their clothes, so we might 
655 expect them to try this almost anywhere; but first of all we have to 
656 check that the ``clothes`` object is actually being worn. If not, we 
657 display a message reminding the player that this action has become 
658 irrelevant. What we do with the ``switch`` statement is to offer a 
659 variety of responses according to the :var:`location` variable. The street 
660 (in or out of the booth) and the café all display refusals of some kind, 
661 until the player character manages to enter the toilet, where we 
662 additionally require that he locks the door before taking off his 
663 clothes. If the door is closed but not locked, he is interrupted in his 
664 naked state by a nervous woman who starts shouting, and the game is lost 
665 (this is not as unfair as it seems, because the player may always revert 
666 to the previous state with UNDO). If the door is locked, he succeeds in 
667 his transformation (we take away the :attr:`worn` attribute from the 
668 ``clothes`` and give it to the ``costume`` instead). We add a special 
669 refusal to change in the dark, forcing players to turn on the light and 
670 then, we hope, to find the coin. And finally we code a ``default`` 
671 entry; you'll remember that, in a ``switch`` statement, this is supposed 
672 to cater for any value not explicitly listed for the expression under 
673 control -- in this case, for the variable :var:`location`. Since we have 
674 already gone through all the possible locations of the game, this entry 
675 appears only as a defensive measure, just in case something unexpected 
676 happens (for instance, we might extend the game with another room and 
677 forget about this ``switch`` statement). In normal and controlled 
678 conditions, it should never be reached, but it doesn't hurt one bit to 
679 have it there.
680
681 The ``Wear`` action just checks if these clothes are already being worn, 
682 to offer two different rejection responses: the goal of the game is to 
683 change into the hero's suit, after which we'll prevent a change back 
684 into ordinary clothes. So now we are dealing with a Captain Fate in full 
685 costume:
686
687 .. code-block:: inform
688
689   Object   costume "your costume"
690     with   name 'captain' 'captain^s' 'fate' 'fate^s' 'costume' 'suit',
691            description
692                "STATE OF THE ART manufacture, from chemically reinforced 100%
693                 COTTON-lastic(tm).",
694            before [;
695              Wear:
696                if (self has worn)
697                    "You are already dressed as Captain FATE.";
698                else
699                    "First you'd have to take off your commonplace unassuming
700                     John Covarth INCOGNITO street clothes.";
701              Change,Disrobe:
702                if (self has worn)
703                    "You need to wear your costume to FIGHT crime!";
704                else
705                    "But you're not yet wearing it!";
706              Drop:
707                "Your UNIQUE Captain FATE multi-coloured costume? The most
708                 coveted clothing ITEM in the whole city? Certainly NOT!";
709            ],
710     has    clothing proper;
711
712 Note that we intercept the action WEAR COSTUME and hint that players 
713 should try TAKE OFF CLOTHES instead. We don't let them take off the 
714 costume once it’s being worn, and we certainly don't let them misplace 
715 it anywhere, by refusing to accept a ``Drop`` action.
716
717
718 It's a wrap
719 ===========
720
721 Nearly there; just a few minor odds and ends to round things off.
722
723 .. rubric:: Initialise routine
724
725 All the objects of our game are defined. Now we must add a couple of 
726 lines to the ``Initialise`` routine to make sure that the player does 
727 not start the game naked:
728
729 .. code-block:: inform
730
731   [ Initialise;
732       #Ifdef DEBUG; pname_verify(); #Endif;       ! suggested by pname.h
733       location = street;
734       move costume to player;
735       move clothes to play; give clothes worn;
736       lookmode = 2;
737       "^^Impersonating mild mannered John Covarth, assistant help boy at an
738        insignificant drugstore, you suddenly STOP when your acute hearing
739        deciphers a stray radio call from the POLICE. There's some MADMAN
740        attacking the population in Granary Park! You must change into your
741        Captain FATE costume fast...!^^";
742   ];
743
744 Remember that we included a disambiguation package, ``pname.h``? There 
745 were some additional comments in the accompanying text file that should 
746 be taken in consideration:
747
748   pname.h provides a pname_verify routine. When DEBUG is defined, you 
749   may call pname_verify() in your Initialise() routine to verify the pname 
750   properties in your objects.
751
752 The designer of the package has made a debugging tool (a routine) to 
753 check for errors when using his library, and he tells us how to use it. 
754 So we include the suggested lines into our ``Initialise`` routine:
755
756 .. code-block:: inform
757
758   #Ifdef DEBUG; pname_verify(); #Endif;
759
760 As the text explains, what this does is: first check whether the game is 
761 being compiled in Debug mode; if this is the case, run the 
762 ``pname_verify`` routine, so that it tests all ``pname`` properties to 
763 see if they are written correctly.
764
765 .. rubric:: Demise of our hero
766
767 We have made three possible endings:
768
769 #.  The player attempts to change in the toilet with an unlocked door.
770
771 #.  The player tries to attack Benny while wearing the costume.
772
773 #.  The player manages to exit the café dressed as Captain Fate.
774
775 (1) and (2) lose the game, (3) wins it. The library defaults for these 
776 two states display, respectively,
777
778 .. code-block:: transcript
779
780   *** You have died ***
781
782   *** You have won ***
783
784 These states correspond to the values of the :var:`deadflag` variable: 1 
785 for losing, 2 for winning. However, we have made up different messages, 
786 because our hero does not really die -- ours suffers a FATE worse than 
787 death -- and because we want to give him a more descriptive winning 
788 line. Therefore, we must define a ``DeathMessage`` routine as we did in 
789 "William Tell", to write our customised messages and assign them to 
790 :var:`deadflag` values greater than 2.
791
792 .. code-block:: inform
793
794   [ DeathMessage;
795       if (deadflag == 3) print "Your secret identity has been revealed";
796       if (deadflag == 4) print "You have been SHAMEFULLY defeated";
797       if (deadflag == 5) print "You fly away to SAVE the DAY";
798   ];
799
800 .. rubric:: Grammar
801
802 Finally, we need to extend the existing grammar, to allow for a couple 
803 of things. We have already seen that we need a verb CHANGE. We'll make 
804 it really simple:
805
806 .. code-block:: inform
807
808   [ ChangeSub;
809       if (noun has pluralname) print "They're";
810       else                     print "That's";
811       " not something you must change to save the day.";
812   ];
813
814   Verb 'change' 'exchange' 'swap' 'swop'
815       * noun                     -> Change;
816
817 Just notice how the verb handler checks whether the noun given is plural 
818 or singular, to display a suitable pronoun.
819
820 A further detail: when players are in the café, they might ask Benny for 
821 the coffee (as we intend and heavily hint), for a sandwich or a pastry 
822 (both mentioned in the café description), for food or a snack (mentioned 
823 here and there, and we have provided for those); but what if they try a 
824 meat pie? Or scrambled eggs? There’s just so much decoration one can 
825 reasonably insert in a game, and loading the dictionary with Benny’s 
826 full menu would be overdoing it a bit.
827
828 One might reasonably imagine that the ``default`` line at the end of the 
829 ``Give`` action in the orders property handles every input not already 
830 specified:
831
832 .. code-block:: inform
833
834   orders [;
835     Give:
836       switch (noun) {
837         toilet_key:  ! code for the key...
838         coffee:      ! code for the coffee...
839         food:        ! code for the food...
840         menu:        ! code for the menu...
841         default:
842           "~I don't think that's on the menu, sir.~";
843       }
844   ],
845
846 Not so. The library grammar that deals with ASK BENNY FOR... is this
847 (specifically, the last line):
848
849 .. code-block:: inform
850
851   Verb 'ask'
852       * creature 'about' topic    -> Ask
853       * creature 'for' noun       -> AskFor
854
855 You'll see the :var:`noun` token, which means that whatever the player asks 
856 him for must be a real game object, visible at that moment. Assuming 
857 that the player mentions such an object, the interpreter finds it in the 
858 dictionary and places its internal ID in the :var:`noun` variable, where 
859 our ``switch`` statement can handle it. So, ASK BENNY FOR KEY assigns 
860 the ``toilet_key`` object to the noun variable, and Benny responds. ASK 
861 BENNY FOR CUSTOMERS also works; the ``default`` case picks that one up. 
862 But, ASK BENNY FOR SPAGHETTI BOLOGNESE won't work: we have no object for 
863 Spaghetti Bolognese (or any other delicacy from Benny's kitchen) -- the 
864 words ``'spaghetti'`` and ``'bolognese'`` simply aren't in the 
865 dictionary. This is perhaps not a major deficiency in our game, but it 
866 takes very little to allow Benny to use his default line for *any* 
867 undefined input from the player. We need to extend the existing ASK 
868 grammar:
869
870 .. code-block:: inform
871
872   Extend 'ask'
873       * creature 'for' topic    -> AskFor;
874
875 This line will be added to the end of the existing grammar for Ask, so 
876 it doesn’t override the conventional noun-matching line. ``topic`` is a 
877 token that roughly means “any input at all”; the value of noun isn't 
878 important, because it'll be handled by the default case. Now players may 
879 ask Benny for a tuna sandwich or a good time; they'll get: "I don’t 
880 think that’s on the menu, sir", which makes Benny a barman with 
881 attitude.
882
883 And that's it; on the slightly surreal note of ASK BENNY FOR A GOOD TIME 
884 we've taken "Captain Fate" as far as we intend to. The guide is nearly 
885 done. All that's left is to recap some of the more important issues, 
886 talk a little more about compilation and debugging, and send you off 
887 into the big wide world of IF authorship.
888
889
890 .. rubric:: Footnotes
891
892 .. [#dark]
893
894   We're alluding here to the Classical concept of mimesis. In an 
895   oft-quoted essay from 1996, Roger Giner-Sorolla wrote: "I see 
896   successful fiction as an imitation or 'mimesis' of reality, be it 
897   this world's or an alternate world's. Well-written fiction leads the 
898   reader to temporarily enter and believe in the reality of that world. 
899   A crime against mimesis is any aspect of an IF game that breaks the 
900   coherence of its fictional world as a representation of reality."
901