1 ===============================
2 William Tell: the end is nigh
3 ===============================
9 | *Q was a queen, who wore a silk slip;*
10 | *R was a robber, and wanted a whip.*
14 .. image:: /images/picQ.png
21 uite a few objects still remain undefined, so we'll talk about them first.
22 Then, we'll explain how to make additions to Inform's standard repertoire
23 of verbs, and how to define the actions which those verbs trigger.
28 The ``marketplace`` room is unremarkable, and the ``tree`` growing there
29 has only one feature of interest::
31 Room marketplace "Marketplace near the square"
33 "Altdorf's marketplace, close by the town square, has been hastily
34 cleared of stalls. A troop of soldiers has pushed back the crowd
35 to leave a clear space in front of the lime tree, which has been
36 growing here for as long as anybody can remember. Usually it
37 provides shade for the old men of the town, who gather below to
38 gossip, watch the girls, and play cards. Today, though, it
39 stands alone... apart, that is, from Walter, who has been lashed
40 to the trunk. About forty yards away, you are restrained by two
42 cant_go "What? And leave your son tied up here?";
44 Object tree "lime tree" marketplace
45 with name 'lime' 'tree',
46 description "It's just a large tree.",
49 if (BowOrArrow(second) == true) {
51 print_ret "Your hand shakes a little, and your arrow flies
52 high, hitting the trunk a few inches above Walter's
59 The tree's ``before`` property is intercepting a ``FireAt`` action, which
60 we'll define in a few moments. This action is the result of a command like
61 SHOOT AT TREE WITH BOW -- we could simulate it with the statement
62 ``<<FireAt tree bow>>`` -- and it needs extra care to ensure that the
63 ``second`` object is a feasible weapon. To deal with silly commands like
64 SHOOT AT TREE WITH HELGA, we must test that ``second`` is the bow, one of
65 the arrows, or ``nothing`` (from just SHOOT AT TREE). Since this is quite
66 a complex test, and one that we'll be making in several places, it's
67 sensible to write a routine to do the job. Which we'll do shortly -- but
68 first, a general introduction to working with routines.
70 A diversion: working with routines
71 ==================================
73 A standalone routine, like the familiar routines embedded as the value of a
74 property such as ``before`` or ``each_turn``, is simply a set of statements
75 to be executed. The major differences are in content, in timing, and in
76 the default return value:
78 * Whereas an embedded routine has to contain statements which do something
79 appropriate for that associated property variable, a standalone routine
80 can contain statements which do anything you wish. You have total
81 freedom as to what the routine actually does and what value it returns.
83 * An embedded routine is called when the interpreter is dealing with that
84 property of that object; you provide the routine, but you don't directly
85 control when it's called. A standalone routine, however, is completely
86 under your control; it runs only when you explicitly call it.
88 * If an embedded routine executes all of its statements and reaches the
89 final ``];`` without encountering some form of ``return`` statement, it
90 returns the value ``false``. In the same circumstances, a standalone
91 routine returns the value ``true``. There's a good reason for this
92 difference -- it usually turns out to be the natural default behaviour --
93 but it can sometimes baffle newcomers. To avoid confusion, we've always
94 included explicit ``return`` statements in our routines.
96 What this generally boils down to is: *if* you have a collection of
97 statements which perform some specific task *and* you need to execute those
98 same statements in more than one place in your game, *then* it often makes
99 sense to turn those statements into a standalone routine. The advantages
100 are: you write the statements only once, so any subsequent changes are
101 easier to make; also, your game becomes simpler and easier to read. We'll
102 look at some simple examples; first consider these unexciting foodstuffs::
104 Object "stale ham sandwich"
105 with name 'stale' 'ham' 'sandwich',
106 description "It doesn't look at all appetising.",
109 Object "elderly jam doughnut"
110 with name 'elderly' 'jam' 'jelly' 'doughnut' 'donut',
111 description "It doesn't look at all appetising.",
114 The ``description``\s are identical: perhaps we could display them using a
117 [ Inedible; print_ret "It doesn't look at all appetising."; ];
119 Object "stale ham sandwich"
120 with name 'stale' 'ham' 'sandwich',
121 description [; Inedible(); ],
124 Object "elderly jam doughnut"
125 with name 'elderly' 'jam' 'jelly' 'doughnut' 'donut',
126 description [; Inedible(); ],
129 This isn't a very realistic approach -- there are more elegant ways of
130 avoiding typing the same string twice -- but it works, and it illustrates
131 how we can define a routine to do something useful, and then call it
134 Here's another simple example showing how, by returning a value, a routine
135 can report back to the piece of code which called it. We've once or twice
136 used the test ``if (self has visited) ...``; we could create a routine
137 which performs that same check and then returns ``true`` or ``false`` to
138 indicate what it discovered::
141 if (self has visited) return true;
145 Then, we'd rewrite our test as ``if (BeenHereBefore() == true) ...``; no
146 shorter or quicker, but maybe more descriptive of what's going on. One
147 more example of using routines. As well as testing ``if (self has visited)
148 ...`` we've also tested ``if (location has visited) ...`` a few times, so
149 we *could* write another routine to perform that check::
152 if (location has visited) return true;
156 However, the two routines are very similar; the only difference is the name
157 of the variable -- ``self`` or ``location`` -- which is being checked. A
158 better approach might be to rework our ``BeenHereBefore`` routine so that
159 it does both jobs, but we somehow need to tell it which variable's value is
160 to be checked. That's easy: we design the routine so that it expects an
163 [ BeenToBefore this_room;
164 if (this_room has visited) return true;
168 Notice that the argument's name is one that we've invented to be
169 descriptive of its content; it doesn't matter if we define it as "``x``",
170 "``this_room``" or "``hubba_hubba``". Whatever its name, the argument acts
171 as a placeholder for a value (here, one of the variables ``self`` or
172 ``location``) which we must supply when calling the routine::
174 if (BeenToBefore(self) == true) ...
176 if (BeenToBefore(location) == true) ...
178 In the first line, we supply ``self`` as the routine's argument. The
179 routine doesn't care where the argument came from; it just sees a value
180 which it knows as ``this_room``, and which it then uses to test for the
181 ``visited`` attribute. On the second line we supply ``location`` as the
182 argument, but the routine just sees another value in its ``this_room``
183 variable. ``this_room`` is called a **local variable** of the
184 ``BeenToBefore`` routine, one that must be set to a suitable value each
185 time that the routine is called. In this example routine, the value needs
186 to be a room object; we could also check an explicit named room::
188 if (BeenToBefore(mid_square) == true) ...
192 #. All routines terminate sooner or later, either because you explicitly
193 write a ``return``, ``rtrue`` or ``rfalse`` statement, or because
194 execution reaches the ``]`` marking the routine's end.
196 #. All routines return a value, which can be ``true``, or ``false``, or any
197 other number. This value is determined by the ``return``, ``rtrue`` or
198 ``rfalse`` statement, or by the the ``]`` marking the routine's end (in
199 which case the default STEF rule applies: Standalone routines return
200 True, Embedded routines return False). We gave this example of an
201 embedded routine in "Adding some props" on page 81. The ``return
202 false`` statement is redundant: we could remove it without affecting the
203 routine's behaviour, because the ``]`` acts like a ``return false``::
206 if (location == street or below_square or south_square or
207 mid_square or north_square or marketplace) return true;
211 On the other hand, just because a routine returns a value doesn't mean
212 you always *have* to use it; you can simply ignore the value if you want
213 to. The ``TooFarAway`` routine that we showed you earlier in this
214 chapter contains a ``print_ret`` statement and so always returns
215 ``true``, but we didn't take any notice; the sole purpose of the routine
216 was to display some text. Compare this with the ``BeenToBefore``
217 routine, which does nothing *except* return a value; if we'd ignored
218 that, then calling the routine would have been a waste of time.
220 For some embedded routines, the value returned by the routine is important;
221 for others it doesn't matter. We've so far seen the following properties
222 whose value can be an embedded routine:
224 ========================= ===========================
225 Return value is important Return value doesn't matter
226 ========================= ===========================
227 ``after [; ... ],`` ``cant_go [; ... ],``
228 ``before [; ... ],`` ``description [; ... ],``
229 ``found_in [; ... ],`` ``each_turn [; ... ],``
230 ``n_to [; ... ]``, et al ``initial [; ... ],``
231 ========================= ===========================
233 For full details on which library property values can be embedded routines,
234 and which return values are significant, see "Object properties" on page
235 266 and Appendix §A2 of the *Inform Designer's Manual*.
237 Return to the marketplace
238 =========================
240 After all that introduction, finally back to the ``FireAt`` action. We
241 want to check on the characteristics of an object, possibly then displaying
242 a message. We don't know exactly *which* object is to be checked, so we
243 need to write our routine in a generalised way, capable of checking any
244 object which we choose; that is, we'll supply the object to be checked as
245 an argument. Here's the routine::
248 if (o == bow or nothing || o ofclass Arrow) return true;
249 print "That's an unlikely weapon, isn't it?^";
253 The routine is designed to inspect any object which is passed to it as its
254 argument ``o``; that is, we could call the routine like this::
256 BowOrArrow(stallholder)
260 Given the ``bow`` object, or any object which we defined as class
261 ``Arrow``, it will silently ``return true`` to signify agreement that this
262 object can be fired. However, given an object like Helga, the apple or the
263 tree, it will print a message and ``return false`` to signify that this
264 object is not a suitable weapon. The test that we make is::
266 if (o == bow or nothing || o ofclass Arrow) ...
268 which is merely a slightly shorter way of saying this::
270 if (o == bow || o == nothing || o ofclass Arrow) ...
272 The result is that we ask three questions: Is ``o`` the ``bow`` object?
273 *Or* is it ``nothing``? Or, using the ``ofclass`` test, is it any object
274 which is a member of the ``Arrow`` class?
276 What this means is that the value returned by the call ``BowOrArrow(bow)``
277 is ``true``, while the value returned by the call ``BowOrArrow(tree)`` is
278 ``false``. Or, more generally, the value returned by the call
279 ``BowOrArrow(second)`` will be either ``true`` or ``false``, depending on
280 the characteristics of the object defined by the value of the variable
281 ``second``. So, we can write this set of statements in an object's
282 ``before`` property::
284 if (BowOrArrow(second) == true) {
285 This object deals with having an arrow fired at it
289 and the effect is either
291 * ``second`` is a weapon: ``BowOrArrow`` displays nothing and returns a
292 value of ``true``, the ``if`` statement reacts to that value and executes
293 the following statements to produce an appropriate response to the
294 fast-approaching arrow; or
296 * ``second`` isn't a weapon: ``BowOrArrow`` displays a standard "don't be
297 silly" message and returns a value of ``false``, the ``if`` statement
298 reacts to that value and ignores the following statements. Then
300 * in both cases, the ``return true`` statement terminates the object's
301 interception of the ``FireAt`` action.
303 That whole ``BowOrArrow()`` bit was rather complex, but the rest of the
304 ``FireAt`` action is straightforward. Once the tree has determined that
305 it's being shot at by something sensible, it can just set ``deadflag`` to 3
306 -- the "You have screwed up" ending, display a message, and be done.
311 There's nothing in Gessler's definition that we haven't already encountered::
313 NPC governor "governor" marketplace
314 with name 'governor' 'vogt' 'Hermann' 'Gessler',
316 "Short, stout but with a thin, mean face, Gessler relishes the
317 power he holds over the local community.",
319 print "Gessler is watching from a safe distance,
320 a sneer on his face.^";
321 if (location hasnt visited)
322 print_ret "^~It appears that you need to be taught a lesson,
323 fool. Nobody shall pass through the square without paying
324 homage to His Imperial Highness Albert; nobody, hear me?
325 I could have you beheaded for treason, but I'm going to
326 be lenient. If you should be so foolish again, you can
327 expect no mercy, but this time, I'll let you go free...
328 just as soon as you demonstrate your archery skills by
329 hitting this apple from where you stand. That shouldn't
330 prove too difficult; here, sergeant, catch. Balance it on
331 the little bastard's head.~";
335 print_ret "You cannot bring yourself to speak to him.";
339 if (BowOrArrow(second) == true) {
341 print_ret "Before the startled soldiers can react, you turn
342 and fire at Gessler; your arrow pierces his heart,
343 and he dies messily. A gasp, and then a cheer,
344 goes up from the crowd.";
350 Like most NPCs, Gessler has a ``life`` property which deals with actions
351 applicable only to animate objects. This one responds merely to ``Talk``
352 (as in TALK TO THE GOVERNOR).
357 Since he's been with you throughout, it's really about time we defined
361 with name 'son' 'your' 'boy' 'lad' 'Walter',
363 if (location == marketplace)
364 print_ret "He stares at you, trying to appear brave and
365 remain still. His arms are pulled back and tied behind
366 the trunk, and the apple nestles amid his blond hair.";
368 print_ret "A quiet, blond lad of eight summers, he's fast
369 learning the ways of mountain folk.";
375 print_ret "~Thank you, Papa.~";
377 if (location == marketplace)
378 print_ret "~Stay calm, my son, and trust in God.~";
380 print_ret "You point out a few interesting sights.";
383 Examine,Listen,Salute,Talk:
386 if (location == marketplace) {
387 if (BowOrArrow(second) == true) {
389 print_ret "Oops! Surely you didn't mean to do that?";
396 if (location == marketplace)
397 print_ret "Your guards won't permit it.";
401 found_in [; return true; ],
402 has male proper scenery transparent;
404 His attributes are ``male`` (he's your son, after all), ``proper`` (so the
405 interpreter doesn't mention "the your son"), ``scenery`` (so he's not
406 listed in every room description), and ``transparent`` (because you see
407 right through him). No, that's wrong: a ``transparent`` object isn't made
408 of glass; it's one whose possessions are visible to you. We've done that
409 because we'd still like to be able to EXAMINE APPLE even when Walter is
410 carrying it. Without the ``transparent`` attribute, it would be as though
411 the apple was in his pocket or otherwise out of sight; the interpreter
412 would reply "You can't see any such thing".
414 Walter has a ``found_in`` property which automatically moves him to the
415 player's location on each turn. We can get away with this because in such
416 a short and simple game, he does indeed follow you everywhere. In a more
417 realistic model world, NPCs often move around independently, but we don't
418 need such complexity here.
420 Several of Walter's properties test whether ``(location == marketplace)``;
421 that is, is the player (and hence Walter) currently in that room? The
422 events in the marketplace are such that specialised responses are more
423 appropriate there than our standard ones.
425 Walter's ``life`` property responds to ``Give`` (as in GIVE APPLE TO
426 WALTER) and Talk (as in TALK TO YOUR SON); during ``Give``, we increment
427 the library variable ``score``, thus rewarding the player's generous good
428 nature. His ``before`` property is perhaps a little confusing. It's
431 #. The ``Examine``, ``Listen``, ``Salute`` and ``Talk`` actions are always
432 available (a ``Talk`` action then gets passed to Walter's ``life``
435 #. The ``FireAt`` action is permitted in the ``marketplace``, albeit with
436 unfortunate results. Elsewhere, it triggers the standard ``FireAt``
437 response of "Unthinkable!"
439 #. All other actions are prevented in the ``marketplace``, and allowed to
440 run their standard course (thanks to the ``return false``) elsewhere.
442 The apple's moment of glory has arrived! Its ``before`` property responds
443 to the ``FireAt`` action by setting ``deadflag`` to 2. When that happens,
444 the game is over; the player has won. ::
449 if (location == marketplace)
450 print_ret "At this distance you can barely see it.";
452 print_ret "The apple is blotchy green and brown.";
456 print_ret "An apple is worth quite a bit --
457 better hang on to it.";
459 print_ret "Helga intended it for Walter...";
461 if (location == marketplace) {
462 if (BowOrArrow(second) == true) {
465 print_ret "Slowly and steadily, you place an arrow in
466 the bow, draw back the string, and take aim with
467 more care than ever in your life. Holding your
468 breath, unblinking, fearful, you release the
469 arrow. It flies across the square towards your
470 son, and drives the apple against the trunk of
471 the tree. The crowd erupts with joy;
472 Gessler looks distinctly disappointed.";
480 And with that, we've defined all of the objects. In doing so, we've added
481 a whole load of new nouns and adjectives to the game's dictionary, but no
482 verbs. That's the final task.
487 The Inform library delivers a standard set of nearly a hundred actions
488 which players can perform; around twenty of those are "meta-actions" (like
489 SAVE and QUIT) aimed at the interpreter itself, and the remainder operate
490 within the model world. Having such a large starting set is a great
491 blessing; it means that many of the actions which players might attempt are
492 already catered for, either by the interpreter doing something useful, or
493 by explaining why it's unable to. Nevertheless, most games find the need
494 to define additional actions, and "William Tell" is no exception. We'll be
495 adding four actions of our own: ``Untie``, ``Salute`` (see page 113),
496 ``FireAt`` (see page 115) and ``Talk`` (see page 116).
500 It's not the most useful action, but it is the simplest. In the
501 marketplace, when Walter is lashed to the tree, it's possible that players
502 might be tempted to try to UNTIE WALTER; unlikely, but as we've said
503 before, anticipating the improbable is part of the craft of IF. For this,
504 and for all new actions, two things are required. We need a grammar
505 definition, spelling out the structure of the English sentences which we're
508 Verb 'untie' 'unfasten' 'unfix' 'free' 'release'
511 and we need a routine to handle the action in the default situation (where
512 the action isn't intercepted by an object's ``before`` property). ::
514 [ UntieSub; print_ret "You really shouldn't try that."; ];
516 The grammar is less complex than it perhaps at first appears:
518 #. The English verbs UNTIE, UNFASTEN, UNFIX, FREE and RELEASE are
521 #. The asterisk ``*`` indicates the start of a pattern defining what
522 word(s) might follow the verb.
524 #. In this example, there's only one pattern: the "``noun``" token
525 represents an object which is currently in scope -- in the same room as
528 #. The ``->`` indicates an action to be triggered.
530 #. If players type something that matches the pattern -- one of those five
531 verbs followed by an object in scope -- the interpreter triggers an
532 ``Untie`` action, which by default is handled by a routine having the
533 same name as the action, with ``Sub`` appended. In this example, that's
534 the ``UntieSub`` routine.
536 #. The grammar is laid out this way just to make it easier to read. All those
537 spaces aren't important; we could equally have typed::
539 Verb 'untie' 'unfasten' 'unfix' 'free' 'release' * noun -> Untie;
541 We can illustrate how this works in the Altdorf street:
543 .. code-block:: transcript
546 The narrow street runs north towards the town square. Local folk are pouring
547 into the town through the gate to the south, shouting greetings, offering
548 produce for sale, exchanging news, enquiring with exaggerated disbelief about
549 the prices of the goods displayed by merchants whose stalls make progress even
552 "Stay close to me, son," you say, "or you'll get lost among all these people."
555 What do you want to untie?
558 You can't see any such thing.
561 You don't need to worry about the local people.
564 You really shouldn't try that.
566 The illustration shows four attempted usages of the new action. In the
567 first, the player omits to mention an object; the interpreter knows (from
568 that ``noun`` in the grammar which implies that the action needs a direct
569 object) that something is missing, so it issues a helpful prompt. In the
570 second, the player mentions an object that isn't in scope (in fact, there's
571 no dog anywhere in the game, but the interpreter isn't about to give *that*
572 away to the player). In the third, the object is in scope, but its
573 ``before`` property intercepts the ``Untie`` action (and indeed, since this
574 object is of the class ``Prop``, all actions apart from ``Examine``) to
575 display a customised rejection message. Finally, the fourth usage refers
576 to an object which *doesn't* intercept the action, so the interpreter calls
577 the default action handler -- ``UntieSub`` -- which displays a
578 general-purpose refusal to perform the action.
580 The principles presented here are those that you should generally employ:
581 write a generic action handler which either refuses to do anything (see,
582 for example SQUASH or HIT), or performs the action without affecting the
583 state of the model world (see, for example, JUMP or WAVE); then, intercept
584 that non-action (generally using a ``before`` property) for those objects
585 which might make a legitimate target for the action, and instead provide a
586 more specific response, either performing or rejecting the action.
588 In the case of ``Untie``, there are no objects which can be untied in this
589 game, so we always generate a refusal of some sort.
593 The next action is ``Salute``, provided in case Wilhelm chooses to defer to
594 the hat on the pole. Here's the default action handler::
597 if (noun has animate) print_ret (The) noun, " acknowledges you.";
598 print_ret (The) noun, " takes no notice.";
601 You'll notice that this is slightly more intelligent than our ``Untie``
602 handler, since it produces different responses depending on whether the
603 object being saluted -- stored in the ``noun`` variable -- is ``animate``
604 or not. But it's basically doing the same job. And here's the grammar::
606 Verb 'bow' 'nod' 'kowtow' 'genuflect'
607 * 'at'/'to'/'towards' noun -> Salute;
609 Verb 'salute' 'greet' 'acknowledge'
612 This grammar says that:
614 #. The English verbs BOW, NOD, KOWTOW, GENUFLECT, SALUTE, GREET and
615 ACKNOWLEDGE are synonymous.
617 #. The first four (but not the last three) can then be followed by any of
618 the prepositions AT, TO or TOWARDS: words in apostrophes ``'...'`` are
619 matched literally, with the slash ``/`` separating alternatives.
621 #. After that comes the name of an object which is currently in scope -- in
622 the same room as the player.
624 #. If players type something that matches one of those patterns, the
625 interpreter triggers a ``Salute`` action, which by default is dealt with
626 by the ``SaluteSub`` routine.
628 So, we're allowing BOW AT HAT and KOWTOW TOWARDS HAT, but not simply NOD
629 HAT. We're allowing SALUTE HAT but not GREET TO HAT. It's not perfect,
630 but it's a fair attempt at defining some new verbs to handle salutation.
632 But suppose that we think of still other ways in which players might
633 attempt this (remember, they don't know which verbs we've defined; they're
634 just stabbing in the dark, trying out things that seem as though they ought
635 to work). How about PAY HOMAGE TO HAT, or maybe WAVE AT HAT? They sound
636 pretty reasonable, don't they? Except that, if we'd written::
638 Verb 'bow' 'nod' 'kowtow' 'genuflect' 'wave'
639 * 'at'/'to'/'towards' noun -> Salute;
641 we'd have caused a compilation error: two different verb definitions refer
642 to "wave". ``Grammar.h``, one of the library files whose contents a
643 beginner might find useful to study, contains these lines::
645 Verb 'give' 'pay' 'offer' 'feed'
646 * held 'to' creature -> Give
647 * creature held -> Give reverse
648 * 'over' held 'to' creature -> Give;
654 The problem is that the verbs PAY and WAVE are already defined by the
655 library, and Inform's rule is that a verb can appear in only one ``Verb``
656 definition. The wrong solution: edit ``Grammar.h`` to *physically* add
657 lines to the existing definitions (it's almost never a good idea to make
658 changes to the standard library files). The right solution: use ``Extend``
659 to *logically* add those lines. If we write this in our source file::
662 * 'homage' 'to' noun -> Salute;
665 * 'at' noun -> Salute;
667 then the effect is exactly as if we'd edited ``Grammar.h`` to read like
670 Verb 'give' 'pay' 'offer' 'feed'
671 * held 'to' creature -> Give
672 * creature held -> Give reverse
673 * 'over' held 'to' creature -> Give
674 * 'homage' 'to' noun -> Salute;
679 * 'at' noun -> Salute;
681 and now players can PAY (or GIVE, or OFFER) HOMAGE to any object. (Because
682 GIVE, PAY, OFFER and FEED are defined as synonyms, players can also FEED
683 HOMAGE, but it's unlikely that anybody will notice this minor aberration;
684 players are usually too busy trying to figure out *logical* possibilities.)
688 As usual, we'll first show you the default handler for this action::
692 print_ret "What, just fire off an arrow at random?";
693 if (BowOrArrow(second) == true)
694 print_ret "Unthinkable!";
699 Some designers frown on the use of a rhetorical question like that,
700 since it may provoke a reply from the player. Admittedly the default
701 response from YES and NO covers the situation, but it might be better
702 design practice to reword the message as a statement rather than a
705 Here is the associated grammar::
707 Verb 'fire' 'shoot' 'aim'
710 * 'at' noun -> FireAt
711 * 'at' noun 'with' noun -> FireAt
712 * noun 'with' noun -> FireAt
713 * noun 'at' noun -> FireAt reverse;
715 This is the most complex grammar that we'll write, and the first one
716 offering several different options for the words which follow the initial
717 verb. The first line of grammar::
721 is going to let us type FIRE (or SHOOT, or AIM) by itself. The second
726 supports FIRE BOW or FIRE ARROW (or something less sensible like
727 FIRE TREE). The third line::
729 * 'at' noun -> FireAt
731 accepts FIRE AT APPLE, FIRE AT TREE, and so on. Note that there's only one
732 semicolon in all of the grammar, right at the very end.
734 The first two statements in ``FireAtSub`` deal with the first line of
735 grammar: FIRE (or SHOOT, or AIM) by itself. If the player types just that,
736 both ``noun`` and ``second`` will contain ``nothing``, so we reject the
737 attempt with the "at random?" message. Otherwise, we've got at least a
738 ``noun`` value, and possibly a ``second`` value also, so we make our
739 standard check that ``second`` is something that can be fired, and then
740 reject the attempt with the "Unthinkable!" message.
742 There are a couple of reasons why you might find this grammar a bit tricky.
743 The first is that on some lines the word ``noun`` appears twice: you need
744 to remember that in this context ``noun`` is a parsing token which matches
745 any single object visible to the player. Thus, the line::
747 * 'at' noun 'with' noun -> FireAt
749 is matching FIRE AT :samp:`{some_visible_target}` WITH
750 :samp:`{some_visible_weapon}`; perhaps confusingly, the value of the target
751 object is then stored in variable ``noun``, and the value of the weapon
752 object in variable ``second``.
754 The second difficulty may be the final grammar line. Whereas on the
755 preceding lines, the first ``noun`` matches a target object and the second
756 ``noun``, if present, matches a weapon object, that final line matches FIRE
757 :samp:`{some_visible_weapon}` AT :samp:`{some_visible_target}` -- the two
758 objects are mentioned in the wrong sequence. If we did nothing, our
759 ``FireAtSub`` would get pretty confused at this point, but we can swap the
760 two objects back into the expected order by adding that ``reverse`` keyword
761 at the end of the line, and then ``FireAtSub`` will work the same in all
764 Before leaving the ``FireAt`` action, we'll add one more piece of grammar::
766 Extend 'attack' replace
769 This uses the ``Extend`` directive which we've just met, this time with a
770 ``replace`` keyword. The effect is to substitute the new grammar defined
771 here for that contained in ``Grammar.h``, so that ATTACK, KILL, MURDER and
772 all the other violent synonyms now trigger our ``FireAt`` action instead of
773 the Library's standard ``Attack`` action. We're doing this so that, in the
774 Marketplace, KILL GESSLER and MURDER WALTER have the same unfortunate
775 results as FIRE AT GESSLER and SHOOT WALTER.
779 The final action that we define -- ``Talk`` -- provides a simple system of
780 canned conversation, a low-key replacement for the standard ``Answer``,
781 ``Ask`` and ``Tell`` actions. The default ``TalkSub`` handler is closely
782 based on ``TellSub`` (defined in library file ``verblibm.h``, should you be
783 curious), and does three things:
785 #. Deals with TALK TO ME or TALK TO MYSELF.
787 #. Checks (a) whether the creature being talked to has a ``life``
788 property, (b) whether that property is prepared to process a ``Talk``
789 action, and (c) if the ``Talk`` processing returns ``true``. If all
790 three checks succeed then ``TalkSub`` need do nothing more; if one or
791 more of them fails then ``TalkSub`` simply...
793 #. Displays a general "nothing to say" refusal to talk. ::
796 if (noun == player) print_ret "Nothing you hear surprises you.";
797 if (RunLife(noun,##Talk) ~= false) return;
798 print_ret "At the moment, you can't think of anything to say.";
803 That second condition ``(RunLife(noun,##Talk) ~= false)`` is a bit of
804 a stumbling block, since it uses ``RunLife`` -- an undocumented
805 internal library routine -- to offer the ``Talk`` action to the NPC's
806 ``life`` property. We've decided to use it in exactly the same way
807 as the ``Tell`` action does, without worrying too much about how it
808 works (though it looks as though ``RunLife`` returns some ``true``
809 value if the ``life`` property has intercepted the action, ``false``
810 if it hasn't). The ``~=`` operator means "not equal to".
812 The grammar is straightforward::
814 Verb 'talk' 't//' 'converse' 'chat' 'gossip'
815 * 'to'/'with' creature -> Talk
818 Notice the use of ``'t//'`` to define T as a synonym for TALK, another way
819 to make life a little easier for the player. (Actually, doing this
820 introduces a minor problem: if the player types just T then the library
821 prompts "Whom do you want to t to?" The fix for this involves enhancing an
822 internal library routine called ``LanguageVerb`` -- not complex, but a
823 little too heavy for our second game.)
825 Here's the simplest ``Talk`` handler that we've seen -- it's from Gessler
826 the governor. Any attempt to TALK TO GESSLER will provoke "You cannot
827 bring yourself to speak to him". ::
830 Talk: print_ret "You cannot bring yourself to speak to him.";
833 Walter's ``Talk`` handler is only slightly more involved::
837 if (location == marketplace)
838 print_ret "~Stay calm, my son, and trust in God.~";
839 print_ret "You point out a few interesting sights.";
842 And Helga's is the most sophisticated (though that isn't saying much)::
844 times_spoken_to 0, ! for counting the conversation topics
847 self.times_spoken_to = self.times_spoken_to + 1;
848 switch (self.times_spoken_to) {
849 1: score = score + 1;
850 print_ret "You warmly thank Helga for the apple.";
851 2: print_ret "~See you again soon.~";
857 This handler uses Helga's ``times_spoken_to`` property -- not a library
858 property, it's one that we invented, like the ``mid_square.warnings_count``
859 and ``pole.has_been_saluted`` properties -- to keep track of what's been
860 said, permitting two snatches of conversation (and awarding a point) before
861 falling back on the embarrassing silences implied by "You can't think of
864 That's the end of our little fable; you'll find a transcript and the full
865 source in "William Tell" story on page 219. And now, it's time to meet --