kpsewhich now expects "-var-value" instead of "-var".
[ibg.git] / chapters / 08.rst
1 ============================
2  William Tell: in his prime
3 ============================
4
5 .. highlight:: inform
6
7 .. epigraph::
8
9    | |CENTER| *O was an oyster girl, and went about town;*
10    | |CENTER| *P was a parson, and wore a black gown.*
11
12 .. only:: html
13
14    .. image:: /images/picO.png
15       :align: left
16
17 |O|\ur game's action nears its climax in the town's central square.  In
18 this chapter we define the square's constituent rooms and deal with
19 Wilhelm's approach to the hat on the pole -- does he salute it, or does he
20 remain proudly defiant?
21
22 .. _south-side:
23
24 The south side of the square
25 ============================
26
27 The town square, notionally one enormous open space, is represented by
28 three rooms.  Here's the south side:
29
30 .. include:: /config/typethis.rst
31
32 ::
33
34    Room     south_square "South side of the square"
35      with   description
36                 "The narrow street to the south has opened onto the town square,
37                  and resumes at the far side of this cobbled meeting place.
38                  To continue along the street towards your destination --
39                  Johansson's tannery -- you must walk north across the square,
40                  in the middle of which you see Gessler's hat set on that
41                  loathsome pole. If you go on, there's no way you can avoid
42                  passing it. Imperial soldiers jostle rudely through the throng,
43                  pushing, kicking and swearing loudly.",
44             n_to mid_square,
45             s_to below_square;
46
47    Prop     "hat on a pole"
48      with   name 'hat' 'pole',
49             before [;
50                default:
51                  print_ret "You're too far away at the moment.";
52             ],
53             found_in south_square north_square;
54
55    Prop     "Gessler's soldiers"
56      with   name 'soldier' 'soldiers' 'guard' 'guards',
57             description "They're uncouth, violent men, not from around here.",
58             before [;
59                FireAt:
60                  print_ret "You're outnumbered many times.";
61                Talk:
62                  print_ret "Such scum are beneath your contempt.";
63             ],
64             found_in south_square mid_square north_square marketplace,
65      has    animate pluralname proper;
66
67 It's all pretty standard stuff: just a ``Room`` and two ``Prop``\s.  The
68 "real" pole object is located in the ``mid_square`` room, which means that
69 players can't EXAMINE it from this room (technically, it's "not in scope").
70 However, since we're pretending that Wilhelm can see the whole of the
71 square from where he's standing, we need to provide a dummy hat on a pole,
72 :prop:`found_in` both this room and the north side of the square, even if it's
73 "too far away" for a detailed description.
74
75 .. Generated by autoindex
76 .. index::
77    pair: Examine; library action
78    pair: before; library property
79
80 In fact, it's "too far away" for anything.  We've replaced the standard
81 :prop:`before` action for the ``Prop`` class (which permits :act:`Examine`,
82 but rejects other actions with "You don't need to worry about...") with one
83 rejecting *all* actions.  Since Wilhelm's hatred of the vogt's activities
84 is central to our plot, a message saying "You don't need to worry about the
85 hat" would be unacceptably misleading.
86
87 .. Generated by autoindex
88 .. index::
89    pair: FireAt; library action
90    pair: Talk; library action
91
92 The obnoxious soldiers are also implemented very sketchily; they need to be
93 there, but they don't do much.  Their most interesting characteristic is
94 probably that they trap two actions -- :act:`FireAt` and :act:`Talk` --
95 which are *not* part of the library, but instead new actions that we've
96 defined specially for this game.  We'll talk about those actions in
97 :ref:`verbs`, at which time the role of this :prop:`before` property will
98 make more sense.
99
100 The middle of the square
101 ========================
102
103 The activities here are pivotal to the game's plot.  Wilhelm has arrived
104 from the south side of the square, and now encounters the pole with the hat
105 on top.  He can do three things:
106
107 #. Return south.  That's allowed, but all it does is waste a little time --
108    there's nothing else to usefully do south of here.
109
110 #. Salute the pole, and then proceed to the north.  That's allowed, though
111    it rather subverts the folk story.
112
113 #. Attempt to proceed northwards without saluting the pole.  Twice, a
114    soldier will prevent this, and issue a verbal warning.  On the third
115    attempt, patience runs out, and Wilhelm is hauled off to perform his
116    party piece.
117
118 .. Generated by autoindex
119 .. index::
120    pair: Go; library action
121    pair: Salute; library action
122
123 So, there are two actions that we need to look out for: :act:`Salute`
124 (trapped by the pole), and :act:`Go` (which can be trapped by the room
125 itself).  :act:`Go` is a standard library action.  :act:`Salute` is one
126 that we've devised; let's deal with it first.  Here's a first cut of the
127 room::
128
129    Room     mid_square "Middle of the square"
130      with   description
131                 "There is less of a crush in the middle of the square; most
132                  people prefer to keep as far away as possible from the pole
133                  which towers here, topped with that absurd ceremonial hat. A
134                  group of soldiers stands nearby, watching everyone who passes.",
135             n_to north_square,
136             s_to south_square;
137
138 and the pole:
139
140 .. include:: /config/typethis.rst
141
142 ::
143
144    Furniture    pole "hat on a pole" mid_square
145      with name 'wooden' 'pole' 'pine' 'hat' 'black' 'red' 'brim' 'feathers',
146            description
147                 "The pole, the trunk of a small pine some few inches in diameter,
148                  stands about nine or ten feet high. Set carefully on top is
149                  Gessler's ludicrous black and red leather hat, with a widely
150                  curving brim and a cluster of dyed goose feathers.",
151            has_been_saluted false,
152            before [;
153               FireAt:
154                 print_ret "Tempting, but you're not looking for trouble.";
155               Salute:
156                 self.has_been_saluted = true;
157                 print_ret "You salute the hat on the pole. ^^
158                     ~Why, thank you, sir,~ sneers the soldier.";
159            ],
160      has   scenery;
161
162 The room will need some more work in a minute, but the pole object is
163 complete (note that we've simplified matters slightly by making one object
164 represent both the pole and the hat which it supports).  It mentions a
165 property which we've not met before: :prop:`has_been_saluted`.  What a
166 remarkable coincidence: the library provides a property with a name that's
167 exactly right for our game; surely not?
168
169 .. Generated by autoindex
170 .. index::
171    pair: has_been_saluted; library property
172
173 No, of course not.  :prop:`has_been_saluted` isn't a standard library
174 property; it's one that we've just invented.  Notice how easily we did it
175 -- we simply included the line::
176
177    has_been_saluted false,
178
179 in the object definition and voilĂ , we've added our own home-made property,
180 and initialised it to :const:`false`.  To switch the state of the property,
181 we can simply write::
182
183    pole.has_been_saluted = true;
184    pole.has_been_saluted = false;
185
186 or just (within the pole object)::
187
188    self.has_been_saluted = true;
189    self.has_been_saluted = false;
190
191 We could also test, if necessary, how the property currently fares::
192
193    if (pole.has_been_saluted == true) ...
194
195 and that is exactly what we'll be doing in a minute to check whether
196 Wilhelm has saluted the pole, and choose between different outcomes.
197
198 Notice that we use ``==`` (that's two equals signs) to test for "is equal
199 to"; don't confuse this usage with ``=`` (a single equals sign) which
200 assigns a value to a variable.  Compare these examples:
201
202 .. list-table::
203    :header-rows: 1
204    :widths: 1 1
205
206    * - Correct
207      - Incorrect
208
209    * - ``score = 10;``
210      - ``score == 10;``
211
212    * - assigns the value 10 to :var:`score`
213      - does nothing; :var:`score` is unchanged
214
215    * - ``if (score == 10) ...``
216      - ``if (score = 10) ...``
217
218    * - executes the next statement only if the value of :var:`score` is 10 
219      - assigns 10 to :var:`score`, then always executes the next statement --
220        because ``score = 10`` evaluates to 10, which is treated as
221        :const:`true`, so the test is always :const:`true`
222
223 Defining a new property variable which, instead of applying to every object
224 in the game (as do the standard library properties), is specific only to a
225 class of objects or even -- as here -- to a single object, is a common and
226 powerful technique.  In this game, we need a ``true/false`` variable to
227 show whether Wilhelm has saluted the pole or not: the clearest way is to
228 create one as part of the pole.  So, when the pole object traps the Salute
229 action, we do two things: use a ``self.has_been_saluted = true`` statement
230 to record the fact, and then use a ``print_ret`` statement to tell players
231 that the salute was "gratefully" received.
232
233 .. note::
234
235    Creating new property variables like this -- at the drop of a hat, as it
236    were -- is the recommended approach, but it isn't the only possibility.
237    We briefly mention some alternative approaches in
238    :ref:`reading-other-code`.
239
240 Back to the ``mid_square`` room.  We've said that we need to detect Wilhelm
241 trying to leave this room, which we can do by trapping the :act:`Go` action
242 in a :prop:`before` property.  Let's sketch the coding we'll need::
243
244    before [;
245       Go:
246         if (noun == s_obj)       { Wilhelm is trying to move south }
247         if (noun == n_obj)       { Wilhelm is trying to move north }
248    ];
249
250 .. Generated by autoindex
251 .. index::
252    pair: Go; library action
253    pair: s_to; library property
254
255 We can easily trap the :act:`Go` action, but which direction is he moving?
256 Well, it turns out that the interpreter turns a command of GO SOUTH (or
257 just SOUTH) into an action of :act:`Go` applied to an object ``s_obj``.
258 This object is defined by the library; so why isn't it called just
259 "``south``"?  Well, because we already have another kind of south, the
260 property :prop:`s_to` used to say what lies in a southerly direction when
261 defining a room.  To avoid confusing them, :prop:`s_to` means "south to"
262 and ``s_obj`` means "south when the player types it as the object of a
263 verb".
264
265 .. Generated by autoindex
266 .. index::
267    pair: noun; library variable
268
269 The identity of the object which is the target of the current action is
270 stored in the :var:`noun` variable, so we can write the statement ``if (noun
271 == s_obj)`` to test whether the contents of the :var:`noun` variable are equal
272 to the ID of the ``s_obj`` object -- and, if so, Wilhelm is trying to move
273 south.  Another similar statement tests whether he's trying to move north,
274 and that's all that we're interested in; we can let other movements take
275 care of themselves.
276
277 The words :samp:`{Wilhelm is trying to move south}` aren't part of our
278 game; they're just a temporary reminder that, if we need to execute any
279 statements in this situation, here's the place to put them.  Actually,
280 that's the simpler case; it's when :samp:`{Wilhelm is trying to move
281 north}` that the fun starts.  We need to behave in one of two ways,
282 depending on whether or not he's saluted the pole.  But we *know* when he's
283 done that; the pole's ``has_been_saluted`` property tells us.  So we can
284 expand our sketch like this::
285
286   before [;
287      Go:
288        if (noun == s_obj)        { Wilhelm is trying to move south [1] }
289        if (noun == n_obj)        { Wilhelm is trying to move north...
290            if (pole.has_been_saluted == true)
291                                  { ...and he's saluted the pole [2] }
292            else                  { ...but he hasn't saluted the pole [3] }
293        }
294   ];
295
296 Here we have one ``if`` statement nested inside another.  And there's more:
297 the inner ``if`` has an ``else`` clause, meaning that we can execute one
298 statement block when the test ``if (pole.has_been_saluted == true)`` is
299 true, and an alternative block when the test isn't true.  Read that again
300 carefully, checking how the braces ``{...}`` pair up; it's quite complex,
301 and you need to understand what's going on.  One important point to
302 remember is that, unless you insert braces to change this, an ``else``
303 clause always pairs with the most recent ``if``.  Compare these two
304 examples::
305
306   if (condition1) {
307       if (condition2) { here when condition1 is true and condition2 is true }
308       else            { here when condition1 is true and condition2 is false }
309   }
310
311   if (condition1) {
312        if (condition2) { here when condition1 is true and condition2 is true }
313   }
314   else                 { here when condition1 is false }
315
316 In the first example, the ``else`` pairs with the most recent :samp:`if
317 ({condition2})`, whereas in the second example the revised positioning of
318 the braces causes the ``else`` to pair with the earlier :samp:`if
319 ({condition1})`.
320
321 .. note::
322
323    We've used indentation as a visual guide to how the ``if`` and ``else``
324    are related.  Be careful, though; the compiler matches an ``else`` to
325    its ``if`` purely on the basis of logical grouping, regardless of how
326    you've laid out the code.
327
328 Back to the before property.  You should be able to see that the cases
329 marked ``[1]``, ``[2]`` and ``[3]`` correspond to the three possible
330 courses of action we listed at the start of this section.  Let's write the
331 code for those, one at a time.
332
333 .. rubric:: Case 1: Returning south
334
335 First, :samp:`{Wilhelm is trying to move south}`; not very much to this::
336
337    warnings_count 0,         ! for counting the soldier's warnings
338    before [;
339       Go:
340         if (noun == s_obj) {
341             self.warnings_count = 0;
342             pole.has_been_saluted = false;
343         }
344         if (noun == n_obj) {
345             if (pole.has_been_saluted == true)
346                       { moving north...and he's saluted the pole }
347             else      { moving north...but he hasn't saluted the pole }
348         }
349    ];
350
351 Wilhelm might wander into the middle of the square, take one look at the
352 pole and promptly return south.  Or, he might make one or two (but not
353 three) attempts to move north first, and then head south.  *Or*, he might
354 be really perverse, salute the pole and only then head south.  In all of
355 these cases, we take him back to square one, as though he'd received no
356 soldier's warnings (irrespective of how many he'd actually had) and as
357 though the pole had not been saluted (irrespective of whether it was or
358 not).  In effect, we're pretending that the soldier has such a short
359 memory, he'll completely forget Wilhelm if our hero should move away from
360 the pole.
361
362 .. Generated by autoindex
363 .. index::
364    pair: has_been_saluted; library property
365    pair: warnings_count; library property
366
367 To do all this, we've added a new property and two statements.  The
368 property is :prop:`warnings_count`, and its value will count how many times
369 Wilhelm has tried to go north without saluting the pole: 0 initially, 1
370 after his first warning, 2 after his second warning, 3 when the soldier's
371 patience finally runs out.  The property :prop:`warnings_count` isn't a
372 standard library property; like the pole's :prop:`has_been_saluted`
373 property, it's one that we've created to meet a specific need.
374
375 Our first statement is ``self.warnings_count = 0``, which resets the value
376 of the :prop:`warnings_count` property of the current object -- the
377 ``mid_square`` room -- to 0.  The second statement is
378 ``pole.has_been_saluted = false``, which signifies that the pole has not be
379 saluted.  That's it: the soldier's memory is erased, and Wilhelm's actions
380 are forgotten.
381
382 .. rubric:: Case 2: Moving north after saluting
383
384 :samp:`{Wilhelm is moving north...and he's saluted the pole}`; another easy
385 one::
386
387   warnings_count 0,         ! for counting the soldier's warnings
388   before [;
389      Go:
390        if (noun == s_obj) {
391            self.warnings_count = 0;
392            pole.has_been_saluted = false;
393        }
394        if (noun == n_obj) {
395            if (pole.has_been_saluted == true) {
396                 print "^~Be sure to have a nice day.~^";
397                 return false;
398            }
399            else                   { moving north...but he hasn't saluted the pole }
400        }
401   ];
402
403 All that we need do is print a sarcastic goodbye from the soldier, and then
404 ``return false``.  You'll remember that doing so tells the interpreter to
405 continue handling the action, which in this case is an attempt to move
406 north.  Since this is a permitted connection, Wilhelm thus ends up in the
407 ``north_square`` room, defined shortly.
408
409 .. rubric:: Case 3: Moving north before saluting
410
411 So that just leaves the final case: :samp:`{moving north...but he hasn't
412 saluted the pole}`.  This one has more to it than the others, because we
413 need the "three strikes and you're out" coding.  Let's sketch a little
414 more::
415
416   warnings_count 0,         ! for counting the soldier's warnings
417   before [;
418      Go:
419        if (noun == s_obj) {
420             self.warnings_count = 0;
421             pole.has_been_saluted = false;
422        }
423        if (noun == n_obj) {
424             if (pole.has_been_saluted == true) {
425                 print "^~Be sure to have a nice day.~^";
426                 return false;
427             }
428             else {
429                 self.warnings_count = self.warnings_count + 1;
430                 switch (self.warnings_count) {
431                     1:       First attempt at moving north
432                     2:       Second attempt at moving north
433                     default: Final attempt at moving north
434                 }
435           }
436        }
437   ];
438
439 First of all, we need to count how many times he's tried to move north.
440 ``self.warnings_count`` is the variable containing his current tally, so we
441 add 1 to whatever value it contains: ``self.warnings_count =
442 self.warnings_count + 1``.  Then, determined by the value of the variable,
443 we must decide what action to take: first attempt, second attempt, or final
444 confrontation.  We could have used three separate ``if`` statements::
445
446    if (self.warnings_count == 1)         { First attempt at moving north }
447    if (self.warnings_count == 2)         { Second attempt at moving north }
448    if (self.warnings_count == 3)         { Final attempt at moving north }
449
450 or a couple of nested ``if`` statements::
451
452    if (self.warnings_count == 1)     { First attempt at moving north }
453    else {
454        if (self.warnings_count == 2) { Second attempt at moving north }
455        else                          { Final attempt at moving north }
456    }
457
458 but for a series of tests all involving the same variable, a ``switch``
459 statement is usually a clearer way of achieving the same effect.  The
460 generic syntax for a ``switch`` statement is::
461
462    switch (expression) {
463      value1: whatever happens when the expression evaluates to value1
464      value2: whatever happens when the expression evaluates to value2
465      ...
466      valueN: whatever happens when the expression evaluates to valueN
467      default: whatever happens when the expression evaluates to something else
468    }
469
470 This means that, according to the current value of an expression, we can
471 get different outcomes.  Remember that the :samp:`{expression}` may be a
472 ``Global`` or local variable, an object's property, one of the variables
473 defined in the library, or any other expression capable of having more than
474 one value.  You could write ``switch (x)`` if ``x`` is a defined variable,
475 or even, for instance, ``switch (x+y)`` if both ``x`` and ``y`` are defined
476 variables.  Those :samp:`{whatever happens when...}` are collections of
477 statements which implement the desired effect for a particular value of the
478 switched variable.
479
480 Although a switch statement :samp:`switch ({expression}) { ... }` needs
481 that one pair of braces, it doesn't need braces around each of the
482 individual "cases", no matter how many statements each of them includes.
483 As it happens, case 1 and case 2 contain only a single ``print_ret``
484 statement each, so we'll move swiftly past them to the third, more
485 interesting, case -- when ``self.warnings_count`` is 3.  Again, we could
486 have written this::
487
488    switch     (self.warnings_count) {
489      1:       First attempt at moving north
490      2:       Second attempt at moving north
491      3:       Final attempt at moving north
492    }
493
494 but using the word ``default`` -- meaning "any value not already catered
495 for" -- is better design practice; it's less likely to produce misleading
496 results if for some unforeseen reason the value of ``self.warnings_count``
497 isn't the 1, 2 or 3 you'd anticipated.  Here's the remainder of the code
498 (with some of the printed text omitted)::
499
500   self.warnings_count = self.warnings_count + 1;
501   switch (self.warnings_count) {
502     1: print_ret "...";
503     2: print_ret "...";
504     default:
505        print "^~OK, ";
506        style underline; print "Herr"; style roman;
507        print " Tell, now you're in real trouble. I asked you
508            ...
509            old lime tree growing in the marketplace.^";
510        move apple to son;
511        PlayerTo(marketplace);
512        return true;
513   }
514
515 .. Generated by autoindex
516 .. index::
517    pair: Go; library action
518
519 The first part is really just displaying a lot of text, made slightly
520 messier because we're adding emphasis to the word "Herr" by using
521 underlining (which actually comes out as *italic type* on most
522 interpreters).  Then, we make sure that Walter has the apple (just in case
523 we didn't give it to him earlier in the game), relocate to the final room
524 using ``PlayerTo(marketplace)``, and finally ``return true`` to tell the
525 interpreter that we've handled this part of the :act:`Go` action ourselves.
526 And so, at long last, here's the complete code for the ``mid_square``, the
527 most complicated object in the whole game:
528
529 .. include:: /config/typethis.rst
530
531 ::
532
533   Room    mid_square "Middle of the square"
534     with  description
535                "There is less of a crush in the middle of the square; most
536                  people prefer to keep as far away as possible from the pole
537                  which towers here, topped with that absurd ceremonial hat.  A
538                  group of soldiers stands nearby, watching everyone who passes.",
539           n_to north_square,
540           s_to south_square,
541           warnings_count 0,          ! for counting the soldier's warnings
542           before [;
543              Go:
544                if (noun == s_obj) {
545                     self.warnings_count = 0;
546                     pole.has_been_saluted = false;
547                }
548                if (noun == n_obj) {
549                     if (pole.has_been_saluted == true) {
550                         print "^~Be sure to have a nice day.~^";
551                         return false;
552                     }   ! end of (pole has_been_saluted)
553                     else {
554                         self.warnings_count = self.warnings_count + 1;
555                         switch (self.warnings_count) {
556                           1: print_ret "A soldier bars your way. ^^
557                                  ~Oi, you, lofty; forgot yer manners, didn't you?
558                                  How's about a nice salute for the vogt's hat?~";
559                           2: print_ret "^~I know you, Tell, yer a troublemaker,
560                                  ain't you? Well, we don't want no bovver here,
561                                  so just be a good boy and salute the friggin'
562                                  hat. Do it now: I ain't gonna ask you again...~";
563                           default:
564                              print "^~OK, ";
565                              style underline; print "Herr"; style roman;
566                              print " Tell, now you're in real trouble. I asked you
567                                  nice, but you was too proud and too stupid. I
568                                  think it's time that the vogt had a little word
569                                  with you.~
570                                  ^^
571                                  And with that the soldiers seize you and Walter
572                                  and, while the sergeant hurries off to fetch
573                                  Gessler, the rest drag you roughly towards the
574                                  old lime tree growing in the marketplace.^";
575                              move apple to son;
576                              PlayerTo(marketplace);
577                              return true;
578                         }    ! end of switch
579                     }   ! end of (pole has_NOT_been_saluted)
580                }    ! end of (noun == n_obj)
581           ];
582
583 The north side of the square
584 ============================
585
586 The only way to get here is by saluting the pole and then moving north; not
587 very likely, but good game design is about predicting the unpredictable.
588
589 .. include:: /config/typethis.rst
590
591 ::
592
593   Room     north_square "North side of the square"
594     with   description
595                "A narrow street leads north from the cobbled square. In its
596                 centre, a little way south, you catch a last glimpse of the pole
597                 and hat.",
598            n_to [;
599                deadflag = 3;
600                print_ret "With Walter at your side, you leave the square by the
601                    north street, heading for Johansson's tannery.";
602            ],
603            s_to "You hardly feel like going through all that again.";
604
605 There's one new feature in this room: the value of the :prop:`n_to` property is
606 a routine, which the interpreter runs when Wilhelm tries to exit the square
607 northwards.  All that the routine does is set the value of the library
608 variable :var:`deadflag` to 3, print a confirmation message, and ``return
609 true``, thus ending the action.
610
611 At this point, the interpreter notices that :var:`deadflag` is no longer zero,
612 and terminates the game.  In fact, the interpreter checks :var:`deadflag` at
613 the end of every turn; these are the values that it's expecting to find:
614
615 * 0 -- this is the normal state; the game continues.
616 * 1 -- the game is over. The interpreter displays "You have died".
617 * 2 -- the game is over. The interpreter displays "You have won".
618 * any other value -- the game is over, but there aren't any appropriate
619   messages built into the library.  Instead, the interpreter looks for an
620   :term:`entry point` routine called ``DeathMessage`` -- which we must
621   provide -- where we can define our own tailored "end messages".
622
623 In this game, we never set :var:`deadflag` to 1, but we do use values of 2
624 and 3.  So we'd better define a ``DeathMessage`` routine to tell players
625 what they've done:
626
627 .. include:: /config/typethis.rst
628
629 ::
630
631     [ DeathMessage; print "You have screwed up a favourite folk story"; ];
632
633 Our game has only one customised ending, so the simple ``DeathMessage``
634 routine we've written is sufficient for our purposes.  Were you to conceive
635 multiple endings for a game, you could specify suitable messages by
636 checking for the current value of the :var:`deadflag` variable::
637
638     [ DeathMessage;
639         if (deadflag == 3) print "You leave Scarlett O'Hara for good";
640         if (deadflag == 4) print "You crush Scarlett with a passionate embrace";
641         if (deadflag == 5) print "You've managed to divorce Scarlett";
642         ...
643     ];
644
645 Of course, you must assign the appropriate value to :var:`deadflag` at the
646 point when the game arrives at each of those possible endings.
647
648 We've nearly finished.  In the concluding chapter of this game, we'll talk
649 about the fateful shooting of the arrow.