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 .. include:: /config/typethis.rst
32 Room marketplace "Marketplace near the square"
34 "Altdorf's marketplace, close by the town square, has been hastily
35 cleared of stalls. A troop of soldiers has pushed back the crowd
36 to leave a clear space in front of the lime tree, which has been
37 growing here for as long as anybody can remember. Usually it
38 provides shade for the old men of the town, who gather below to
39 gossip, watch the girls, and play cards. Today, though, it
40 stands alone... apart, that is, from Walter, who has been lashed
41 to the trunk. About forty yards away, you are restrained by two
43 cant_go "What? And leave your son tied up here?";
45 Object tree "lime tree" marketplace
46 with name 'lime' 'tree',
47 description "It's just a large tree.",
50 if (BowOrArrow(second) == true) {
52 print_ret "Your hand shakes a little, and your arrow flies
53 high, hitting the trunk a few inches above Walter's
60 The tree's :prop:`before` property is intercepting a :act:`FireAt` action,
61 which we'll define in a few moments. This action is the result of a
62 command like SHOOT AT TREE WITH BOW -- we could simulate it with the
63 statement ``<<FireAt tree bow>>`` -- and it needs extra care to ensure that
64 the :var:`second` object is a feasible weapon. To deal with silly commands
65 like SHOOT AT TREE WITH HELGA, we must test that :var:`second` is the bow,
66 one of the arrows, or ``nothing`` (from just SHOOT AT TREE). Since this is
67 quite a complex test, and one that we'll be making in several places, it's
68 sensible to write a routine to do the job. Which we'll do shortly -- but
69 first, a general introduction to working with routines.
72 single: arguments (of a routine)
74 .. _working-with-routines:
76 A diversion: working with routines
77 ==================================
79 .. Generated by autoindex
81 pair: each_turn; library property
83 A standalone routine, like the familiar routines embedded as the value of a
84 property such as :prop:`before` or :prop:`each_turn`, is simply a set of statements
85 to be executed. The major differences are in content, in timing, and in
86 the default return value:
88 * Whereas an embedded routine has to contain statements which do something
89 appropriate for that associated property variable, a standalone routine
90 can contain statements which do anything you wish. You have total
91 freedom as to what the routine actually does and what value it returns.
93 * An embedded routine is called when the interpreter is dealing with that
94 property of that object; you provide the routine, but you don't directly
95 control when it's called. A standalone routine, however, is completely
96 under your control; it runs only when you explicitly call it.
98 .. Generated by autoindex
100 pair: false; library constant
101 pair: true; library constant
103 * If an embedded routine executes all of its statements and reaches the
104 final ``];`` without encountering some form of ``return`` statement, it
105 returns the value :const:`false`. In the same circumstances, a standalone
106 routine returns the value :const:`true`. There's a good reason for this
107 difference -- it usually turns out to be the natural default behaviour --
108 but it can sometimes baffle newcomers. To avoid confusion, we've always
109 included explicit ``return`` statements in our routines.
111 What this generally boils down to is: *if* you have a collection of
112 statements which perform some specific task *and* you need to execute those
113 same statements in more than one place in your game, *then* it often makes
114 sense to turn those statements into a standalone routine. The advantages
115 are: you write the statements only once, so any subsequent changes are
116 easier to make; also, your game becomes simpler and easier to read. We'll
117 look at some simple examples; first consider these unexciting foodstuffs::
119 Object "stale ham sandwich"
120 with name 'stale' 'ham' 'sandwich',
121 description "It doesn't look at all appetising.",
124 Object "elderly jam doughnut"
125 with name 'elderly' 'jam' 'jelly' 'doughnut' 'donut',
126 description "It doesn't look at all appetising.",
129 The :prop:`description`\s are identical: perhaps we could display them using a
132 [ Inedible; print_ret "It doesn't look at all appetising."; ];
134 Object "stale ham sandwich"
135 with name 'stale' 'ham' 'sandwich',
136 description [; Inedible(); ],
139 Object "elderly jam doughnut"
140 with name 'elderly' 'jam' 'jelly' 'doughnut' 'donut',
141 description [; Inedible(); ],
144 This isn't a very realistic approach -- there are more elegant ways of
145 avoiding typing the same string twice -- but it works, and it illustrates
146 how we can define a routine to do something useful, and then call it
149 Here's another simple example showing how, by returning a value, a routine
150 can report back to the piece of code which called it. We've once or twice
151 used the test ``if (self has visited) ...``; we could create a routine
152 which performs that same check and then returns :const:`true` or :const:`false` to
153 indicate what it discovered::
156 if (self has visited) return true;
160 Then, we'd rewrite our test as ``if (BeenHereBefore() == true) ...``; no
161 shorter or quicker, but maybe more descriptive of what's going on. One
162 more example of using routines. As well as testing ``if (self has visited)
163 ...`` we've also tested ``if (location has visited) ...`` a few times, so
164 we *could* write another routine to perform that check::
167 if (location has visited) return true;
171 .. Generated by autoindex
173 pair: location; library variable
174 pair: self; library variable
176 However, the two routines are very similar; the only difference is the name
177 of the variable -- :var:`self` or :var:`location` -- which is being checked. A
178 better approach might be to rework our ``BeenHereBefore`` routine so that
179 it does both jobs, but we somehow need to tell it which variable's value is
180 to be checked. That's easy: we design the routine so that it expects an
183 [ BeenToBefore this_room;
184 if (this_room has visited) return true;
188 Notice that the argument's name is one that we've invented to be
189 descriptive of its content; it doesn't matter if we define it as "``x``",
190 "``this_room``" or "``hubba_hubba``". Whatever its name, the argument acts
191 as a placeholder for a value (here, one of the variables :var:`self` or
192 :var:`location`) which we must supply when calling the routine::
194 if (BeenToBefore(self) == true) ...
196 if (BeenToBefore(location) == true) ...
198 .. Generated by autoindex
200 pair: visited; library attribute
202 In the first line, we supply :var:`self` as the routine's argument. The
203 routine doesn't care where the argument came from; it just sees a value
204 which it knows as ``this_room``, and which it then uses to test for the
205 :attr:`visited` attribute. On the second line we supply :var:`location` as the
206 argument, but the routine just sees another value in its ``this_room``
207 variable. ``this_room`` is called a :term:`local variable` of the
208 ``BeenToBefore`` routine, one that must be set to a suitable value each
209 time that the routine is called. In this example routine, the value needs
210 to be a room object; we could also check an explicit named room::
212 if (BeenToBefore(mid_square) == true) ...
216 #. All routines terminate sooner or later, either because you explicitly
217 write a ``return``, ``rtrue`` or ``rfalse`` statement, or because
218 execution reaches the ``]`` marking the routine's end.
220 #. All routines return a value, which can be :const:`true`, or :const:`false`, or any
221 other number. This value is determined by the ``return``, ``rtrue`` or
222 ``rfalse`` statement, or by the the ``]`` marking the routine's end (in
223 which case the default STEF rule applies: Standalone routines return
224 True, Embedded routines return False). We gave this example of an
225 embedded routine in :ref:`adding-props`. The ``return false`` statement
226 is redundant: we could remove it without affecting the routine's
227 behaviour, because the ``]`` acts like a ``return false``::
230 if (location == street or below_square or south_square or
231 mid_square or north_square or marketplace) return true;
235 .. Generated by autoindex
237 pair: true; library constant
239 On the other hand, just because a routine returns a value doesn't mean
240 you always *have* to use it; you can simply ignore the value if you want
241 to. The ``TooFarAway`` routine that we showed you earlier in this
242 chapter contains a ``print_ret`` statement and so always returns
243 :const:`true`, but we didn't take any notice; the sole purpose of the routine
244 was to display some text. Compare this with the ``BeenToBefore``
245 routine, which does nothing *except* return a value; if we'd ignored
246 that, then calling the routine would have been a waste of time.
248 For some embedded routines, the value returned by the routine is important;
249 for others it doesn't matter. We've so far seen the following properties
250 whose value can be an embedded routine:
252 ========================= ===========================
253 Return value is important Return value doesn't matter
254 ========================= ===========================
255 ``after [; ... ],`` ``cant_go [; ... ],``
256 ``before [; ... ],`` ``description [; ... ],``
257 ``found_in [; ... ],`` ``each_turn [; ... ],``
258 ``n_to [; ... ]``, et al ``initial [; ... ],``
259 ========================= ===========================
261 For full details on which library property values can be embedded routines,
262 and which return values are significant, see :ref:`object-props` and
263 :dm4:`Appendix §A2 <sa2.html>` of the |DM4|.
265 Return to the marketplace
266 =========================
268 .. Generated by autoindex
270 pair: FireAt; library action
272 After all that introduction, finally back to the :act:`FireAt` action. We
273 want to check on the characteristics of an object, possibly then displaying
274 a message. We don't know exactly *which* object is to be checked, so we
275 need to write our routine in a generalised way, capable of checking any
276 object which we choose; that is, we'll supply the object to be checked as
277 an argument. Here's the routine:
279 .. include:: /config/typethis.rst
284 if (o == bow or nothing || o ofclass Arrow) return true;
285 print "That's an unlikely weapon, isn't it?^";
289 The routine is designed to inspect any object which is passed to it as its
290 argument ``o``; that is, we could call the routine like this::
292 BowOrArrow(stallholder)
296 Given the ``bow`` object, or any object which we defined as class
297 ``Arrow``, it will silently ``return true`` to signify agreement that this
298 object can be fired. However, given an object like Helga, the apple or the
299 tree, it will print a message and ``return false`` to signify that this
300 object is not a suitable weapon. The test that we make is::
302 if (o == bow or nothing || o ofclass Arrow) ...
304 which is merely a slightly shorter way of saying this::
306 if (o == bow || o == nothing || o ofclass Arrow) ...
308 The result is that we ask three questions: Is ``o`` the ``bow`` object?
309 *Or* is it ``nothing``? Or, using the ``ofclass`` test, is it any object
310 which is a member of the ``Arrow`` class?
312 .. Generated by autoindex
314 pair: before; library property
315 pair: false; library constant
316 pair: second; library variable
318 What this means is that the value returned by the call ``BowOrArrow(bow)``
319 is :const:`true`, while the value returned by the call ``BowOrArrow(tree)`` is
320 :const:`false`. Or, more generally, the value returned by the call
321 ``BowOrArrow(second)`` will be either :const:`true` or :const:`false`, depending on
322 the characteristics of the object defined by the value of the variable
323 :var:`second`. So, we can write this set of statements in an object's
324 :prop:`before` property::
326 if (BowOrArrow(second) == true) {
327 This object deals with having an arrow fired at it
331 and the effect is either
333 * :var:`second` is a weapon: ``BowOrArrow`` displays nothing and returns a
334 value of :const:`true`, the ``if`` statement reacts to that value and executes
335 the following statements to produce an appropriate response to the
336 fast-approaching arrow; or
338 * :var:`second` isn't a weapon: ``BowOrArrow`` displays a standard "don't be
339 silly" message and returns a value of :const:`false`, the ``if`` statement
340 reacts to that value and ignores the following statements. Then
342 * in both cases, the ``return true`` statement terminates the object's
343 interception of the :act:`FireAt` action.
345 .. Generated by autoindex
347 pair: deadflag; library variable
349 That whole ``BowOrArrow()`` bit was rather complex, but the rest of the
350 :act:`FireAt` action is straightforward. Once the tree has determined that
351 it's being shot at by something sensible, it can just set :var:`deadflag`
352 to 3 -- the "You have screwed up" ending, display a message, and be done.
357 There's nothing in Gessler's definition that we haven't already
360 .. include:: /config/typethis.rst
364 NPC governor "governor" marketplace
365 with name 'governor' 'vogt' 'Hermann' 'Gessler',
367 "Short, stout but with a thin, mean face, Gessler relishes the
368 power he holds over the local community.",
370 print "Gessler is watching from a safe distance,
371 a sneer on his face.^";
372 if (location hasnt visited)
373 print_ret "^~It appears that you need to be taught a lesson,
374 fool. Nobody shall pass through the square without paying
375 homage to His Imperial Highness Albert; nobody, hear me?
376 I could have you beheaded for treason, but I'm going to
377 be lenient. If you should be so foolish again, you can
378 expect no mercy, but this time, I'll let you go free...
379 just as soon as you demonstrate your archery skills by
380 hitting this apple from where you stand. That shouldn't
381 prove too difficult; here, sergeant, catch. Balance it on
382 the little bastard's head.~";
386 print_ret "You cannot bring yourself to speak to him.";
390 if (BowOrArrow(second) == true) {
392 print_ret "Before the startled soldiers can react, you turn
393 and fire at Gessler; your arrow pierces his heart,
394 and he dies messily. A gasp, and then a cheer,
395 goes up from the crowd.";
401 Like most NPCs, Gessler has a :prop:`life` property which deals with
402 actions applicable only to animate objects. This one responds merely to
403 :act:`Talk` (as in TALK TO THE GOVERNOR).
408 Since he's been with you throughout, it's really about time we defined
411 .. include:: /config/typethis.rst
416 with name 'son' 'your' 'boy' 'lad' 'Walter',
418 if (location == marketplace)
419 print_ret "He stares at you, trying to appear brave and
420 remain still. His arms are pulled back and tied behind
421 the trunk, and the apple nestles amid his blond hair.";
423 print_ret "A quiet, blond lad of eight summers, he's fast
424 learning the ways of mountain folk.";
430 print_ret "~Thank you, Papa.~";
432 if (location == marketplace)
433 print_ret "~Stay calm, my son, and trust in God.~";
435 print_ret "You point out a few interesting sights.";
438 Examine,Listen,Salute,Talk:
441 if (location == marketplace) {
442 if (BowOrArrow(second) == true) {
444 print_ret "Oops! Surely you didn't mean to do that?";
451 if (location == marketplace)
452 print_ret "Your guards won't permit it.";
456 found_in [; return true; ],
457 has male proper scenery transparent;
459 His attributes are :attr:`male` (he's your son, after all), :attr:`proper` (so the
460 interpreter doesn't mention "the your son"), :attr:`scenery` (so he's not
461 listed in every room description), and :attr:`transparent` (because you see
462 right through him). No, that's wrong: a :attr:`transparent` object isn't made
463 of glass; it's one whose possessions are visible to you. We've done that
464 because we'd still like to be able to EXAMINE APPLE even when Walter is
465 carrying it. Without the :attr:`transparent` attribute, it would be as though
466 the apple was in his pocket or otherwise out of sight; the interpreter
467 would reply "You can't see any such thing".
469 .. Generated by autoindex
471 pair: found_in; library property
473 Walter has a :prop:`found_in` property which automatically moves him to the
474 player's location on each turn. We can get away with this because in such
475 a short and simple game, he does indeed follow you everywhere. In a more
476 realistic model world, NPCs often move around independently, but we don't
477 need such complexity here.
479 Several of Walter's properties test whether ``(location == marketplace)``;
480 that is, is the player (and hence Walter) currently in that room? The
481 events in the marketplace are such that specialised responses are more
482 appropriate there than our standard ones.
484 .. Generated by autoindex
486 pair: Give; library action
487 pair: before; library property
488 pair: score; library variable
490 Walter's :prop:`life` property responds to :act:`Give` (as in GIVE APPLE TO
491 WALTER) and Talk (as in TALK TO YOUR SON); during :act:`Give`, we increment
492 the library variable :var:`score`, thus rewarding the player's generous
493 good nature. His :prop:`before` property is perhaps a little confusing.
496 .. Generated by autoindex
498 pair: Examine; library action
499 pair: Listen; library action
500 pair: Salute; library action
502 #. The :act:`Examine`, :act:`Listen`, :act:`Salute` and :act:`Talk` actions
503 are always available (a :act:`Talk` action then gets passed to Walter's
504 :prop:`life` property).
506 .. Generated by autoindex
508 pair: FireAt; library action
510 #. The :act:`FireAt` action is permitted in the ``marketplace``, albeit
511 with unfortunate results. Elsewhere, it triggers the standard
512 :act:`FireAt` response of "Unthinkable!"
514 #. All other actions are prevented in the ``marketplace``, and allowed to
515 run their standard course (thanks to the ``return false``) elsewhere.
517 .. Generated by autoindex
519 pair: deadflag; library variable
521 The apple's moment of glory has arrived! Its :prop:`before` property
522 responds to the :act:`FireAt` action by setting :var:`deadflag` to 2. When
523 that happens, the game is over; the player has won.
525 .. include:: /config/typethis.rst
532 if (location == marketplace)
533 print_ret "At this distance you can barely see it.";
535 print_ret "The apple is blotchy green and brown.";
539 print_ret "An apple is worth quite a bit --
540 better hang on to it.";
542 print_ret "Helga intended it for Walter...";
544 if (location == marketplace) {
545 if (BowOrArrow(second) == true) {
548 print_ret "Slowly and steadily, you place an arrow in
549 the bow, draw back the string, and take aim with
550 more care than ever in your life. Holding your
551 breath, unblinking, fearful, you release the
552 arrow. It flies across the square towards your
553 son, and drives the apple against the trunk of
554 the tree. The crowd erupts with joy;
555 Gessler looks distinctly disappointed.";
563 And with that, we've defined all of the objects. In doing so, we've added
564 a whole load of new nouns and adjectives to the game's dictionary, but no
565 verbs. That's the final task.
572 .. Generated by autoindex
574 pair: Talk; library action
576 The Inform library delivers a standard set of nearly a hundred actions
577 which players can perform; around twenty of those are "meta-actions" (like
578 SAVE and QUIT) aimed at the interpreter itself, and the remainder operate
579 within the model world. Having such a large starting set is a great
580 blessing; it means that many of the actions which players might attempt are
581 already catered for, either by the interpreter doing something useful, or
582 by explaining why it's unable to. Nevertheless, most games find the need
583 to define additional actions, and "William Tell" is no exception. We'll be
584 adding four actions of our own: :act:`Untie`, :act:`Salute`, :act:`FireAt`
589 It's not the most useful action, but it is the simplest. In the
590 marketplace, when Walter is lashed to the tree, it's possible that players
591 might be tempted to try to UNTIE WALTER; unlikely, but as we've said
592 before, anticipating the improbable is part of the craft of IF. For this,
593 and for all new actions, two things are required. We need a grammar
594 definition, spelling out the structure of the English sentences which we're
597 .. include:: /config/typethis.rst
601 Verb 'untie' 'unfasten' 'unfix' 'free' 'release'
604 and we need a routine to handle the action in the default situation (where
605 the action isn't intercepted by an object's :prop:`before` property).
607 .. include:: /config/typethis.rst
611 [ UntieSub; print_ret "You really shouldn't try that."; ];
613 The grammar is less complex than it perhaps at first appears:
615 #. The English verbs UNTIE, UNFASTEN, UNFIX, FREE and RELEASE are
618 #. The asterisk ``*`` indicates the start of a pattern defining what
619 word(s) might follow the verb.
621 #. In this example, there's only one pattern: the ":var:`noun`" token
622 represents an object which is currently in scope -- in the same room as
625 #. The ``->`` indicates an action to be triggered.
627 .. Generated by autoindex
629 pair: Untie; library action
631 #. If players type something that matches the pattern -- one of those five
632 verbs followed by an object in scope -- the interpreter triggers an
633 :act:`Untie` action, which by default is handled by a routine having the
634 same name as the action, with ``Sub`` appended. In this example, that's
635 the ``UntieSub`` routine.
637 #. The grammar is laid out this way just to make it easier to read. All those
638 spaces aren't important; we could equally have typed::
640 Verb 'untie' 'unfasten' 'unfix' 'free' 'release' * noun -> Untie;
642 We can illustrate how this works in the Altdorf street:
644 .. code-block:: transcript
647 The narrow street runs north towards the town square. Local folk are pouring
648 into the town through the gate to the south, shouting greetings, offering
649 produce for sale, exchanging news, enquiring with exaggerated disbelief about
650 the prices of the goods displayed by merchants whose stalls make progress even
653 "Stay close to me, son," you say, "or you'll get lost among all these people."
656 What do you want to untie?
659 You can't see any such thing.
662 You don't need to worry about the local people.
665 You really shouldn't try that.
667 The illustration shows four attempted usages of the new action. In the
668 first, the player omits to mention an object; the interpreter knows (from
669 that :var:`noun` in the grammar which implies that the action needs a
670 direct object) that something is missing, so it issues a helpful prompt.
671 In the second, the player mentions an object that isn't in scope (in fact,
672 there's no dog anywhere in the game, but the interpreter isn't about to
673 give *that* away to the player). In the third, the object is in scope, but
674 its :prop:`before` property intercepts the :act:`Untie` action (and indeed,
675 since this object is of the class ``Prop``, all actions apart from
676 :act:`Examine`) to display a customised rejection message. Finally, the
677 fourth usage refers to an object which *doesn't* intercept the action, so
678 the interpreter calls the default action handler -- ``UntieSub`` -- which
679 displays a general-purpose refusal to perform the action.
681 The principles presented here are those that you should generally employ:
682 write a generic action handler which either refuses to do anything (see,
683 for example SQUASH or HIT), or performs the action without affecting the
684 state of the model world (see, for example, JUMP or WAVE); then, intercept
685 that non-action (generally using a :prop:`before` property) for those objects
686 which might make a legitimate target for the action, and instead provide a
687 more specific response, either performing or rejecting the action.
689 In the case of :act:`Untie`, there are no objects which can be untied in
690 this game, so we always generate a refusal of some sort.
694 .. Generated by autoindex
696 pair: Salute; library action
698 The next action is :act:`Salute`, provided in case Wilhelm chooses to defer
699 to the hat on the pole. Here's the default action handler:
701 .. include:: /config/typethis.rst
706 if (noun has animate) print_ret (The) noun, " acknowledges you.";
707 print_ret (The) noun, " takes no notice.";
710 You'll notice that this is slightly more intelligent than our :act:`Untie`
711 handler, since it produces different responses depending on whether the
712 object being saluted -- stored in the :var:`noun` variable -- is
713 :attr:`animate` or not. But it's basically doing the same job. And here's
716 .. include:: /config/typethis.rst
720 Verb 'bow' 'nod' 'kowtow' 'genuflect'
721 * 'at'/'to'/'towards' noun -> Salute;
723 Verb 'salute' 'greet' 'acknowledge'
726 This grammar says that:
728 #. The English verbs BOW, NOD, KOWTOW, GENUFLECT, SALUTE, GREET and
729 ACKNOWLEDGE are synonymous.
731 #. The first four (but not the last three) can then be followed by any of
732 the prepositions AT, TO or TOWARDS: words in apostrophes ``'...'`` are
733 matched literally, with the slash ``/`` separating alternatives.
735 #. After that comes the name of an object which is currently in scope -- in
736 the same room as the player.
738 #. If players type something that matches one of those patterns, the
739 interpreter triggers a :act:`Salute` action, which by default is dealt
740 with by the ``SaluteSub`` routine.
742 So, we're allowing BOW AT HAT and KOWTOW TOWARDS HAT, but not simply NOD
743 HAT. We're allowing SALUTE HAT but not GREET TO HAT. It's not perfect,
744 but it's a fair attempt at defining some new verbs to handle salutation.
746 But suppose that we think of still other ways in which players might
747 attempt this (remember, they don't know which verbs we've defined; they're
748 just stabbing in the dark, trying out things that seem as though they ought
749 to work). How about PAY HOMAGE TO HAT, or maybe WAVE AT HAT? They sound
750 pretty reasonable, don't they? Except that, if we'd written::
752 Verb 'bow' 'nod' 'kowtow' 'genuflect' 'wave'
753 * 'at'/'to'/'towards' noun -> Salute;
755 we'd have caused a compilation error: two different verb definitions refer
756 to "wave". ``Grammar.h``, one of the library files whose contents a
757 beginner might find useful to study, contains these lines::
759 Verb 'give' 'pay' 'offer' 'feed'
760 * held 'to' creature -> Give
761 * creature held -> Give reverse
762 * 'over' held 'to' creature -> Give;
768 The problem is that the verbs PAY and WAVE are already defined by the
769 library, and Inform's rule is that a verb can appear in only one ``Verb``
770 definition. The wrong solution: edit ``Grammar.h`` to *physically* add
771 lines to the existing definitions (it's almost never a good idea to make
772 changes to the standard library files). The right solution: use ``Extend``
773 to *logically* add those lines. If we write this in our source file:
775 .. include:: /config/typethis.rst
780 * 'homage' 'to' noun -> Salute;
783 * 'at' noun -> Salute;
785 then the effect is exactly as if we'd edited ``Grammar.h`` to read like
788 Verb 'give' 'pay' 'offer' 'feed'
789 * held 'to' creature -> Give
790 * creature held -> Give reverse
791 * 'over' held 'to' creature -> Give
792 * 'homage' 'to' noun -> Salute;
797 * 'at' noun -> Salute;
799 and now players can PAY (or GIVE, or OFFER) HOMAGE to any object. (Because
800 GIVE, PAY, OFFER and FEED are defined as synonyms, players can also FEED
801 HOMAGE, but it's unlikely that anybody will notice this minor aberration;
802 players are usually too busy trying to figure out *logical* possibilities.)
806 As usual, we'll first show you the default handler for this action:
808 .. include:: /config/typethis.rst
814 print_ret "What, just fire off an arrow at random?";
815 if (BowOrArrow(second) == true)
816 print_ret "Unthinkable!";
821 Some designers frown on the use of a rhetorical question like that,
822 since it may provoke a reply from the player. Admittedly the default
823 response from YES and NO covers the situation, but it might be better
824 design practice to reword the message as a statement rather than a
827 Here is the associated grammar:
829 .. include:: /config/typethis.rst
833 Verb 'fire' 'shoot' 'aim'
836 * 'at' noun -> FireAt
837 * 'at' noun 'with' noun -> FireAt
838 * noun 'with' noun -> FireAt
839 * noun 'at' noun -> FireAt reverse;
841 This is the most complex grammar that we'll write, and the first one
842 offering several different options for the words which follow the initial
843 verb. The first line of grammar::
847 is going to let us type FIRE (or SHOOT, or AIM) by itself. The second
852 supports FIRE BOW or FIRE ARROW (or something less sensible like
853 FIRE TREE). The third line::
855 * 'at' noun -> FireAt
857 accepts FIRE AT APPLE, FIRE AT TREE, and so on. Note that there's only one
858 semicolon in all of the grammar, right at the very end.
860 .. Generated by autoindex
862 pair: noun; library variable
863 pair: second; library variable
865 The first two statements in ``FireAtSub`` deal with the first line of
866 grammar: FIRE (or SHOOT, or AIM) by itself. If the player types just that,
867 both :var:`noun` and :var:`second` will contain ``nothing``, so we reject the
868 attempt with the "at random?" message. Otherwise, we've got at least a
869 :var:`noun` value, and possibly a :var:`second` value also, so we make our
870 standard check that :var:`second` is something that can be fired, and then
871 reject the attempt with the "Unthinkable!" message.
873 There are a couple of reasons why you might find this grammar a bit tricky.
874 The first is that on some lines the word :var:`noun` appears twice: you need
875 to remember that in this context :var:`noun` is a parsing token which matches
876 any single object visible to the player. Thus, the line::
878 * 'at' noun 'with' noun -> FireAt
880 is matching FIRE AT :samp:`{some_visible_target}` WITH
881 :samp:`{some_visible_weapon}`; perhaps confusingly, the value of the target
882 object is then stored in variable :var:`noun`, and the value of the weapon
883 object in variable :var:`second`.
885 The second difficulty may be the final grammar line. Whereas on the
886 preceding lines, the first :var:`noun` matches a target object and the second
887 :var:`noun`, if present, matches a weapon object, that final line matches FIRE
888 :samp:`{some_visible_weapon}` AT :samp:`{some_visible_target}` -- the two
889 objects are mentioned in the wrong sequence. If we did nothing, our
890 ``FireAtSub`` would get pretty confused at this point, but we can swap the
891 two objects back into the expected order by adding that ``reverse`` keyword
892 at the end of the line, and then ``FireAtSub`` will work the same in all
895 .. Generated by autoindex
897 pair: FireAt; library action
899 Before leaving the :act:`FireAt` action, we'll add one more piece of
902 .. include:: /config/typethis.rst
906 Extend 'attack' replace
909 This uses the ``Extend`` directive which we've just met, this time with a
910 ``replace`` keyword. The effect is to substitute the new grammar defined
911 here for that contained in ``Grammar.h``, so that ATTACK, KILL, MURDER and
912 all the other violent synonyms now trigger our :act:`FireAt` action instead
913 of the Library's standard :act:`Attack` action. We're doing this so that,
914 in the Marketplace, KILL GESSLER and MURDER WALTER have the same
915 unfortunate results as FIRE AT GESSLER and SHOOT WALTER.
919 .. Generated by autoindex
921 pair: Answer; library action
922 pair: Ask; library action
923 pair: Talk; library action
924 pair: Tell; library action
926 The final action that we define -- :act:`Talk` -- provides a simple system
927 of canned conversation, a low-key replacement for the standard
928 :act:`Answer`, :act:`Ask` and :act:`Tell` actions. The default ``TalkSub``
929 handler is closely based on ``TellSub`` (defined in library file
930 ``verblibm.h``, should you be curious), and does three things:
932 #. Deals with TALK TO ME or TALK TO MYSELF.
934 .. Generated by autoindex
936 pair: life; library property
937 pair: true; library constant
939 #. Checks (a) whether the creature being talked to has a :prop:`life`
940 property, (b) whether that property is prepared to process a :act:`Talk`
941 action, and (c) if the :act:`Talk` processing returns :const:`true`. If
942 all three checks succeed then ``TalkSub`` need do nothing more; if one
943 or more of them fails then ``TalkSub`` simply...
945 #. Displays a general "nothing to say" refusal to talk.
947 .. include:: /config/typethis.rst
952 if (noun == player) print_ret "Nothing you hear surprises you.";
953 if (RunLife(noun,##Talk) ~= false) return;
954 print_ret "At the moment, you can't think of anything to say.";
959 That second condition ``(RunLife(noun,##Talk) ~= false)`` is a bit of
960 a stumbling block, since it uses ``RunLife`` -- an undocumented
961 internal library routine -- to offer the :act:`Talk` action to the
962 NPC's :prop:`life` property. We've decided to use it in exactly the
963 same way as the :act:`Tell` action does, without worrying too much
964 about how it works (though it looks as though ``RunLife`` returns
965 some :const:`true` value if the :prop:`life` property has intercepted
966 the action, :const:`false` if it hasn't). The ``~=`` operator means
969 The grammar is straightforward::
971 Verb 'talk' 't//' 'converse' 'chat' 'gossip'
972 * 'to'/'with' creature -> Talk
975 Notice the use of ``'t//'`` to define T as a synonym for TALK, another way
976 to make life a little easier for the player. (Actually, doing this
977 introduces a minor problem: if the player types just T then the library
978 prompts "Whom do you want to t to?" The fix for this involves enhancing an
979 internal library routine called ``LanguageVerb`` -- not complex, but a
980 little too heavy for our second game.)
982 Here's the simplest :act:`Talk` handler that we've seen -- it's from
983 Gessler the governor. Any attempt to TALK TO GESSLER will provoke "You
984 cannot bring yourself to speak to him". ::
987 Talk: print_ret "You cannot bring yourself to speak to him.";
990 Walter's :act:`Talk` handler is only slightly more involved::
994 if (location == marketplace)
995 print_ret "~Stay calm, my son, and trust in God.~";
996 print_ret "You point out a few interesting sights.";
999 And Helga's is the most sophisticated (though that isn't saying much)::
1001 times_spoken_to 0, ! for counting the conversation topics
1004 self.times_spoken_to = self.times_spoken_to + 1;
1005 switch (self.times_spoken_to) {
1006 1: score = score + 1;
1007 print_ret "You warmly thank Helga for the apple.";
1008 2: print_ret "~See you again soon.~";
1014 This handler uses Helga's :prop:`times_spoken_to` property -- not a library
1015 property, it's one that we invented, like the
1016 :prop:`mid_square.warnings_count` and :prop:`pole.has_been_saluted`
1017 properties -- to keep track of what's been said, permitting two snatches of
1018 conversation (and awarding a point) before falling back on the embarrassing
1019 silences implied by "You can't think of anything to say".
1021 That's the end of our little fable; you'll find a transcript and the full
1022 source in :doc:`/appendices/c`. And now, it's time to meet -- Captain