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 :prop:`before` property is intercepting a :act:`FireAt` action,
57 which we'll define in a few moments. This action is the result of a
58 command like SHOOT AT TREE WITH BOW -- we could simulate it with the
59 statement ``<<FireAt tree bow>>`` -- and it needs extra care to ensure that
60 the :var:`second` object is a feasible weapon. To deal with silly commands
61 like SHOOT AT TREE WITH HELGA, we must test that :var:`second` is the bow,
62 one of the arrows, or ``nothing`` (from just SHOOT AT TREE). Since this is
63 quite 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.
68 single: arguments (of a routine)
70 .. _working-with-routines:
72 A diversion: working with routines
73 ==================================
75 .. Generated by autoindex
77 pair: each_turn; library property
79 A standalone routine, like the familiar routines embedded as the value of a
80 property such as :prop:`before` or :prop:`each_turn`, is simply a set of statements
81 to be executed. The major differences are in content, in timing, and in
82 the default return value:
84 * Whereas an embedded routine has to contain statements which do something
85 appropriate for that associated property variable, a standalone routine
86 can contain statements which do anything you wish. You have total
87 freedom as to what the routine actually does and what value it returns.
89 * An embedded routine is called when the interpreter is dealing with that
90 property of that object; you provide the routine, but you don't directly
91 control when it's called. A standalone routine, however, is completely
92 under your control; it runs only when you explicitly call it.
94 .. Generated by autoindex
96 pair: false; library constant
97 pair: true; library constant
99 * If an embedded routine executes all of its statements and reaches the
100 final ``];`` without encountering some form of ``return`` statement, it
101 returns the value :const:`false`. In the same circumstances, a standalone
102 routine returns the value :const:`true`. There's a good reason for this
103 difference -- it usually turns out to be the natural default behaviour --
104 but it can sometimes baffle newcomers. To avoid confusion, we've always
105 included explicit ``return`` statements in our routines.
107 What this generally boils down to is: *if* you have a collection of
108 statements which perform some specific task *and* you need to execute those
109 same statements in more than one place in your game, *then* it often makes
110 sense to turn those statements into a standalone routine. The advantages
111 are: you write the statements only once, so any subsequent changes are
112 easier to make; also, your game becomes simpler and easier to read. We'll
113 look at some simple examples; first consider these unexciting foodstuffs::
115 Object "stale ham sandwich"
116 with name 'stale' 'ham' 'sandwich',
117 description "It doesn't look at all appetising.",
120 Object "elderly jam doughnut"
121 with name 'elderly' 'jam' 'jelly' 'doughnut' 'donut',
122 description "It doesn't look at all appetising.",
125 The :prop:`description`\s are identical: perhaps we could display them using a
128 [ Inedible; print_ret "It doesn't look at all appetising."; ];
130 Object "stale ham sandwich"
131 with name 'stale' 'ham' 'sandwich',
132 description [; Inedible(); ],
135 Object "elderly jam doughnut"
136 with name 'elderly' 'jam' 'jelly' 'doughnut' 'donut',
137 description [; Inedible(); ],
140 This isn't a very realistic approach -- there are more elegant ways of
141 avoiding typing the same string twice -- but it works, and it illustrates
142 how we can define a routine to do something useful, and then call it
145 Here's another simple example showing how, by returning a value, a routine
146 can report back to the piece of code which called it. We've once or twice
147 used the test ``if (self has visited) ...``; we could create a routine
148 which performs that same check and then returns :const:`true` or :const:`false` to
149 indicate what it discovered::
152 if (self has visited) return true;
156 Then, we'd rewrite our test as ``if (BeenHereBefore() == true) ...``; no
157 shorter or quicker, but maybe more descriptive of what's going on. One
158 more example of using routines. As well as testing ``if (self has visited)
159 ...`` we've also tested ``if (location has visited) ...`` a few times, so
160 we *could* write another routine to perform that check::
163 if (location has visited) return true;
167 .. Generated by autoindex
169 pair: location; library variable
170 pair: self; library variable
172 However, the two routines are very similar; the only difference is the name
173 of the variable -- :var:`self` or :var:`location` -- which is being checked. A
174 better approach might be to rework our ``BeenHereBefore`` routine so that
175 it does both jobs, but we somehow need to tell it which variable's value is
176 to be checked. That's easy: we design the routine so that it expects an
179 [ BeenToBefore this_room;
180 if (this_room has visited) return true;
184 Notice that the argument's name is one that we've invented to be
185 descriptive of its content; it doesn't matter if we define it as "``x``",
186 "``this_room``" or "``hubba_hubba``". Whatever its name, the argument acts
187 as a placeholder for a value (here, one of the variables :var:`self` or
188 :var:`location`) which we must supply when calling the routine::
190 if (BeenToBefore(self) == true) ...
192 if (BeenToBefore(location) == true) ...
194 .. Generated by autoindex
196 pair: visited; library attribute
198 In the first line, we supply :var:`self` as the routine's argument. The
199 routine doesn't care where the argument came from; it just sees a value
200 which it knows as ``this_room``, and which it then uses to test for the
201 :attr:`visited` attribute. On the second line we supply :var:`location` as the
202 argument, but the routine just sees another value in its ``this_room``
203 variable. ``this_room`` is called a :term:`local variable` of the
204 ``BeenToBefore`` routine, one that must be set to a suitable value each
205 time that the routine is called. In this example routine, the value needs
206 to be a room object; we could also check an explicit named room::
208 if (BeenToBefore(mid_square) == true) ...
212 #. All routines terminate sooner or later, either because you explicitly
213 write a ``return``, ``rtrue`` or ``rfalse`` statement, or because
214 execution reaches the ``]`` marking the routine's end.
216 #. All routines return a value, which can be :const:`true`, or :const:`false`, or any
217 other number. This value is determined by the ``return``, ``rtrue`` or
218 ``rfalse`` statement, or by the the ``]`` marking the routine's end (in
219 which case the default STEF rule applies: Standalone routines return
220 True, Embedded routines return False). We gave this example of an
221 embedded routine in :ref:`adding-props`. The ``return false`` statement
222 is redundant: we could remove it without affecting the routine's
223 behaviour, because the ``]`` acts like a ``return false``::
226 if (location == street or below_square or south_square or
227 mid_square or north_square or marketplace) return true;
231 .. Generated by autoindex
233 pair: true; library constant
235 On the other hand, just because a routine returns a value doesn't mean
236 you always *have* to use it; you can simply ignore the value if you want
237 to. The ``TooFarAway`` routine that we showed you earlier in this
238 chapter contains a ``print_ret`` statement and so always returns
239 :const:`true`, but we didn't take any notice; the sole purpose of the routine
240 was to display some text. Compare this with the ``BeenToBefore``
241 routine, which does nothing *except* return a value; if we'd ignored
242 that, then calling the routine would have been a waste of time.
244 For some embedded routines, the value returned by the routine is important;
245 for others it doesn't matter. We've so far seen the following properties
246 whose value can be an embedded routine:
248 ========================= ===========================
249 Return value is important Return value doesn't matter
250 ========================= ===========================
251 ``after [; ... ],`` ``cant_go [; ... ],``
252 ``before [; ... ],`` ``description [; ... ],``
253 ``found_in [; ... ],`` ``each_turn [; ... ],``
254 ``n_to [; ... ]``, et al ``initial [; ... ],``
255 ========================= ===========================
257 For full details on which library property values can be embedded routines,
258 and which return values are significant, see :ref:`object-props` and
259 :dm4:`Appendix §A2 <sa2.html>` of the |DM4|.
261 Return to the marketplace
262 =========================
264 .. Generated by autoindex
266 pair: FireAt; library action
268 After all that introduction, finally back to the :act:`FireAt` action. We
269 want to check on the characteristics of an object, possibly then displaying
270 a message. We don't know exactly *which* object is to be checked, so we
271 need to write our routine in a generalised way, capable of checking any
272 object which we choose; that is, we'll supply the object to be checked as
273 an argument. Here's the routine::
276 if (o == bow or nothing || o ofclass Arrow) return true;
277 print "That's an unlikely weapon, isn't it?^";
281 The routine is designed to inspect any object which is passed to it as its
282 argument ``o``; that is, we could call the routine like this::
284 BowOrArrow(stallholder)
288 Given the ``bow`` object, or any object which we defined as class
289 ``Arrow``, it will silently ``return true`` to signify agreement that this
290 object can be fired. However, given an object like Helga, the apple or the
291 tree, it will print a message and ``return false`` to signify that this
292 object is not a suitable weapon. The test that we make is::
294 if (o == bow or nothing || o ofclass Arrow) ...
296 which is merely a slightly shorter way of saying this::
298 if (o == bow || o == nothing || o ofclass Arrow) ...
300 The result is that we ask three questions: Is ``o`` the ``bow`` object?
301 *Or* is it ``nothing``? Or, using the ``ofclass`` test, is it any object
302 which is a member of the ``Arrow`` class?
304 .. Generated by autoindex
306 pair: before; library property
307 pair: false; library constant
308 pair: second; library variable
310 What this means is that the value returned by the call ``BowOrArrow(bow)``
311 is :const:`true`, while the value returned by the call ``BowOrArrow(tree)`` is
312 :const:`false`. Or, more generally, the value returned by the call
313 ``BowOrArrow(second)`` will be either :const:`true` or :const:`false`, depending on
314 the characteristics of the object defined by the value of the variable
315 :var:`second`. So, we can write this set of statements in an object's
316 :prop:`before` property::
318 if (BowOrArrow(second) == true) {
319 This object deals with having an arrow fired at it
323 and the effect is either
325 * :var:`second` is a weapon: ``BowOrArrow`` displays nothing and returns a
326 value of :const:`true`, the ``if`` statement reacts to that value and executes
327 the following statements to produce an appropriate response to the
328 fast-approaching arrow; or
330 * :var:`second` isn't a weapon: ``BowOrArrow`` displays a standard "don't be
331 silly" message and returns a value of :const:`false`, the ``if`` statement
332 reacts to that value and ignores the following statements. Then
334 * in both cases, the ``return true`` statement terminates the object's
335 interception of the :act:`FireAt` action.
337 .. Generated by autoindex
339 pair: deadflag; library variable
341 That whole ``BowOrArrow()`` bit was rather complex, but the rest of the
342 :act:`FireAt` action is straightforward. Once the tree has determined that
343 it's being shot at by something sensible, it can just set :var:`deadflag`
344 to 3 -- the "You have screwed up" ending, display a message, and be done.
349 There's nothing in Gessler's definition that we haven't already encountered::
351 NPC governor "governor" marketplace
352 with name 'governor' 'vogt' 'Hermann' 'Gessler',
354 "Short, stout but with a thin, mean face, Gessler relishes the
355 power he holds over the local community.",
357 print "Gessler is watching from a safe distance,
358 a sneer on his face.^";
359 if (location hasnt visited)
360 print_ret "^~It appears that you need to be taught a lesson,
361 fool. Nobody shall pass through the square without paying
362 homage to His Imperial Highness Albert; nobody, hear me?
363 I could have you beheaded for treason, but I'm going to
364 be lenient. If you should be so foolish again, you can
365 expect no mercy, but this time, I'll let you go free...
366 just as soon as you demonstrate your archery skills by
367 hitting this apple from where you stand. That shouldn't
368 prove too difficult; here, sergeant, catch. Balance it on
369 the little bastard's head.~";
373 print_ret "You cannot bring yourself to speak to him.";
377 if (BowOrArrow(second) == true) {
379 print_ret "Before the startled soldiers can react, you turn
380 and fire at Gessler; your arrow pierces his heart,
381 and he dies messily. A gasp, and then a cheer,
382 goes up from the crowd.";
388 Like most NPCs, Gessler has a :prop:`life` property which deals with
389 actions applicable only to animate objects. This one responds merely to
390 :act:`Talk` (as in TALK TO THE GOVERNOR).
395 Since he's been with you throughout, it's really about time we defined
399 with name 'son' 'your' 'boy' 'lad' 'Walter',
401 if (location == marketplace)
402 print_ret "He stares at you, trying to appear brave and
403 remain still. His arms are pulled back and tied behind
404 the trunk, and the apple nestles amid his blond hair.";
406 print_ret "A quiet, blond lad of eight summers, he's fast
407 learning the ways of mountain folk.";
413 print_ret "~Thank you, Papa.~";
415 if (location == marketplace)
416 print_ret "~Stay calm, my son, and trust in God.~";
418 print_ret "You point out a few interesting sights.";
421 Examine,Listen,Salute,Talk:
424 if (location == marketplace) {
425 if (BowOrArrow(second) == true) {
427 print_ret "Oops! Surely you didn't mean to do that?";
434 if (location == marketplace)
435 print_ret "Your guards won't permit it.";
439 found_in [; return true; ],
440 has male proper scenery transparent;
442 His attributes are :attr:`male` (he's your son, after all), :attr:`proper` (so the
443 interpreter doesn't mention "the your son"), :attr:`scenery` (so he's not
444 listed in every room description), and :attr:`transparent` (because you see
445 right through him). No, that's wrong: a :attr:`transparent` object isn't made
446 of glass; it's one whose possessions are visible to you. We've done that
447 because we'd still like to be able to EXAMINE APPLE even when Walter is
448 carrying it. Without the :attr:`transparent` attribute, it would be as though
449 the apple was in his pocket or otherwise out of sight; the interpreter
450 would reply "You can't see any such thing".
452 .. Generated by autoindex
454 pair: found_in; library property
456 Walter has a :prop:`found_in` property which automatically moves him to the
457 player's location on each turn. We can get away with this because in such
458 a short and simple game, he does indeed follow you everywhere. In a more
459 realistic model world, NPCs often move around independently, but we don't
460 need such complexity here.
462 Several of Walter's properties test whether ``(location == marketplace)``;
463 that is, is the player (and hence Walter) currently in that room? The
464 events in the marketplace are such that specialised responses are more
465 appropriate there than our standard ones.
467 .. Generated by autoindex
469 pair: Give; library action
470 pair: before; library property
471 pair: score; library variable
473 Walter's :prop:`life` property responds to :act:`Give` (as in GIVE APPLE TO
474 WALTER) and Talk (as in TALK TO YOUR SON); during :act:`Give`, we increment
475 the library variable :var:`score`, thus rewarding the player's generous
476 good nature. His :prop:`before` property is perhaps a little confusing.
479 .. Generated by autoindex
481 pair: Examine; library action
482 pair: Listen; library action
483 pair: Salute; library action
485 #. The :act:`Examine`, :act:`Listen`, :act:`Salute` and :act:`Talk` actions
486 are always available (a :act:`Talk` action then gets passed to Walter's
487 :prop:`life` property).
489 .. Generated by autoindex
491 pair: FireAt; library action
493 #. The :act:`FireAt` action is permitted in the ``marketplace``, albeit
494 with unfortunate results. Elsewhere, it triggers the standard
495 :act:`FireAt` response of "Unthinkable!"
497 #. All other actions are prevented in the ``marketplace``, and allowed to
498 run their standard course (thanks to the ``return false``) elsewhere.
500 .. Generated by autoindex
502 pair: deadflag; library variable
504 The apple's moment of glory has arrived! Its :prop:`before` property
505 responds to the :act:`FireAt` action by setting :var:`deadflag` to 2. When
506 that happens, the game is over; the player has won. ::
511 if (location == marketplace)
512 print_ret "At this distance you can barely see it.";
514 print_ret "The apple is blotchy green and brown.";
518 print_ret "An apple is worth quite a bit --
519 better hang on to it.";
521 print_ret "Helga intended it for Walter...";
523 if (location == marketplace) {
524 if (BowOrArrow(second) == true) {
527 print_ret "Slowly and steadily, you place an arrow in
528 the bow, draw back the string, and take aim with
529 more care than ever in your life. Holding your
530 breath, unblinking, fearful, you release the
531 arrow. It flies across the square towards your
532 son, and drives the apple against the trunk of
533 the tree. The crowd erupts with joy;
534 Gessler looks distinctly disappointed.";
542 And with that, we've defined all of the objects. In doing so, we've added
543 a whole load of new nouns and adjectives to the game's dictionary, but no
544 verbs. That's the final task.
551 .. Generated by autoindex
553 pair: Talk; library action
555 The Inform library delivers a standard set of nearly a hundred actions
556 which players can perform; around twenty of those are "meta-actions" (like
557 SAVE and QUIT) aimed at the interpreter itself, and the remainder operate
558 within the model world. Having such a large starting set is a great
559 blessing; it means that many of the actions which players might attempt are
560 already catered for, either by the interpreter doing something useful, or
561 by explaining why it's unable to. Nevertheless, most games find the need
562 to define additional actions, and "William Tell" is no exception. We'll be
563 adding four actions of our own: :act:`Untie`, :act:`Salute`, :act:`FireAt`
568 It's not the most useful action, but it is the simplest. In the
569 marketplace, when Walter is lashed to the tree, it's possible that players
570 might be tempted to try to UNTIE WALTER; unlikely, but as we've said
571 before, anticipating the improbable is part of the craft of IF. For this,
572 and for all new actions, two things are required. We need a grammar
573 definition, spelling out the structure of the English sentences which we're
576 Verb 'untie' 'unfasten' 'unfix' 'free' 'release'
579 and we need a routine to handle the action in the default situation (where
580 the action isn't intercepted by an object's :prop:`before` property). ::
582 [ UntieSub; print_ret "You really shouldn't try that."; ];
584 The grammar is less complex than it perhaps at first appears:
586 #. The English verbs UNTIE, UNFASTEN, UNFIX, FREE and RELEASE are
589 #. The asterisk ``*`` indicates the start of a pattern defining what
590 word(s) might follow the verb.
592 #. In this example, there's only one pattern: the ":var:`noun`" token
593 represents an object which is currently in scope -- in the same room as
596 #. The ``->`` indicates an action to be triggered.
598 .. Generated by autoindex
600 pair: Untie; library action
602 #. If players type something that matches the pattern -- one of those five
603 verbs followed by an object in scope -- the interpreter triggers an
604 :act:`Untie` action, which by default is handled by a routine having the
605 same name as the action, with ``Sub`` appended. In this example, that's
606 the ``UntieSub`` routine.
608 #. The grammar is laid out this way just to make it easier to read. All those
609 spaces aren't important; we could equally have typed::
611 Verb 'untie' 'unfasten' 'unfix' 'free' 'release' * noun -> Untie;
613 We can illustrate how this works in the Altdorf street:
615 .. code-block:: transcript
618 The narrow street runs north towards the town square. Local folk are pouring
619 into the town through the gate to the south, shouting greetings, offering
620 produce for sale, exchanging news, enquiring with exaggerated disbelief about
621 the prices of the goods displayed by merchants whose stalls make progress even
624 "Stay close to me, son," you say, "or you'll get lost among all these people."
627 What do you want to untie?
630 You can't see any such thing.
633 You don't need to worry about the local people.
636 You really shouldn't try that.
638 The illustration shows four attempted usages of the new action. In the
639 first, the player omits to mention an object; the interpreter knows (from
640 that :var:`noun` in the grammar which implies that the action needs a
641 direct object) that something is missing, so it issues a helpful prompt.
642 In the second, the player mentions an object that isn't in scope (in fact,
643 there's no dog anywhere in the game, but the interpreter isn't about to
644 give *that* away to the player). In the third, the object is in scope, but
645 its :prop:`before` property intercepts the :act:`Untie` action (and indeed,
646 since this object is of the class ``Prop``, all actions apart from
647 :act:`Examine`) to display a customised rejection message. Finally, the
648 fourth usage refers to an object which *doesn't* intercept the action, so
649 the interpreter calls the default action handler -- ``UntieSub`` -- which
650 displays a general-purpose refusal to perform the action.
652 The principles presented here are those that you should generally employ:
653 write a generic action handler which either refuses to do anything (see,
654 for example SQUASH or HIT), or performs the action without affecting the
655 state of the model world (see, for example, JUMP or WAVE); then, intercept
656 that non-action (generally using a :prop:`before` property) for those objects
657 which might make a legitimate target for the action, and instead provide a
658 more specific response, either performing or rejecting the action.
660 In the case of :act:`Untie`, there are no objects which can be untied in
661 this game, so we always generate a refusal of some sort.
665 .. Generated by autoindex
667 pair: Salute; library action
669 The next action is :act:`Salute`, provided in case Wilhelm chooses to defer
670 to the hat on the pole. Here's the default action handler::
673 if (noun has animate) print_ret (The) noun, " acknowledges you.";
674 print_ret (The) noun, " takes no notice.";
677 You'll notice that this is slightly more intelligent than our :act:`Untie`
678 handler, since it produces different responses depending on whether the
679 object being saluted -- stored in the :var:`noun` variable -- is
680 :attr:`animate` or not. But it's basically doing the same job. And here's
683 Verb 'bow' 'nod' 'kowtow' 'genuflect'
684 * 'at'/'to'/'towards' noun -> Salute;
686 Verb 'salute' 'greet' 'acknowledge'
689 This grammar says that:
691 #. The English verbs BOW, NOD, KOWTOW, GENUFLECT, SALUTE, GREET and
692 ACKNOWLEDGE are synonymous.
694 #. The first four (but not the last three) can then be followed by any of
695 the prepositions AT, TO or TOWARDS: words in apostrophes ``'...'`` are
696 matched literally, with the slash ``/`` separating alternatives.
698 #. After that comes the name of an object which is currently in scope -- in
699 the same room as the player.
701 #. If players type something that matches one of those patterns, the
702 interpreter triggers a :act:`Salute` action, which by default is dealt
703 with by the ``SaluteSub`` routine.
705 So, we're allowing BOW AT HAT and KOWTOW TOWARDS HAT, but not simply NOD
706 HAT. We're allowing SALUTE HAT but not GREET TO HAT. It's not perfect,
707 but it's a fair attempt at defining some new verbs to handle salutation.
709 But suppose that we think of still other ways in which players might
710 attempt this (remember, they don't know which verbs we've defined; they're
711 just stabbing in the dark, trying out things that seem as though they ought
712 to work). How about PAY HOMAGE TO HAT, or maybe WAVE AT HAT? They sound
713 pretty reasonable, don't they? Except that, if we'd written::
715 Verb 'bow' 'nod' 'kowtow' 'genuflect' 'wave'
716 * 'at'/'to'/'towards' noun -> Salute;
718 we'd have caused a compilation error: two different verb definitions refer
719 to "wave". ``Grammar.h``, one of the library files whose contents a
720 beginner might find useful to study, contains these lines::
722 Verb 'give' 'pay' 'offer' 'feed'
723 * held 'to' creature -> Give
724 * creature held -> Give reverse
725 * 'over' held 'to' creature -> Give;
731 The problem is that the verbs PAY and WAVE are already defined by the
732 library, and Inform's rule is that a verb can appear in only one ``Verb``
733 definition. The wrong solution: edit ``Grammar.h`` to *physically* add
734 lines to the existing definitions (it's almost never a good idea to make
735 changes to the standard library files). The right solution: use ``Extend``
736 to *logically* add those lines. If we write this in our source file::
739 * 'homage' 'to' noun -> Salute;
742 * 'at' noun -> Salute;
744 then the effect is exactly as if we'd edited ``Grammar.h`` to read like
747 Verb 'give' 'pay' 'offer' 'feed'
748 * held 'to' creature -> Give
749 * creature held -> Give reverse
750 * 'over' held 'to' creature -> Give
751 * 'homage' 'to' noun -> Salute;
756 * 'at' noun -> Salute;
758 and now players can PAY (or GIVE, or OFFER) HOMAGE to any object. (Because
759 GIVE, PAY, OFFER and FEED are defined as synonyms, players can also FEED
760 HOMAGE, but it's unlikely that anybody will notice this minor aberration;
761 players are usually too busy trying to figure out *logical* possibilities.)
765 As usual, we'll first show you the default handler for this action::
769 print_ret "What, just fire off an arrow at random?";
770 if (BowOrArrow(second) == true)
771 print_ret "Unthinkable!";
776 Some designers frown on the use of a rhetorical question like that,
777 since it may provoke a reply from the player. Admittedly the default
778 response from YES and NO covers the situation, but it might be better
779 design practice to reword the message as a statement rather than a
782 Here is the associated grammar::
784 Verb 'fire' 'shoot' 'aim'
787 * 'at' noun -> FireAt
788 * 'at' noun 'with' noun -> FireAt
789 * noun 'with' noun -> FireAt
790 * noun 'at' noun -> FireAt reverse;
792 This is the most complex grammar that we'll write, and the first one
793 offering several different options for the words which follow the initial
794 verb. The first line of grammar::
798 is going to let us type FIRE (or SHOOT, or AIM) by itself. The second
803 supports FIRE BOW or FIRE ARROW (or something less sensible like
804 FIRE TREE). The third line::
806 * 'at' noun -> FireAt
808 accepts FIRE AT APPLE, FIRE AT TREE, and so on. Note that there's only one
809 semicolon in all of the grammar, right at the very end.
811 .. Generated by autoindex
813 pair: noun; library variable
814 pair: second; library variable
816 The first two statements in ``FireAtSub`` deal with the first line of
817 grammar: FIRE (or SHOOT, or AIM) by itself. If the player types just that,
818 both :var:`noun` and :var:`second` will contain ``nothing``, so we reject the
819 attempt with the "at random?" message. Otherwise, we've got at least a
820 :var:`noun` value, and possibly a :var:`second` value also, so we make our
821 standard check that :var:`second` is something that can be fired, and then
822 reject the attempt with the "Unthinkable!" message.
824 There are a couple of reasons why you might find this grammar a bit tricky.
825 The first is that on some lines the word :var:`noun` appears twice: you need
826 to remember that in this context :var:`noun` is a parsing token which matches
827 any single object visible to the player. Thus, the line::
829 * 'at' noun 'with' noun -> FireAt
831 is matching FIRE AT :samp:`{some_visible_target}` WITH
832 :samp:`{some_visible_weapon}`; perhaps confusingly, the value of the target
833 object is then stored in variable :var:`noun`, and the value of the weapon
834 object in variable :var:`second`.
836 The second difficulty may be the final grammar line. Whereas on the
837 preceding lines, the first :var:`noun` matches a target object and the second
838 :var:`noun`, if present, matches a weapon object, that final line matches FIRE
839 :samp:`{some_visible_weapon}` AT :samp:`{some_visible_target}` -- the two
840 objects are mentioned in the wrong sequence. If we did nothing, our
841 ``FireAtSub`` would get pretty confused at this point, but we can swap the
842 two objects back into the expected order by adding that ``reverse`` keyword
843 at the end of the line, and then ``FireAtSub`` will work the same in all
846 .. Generated by autoindex
848 pair: FireAt; library action
850 Before leaving the :act:`FireAt` action, we'll add one more piece of
853 Extend 'attack' replace
856 This uses the ``Extend`` directive which we've just met, this time with a
857 ``replace`` keyword. The effect is to substitute the new grammar defined
858 here for that contained in ``Grammar.h``, so that ATTACK, KILL, MURDER and
859 all the other violent synonyms now trigger our :act:`FireAt` action instead
860 of the Library's standard :act:`Attack` action. We're doing this so that,
861 in the Marketplace, KILL GESSLER and MURDER WALTER have the same
862 unfortunate results as FIRE AT GESSLER and SHOOT WALTER.
866 .. Generated by autoindex
868 pair: Answer; library action
869 pair: Ask; library action
870 pair: Talk; library action
871 pair: Tell; library action
873 The final action that we define -- :act:`Talk` -- provides a simple system
874 of canned conversation, a low-key replacement for the standard
875 :act:`Answer`, :act:`Ask` and :act:`Tell` actions. The default ``TalkSub``
876 handler is closely based on ``TellSub`` (defined in library file
877 ``verblibm.h``, should you be curious), and does three things:
879 #. Deals with TALK TO ME or TALK TO MYSELF.
881 .. Generated by autoindex
883 pair: life; library property
884 pair: true; library constant
886 #. Checks (a) whether the creature being talked to has a :prop:`life`
887 property, (b) whether that property is prepared to process a :act:`Talk`
888 action, and (c) if the :act:`Talk` processing returns :const:`true`. If
889 all three checks succeed then ``TalkSub`` need do nothing more; if one
890 or more of them fails then ``TalkSub`` simply...
892 #. Displays a general "nothing to say" refusal to talk. ::
895 if (noun == player) print_ret "Nothing you hear surprises you.";
896 if (RunLife(noun,##Talk) ~= false) return;
897 print_ret "At the moment, you can't think of anything to say.";
902 That second condition ``(RunLife(noun,##Talk) ~= false)`` is a bit of
903 a stumbling block, since it uses ``RunLife`` -- an undocumented
904 internal library routine -- to offer the :act:`Talk` action to the
905 NPC's :prop:`life` property. We've decided to use it in exactly the
906 same way as the :act:`Tell` action does, without worrying too much
907 about how it works (though it looks as though ``RunLife`` returns
908 some :const:`true` value if the :prop:`life` property has intercepted
909 the action, :const:`false` if it hasn't). The ``~=`` operator means
912 The grammar is straightforward::
914 Verb 'talk' 't//' 'converse' 'chat' 'gossip'
915 * 'to'/'with' creature -> Talk
918 Notice the use of ``'t//'`` to define T as a synonym for TALK, another way
919 to make life a little easier for the player. (Actually, doing this
920 introduces a minor problem: if the player types just T then the library
921 prompts "Whom do you want to t to?" The fix for this involves enhancing an
922 internal library routine called ``LanguageVerb`` -- not complex, but a
923 little too heavy for our second game.)
925 Here's the simplest :act:`Talk` handler that we've seen -- it's from
926 Gessler the governor. Any attempt to TALK TO GESSLER will provoke "You
927 cannot bring yourself to speak to him". ::
930 Talk: print_ret "You cannot bring yourself to speak to him.";
933 Walter's :act:`Talk` handler is only slightly more involved::
937 if (location == marketplace)
938 print_ret "~Stay calm, my son, and trust in God.~";
939 print_ret "You point out a few interesting sights.";
942 And Helga's is the most sophisticated (though that isn't saying much)::
944 times_spoken_to 0, ! for counting the conversation topics
947 self.times_spoken_to = self.times_spoken_to + 1;
948 switch (self.times_spoken_to) {
949 1: score = score + 1;
950 print_ret "You warmly thank Helga for the apple.";
951 2: print_ret "~See you again soon.~";
957 This handler uses Helga's :prop:`times_spoken_to` property -- not a library
958 property, it's one that we invented, like the
959 :prop:`mid_square.warnings_count` and :prop:`pole.has_been_saluted`
960 properties -- to keep track of what's been said, permitting two snatches of
961 conversation (and awarding a point) before falling back on the embarrassing
962 silences implied by "You can't think of anything to say".
964 That's the end of our little fable; you'll find a transcript and the full
965 source in :doc:`/appendices/c`. And now, it's time to meet -- Captain