Added Chapter 11.
[ibg.git] / chapters / 11.rst
1 ====================
2 Captain Fate: take 2
3 ====================
4
5 .. epigraph::
6
7    | *U was a usurer, a miserable elf;*
8    | *V was a vintner, who drank all himself.*
9
10 .. only:: html
11
12    .. image:: /images/picV.png
13       :align: left
14
15 .. raw:: latex
16
17    \dropcap{v}
18
19 iewed from the inside, Benny's café is warm and welcoming, and packed 
20 with lunchtime customers. We'll try to conjure up some appropriate 
21 images, but the main focus of the room isn't the decor: it's the door 
22 leading to the toilet -- and, perhaps, privacy?
23
24 A homely atmosphere
25 ===================
26
27 Benny's café is populated with customers enjoying their lunch, so it 
28 won't be a good place to change identities. However, the toilet to the 
29 north looks promising, though Benny has strict rules about its use and 
30 the door seems to be locked.
31
32 .. admonition:: Cultural Note
33    :class: admonition note
34
35    not for the first time, this guide betrays its origins. In
36    European countries the word "toilet" often refers not only to the 
37    white porcelain artefact, but also to the room in which it can be 
38    found (also, a "bathroom" is for taking a bath, a "restroom" for 
39    taking a rest). Bear with us on this; the dual usage becomes 
40    important a little later on.
41
42 We define the café room in simple form:
43
44 .. code-block:: inform6
45
46   Room    cafe "Inside Benny's cafe"
47     with  description
48           "Benny's offers the FINEST selection of pastries and
49            sandwiches. Customers clog the counter, where Benny himself
50            manages to serve, cook and charge without missing a step. At
51            the north side of the cafe you can see a red door connecting
52            with the toilet.",
53           s_to street,
54           n_to toilet_door;
55
56 We'll elaborate on the last line (``n_to toilet_door``) later, when we 
57 define the door object which lies between the café and the toilet.
58
59 We've mentioned a counter:
60
61 .. code-block:: inform6
62
63   Appliance counter "counter" cafe
64     with name 'counter' 'bar',
65          article "the",
66          description
67              "The counter is made of an astonishing ALLOY of metals,
68               STAIN-PROOF, SPILL-RESISTANT and VERY EASY to clean. Customers
69               enjoy their snacks with UTTER tranquillity, safe in the notion
70               that the counter can take it all.",
71          before [;
72            Receive:
73              <<Give noun benny>>;
74          ],
75     has  supporter;
76
77 That ``before property``, superficially normal, actually conceals a 
78 little surprise. By now you should be entirely comfortable with using an 
79 object's ``before`` property to intercept an action directed at that 
80 object; for example, if the player types HIT COUNTER then the counter's 
81 ``before`` property is potentially able to intercept the resulting 
82 Attack action. However, the command PUT KEY ON COUNTER generates *two* 
83 actions. First, a PutOn action is offered to the key (effectively 
84 saying, do you want to be placed on top of the counter?); that’s the 
85 normal bit. And then the surprise: a Receive action is offered to the 
86 counter (effectively saying, are you happy to have the key placed on 
87 you?) Both actions have the same opportunity of returning ``false`` to 
88 let the action continue, ``true`` to prevent it.
89
90 .. todo::
91
92   There are a lot of actions here that are rendered in a typewriter font
93   and others that are not.  Should these ones that are not be promoted 
94   to having a typewriter font?
95
96 The Receive action is generated by the library in the PutOnSub action 
97 handler, and also in InsertSub (so a command like PUT BIRD IN NEST sends 
98 a Receive to the nest object). There’s a matching LetGo, generated by 
99 the library from commands like TAKE KEY OFF COUNTER and REMOVE BIRD FROM 
100 NEST. Receive and LetGo are examples of what’s called a **fake action**.
101
102 .. note::
103
104   in "William Tell" we defined the ``quiver``, way back in "The 
105   player's possessions" on page 83, as an ``open container``. As things 
106   stand, the player can put *any* held object, however inappropriate, 
107   into it. We could have trapped the Receive action to ensure that 
108   arrows are the only acceptable contents (recollect that ``~~``, to be 
109   read as "not", turns true into false and vice versa):
110
111   .. code-block:: inform6
112
113     before [;
114       Drop,Give:
115         print_ret "But it was a present from Hedwig, your wife.";
116       Receive:
117         if (~~(noun ofclass Arrow))
118             print_ret "Only arrows -- clean arrows -- go in your quiver.";
119     ],
120
121 Here, we intercept any attempt to place an item on the counter, and 
122 translate it into an attempt to give that item to Benny. Part of the 
123 game's plot depends on the player returning the toilet key to Benny, and 
124 also paying him for his delicious cup of world-famous Cappuccino. 
125 Putting the key and the money on the counter is a reasonable alternative 
126 way for the player to accomplish this.
127
128 We've also mentioned some customers. These are treated as NPCs, reacting 
129 to our hero’s performance.
130
131 .. code-block:: inform6
132
133   Object  customers "customers" cafe
134     with  name 'customers' 'people' 'customer' 'men' 'women',
135           description [;
136               if (costume has worn)
137                   "Most seem to be concentrating on their food, but some do
138                    look at you quite blatantly. Must be the MIND-BEFUDDLING
139                    colours of your costume.";
140               else
141                   "A group of HELPLESS and UNSUSPECTING mortals, the kind
142                    Captain FATE swore to DEFEND the day his parents choked on a
143                    DEVIOUS slice of RASPBERRY PIE.";
144           ],
145           life [;
146             Ask,Tell,Answer:
147               if (costume has worn)
148                   "People seem to MISTRUST the look of your FABULOUS costume.";
149               else
150                   "As John Covarth, you attract LESS interest than Benny's
151                    food.";
152             Kiss:
153               "There's no telling what sorts of MUTANT bacteria these
154                STRANGERS may be carrying around.";
155             Attack:
156               "Mindless massacre of civilians is the qualification for
157                VILLAINS. You are SUPPOSED to protect the likes of these
158                people.";
159           ],
160           orders [;
161               "These people don't appear to be of the cooperative sort.";
162           ],
163           number_of_comments 0,          ! for counting the customer comments
164           daemon [;
165               if (location ~= cafe) return;
166               if (self.number_of_comments == 0) {
167                   self.number_of_comments = 1;
168                   print "^Nearby customers glance at your costume with open
169                       curiosity.^";
170               }
171               if (random(2) == 1) {       ! do this 50% of the time
172                   self.number_of_comments = self.number_of_comments + 1;
173                   switch (self.number_of_comments) {
174                    2: "^~Didn't know there was a circus in town,~ comments one
175                         customer to another. ~Seems like the clowns have the
176                         day off.~";
177                    3: "^~These fashion designers don't know what to do to show
178                         off,~ snorts a fat gentleman, looking your way. Those
179                         within earshot try to conceal their smiles.";
180                    4: "^~Must be carnival again,~ says a man to his wife, who
181                         giggles, stealing a peek at you. ~Time sure flies.~";
182                    5: "^~Bad thing about big towns~, comments someone to his
183                         table companion, ~is you get the damnedest bugs coming
184                         out from toilets.~";
185                    6: "^~I sure WISH I could go to work in my pyjamas,~ says a
186                         girl in an office suit to some colleagues. ~It looks SO
187                         comfortable.~";
188                    default: StopDaemon(self);
189                   }
190               }      
191           ],      
192     has   scenery animate pluralname;
193
194 Let's go step by step. Our hero enters the café dressed as John Covarth, 
195 but will eventually manage to change clothes in the toilet, and he'll 
196 have to cross back through the café to reach the street and win the 
197 game. The customers' ``description`` takes into consideration which 
198 outfit the player character is wearing.
199
200 In "William Tell" we’ve seen a brief manifestation of the ``life`` 
201 property, but here we'll extend it a little. As we explained, ``life`` 
202 lets you intercept those actions particular to animate objects. Here we 
203 trap ``Attack`` and ``Kiss`` to offer some customised messages for these 
204 actions when applied to the customers. Also, we avoid conversation by 
205 intercepting ``Ask``, ``Tell`` and ``Answer`` in order just to produce a 
206 message which depends on the player character's attire.
207
208 One other feature of ``animate`` objects is the possibility of giving 
209 them orders: BILL, SHAKE THE SPEAR or ANNIE, GET YOUR GUN . These 
210 actions are dealt with in the ``orders`` property and, as with the 
211 ``life`` property, the embedded routine can become quite complex if you 
212 want your NPCs to behave in an interesting way. In this case, we don't 
213 need the customers to perform tasks for us, so instead we provide a 
214 simple rejection message, just in case the player tries to order people 
215 around.
216
217 Which leaves us with the ``daemon`` bit. A daemon is a property normally 
218 used to perform some timed or repetitive action without the need of the 
219 player’s direct interaction; for example, machines which work by 
220 themselves, animals that move on their own, or people going about their 
221 business. More powerfully, a daemon may take notice of the player’s 
222 decisions at a particular moment, allowing for some interactive 
223 behaviour; this is, however, an advanced feature that we won't use in 
224 this example. A daemon gets a chance of doing something at the end of 
225 every turn, typically to (or with) the object to which it’s associated. 
226 In our example, the daemon triggers some sneers and nasty comments from 
227 the customers once our hero comes out of the toilet dressed in Captain 
228 Fate’s costume.
229
230 To code a daemon, you need to do three things:
231
232 #.  First, define a daemon property in the object’s body; the value of 
233     the property is always an embedded routine.
234
235 #.  However, daemons do nothing until you activate them. This is easily
236     achieved with the call ``StartDaemon(obj_id)``, which may happen 
237     anywhere (if you want some object's daemon to be active from the 
238     beginning of the game,you can make the call in your Initialise 
239     routine).
240
241 #.  Once the daemon has finished its mission (if ever) you may stop it 
242     with the call ``StopDaemon(obj_id)``.
243
244 How does our particular daemon work? The appearance of our hero in full 
245 crime-fighting wear will make the customers stare at him and make snarky 
246 remarks. This must happen in the café room – the place where the 
247 customers are -- so we need to make certain that the daemon does 
248 something interesting only while the player stays in the right place 
249 (and hasn’t wandered, say, back into the toilet):
250
251 .. code-block:: inform6
252
253   if (location ~= cafe) return;
254
255 So if the location is not the café room (remember ~= means "not equal 
256 to"), return without doing anything else; on this turn, there’s nothing 
257 for the daemon to do. We use a plain ``return`` statement because the 
258 value returned from a daemon doesn’t matter.
259
260 We have defined a customised local property, ``number_of_comments``, to 
261 control the sequence of customers' remarks. When the Captain enters the 
262 café room from the toilet for the first time, the value of the property 
263 should be zero, so the statement block under the test:
264
265 .. code-block:: inform6
266
267   if (self.number_of_comments == 0) {
268       self.number_of_comments = 1;
269       print "^Nearby customers glance at your costume with open
270           curiosity.^";
271   }
272
273 will happen only this once. What we intend is to output the text "Nearby 
274 customers..." right after the startling entrance of our hero, setting up 
275 the scene for the comments which are about to happen. Since we assign a 
276 value of 1 to the property, the message will not be printed again. 
277 Notice how we use an explicit ``print`` statement; the execution of the 
278 daemon will continue normally to the next line.
279
280 We want the customers to indulge in witticisms once they see the 
281 costumed Captain, but not on a completely predictable basis.
282
283 .. code-block:: inform6
284
285   if (random(2) == 1) ...
286
287 .. todo::
288
289    "expression" in "random(expression)" should be typewriter and italic
290
291 ``random`` is an Inform routine used to generate random numbers or to 
292 choose randomly between given choices; in the form 
293 ``random(expression)`` it returns a random number between 1 and 
294 ``expression`` inclusive. So our condition is actually stating: if a 
295 random choice between 1 and 2 happens to be 1 then perform some action. 
296 Remember that a daemon is run once at the end of every turn, so the 
297 condition is trying to squeeze a comment from a customer roughly once 
298 every other turn.
299
300 Next, we proceed as we have already seen in "William Tell", with a 
301 switch statement to order the comments in a controlled sequence by 
302 cunning use of our tailored local property, ``number_of_comments``. We 
303 have written just five messages (could have been one or a hundred) and 
304 then we reach the default case, which is a good place to stop the 
305 daemon, since we have no more customers’ remarks to display.
306
307 Ah, but when does the daemon *start* functioning? Well, as soon as our 
308 protagonist comes out of the toilet dressed in his multicoloured 
309 super-hero pyjamas. Since we want to minimise the possible game states, 
310 we’ll make some general rules to avoid trouble: (a) players will be able 
311 to change only in the toilet; (b) we won’t let players change back into 
312 street clothes; and (c) once players manage to step into the street thus 
313 dressed, the game is won. So, we can safely assume that if players enter 
314 the café in their Captain’s outfit, they’ll be coming from the toilet. 
315 As a consequence of all this, we add an ``after`` property to the café 
316 room object:
317
318 .. code-block:: inform6
319
320   Room   cafe "Inside Benny's cafe"
321          ...
322          first_time_out false,           ! Captain Fate's first appearance?
323          after [;
324            Go:   ! The player has just arrived. Did he come from the toilet?
325              if (noun ~= s_obj) return false;
326              if (costume has worn && self.first_time_out == false) {
327                  self.first_time_out = true;
328                  StartDaemon(customers);
329              }
330          ],
331          s_to  street,
332          n_to  toilet_door
333
334 There are two useful techniques to detect when the player is entering or 
335 leaving a room. We'll later see in detail how to deal with a player 
336 trying to go away and how to avoid it if need be. For now, let’s just 
337 mention that, in both cases, you have to intercept the ``Go`` action in 
338 a room object; if you trap it in a ``before`` property, you’re checking 
339 for departure from the room; if you trap it in an ``after`` property, 
340 you’re checking for arrivals into the room. Right now we wish to know if 
341 the player just came from the toilet, so we use an ``after`` property.
342
343 The first line:
344
345 .. code-block:: inform6
346
347   if (noun ~= s_obj) return false;
348
349 is telling the interpreter that we want to do something if the player 
350 entered the room by typing a GO SOUTH command (this would normally mean 
351 "coming from the north", but remember that nothing stops you from 
352 connecting rooms without cardinal logic); the interpreter will apply 
353 normal rules for the other available directions.
354
355 Then we check whether the player character is wearing the costume, in 
356 which case it starts the ``daemon`` of the ``customers`` object. The use 
357 of the local first_time_out property ensures that the condition is 
358 ``true`` only once, so the statement block attached to it runs also 
359 once.
360
361 We've finished with the customers in the café. Now, we have the toilet 
362 to the north which, for reasons of gameplay *and* decency, is protected 
363 by a door.
364
365 A door to adore
366 ===============
367
368 Door objects require some specific properties and attributes. Let's 
369 first code a simple door:
370
371 .. code-block:: inform6
372
373   Object  toilet_door "toilet door" cafe
374     name name 'red' 'toilet' 'door',
375          description
376              "A red door with the unequivocal black man-woman
377               silhouettes marking the entrance to hygienic facilities.
378               There is a scribbled note stuck on its surface.",
379          door_dir n_to,
380          door_to toilet,
381          with_key toilet_key,
382     has  scenery door openable lockable locked;
383
384 We find this door in the café. We must specify the direction in which 
385 the door leads and, as we have mentioned in the café's description, that 
386 would be to the north. That’s what the ``door_dir`` property is for, and 
387 in this case it takes the value of the north direction property 
388 ``n_to``. Then we must tell Inform the identity of the room to be found 
389 behind the door, hence the ``door_to`` property, which takes the value 
390 of the toilet room -- to be defined later. Remember the café's 
391 connection to the north, ``n_to toilet_door``? Thanks to it, Inform will 
392 know that the door is in the way, and thanks to the ``door_to`` 
393 property, what lies beyond.
394
395 Doors *must* have the attribute ``door``, but beyond that we have a 
396 stock of options to help us define exactly what kind of door we are 
397 dealing with. As for containers, doors can be ``openable`` (which 
398 activates the verbs OPEN and CLOSE so that they can be applied to this 
399 object) and, since by default they are closed, you can give them the 
400 attribute ``open`` if you wish otherwise. Additionally, doors can be 
401 ``lockable`` (which sets up the LOCK/UNLOCK verbs) and you can make them 
402 ``locked`` to override their default unlocked status. The verbs LOCK 
403 and UNLOCK are expecting some kind of key object to operate the door. 
404 This must be defined using the ``with_key`` property, whose value should 
405 be the internal ID of the key; in our example, the soon-to-be-defined 
406 ``toilet_key`` . If you don't supply this property, players won't be 
407 able to lock or unlock the door.
408
409 This simple door definition has one problem, namely, that it exists only 
410 in the café room. If you wish the door to be present also from the 
411 toilet side, you can either (a) define another door to be found in the 
412 ``toilet room``, or (b) make this one a two-sided door.
413
414 Solution (a) seems superficially straightforward, but then you have the 
415 problem of keeping the states of the two doors – open/closed, 
416 locked/unlocked -- in synch. In this scenario, where you can access the 
417 toilet only through this door, that wouldn't be too complicated, since 
418 you could leave the door object in the café room opened all the time, 
419 regardless of what players do with the door object in the toilet room 
420 and vice versa -- they are never going to see them at the same time. In 
421 general terms, though, such inconsistencies lead to problems; solution 
422 (a) is best ignored for most purposes.
423
424 Solution (b) is better, since you have only one door object to deal with 
425 and its possible states affect both sides. However, the coding gets a 
426 little bit complicated and you''ll have to define routines for most 
427 properties:
428
429 .. code-block:: inform6
430
431   Object  toilet_door "toilet door"
432     with  name 'red' 'toilet' 'door',
433           description [;
434               if (location == cafe)
435                    "A red door with the unequivocal black man-woman silhouettes
436                     marking the entrance to hygienic facilities. There is a
437                     scribbled note stuck on its surface.";
438               else
439                     "A red door with no OUTSTANDING features.";
440           ],
441           found_in cafe toilet,
442           door_dir [;
443               if (location == cafe) return n_to;
444               else                  return s_to;
445           ],
446           door_to [;
447               if (location == cafe) return toilet;
448               else                  return cafe;
449           ],
450           with_key toilet_key,
451     has   scenery door openable lockable locked;
452
453 First of all, the door now needs a ``found_in`` property, since it's 
454 going to be located both in the café and the toilet. The ``description`` 
455 checks which side of the door we are looking at – testing the current 
456 value of the variable ``location``, which holds the room the player is 
457 in -- because we have a scribbled note stuck on one side, but not on the 
458 other. And the ``door_dir`` and ``door_to`` properties must use the same 
459 trick, because we travel north from the café into the toilet, but south 
460 from the toilet into the café.
461
462 Right now, the game will display "the toilet door" every time it needs 
463 to refer to this object. It would be nice if we could somehow get the 
464 game to distinguish between "the door to the toilet" and "the door to 
465 the cafe", depending on the side we are facing. For this, a ``short_name 
466 property`` is the thing. We have already talked about the external name 
467 defined as part of an object's header information:
468
469 .. code-block:: inform6
470
471   Object  toilet_door "toilet door"
472
473 That ``toilet door`` will be the name displayed by the game at run-time 
474 to refer to the door. With identical effect, this could also have been 
475 coded thus:
476
477 .. code-block:: inform6
478
479   Object  toilet_door
480     with  short_name "toilet door",
481
482 ``short_name`` is a property that supplies the external name of an 
483 object, either as a string or an embedded routine. Normally, objects 
484 retain the same external name throughout the game -- and the header 
485 information method is perfect in that case -- but if it needs to change, 
486 it's easy to write a routine as the value of ``short_name``:
487
488 .. code-block:: inform6
489
490   Object  toilet_door
491     with  name 'red' 'toilet' 'door'
492           short_name [;
493               if (location == cafe) print "door to the toilet";
494               else                  print "door to the cafe";
495           ],
496           description
497               ...
498
499 Notice the ``return true`` at the end of the routine. You''ll recall 
500 that the standard rule says "return false to carry on, true to take over 
501 and stop normal execution”. In the case of ``short_name``, "carry on" 
502 means "and now display the external name from the header information", 
503 which is sometimes handy; for instance, you could write a ``short_name`` 
504 routine to prefix an object's external name with one of a range of 
505 adjectives -- perhaps a shining/flickering/fading/useless lantern.
506
507 .. note::
508
509   what's displayed if there isn't an external name in an object's 
510   header? If you've read the section "Compile-as-you-go" on page 233, 
511   you'll recall that the interpreter simply uses the internal 
512   identifier within parentheses; that is, with no external name and no 
513   ``short_name`` property, we might see:
514
515   .. code-block:: inform6
516
517     You open the (toilet_door).
518
519   And the same principle applies if we were mistakenly to ``return 
520   false`` from this short_name routine: we would get, first, the result 
521   of our ``print`` statement, and then the standard rules would display 
522   the internal ID:
523
524   .. code-block:: inform6
525
526     You open the door to the toilet(toilet_door).
527
528 Doors can get more complicated than this (no, please, don't throw our 
529 guide out of the window). Here comes some optional deluxe coding to make 
530 the door object a bit friendlier in game play, so you can skip it if you 
531 foresee headaches.
532
533 Our door now behaves nicely at run-time. It can be locked and unlocked 
534 if the player character has the right key; it can be opened and closed. 
535 A sequence of commands to go into the toilet and lock the door behind 
536 you would be: UNLOCK DOOR WITH KEY, OPEN DOOR, GO NORTH, CLOSE DOOR, 
537 LOCK DOOR WITH KEY. After we are finished, let's go back to the café: 
538 UNLOCK DOOR WITH KEY, OPEN DOOR, SOUTH. If the player is of the 
539 fastidious kind: CLOSE DOOR, LOCK DOOR WITH KEY. This game features only 
540 one door, but if it had three or four of them, players would grow 
541 restless (at the very least) if they needed to type so many commands 
542 just to go through a door. This is the kind of thing reportedly 
543 considered as poor design, because the game is suddenly slowed down to 
544 get over a simple action which involves no secrets or surprises. How 
545 exciting can the crossing of an ordinary door be, after all?
546
547 If a few lines of code can make the life of the player easier, it's 
548 worth a shot. Let's provide a few improvements to our toilet door in 
549 ``before`` and ``after`` properties:
550
551 .. code-block:: inform6
552
553   before [ ks;
554     Open:
555       if (self hasnt locked || toilet_key notin player)
556           return false;
557       ks = keep_silent; keep_silent = true;
558       <Unlock self toilet_key>; keep_silent = ks;
559       return true;
560     Lock:
561       if (self hasnt open) return false;
562       print "(first closing ", (the) self, ")^";
563       ks = keep_silent; keep_silent = true;
564       <Close self>; keep_silent = ks;
565       return false;
566     ],
567     after [ ks;
568       Unlock:
569         if (self has locked) return false;
570         print "You unlock ", (the) self, " and open it.^";
571         ks = keep_silent; keep_silent = true;
572         <Open self>; keep_silent = ks;
573         return true;
574     ],
575
576 The basic idea here is to let the player who holds the key perform just 
577 one action to both unlock *and* open the door (and, conversely, to close 
578 *and* lock it). The relevant actions are ``Unlock`` and ``Open``, and 
579 ``Lock`` ( ``Close`` is not necessary; if players just close the door we 
580 shouldn’t assume that they want to lock it as well).
581
582 * **Open**: if the door isn't locked or the player doesn't hold the key, 
583   keep going with the default ``Open`` action defined by the library. 
584   That leaves a locked door and a player holding the key, so we 
585   redirect processing to the ``Unlock`` action, giving as arguments the 
586   door (self) and the toilet key. Since we are using single 
587   angle-brackets ``<...>``, the action resumes after the unlocking is 
588   done (note that the ``Unlock`` action also takes care of opening the 
589   door). Finally, we ``return true`` to stop the library from trying to 
590   open the door by itself.
591
592 * **Lock**: if the door is already closed, keep going with the standard 
593   library ``Lock`` action. If not, tell players that we are closing the 
594   door for them, redirect the action briefly to actually close it, and 
595   then ``return false`` to let the ``Lock`` action proceed as before.
596
597 * **Unlock**: we place this action in the after property, so (let's 
598   hope) the ``Unlock`` action has already happened. If the door is still 
599   locked, something went wrong, so we ``return false`` to display the 
600   standard message for an unsuccessful unlocking. Otherwise, the door is 
601   now unlocked, so we inform the player that we are opening the door and 
602   redirect the action to actually open it, returning ``true`` to 
603   suppress the standard message.
604
605 In all processes there is a library variable called ``keep_silent``, 
606 which can be either ``false`` (the normal state) or ``true``; when 
607 ``true``, the interpreter does not display the associated message of an 
608 action in progress, so we can avoid things like::
609
610   >OPEN DOOR
611   You open the door to the toilet.
612   You unlock the door to the toilet and open it.
613
614 Although we want to set ``keep_silent`` to ``true`` for the duration of 
615 our extra processing, we need to reset it afterwards. In a case like 
616 this, good design practice is to preserve its initial value (which was 
617 probably ``false``, but you should avoid risky assumptions); we use a 
618 local variable ``ks`` to remember that initial setting so that we can 
619 safely restore it afterwards. You’ll remember that a local variable in a 
620 standalone routine is declared between the routine’s name and the 
621 semicolon:
622
623 .. code-block:: inform6
624
625   [ BeenToBefore this_room;
626
627 In exactly the same way, a local variable in an embedded routine is 
628 declared between the ``[`` starting marker of the routine and the 
629 semicolon:
630
631 .. code-block:: inform6
632
633   before [ ks;
634
635 You can declare up to fifteen variables this way -- just separated by 
636 spaces -- which are usable only within the embedded routine. When we 
637 assign it thus:
638
639 .. code-block:: inform6
640
641   ks = keep_silent;
642
643 we are actually making ``ks`` equal to whatever value ``keep_silent`` 
644 has (either ``true`` or ``false``; we actually don't care). We then set 
645 ``keep_silent`` to ``true``, make the desired silent actions, and we 
646 assign:
647
648 .. code-block:: inform6
649
650   keep_silent = ks;
651
652 which restores the value originally stored in ``ks`` to ``keep_silent``. 
653 The effect is that we manage to leave it as it was before we tampered 
654 with it.
655
656 Well, that's about everything about doors. Everything? Well, no, not 
657 really; any object can grow as complex as your imagination allows, but 
658 we’ll drop the subject here. If you care to see more sophisticated 
659 doors, check Exercises 3 and 4 in the *Inform Designer's Manual*, where 
660 an obliging door opens and unlocks by itself if the player simply walks 
661 in its direction.
662
663 So far, we have the player in front of a locked door leading to the 
664 toilet. A dead end? No, the description mentions a scribbled note on its 
665 surface. This one should offer no problem:
666
667 .. code-block:: inform6
668
669   Object  "scribbled note" cafe
670     with  name 'scribbled' 'note',
671           description [;
672               if (self.read_once == false) {
673                   self.read_once = true;
674                   "You apply your ENHANCED ULTRAFREQUENCY vision to the note
675                    and squint in concentration, giving up only when you see the
676                    borders of the note begin to blacken under the incredible
677                    intensity of your burning stare. You reflect once more how
678                    helpful it would've been if you'd ever learnt to read.
679                    ^^A kind old lady passes by and explains:
680                    ~You have to ask Benny for the key, at the counter.~^^
681                    You turn quickly and begin, ~Oh, I KNOW that, but...~^^
682                    ~My pleasure, son,~ says the lady, as she exits the cafe.";
683               }
684               else
685                   "The scorched undecipherable note holds no SECRETS from
686                    you NOW! Ha!";
687           ],
688           read_once false,                ! has the player read the note once?
689           before [;
690             Take:
691               "No reason to start collecting UNDECIPHERABLE notes.";
692           ],
693     has   scenery;
694
695 Just notice how we change the description after the first time the 
696 player examines the note, using the local property ``read_once`` created 
697 just for this purpose. We don’t want the player to walk off with the 
698 note, so we intercept the ``Take`` action and display something more in 
699 character than the default message for scenery objects: "That's hardly 
700 portable".
701
702 We've talked a lot about the toilet key; it seems about time to code it. 
703 Originally, the key is in Benny's possession, and the player will have 
704 to ask for it, just as the note explains. Although we'll define Benny in 
705 detail throughout the next chapter, here we present a basic definition, 
706 largely so that the key has a parent object.
707
708 .. code-block:: inform6
709
710   Object  benny "Benny"  cafe
711     with  name 'benny',
712           description
713               "A deceptively FAT man of uncanny agility, Benny entertains his
714                customers crushing coconuts against his forehead when the mood
715                strikes him.",
716     has   scenery animate male proper transparent;
717
718   Object  toilet_key "toilet key" benny
719     with  name 'toilet' 'key',
720           article "the",
721           invent [;
722               if (clothes has worn) print "the CRUCIAL key";
723               else                  print "the used and IRRELEVANT key";
724               return true;
725           ],
726           description
727               "Your SUPRA PERCEPTIVE senses detect nothing of consequence
728                about the toilet key.",
729           before [;
730               if (self in benny)
731                   "You SCAN your surroundings with ENHANCED AWARENESS,
732                    but fail to detect any key.";
733             Drop:
734               "Benny is trusting you to look after that key.";
735           ];
736
737 While Benny has the key, there's logically no way to examine it (or 
738 perform any other action involving it), but we want to prevent the 
739 interpreter from objecting that ``You can't see any such thing``. We've 
740 made the ``toilet_key`` a child of the ``benny`` object, and you can see 
741 that Benny's got a ``transparent`` attribute; this means that the key is 
742 in scope, and enables the player to refer to it without the interpreter 
743 complaining. Because Benny also has an ``animate`` attribute, the 
744 interpreter would normally intercept a TAKE KEY action with "That seems 
745 to belong to Benny"; however, the same wouldn't apply to other commands 
746 like TOUCH KEY and TASTE KEY . So, to prevent any interaction with the 
747 key while it’s in Benny’s pockets, we define a ``before`` property.
748
749 .. code-block:: inform6
750
751   before [;
752       if (self in benny)
753           "You SCAN your surroundings with ENHANCED AWARENESS,
754            but fail to detect any key.";
755     Drop:
756       "Benny is trusting you to look after that key.";
757   ];
758
759 All of the ``before`` properties that we've so far created have 
760 contained one or more labels specifying the actions which they are to 
761 intercept; you'll remember that in "William Tell" we introduced the 
762 ``default`` action (see "A class for props" on page 74) to mean "any 
763 value not already catered for". There's one of those labels here, for 
764 the Drop action, but that's preceded by a piece of code that will be 
765 executed at the start of *every* action directed at the key. If it’s 
766 still in Benny’s possession, we display a polite refusal; if the player 
767 has it then we prevent careless disposal; otherwise, the action 
768 continues unhindered.
769
770 (In fact, the hat-on-a-pole ``Prop`` introduced on page 91 had this 
771 all-exclusive ``before`` property:
772
773 .. code-block:: inform6
774
775   before [;
776     default:
777       print_ret "You're too far away at the moment.";
778   ],
779
780 It would have behaved exactly the same if we'd omitted the ``default`` 
781 label, as we do here for Benny's key.)
782
783 Another small innovation here: the ``invent`` library property (we 
784 didn’t make it up) which enables you to control how objects appear in 
785 inventory listings, overriding the default. Left to itself, the 
786 interpreter simply displays the object’s external name, preceded either 
787 by a standard article like "a" or "some", or one specifically defined in 
788 the object's ``article`` property. Here we replace "the toilet key" with 
789 one of two more helpful descriptions, making it a most valuable object 
790 in the eyes of John Covarth, and something to be despised haughtily by 
791 Captain Fate once it's of no further use to him.
792
793 When we had players in the street, we faced the problem that they might 
794 choose to examine the café from the outside. While it's unlikely that 
795 they'll try to examine the toilet room from the outside, it takes very 
796 little effort to offer a sensible output just in case:
797
798 .. code-block:: inform6
799
800   Object  outside_of_toilet "toilet" cafe
801     with  name 'toilet' 'bath' 'rest' 'room' 'bathroom' 'restroom',
802           before [;
803             Enter:
804               if (toilet_door has open) {
805                   PlayerTo(toilet);
806                   return true;
807               }
808               else
809                   "Your SUPERB deductive mind detects that the DOOR is
810                    CLOSED.";
811             Examine:
812               if (toilet_door has open)
813                    "A brilliant thought flashes through your SUPERLATIVE
814                     brain: detailed examination of the toilet would be
815                     EXTREMELY facilitated if you entered it.";
816               else
817                    "With a TREMENDOUS effort of will, you summon your
818                     unfathomable ASTRAL VISION and project it FORWARD
819                     towards the closed door... until you remember that it's
820                     Dr Mystere who's the one with mystic powers.";
821             Open:
822               <<Open   toilet_door>>;
823             Close:
824               <<Close  toilet_door>>;
825             Take,Push,Pull:
826               "That would be PART of the building.";
827           ],  
828     has   scenery openable enterable;
829
830 As with the ``outside_of_cafe`` object, we intercept an ``Enter`` 
831 action, to teleport players into the toilet room if they type ENTER 
832 TOILET (or to display a refusal if the toilet door is closed). Players 
833 may try to EXAMINE TOILET; they'll get a different message if the door 
834 is open -- we invite them to enter it -- or if it's closed. OPEN TOILET 
835 and CLOSE TOILET inputs are redirected to ``Open`` and ``Close`` actions 
836 for the toilet door; remember that the double angle-brackets imply a 
837 ``return true``, so that the action stops there and the interpreter does 
838 not attempt to ``Open`` or ``Close`` the ``outside_of_toilet`` object 
839 itself after it has dealt with the door.
840
841 You're right: the toilet looms large in this game (we blame it on early 
842 maternal influences). We’ve introduced an ambiguity problem with the 
843 ``outside_of_toilet`` object, and we'll need some help in fixing it.