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