1 ===========================
2 Captain Fate: the final cut
3 ===========================
7 | *Y was a youth, that did not love school;*
8 | *Z was a zany, a poor harmless fool.*
12 .. image:: /images/picY.png
19 ou'll probably be pleased to hear that Captain Fate has almost run his
20 allotted span. There are some minor objects still to be defined -- the
21 toilet, our hero’s clothes, the all-important costume -- but first we
22 need to decorate the café a little more.
24 Additional catering garnish
25 ===========================
27 We must not forget a couple of tiny details in the café room:
29 .. code-block:: inform6
31 Object food "Benny's snacks" cafe
32 with name 'food' 'pastry' 'pastries' 'sandwich' 'sandwiches' 'snack'
33 before [; "There is no time for FOOD right now."; ],
36 Object menu "menu" cafe
37 with name 'informative' 'menu' 'board' 'picture' 'writing',
39 "The menu board lists Benny's food and drinks, along with their
40 prices. Too bad you've never learnt how to read, but luckily
41 there is a picture of a big cup of coffee among the
42 incomprehensible writing.",
45 "The board is mounted on the wall behind Benny. Besides, it's
50 And a not-so-trivial object:
52 .. code-block:: inform6
54 Object coffee "cup of coffee" benny
55 with name 'cup' 'of' 'coffee' 'steaming' 'cappuccino'
56 'cappucino' 'capuccino' 'capucino',
59 "The picture on the menu board SURE looks good.";
61 "It smells delicious.";
65 if (self in benny) "You should ask Benny for one first.";
68 print "You pick up the cup and swallow a mouthful. Benny's
69 WORLDWIDE REPUTATION is well deserved. Just as you
70 finish, Benny takes away the empty cup.";
71 if (benny.coffee_not_paid == true)
72 " ~That will be one quidbuck, sir.~";
77 if (coin in player) <<Give coin benny>>;
78 else "You have no money.";
80 "If your HYPERACTIVE pituitary glands are to be trusted,
84 There's nothing really new in this object (other than that the ``name``
85 property caters for orthographically challenged players), but notice how
86 we don't ``remove`` it after the player drinks it. In an apparently
87 absurd whim, the coffee returns to Benny magically (although this is not
88 information that the player needs to know). Why? After you remove an
89 object from the game, if the player attempts, say, to EXAMINE it, the
90 interpreter will impertinently state that "You can't see any such
91 thing". Moreover, if the player asks Benny for a second coffee, once the
92 first one has been removed, Benny will complain "I don’t think that’s on
93 the menu, sir" -- a blatant lie -- which was the default in Benny’s
94 orders property. Since the removed coffee object does not belong to
95 Benny, it's not a noun that the player can ASK Benny FOR. By making it a
96 child of the barman (who has the ``transparent`` attribute set), the
97 coffee is still an object that players can refer to. We ensure that they
98 don't get more cups thanks to Benny's ``coffee_asked_for property``,
99 which will remain ``true`` after the first time.
101 We also ensure that Benny doesn't ask for money from players who have
102 already paid, by first printing a "You pick up the cup..." message and
103 then testing Benny's ``coffee_not_paid`` property. If its value is
104 ``true``, we can finish the message with the "quidbuck" print-and-return
105 statement. If its value is ``false``, the player has previously paid,
106 and so there's nothing else to say. However, we still need to terminate
107 the incomplete message with a newline, and to return ``true`` from the
108 property routine; we *could* have used the statements ``{ print "^";
109 return true; }``, but an empty ``""`` statement does the same thing more
113 Toilet or dressing room?
114 ========================
116 Rather more of the latter, actually, since it's the only place away from
117 curious eyes where our hero will be able to metamorphose from weakling
118 into the bane of all evildoers. And we *really* don't want to become,
119 erm, bogged down with details of the room's function or plumbing.
121 There's not a lot about the toilet room and its contents, though there
122 will be some tricky side effects:
124 .. code-block:: inform6
126 Room toilet "Unisex toilet"
128 "A surprisingly CLEAN square room covered with glazed-ceramic
129 tiles, featuring little more than a lavatory and a light switch.
130 The only exit is south, through the door and into the cafe.",
134 Appliance lavatory "lavatory" toilet
135 with name 'lavatory' 'wc' 'toilet' 'loo' 'bowl' 'can' 'john' 'bog',
137 Examine,Search,LookUnder:
139 move coin to parent(self);
140 "The latest user CIVILLY flushed it after use, but failed to
141 pick up the VALUABLE coin that fell from his pants.";
144 "While any other MORTALS might unwittingly throw just about
145 ANYTHING into ", (the) self, ", you remember the WISE teachings
146 of your mentor, Duke ELEGANT, about elderly plumbing and rising
150 Object coin "valuable coin" lavatory
151 with name 'valuable' 'coin' 'silver' 'quidbuck',
152 description "It's a genuine SILVER QUIDBUCK.",
155 if (self notin player) return false;
156 "Such a valuable coin? Har, har! This must be a demonstration of
157 your ULTRA-FLIPPANT jesting!";
161 "You crouch into the SLEEPING DRAGON position and deftly, with
162 PARAMOUNT STEALTH, you pocket the lost coin.";
166 We initially place the coin as a child of the lavatory (just so that we
167 can easily make the ``if (coin in self)`` one-time test). Since the
168 lavatory does not have the ``transparent`` attribute set, the coin will
169 be invisible to players until they try to inspect the lavatory, an
170 action that will move the coin into the toilet room. Once taken, the
171 coin will remain in the inventory until the player gives it to Benny,
172 because we trap any ``Drop`` actions to help the player to Do the Right
175 The lavatory object includes a load of helpful synonyms in its name
176 property, including our favourite word ``'toilet'`` . That won't be a
177 problem: the other objects here which may have TOILET in their names --
178 the key and the door -- both use the ``pname`` property to turn their
179 use of ``'toilet'`` into a lower-priority adjective.
181 See that here we have the only two ``scored`` attributes of the game.
182 The player will be awarded one point for entering the toilet room, and
183 another for finding and picking up the coin.
185 You might have noticed that we are forcefully clearing the ``light``
186 attribute, inherited from the ``Room`` class. This will be a windowless
187 space and, to add a touch of realism, we'll make the room a dark one,
188 which will enable us to tell you about Inform's default behaviour when
189 there's no light to see by. However, let's define first the light switch
190 mentioned in the room's description to aid players in their dressing
193 .. code-block:: inform6
195 Appliance light_switch "light switch" toilet
196 with name 'light' 'switch',
198 "A notorious ACHIEVEMENT of technological SCIENCE, elegant yet
202 if (self has on) <<SwitchOff self>>;
203 else <<SwitchOn self>>;
208 "You turn on the light in the toilet.";
211 "You turn off the light in the toilet.";
215 Please notice the appearance of new attributes ``switchable`` and
216 ``on``. switchable enables the object to be turned on and off, and is
217 typical of lanterns, computers, television sets, radios, and so on. The
218 library automatically extends the description of these objects by
219 indicating if they are currently on or off::
222 A notorious ACHIEVEMENT of technological SCIENCE, elegant yet EASY to use.
223 The light switch is currently switched on.
225 Two new actions are ready to use, ``SwitchOn`` and ``SwitchOff``. Left
226 to themselves, they toggle the object's state between ON and OFF and
227 display a message like::
229 You switch the brass lantern on.
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 ``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
238 .. code-block:: inform6
244 and check if a ``switchable`` object is on or off with the test:
246 .. code-block:: inform6
248 if (light_switch has on) ...
250 if (light_switch hasnt on) ...
252 A ``switchable`` object is OFF by default. However, you’ll notice that
253 the has line of the object definition includes ``~on`` :
255 .. code-block:: inform6
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?
262 .. code-block:: inform6
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.
272 Let’s see how our light switch works. We trap the ``SwitchOn`` and
273 ``SwitchOff`` actions in the ``after`` property (when the switching has
274 successfully taken place) and use them to give ``light`` to the light
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 ``light`` attribute set. It doesn't have to be the room
281 itself (though this is usually convenient).
283 After setting the ``light`` attribute, we display a customised message,
284 to avoid the default::
286 You switch the light switch on.
288 which, given the name of the object, doesn't read very elegantly. We
289 foresee that players might try to PUSH SWITCH, so we trap this attempt
290 in a ``before`` property and redirect it to ``SwitchOn`` and
291 ``SwitchOff`` actions, checking first which one is needed by testing the
292 ``on`` attribute. Finally, we have made the switch a member of the class
293 ``Appliance``, so that the player doesn't walk away with it.
297 remember what we said about class inheritance? No matter what you
298 define in the class, the object’s definition has priority. The class
299 ``Appliance`` defines a response for the ``Push`` action, but we
300 override it here with a new behaviour.
306 So the player walks into the toilet and
308 .. code-block:: transcript
311 It is pitch dark, and you can't see a thing.
313 Oops! No toilet description, no mention of the light switch, nothing. It
314 is reasonable to think that if we have opened the toilet door to access
315 the toilet, some light coming from the café room will illuminate our
316 surroundings -- at least until the player decides to close the door. So
317 perhaps it would be a good idea to append a little code to the door
318 object to account for this. A couple of lines in the after property will
321 .. code-block:: inform6
325 if (self has locked) return false;
326 print "You unlock ", (the) self, " and open it.^";
327 ks = keep_silent; keep_silent = true;
328 <Open self>; keep_silent = ks;
337 And this is the reason why the light switch didn't set the ``light``
338 attribute of the toilet room, but did it to itself. We avoid running
339 into trouble if we let the open/closed states of the door control the
340 light of the room object, and the on/off states of the switch control
341 the light of the switch. So it is one shiny light switch. Fortunately,
342 players are never aware of this glowing artefact.
346 now, could they? Well, if players could TAKE the light switch (which
347 we have forbidden) and then did INVENTORY, the trick would be given
348 away, because all objects with the ``light`` attribute set are listed
349 as ``(providing light)`` .
351 So the player walks into the toilet and
353 .. code-block:: transcript
356 A surprisingly CLEAN square room covered with glazed-ceramic tiles, featuring
357 little more than a lavatory and a light switch. The only exit is south, through
358 the door and into the cafe.
360 [Your score has just gone up by one point.]
362 Better. Now, suppose the player closes the door.
364 .. code-block:: transcript
367 You close the door to the cafe.
369 It is now pitch dark in here!
371 The player might try then to LOOK:
373 Well, no problem. We have mentioned that there is a light switch. Surely
374 the player will now try to:
376 .. code-block:: transcript
378 >TURN ON LIGHT SWITCH
379 You can't see any such thing.
381 Oops! Things are getting nasty here in the dark. It's probably time to
382 leave this place and try another approach:
384 .. code-block:: transcript
387 You can't see any such thing.
389 And this illustrates one of the terrible things about darkness in a
390 game. You can't see anything; you can do very little indeed. All objects
391 except those in your inventory are out of scope, unreachable, as if
392 non-existent. Worse, if you DROP one of the objects you are carrying, it
393 will be swallowed by the dark, never to be found until there is light to
396 The player, who is doubtless immersed in the fantasy of the game, will
397 now be a little annoyed. "I am in a small bathroom and I can't even
398 reach the door I have just closed?" The player's right, of
399 course [#dark]_. Darkened rooms are one cliché of traditional games.
400 Usually you move in one direction while looking for treasure in some
401 underground cave, and suddenly arrive at a pitch black place. It's good
402 behaviour of the game to disallow exploration of unknown dark territory,
403 and it's a convention to bar passage to players until they return with a
404 light source. However, if the scenario of the game features, say, the
405 player character's home, a little apartment with two rooms, and there’s
406 no light in the kitchen, we could expect the owner of the house to know
407 how to move around a little, perhaps groping for the light switch or
408 even going to the refrigerator in the dark.
410 We are in a similar situation. The inner logic of the game demands that
411 blind players should be able to open the door and probably operate the
412 light switch they've just encountered. We have been telling you that an
413 object is in scope when it’s in the same room as the player. Darkness
414 changes that rule. All objects not directly carried by the player become
417 One of the advantages of an advanced design system like Inform is the
418 flexibility to change all default behaviours to suit your particular
419 needs. Scope problems are no different. There is a set of routines and
420 functions to tamper with what's in scope when. We'll see just a tiny
421 example to fix our particular problem. In the section "``Entry point
422 routines``" of our game -- after the ``Initialise`` routine, for
423 instance -- include the following lines:
425 .. code-block:: inform6
428 if (person == player && location == thedark && real_location == toilet) {
429 PlaceInScope(light_switch);
430 PlaceInScope(toilet_door);
435 ``InScope(actor_obj_id)`` is an entry point routine that can tamper with
436 the scope rules for the given ``actor_obj_id`` (either the player
437 character or a NPC). We define it with one variable (which we name as we
438 please; it's also a good idea to name variables in an intuitive way to
439 remind us of what they represent), ``person`` , and then we make a
440 complex test to see if the player is actually in the toilet and in the
443 We have told you that the library variable ``location`` holds the
445 room that the player is in. However, when there is no light, the
446 variable location gets assigned to the value of the special library
447 object thedark . It doesn't matter if we have ten dark rooms in our
448 game; location will be equal to thedark in all of them. There is yet
449 another variable, called ``real_location``, which holds the room the
450 player is in *even when there is no light to see by*.
454 .. code-block:: inform6
456 if (person == player && location == thedark && real_location == toilet) ...
458 is stating: if the specified actor is the ``player`` character *and* he
459 finds himself in the dark *and* he actually happens to be in the
462 Then we make a call to one of the library routines,
463 ``PlaceInScope(obj_id)``, which has a very descriptive name: it places
464 in scope the given object. In our case, we want both the door and the
465 light switch to be within reach of the player, hence both additional
466 lines. Finally, we must ``return false``, because we want the normal
467 scope rules for the defined actor -- the player -- to apply to the rest
468 of the objects of the game (if we returned ``true``, players would find
469 that they are able to interact with very little indeed). Now we get a
470 friendlier and more logical response:
472 .. code-block:: transcript
475 It is pitch dark, and you can't see a thing.
478 You turn on the light in the toilet.
481 A surprisingly CLEAN square room covered with glazed-ceramic tiles, featuring
482 little more than a lavatory and a light switch. The only exit is south, through
483 the door and into the cafe.
485 And the same would happen with the door. Notice how the room description
486 gets displayed after we pass from dark to light; this is the normal
489 There is still one final problem which, admittedly, might originate from
490 an improbable course of action; however, it could be a nuisance. Suppose
491 that the player enters the toilet, locks the door -- which is possible
492 in the dark now that the door is in scope -- and then drops the key.
493 There's no way to exit the toilet -- because the door is locked and the
494 key has disappeared, engulfed by the darkness -- unless the player
495 thinks to turn on the light switch, thereby placing the key in scope
498 Why don't we add a ``PlaceInScope(toilet_key)`` to the above routine?
499 Well, for starters, the key can be moved around (as opposed to the door
500 or the light switch, which are fixed items in the toilet room). Suppose
501 the player opens the door of the toilet, but drops the key in the café,
502 then enters the toilet and closes the door. The condition is met and the
503 key is placed in scope, when it's in another room. Second, this is a
504 simple game with just a few objects, so you can define a rule for each
505 of them; but in any large game, you might like to be able to refer to
506 objects in bunches, and make general rules that apply to all (or some)
509 We need to add code to the ``InScope`` routine, telling the game to
510 place in scope all objects that we drop in the dark, so that we might
511 recover them (maybe going on all fours and groping a little, but it’s a
512 possible action). We don’t want the player to have other objects in
513 scope (like the coin, for instance), so it might be good to have a way
514 of testing if the objects have been touched and carried by the player.
515 The attribute ``moved`` is perfect for this. The library sets it for
516 every object that the player has picked up at one time in the game;
517 ``scenery`` and ``static`` objects, and those we have not yet seen don't
518 have ``moved``. Here is the reworked ``InScope`` routine. There are a
519 couple of new concepts to look at:
521 .. code-block:: inform6
523 [ InScope person item;
524 if (person == player && location == thedark && real_location == toilet) {
525 PlaceInScope(light_switch);
526 PlaceInScope(toilet_door);
528 if (person == player && location == thedark)
529 objectloop (item in parent(player))
530 if (item has moved) PlaceInScope(item);
534 We have added one more local variable to the routine, ``item`` -- again,
535 this is a variable we have created and named on our own; it is not part
536 of the library. We make now a new test: if the actor is the player and
537 the location is any dark room, then perform a certain action. We don't
538 need to specify the toilet, because we want this rule to apply to all
539 dark rooms (well, the only dark room in the game *is* the toilet, but we
540 are trying to provide a general rule).
544 Lots of italicized typewriter stuff here...
546 .. code-block:: inform6
548 objectloop (variable) statement;
550 is a loop statement, one of the four defined in Inform. A loop statement
551 is a construct that allows you to run several times through a statement
552 (or a statement block). ``objectloop`` performs the ``statement`` once
553 for every object defined in the (``variable``) . If we were to code:
555 .. code-block:: inform6
557 objectloop (item) statement;
559 then the ``statement`` would be executed once for each object in the
560 game. However, we want to perform the statement only for those objects
561 whose parent object is the same as the player's parent object: that is,
562 for objects in the same room as the player, so we instead code:
564 .. code-block:: inform6
566 objectloop (item in parent(player)) statement;
568 What is the actual ``statement`` that we'll repeatedly execute?
570 .. code-block:: inform6
575 The test: ``if (item has moved)`` ensures that ``PlaceInScope(item)``
576 deals only with objects with the ``moved`` attribute set. So: if the
577 player is in the dark, let’s go through the objects which are in the
578 same room, one at a time. For each of them, check if it's an item that
579 the player has at some time carried, in which case, place it in scope.
580 All dropped objects within the room were carried at one time, so we let
581 players recollect them even if they can’t see them.
583 As you see, darkness has its delicate side. If you plan to have dark
584 rooms galore in your games, bear in mind that you are in for some
585 elaborate code (unless you let the library carry on with default rules,
586 in which case there won't be much for your players to do).
589 Amazing techicolour dreamcoats
590 ==============================
592 This leaves us the clothing items themselves, which will require a few
593 tailored actions. Let's see first the ordinary garments of John Covarth:
595 .. code-block:: inform6
597 Object clothes "your clothes"
598 with name 'ordinary' 'street' 'clothes' 'clothing',
600 "Perfectly ORDINARY-LOOKING street clothes for a NOBODY like
605 "You are already dressed as John Covarth.";
607 "The town NEEDS the power of Captain FATE, not the anonymity
611 "Your KEEN eye detects that you're no longer wearing them.";
615 "Lacking Superman's super-speed, you realise that it
616 would be awkward to change in plain view of the passing
619 "In the middle of the street? That would be a PUBLIC
620 SCANDAL, to say nothing of revealing your secret
623 "Benny allows no monkey business in his establishment.";
625 if (toilet_door has open)
626 "The door to the bar stands OPEN at tens of curious eyes.
627 You'd be forced to arrest yourself for LEWD conduct.";
628 print "You quickly remove your street clothes and bundle them
629 up together into an INFRA MINUSCULE pack ready for easy
631 if (toilet_door has locked) {
632 give clothes ~worn; give costume worn;
633 "Then you unfold your INVULNERABLE-COTTON costume and
634 turn into Captain FATE, defender of free will, adversary
639 "Just as you are slipping into Captain FATE's costume,
640 the door opens and a young woman enters. She looks at
641 you and starts screaming, ~RAPIST! NAKED RAPIST IN THE
643 Everybody in the cafe quickly comes to the rescue, only
644 to find you ridiculously jumping on one leg while trying
645 to get dressed. Their laughter brings a QUICK END to
646 your crime-fighting career!";
649 "Last time you changed in the dark, you wore the suit inside
651 default: ! this _should_ never happen...
652 "There must be better places to change your clothes!";
655 clothing proper pluralname;
657 See how the object deals only with ``Wear``, ``Disrobe`` and ``Change``.
658 ``Wear`` and ``Disrobe`` are standard library actions already defined in
659 Inform, but we'll have to make a new verb to allow for CHANGE CLOTHES.
660 In this game, ``Disrobe`` and ``Change`` are considered synonymous for
661 all purposes; we'll deal with them first.
663 The goal of the game is for players to change their clothes, so we might
664 expect them to try this almost anywhere; but first of all we have to
665 check that the ``clothes`` object is actually being worn. If not, we
666 display a message reminding the player that this action has become
667 irrelevant. What we do with the ``switch`` statement is to offer a
668 variety of responses according to the ``location`` variable. The street
669 (in or out of the booth) and the café all display refusals of some kind,
670 until the player character manages to enter the toilet, where we
671 additionally require that he locks the door before taking off his
672 clothes. If the door is closed but not locked, he is interrupted in his
673 naked state by a nervous woman who starts shouting, and the game is lost
674 (this is not as unfair as it seems, because the player may always revert
675 to the previous state with UNDO). If the door is locked, he succeeds in
676 his transformation (we take away the ``worn`` attribute from the
677 ``clothes`` and give it to the ``costume`` instead). We add a special
678 refusal to change in the dark, forcing players to turn on the light and
679 then, we hope, to find the coin. And finally we code a ``default``
680 entry; you'll remember that, in a ``switch`` statement, this is supposed
681 to cater for any value not explicitly listed for the expression under
682 control -- in this case, for the variable ``location``. Since we have
683 already gone through all the possible locations of the game, this entry
684 appears only as a defensive measure, just in case something unexpected
685 happens (for instance, we might extend the game with another room and
686 forget about this ``switch`` statement). In normal and controlled
687 conditions, it should never be reached, but it doesn't hurt one bit to
690 The ``Wear`` action just checks if these clothes are already being worn,
691 to offer two different rejection responses: the goal of the game is to
692 change into the hero's suit, after which we'll prevent a change back
693 into ordinary clothes. So now we are dealing with a Captain Fate in full
696 .. code-block:: inform6
698 Object costume "your costume"
699 with name 'captain' 'captain^s' 'fate' 'fate^s' 'costume' 'suit',
701 "STATE OF THE ART manufacture, from chemically reinforced 100%
706 "You are already dressed as Captain FATE.";
708 "First you'd have to take off your commonplace unassuming
709 John Covarth INCOGNITO street clothes.";
712 "You need to wear your costume to FIGHT crime!";
714 "But you're not yet wearing it!";
716 "Your UNIQUE Captain FATE multi-coloured costume? The most
717 coveted clothing ITEM in the whole city? Certainly NOT!";
721 Note that we intercept the action WEAR COSTUME and hint that players
722 should try TAKE OFF CLOTHES instead. We don't let them take off the
723 costume once it’s being worn, and we certainly don't let them misplace
724 it anywhere, by refusing to accept a ``Drop`` action.
730 Nearly there; just a few minor odds and ends to round things off.
732 .. rubric:: Initialise routine
734 All the objects of our game are defined. Now we must add a couple of
735 lines to the ``Initialise`` routine to make sure that the player does
736 not start the game naked:
741 .. rubric:: Footnotes
745 We're alluding here to the Classical concept of mimesis. In an
746 oft-quoted essay from 1996, Roger Giner-Sorolla wrote: "I see
747 successful fiction as an imitation or 'mimesis' of reality, be it
748 this world's or an alternate world's. Well-written fiction leads the
749 reader to temporarily enter and believe in the reality of that world.
750 A crime against mimesis is any aspect of an IF game that breaks the
751 coherence of its fictional world as a representation of reality."
753 .. code-block:: inform6
756 #Ifdef DEBUG; pname_verify(); #Endif; ! suggested by pname.h
758 move costume to player;
759 move clothes to play; give clothes worn;
761 "^^Impersonating mild mannered John Covarth, assistant help boy at an
762 insignificant drugstore, you suddenly STOP when your acute hearing
763 deciphers a stray radio call from the POLICE. There's some MADMAN
764 attacking the population in Granary Park! You must change into your
765 Captain FATE costume fast...!^^";
768 Remember that we included a disambiguation package, ``pname.h``? There
769 were some additional comments in the accompanying text file that should
770 be taken in consideration:
772 pname.h provides a pname_verify routine. When DEBUG is defined, you
773 may call pname_verify() in your Initialise() routine to verify the pname
774 properties in your objects.
776 The designer of the package has made a debugging tool (a routine) to
777 check for errors when using his library, and he tells us how to use it.
778 So we include the suggested lines into our ``Initialise`` routine:
780 .. code-block:: inform6
782 #Ifdef DEBUG; pname_verify(); #Endif;
784 As the text explains, what this does is: first check whether the game is
785 being compiled in Debug mode; if this is the case, run the
786 ``pname_verify`` routine, so that it tests all ``pname`` properties to
787 see if they are written correctly.
789 .. rubric:: Demise of our hero
791 We have made three possible endings:
793 #. The player attempts to change in the toilet with an unlocked door.
795 #. The player tries to attack Benny while wearing the costume.
797 #. The player manages to exit the café dressed as Captain Fate.
799 (1) and (2) lose the game, (3) wins it. The library defaults for these
800 two states display, respectively,
802 .. code-block:: transcript
804 *** You have died ***
808 These states correspond to the values of the ``deadflag`` variable: 1
809 for losing, 2 for winning. However, we have made up different messages,
810 because our hero does not really die -- ours suffers a FATE worse than
811 death -- and because we want to give him a more descriptive winning
812 line. Therefore, we must define a ``DeathMessage`` routine as we did in
813 "William Tell", to write our customised messages and assign them to
814 ``deadflag`` values greater than 2.
816 .. code-block:: inform6
819 if (deadflag == 3) print "Your secret identity has been revealed";
820 if (deadflag == 4) print "You have been SHAMEFULLY defeated";
821 if (deadflag == 5) print "You fly away to SAVE the DAY";
826 Finally, we need to extend the existing grammar, to allow for a couple
827 of things. We have already seen that we need a verb CHANGE. We'll make
830 .. code-block:: inform6
833 if (noun has pluralname) print "They're";
835 " not something you must change to save the day.";
838 Verb 'change' 'exchange' 'swap' 'swop'
841 Just notice how the verb handler checks whether the noun given is plural
842 or singular, to display a suitable pronoun.
844 A further detail: when players are in the café, they might ask Benny for
845 the coffee (as we intend and heavily hint), for a sandwich or a pastry
846 (both mentioned in the café description), for food or a snack (mentioned
847 here and there, and we have provided for those); but what if they try a
848 meat pie? Or scrambled eggs? There’s just so much decoration one can
849 reasonably insert in a game, and loading the dictionary with Benny’s
850 full menu would be overdoing it a bit.
852 One might reasonably imagine that the ``default`` line at the end of the
853 ``Give`` action in the orders property handles every input not already
856 .. code-block:: inform6
861 toilet_key: ! code for the key...
862 coffee: ! code for the coffee...
863 food: ! code for the food...
864 menu: ! code for the menu...
870 Not so. The library grammar that deals with ASK BENNY FOR... is this
871 (specifically, the last line):
873 .. code-block:: inform6
876 * creature 'about' topic -> Ask
877 * creature 'for' noun -> AskFor
879 You'll see the ``noun`` token, which means that whatever the player asks
880 him for must be a real game object, visible at that moment. Assuming
881 that the player mentions such an object, the interpreter finds it in the
882 dictionary and places its internal ID in the ``noun`` variable, where
883 our ``switch`` statement can handle it. So, ASK BENNY FOR KEY assigns
884 the ``toilet_key`` object to the noun variable, and Benny responds. ASK
885 BENNY FOR CUSTOMERS also works; the ``default`` case picks that one up.
886 But, ASK BENNY FOR SPAGHETTI BOLOGNESE won't work: we have no object for
887 Spaghetti Bolognese (or any other delicacy from Benny's kitchen) -- the
888 words ``'spaghetti'`` and ``'bolognese'`` simply aren't in the
889 dictionary. This is perhaps not a major deficiency in our game, but it
890 takes very little to allow Benny to use his default line for *any*
891 undefined input from the player. We need to extend the existing ASK
894 .. code-block:: inform6
897 * creature 'for' topic -> AskFor;
899 This line will be added to the end of the existing grammar for Ask, so
900 it doesn’t override the conventional noun-matching line. ``topic`` is a
901 token that roughly means “any input at all”; the value of noun isn't
902 important, because it'll be handled by the default case. Now players may
903 ask Benny for a tuna sandwich or a good time; they'll get: "I don’t
904 think that’s on the menu, sir", which makes Benny a barman with
907 And that's it; on the slightly surreal note of ASK BENNY FOR A GOOD TIME
908 we've taken "Captain Fate" as far as we intend to. The guide is nearly
909 done. All that's left is to recap some of the more important issues,
910 talk a little more about compilation and debugging, and send you off
911 into the big wide world of IF authorship.