--- /dev/null
+===============================
+ William Tell: the end is nigh
+===============================
+
+.. highlight:: inform6
+
+.. epigraph::
+
+ | *Q was a queen, who wore a silk slip;*
+ | *R was a robber, and wanted a whip.*
+
+.. only:: html
+
+ .. image:: /images/picQ.png
+ :align: left
+
+.. raw:: latex
+
+ \dropcap{q}
+
+uite a few objects still remain undefined, so we'll talk about them first.
+Then, we'll explain how to make additions to Inform's standard repertoire
+of verbs, and how to define the actions which those verbs trigger.
+
+The marketplace
+===============
+
+The ``marketplace`` room is unremarkable, and the ``tree`` growing there
+has only one feature of interest::
+
+ Room marketplace "Marketplace near the square"
+ with description
+ "Altdorf's marketplace, close by the town square, has been hastily
+ cleared of stalls. A troop of soldiers has pushed back the crowd
+ to leave a clear space in front of the lime tree, which has been
+ growing here for as long as anybody can remember. Usually it
+ provides shade for the old men of the town, who gather below to
+ gossip, watch the girls, and play cards. Today, though, it
+ stands alone... apart, that is, from Walter, who has been lashed
+ to the trunk. About forty yards away, you are restrained by two
+ of the vogt's men.",
+ cant_go "What? And leave your son tied up here?";
+
+ Object tree "lime tree" marketplace
+ with name 'lime' 'tree',
+ description "It's just a large tree.",
+ before [;
+ FireAt:
+ if (BowOrArrow(second) == true) {
+ deadflag = 3;
+ print_ret "Your hand shakes a little, and your arrow flies
+ high, hitting the trunk a few inches above Walter's
+ head.";
+ }
+ return true;
+ ],
+ has scenery;
+
+The tree's ``before`` property is intercepting a ``FireAt`` action, which
+we'll define in a few moments. This action is the result of a command like
+SHOOT AT TREE WITH BOW -- we could simulate it with the statement
+``<<FireAt tree bow>>`` -- and it needs extra care to ensure that the
+``second`` object is a feasible weapon. To deal with silly commands like
+SHOOT AT TREE WITH HELGA, we must test that ``second`` is the bow, one of
+the arrows, or ``nothing`` (from just SHOOT AT TREE). Since this is quite
+a complex test, and one that we'll be making in several places, it's
+sensible to write a routine to do the job. Which we'll do shortly -- but
+first, a general introduction to working with routines.
+
+A diversion: working with routines
+==================================
+
+A standalone routine, like the familiar routines embedded as the value of a
+property such as ``before`` or ``each_turn``, is simply a set of statements
+to be executed. The major differences are in content, in timing, and in
+the default return value:
+
+* Whereas an embedded routine has to contain statements which do something
+ appropriate for that associated property variable, a standalone routine
+ can contain statements which do anything you wish. You have total
+ freedom as to what the routine actually does and what value it returns.
+
+* An embedded routine is called when the interpreter is dealing with that
+ property of that object; you provide the routine, but you don't directly
+ control when it's called. A standalone routine, however, is completely
+ under your control; it runs only when you explicitly call it.
+
+* If an embedded routine executes all of its statements and reaches the
+ final ``];`` without encountering some form of ``return`` statement, it
+ returns the value ``false``. In the same circumstances, a standalone
+ routine returns the value ``true``. There's a good reason for this
+ difference -- it usually turns out to be the natural default behaviour --
+ but it can sometimes baffle newcomers. To avoid confusion, we've always
+ included explicit ``return`` statements in our routines.
+
+What this generally boils down to is: *if* you have a collection of
+statements which perform some specific task *and* you need to execute those
+same statements in more than one place in your game, *then* it often makes
+sense to turn those statements into a standalone routine. The advantages
+are: you write the statements only once, so any subsequent changes are
+easier to make; also, your game becomes simpler and easier to read. We'll
+look at some simple examples; first consider these unexciting foodstuffs::
+
+ Object "stale ham sandwich"
+ with name 'stale' 'ham' 'sandwich',
+ description "It doesn't look at all appetising.",
+ ...
+
+ Object "elderly jam doughnut"
+ with name 'elderly' 'jam' 'jelly' 'doughnut' 'donut',
+ description "It doesn't look at all appetising.",
+ ...
+
+The ``description``\s are identical: perhaps we could display them using a
+routine? ::
+
+ [ Inedible; print_ret "It doesn't look at all appetising."; ];
+
+ Object "stale ham sandwich"
+ with name 'stale' 'ham' 'sandwich',
+ description [; Inedible(); ],
+ ...
+
+ Object "elderly jam doughnut"
+ with name 'elderly' 'jam' 'jelly' 'doughnut' 'donut',
+ description [; Inedible(); ],
+ ...
+
+This isn't a very realistic approach -- there are more elegant ways of
+avoiding typing the same string twice -- but it works, and it illustrates
+how we can define a routine to do something useful, and then call it
+wherever we need to.
+
+Here's another simple example showing how, by returning a value, a routine
+can report back to the piece of code which called it. We've once or twice
+used the test ``if (self has visited) ...``; we could create a routine
+which performs that same check and then returns ``true`` or ``false`` to
+indicate what it discovered::
+
+ [ BeenHereBefore;
+ if (self has visited) return true;
+ else return false;
+ ];
+
+Then, we'd rewrite our test as ``if (BeenHereBefore() == true) ...``; no
+shorter or quicker, but maybe more descriptive of what's going on. One
+more example of using routines. As well as testing ``if (self has visited)
+...`` we've also tested ``if (location has visited) ...`` a few times, so
+we *could* write another routine to perform that check::
+
+ [ BeenThereBefore;
+ if (location has visited) return true;
+ else return false;
+ ];
+
+However, the two routines are very similar; the only difference is the name
+of the variable -- ``self`` or ``location`` -- which is being checked. A
+better approach might be to rework our ``BeenHereBefore`` routine so that
+it does both jobs, but we somehow need to tell it which variable's value is
+to be checked. That's easy: we design the routine so that it expects an
+**argument**::
+
+ [ BeenToBefore this_room;
+ if (this_room has visited) return true;
+ else return false;
+ ];
+
+Notice that the argument's name is one that we've invented to be
+descriptive of its content; it doesn't matter if we define it as "``x``",
+"``this_room``" or "``hubba_hubba``". Whatever its name, the argument acts
+as a placeholder for a value (here, one of the variables ``self`` or
+``location``) which we must supply when calling the routine::
+
+ if (BeenToBefore(self) == true) ...
+
+ if (BeenToBefore(location) == true) ...
+
+In the first line, we supply ``self`` as the routine's argument. The
+routine doesn't care where the argument came from; it just sees a value
+which it knows as ``this_room``, and which it then uses to test for the
+``visited`` attribute. On the second line we supply ``location`` as the
+argument, but the routine just sees another value in its ``this_room``
+variable. ``this_room`` is called a **local variable** of the
+``BeenToBefore`` routine, one that must be set to a suitable value each
+time that the routine is called. In this example routine, the value needs
+to be a room object; we could also check an explicit named room::
+
+ if (BeenToBefore(mid_square) == true) ...
+
+Remember that:
+
+#. All routines terminate sooner or later, either because you explicitly
+ write a ``return``, ``rtrue`` or ``rfalse`` statement, or because
+ execution reaches the ``]`` marking the routine's end.
+
+#. All routines return a value, which can be ``true``, or ``false``, or any
+ other number. This value is determined by the ``return``, ``rtrue`` or
+ ``rfalse`` statement, or by the the ``]`` marking the routine's end (in
+ which case the default STEF rule applies: Standalone routines return
+ True, Embedded routines return False). We gave this example of an
+ embedded routine in "Adding some props" on page 81. The ``return
+ false`` statement is redundant: we could remove it without affecting the
+ routine's behaviour, because the ``]`` acts like a ``return false``::
+
+ found_in [;
+ if (location == street or below_square or south_square or
+ mid_square or north_square or marketplace) return true;
+ return false;
+ ],
+
+ On the other hand, just because a routine returns a value doesn't mean
+ you always *have* to use it; you can simply ignore the value if you want
+ to. The ``TooFarAway`` routine that we showed you earlier in this
+ chapter contains a ``print_ret`` statement and so always returns
+ ``true``, but we didn't take any notice; the sole purpose of the routine
+ was to display some text. Compare this with the ``BeenToBefore``
+ routine, which does nothing *except* return a value; if we'd ignored
+ that, then calling the routine would have been a waste of time.
+
+For some embedded routines, the value returned by the routine is important;
+for others it doesn't matter. We've so far seen the following properties
+whose value can be an embedded routine:
+
+========================= ===========================
+Return value is important Return value doesn't matter
+========================= ===========================
+``after [; ... ],`` ``cant_go [; ... ],``
+``before [; ... ],`` ``description [; ... ],``
+``found_in [; ... ],`` ``each_turn [; ... ],``
+``n_to [; ... ]``, et al ``initial [; ... ],``
+========================= ===========================
+
+For full details on which library property values can be embedded routines,
+and which return values are significant, see "Object properties" on page
+266 and Appendix §A2 of the *Inform Designer's Manual*.
+
+Return to the marketplace
+=========================
+
+After all that introduction, finally back to the ``FireAt`` action. We
+want to check on the characteristics of an object, possibly then displaying
+a message. We don't know exactly *which* object is to be checked, so we
+need to write our routine in a generalised way, capable of checking any
+object which we choose; that is, we'll supply the object to be checked as
+an argument. Here's the routine::
+
+ [ BowOrArrow o;
+ if (o == bow or nothing || o ofclass Arrow) return true;
+ print "That's an unlikely weapon, isn't it?^";
+ return false;
+ ];
+
+The routine is designed to inspect any object which is passed to it as its
+argument ``o``; that is, we could call the routine like this::
+
+ BowOrArrow(stallholder)
+ BowOrArrow(tree)
+ BowOrArrow(bow)
+
+Given the ``bow`` object, or any object which we defined as class
+``Arrow``, it will silently ``return true`` to signify agreement that this
+object can be fired. However, given an object like Helga, the apple or the
+tree, it will print a message and ``return false`` to signify that this
+object is not a suitable weapon. The test that we make is::
+
+ if (o == bow or nothing || o ofclass Arrow) ...
+
+which is merely a slightly shorter way of saying this::
+
+ if (o == bow || o == nothing || o ofclass Arrow) ...
+
+The result is that we ask three questions: Is ``o`` the ``bow`` object?
+*Or* is it ``nothing``? Or, using the ``ofclass`` test, is it any object
+which is a member of the ``Arrow`` class?
+
+What this means is that the value returned by the call ``BowOrArrow(bow)``
+is ``true``, while the value returned by the call ``BowOrArrow(tree)`` is
+``false``. Or, more generally, the value returned by the call
+``BowOrArrow(second)`` will be either ``true`` or ``false``, depending on
+the characteristics of the object defined by the value of the variable
+``second``. So, we can write this set of statements in an object's
+``before`` property::
+
+ if (BowOrArrow(second) == true) {
+ This object deals with having an arrow fired at it
+ }
+ return true;
+
+and the effect is either
+
+* ``second`` is a weapon: ``BowOrArrow`` displays nothing and returns a
+ value of ``true``, the ``if`` statement reacts to that value and executes
+ the following statements to produce an appropriate response to the
+ fast-approaching arrow; or
+
+* ``second`` isn't a weapon: ``BowOrArrow`` displays a standard "don't be
+ silly" message and returns a value of ``false``, the ``if`` statement
+ reacts to that value and ignores the following statements. Then
+
+* in both cases, the ``return true`` statement terminates the object's
+ interception of the ``FireAt`` action.
+
+That whole ``BowOrArrow()`` bit was rather complex, but the rest of the
+``FireAt`` action is straightforward. Once the tree has determined that
+it's being shot at by something sensible, it can just set ``deadflag`` to 3
+-- the "You have screwed up" ending, display a message, and be done.
+
+Gessler the governor
+====================
+
+There's nothing in Gessler's definition that we haven't already encountered::
+
+ NPC governor "governor" marketplace
+ with name 'governor' 'vogt' 'Hermann' 'Gessler',
+ description
+ "Short, stout but with a thin, mean face, Gessler relishes the
+ power he holds over the local community.",
+ initial [;
+ print "Gessler is watching from a safe distance,
+ a sneer on his face.^";
+ if (location hasnt visited)
+ print_ret "^~It appears that you need to be taught a lesson,
+ fool. Nobody shall pass through the square without paying
+ homage to His Imperial Highness Albert; nobody, hear me?
+ I could have you beheaded for treason, but I'm going to
+ be lenient. If you should be so foolish again, you can
+ expect no mercy, but this time, I'll let you go free...
+ just as soon as you demonstrate your archery skills by
+ hitting this apple from where you stand. That shouldn't
+ prove too difficult; here, sergeant, catch. Balance it on
+ the little bastard's head.~";
+ ],
+ life [;
+ Talk:
+ print_ret "You cannot bring yourself to speak to him.";
+ ],
+ before [;
+ FireAt:
+ if (BowOrArrow(second) == true) {
+ deadflag = 3;
+ print_ret "Before the startled soldiers can react, you turn
+ and fire at Gessler; your arrow pierces his heart,
+ and he dies messily. A gasp, and then a cheer,
+ goes up from the crowd.";
+ }
+ return true;
+ ],
+ has male;
+
+Like most NPCs, Gessler has a ``life`` property which deals with actions
+applicable only to animate objects. This one responds merely to ``Talk``
+(as in TALK TO THE GOVERNOR).
+
+Walter and the apple
+====================
+
+Since he's been with you throughout, it's really about time we defined
+Walter::
+
+ NPC son "your son"
+ with name 'son' 'your' 'boy' 'lad' 'Walter',
+ description [;
+ if (location == marketplace)
+ print_ret "He stares at you, trying to appear brave and
+ remain still. His arms are pulled back and tied behind
+ the trunk, and the apple nestles amid his blond hair.";
+ else
+ print_ret "A quiet, blond lad of eight summers, he's fast
+ learning the ways of mountain folk.";
+ ],
+ life [;
+ Give:
+ score = score + 1;
+ move noun to self;
+ print_ret "~Thank you, Papa.~";
+ Talk:
+ if (location == marketplace)
+ print_ret "~Stay calm, my son, and trust in God.~";
+ else
+ print_ret "You point out a few interesting sights.";
+ ],
+ before [;
+ Examine,Listen,Salute,Talk:
+ return false;
+ FireAt:
+ if (location == marketplace) {
+ if (BowOrArrow(second) == true) {
+ deadflag = 3;
+ print_ret "Oops! Surely you didn't mean to do that?";
+ }
+ return true;
+ }
+ else
+ return false;
+ default:
+ if (location == marketplace)
+ print_ret "Your guards won't permit it.";
+ else
+ return false;
+ ],
+ found_in [; return true; ],
+ has male proper scenery transparent;
+
+His attributes are ``male`` (he's your son, after all), ``proper`` (so the
+interpreter doesn't mention "the your son"), ``scenery`` (so he's not
+listed in every room description), and ``transparent`` (because you see
+right through him). No, that's wrong: a ``transparent`` object isn't made
+of glass; it's one whose possessions are visible to you. We've done that
+because we'd still like to be able to EXAMINE APPLE even when Walter is
+carrying it. Without the ``transparent`` attribute, it would be as though
+the apple was in his pocket or otherwise out of sight; the interpreter
+would reply "You can't see any such thing".
+
+Walter has a ``found_in`` property which automatically moves him to the
+player's location on each turn. We can get away with this because in such
+a short and simple game, he does indeed follow you everywhere. In a more
+realistic model world, NPCs often move around independently, but we don't
+need such complexity here.
+
+Several of Walter's properties test whether ``(location == marketplace)``;
+that is, is the player (and hence Walter) currently in that room? The
+events in the marketplace are such that specialised responses are more
+appropriate there than our standard ones.
+
+Walter's ``life`` property responds to ``Give`` (as in GIVE APPLE TO
+WALTER) and Talk (as in TALK TO YOUR SON); during ``Give``, we increment
+the library variable ``score``, thus rewarding the player's generous good
+nature. His ``before`` property is perhaps a little confusing. It's
+saying:
+
+#. The ``Examine``, ``Listen``, ``Salute`` and ``Talk`` actions are always
+ available (a ``Talk`` action then gets passed to Walter's ``life``
+ property).
+
+#. The ``FireAt`` action is permitted in the ``marketplace``, albeit with
+ unfortunate results. Elsewhere, it triggers the standard ``FireAt``
+ response of "Unthinkable!"
+
+#. All other actions are prevented in the ``marketplace``, and allowed to
+ run their standard course (thanks to the ``return false``) elsewhere.
+
+The apple's moment of glory has arrived! Its ``before`` property responds
+to the ``FireAt`` action by setting ``deadflag`` to 2. When that happens,
+the game is over; the player has won. ::
+
+ Object apple "apple"
+ with name 'apple',
+ description [;
+ if (location == marketplace)
+ print_ret "At this distance you can barely see it.";
+ else
+ print_ret "The apple is blotchy green and brown.";
+ ],
+ before [;
+ Drop:
+ print_ret "An apple is worth quite a bit --
+ better hang on to it.";
+ Eat:
+ print_ret "Helga intended it for Walter...";
+ FireAt:
+ if (location == marketplace) {
+ if (BowOrArrow(second) == true) {
+ score = score + 1;
+ deadflag = 2;
+ print_ret "Slowly and steadily, you place an arrow in
+ the bow, draw back the string, and take aim with
+ more care than ever in your life. Holding your
+ breath, unblinking, fearful, you release the
+ arrow. It flies across the square towards your
+ son, and drives the apple against the trunk of
+ the tree. The crowd erupts with joy;
+ Gessler looks distinctly disappointed.";
+ }
+ return true;
+ }
+ else
+ return false;
+ ];
+
+And with that, we've defined all of the objects. In doing so, we've added
+a whole load of new nouns and adjectives to the game's dictionary, but no
+verbs. That's the final task.
+
+Verbs, verbs, verbs
+===================
+
+The Inform library delivers a standard set of nearly a hundred actions
+which players can perform; around twenty of those are "meta-actions" (like
+SAVE and QUIT) aimed at the interpreter itself, and the remainder operate
+within the model world. Having such a large starting set is a great
+blessing; it means that many of the actions which players might attempt are
+already catered for, either by the interpreter doing something useful, or
+by explaining why it's unable to. Nevertheless, most games find the need
+to define additional actions, and "William Tell" is no exception. We'll be
+adding four actions of our own: ``Untie``, ``Salute`` (see page 113),
+``FireAt`` (see page 115) and ``Talk`` (see page 116).
+
+.. rubric:: Untie
+
+It's not the most useful action, but it is the simplest. In the
+marketplace, when Walter is lashed to the tree, it's possible that players
+might be tempted to try to UNTIE WALTER; unlikely, but as we've said
+before, anticipating the improbable is part of the craft of IF. For this,
+and for all new actions, two things are required. We need a grammar
+definition, spelling out the structure of the English sentences which we're
+prepared to accept::
+
+ Verb 'untie' 'unfasten' 'unfix' 'free' 'release'
+ * noun -> Untie;
+
+and we need a routine to handle the action in the default situation (where
+the action isn't intercepted by an object's ``before`` property). ::
+
+ [ UntieSub; print_ret "You really shouldn't try that."; ];
+
+The grammar is less complex than it perhaps at first appears:
+
+#. The English verbs UNTIE, UNFASTEN, UNFIX, FREE and RELEASE are
+ synonymous.
+
+#. The asterisk ``*`` indicates the start of a pattern defining what
+ word(s) might follow the verb.
+
+#. In this example, there's only one pattern: the "``noun``" token
+ represents an object which is currently in scope -- in the same room as
+ the player.
+
+#. The ``->`` indicates an action to be triggered.
+
+#. If players type something that matches the pattern -- one of those five
+ verbs followed by an object in scope -- the interpreter triggers an
+ ``Untie`` action, which by default is handled by a routine having the
+ same name as the action, with ``Sub`` appended. In this example, that's
+ the ``UntieSub`` routine.
+
+#. The grammar is laid out this way just to make it easier to read. All those
+ spaces aren't important; we could equally have typed::
+
+ Verb 'untie' 'unfasten' 'unfix' 'free' 'release' * noun -> Untie;
+
+We can illustrate how this works in the Altdorf street:
+
+.. code-block:: transcript
+
+ A street in Altdorf
+ The narrow street runs north towards the town square. Local folk are pouring
+ into the town through the gate to the south, shouting greetings, offering
+ produce for sale, exchanging news, enquiring with exaggerated disbelief about
+ the prices of the goods displayed by merchants whose stalls make progress even
+ more difficult.
+
+ "Stay close to me, son," you say, "or you'll get lost among all these people."
+
+ >UNTIE
+ What do you want to untie?
+
+ >UNFASTEN THE DOG
+ You can't see any such thing.
+
+ >UNTIE THE PEOPLE
+ You don't need to worry about the local people.
+
+ >UNFIX YOUR SON
+ You really shouldn't try that.
+
+The illustration shows four attempted usages of the new action. In the
+first, the player omits to mention an object; the interpreter knows (from
+that ``noun`` in the grammar which implies that the action needs a direct
+object) that something is missing, so it issues a helpful prompt. In the
+second, the player mentions an object that isn't in scope (in fact, there's
+no dog anywhere in the game, but the interpreter isn't about to give *that*
+away to the player). In the third, the object is in scope, but its
+``before`` property intercepts the ``Untie`` action (and indeed, since this
+object is of the class ``Prop``, all actions apart from ``Examine``) to
+display a customised rejection message. Finally, the fourth usage refers
+to an object which *doesn't* intercept the action, so the interpreter calls
+the default action handler -- ``UntieSub`` -- which displays a
+general-purpose refusal to perform the action.
+
+The principles presented here are those that you should generally employ:
+write a generic action handler which either refuses to do anything (see,
+for example SQUASH or HIT), or performs the action without affecting the
+state of the model world (see, for example, JUMP or WAVE); then, intercept
+that non-action (generally using a ``before`` property) for those objects
+which might make a legitimate target for the action, and instead provide a
+more specific response, either performing or rejecting the action.
+
+In the case of ``Untie``, there are no objects which can be untied in this
+game, so we always generate a refusal of some sort.
+
+.. rubric:: Salute
+
+The next action is ``Salute``, provided in case Wilhelm chooses to defer to
+the hat on the pole. Here's the default action handler::
+
+ [ SaluteSub;
+ if (noun has animate) print_ret (The) noun, " acknowledges you.";
+ print_ret (The) noun, " takes no notice.";
+ ];
+
+You'll notice that this is slightly more intelligent than our ``Untie``
+handler, since it produces different responses depending on whether the
+object being saluted -- stored in the ``noun`` variable -- is ``animate``
+or not. But it's basically doing the same job. And here's the grammar::
+
+ Verb 'bow' 'nod' 'kowtow' 'genuflect'
+ * 'at'/'to'/'towards' noun -> Salute;
+
+ Verb 'salute' 'greet' 'acknowledge'
+ * noun -> Salute;
+
+This grammar says that:
+
+#. The English verbs BOW, NOD, KOWTOW, GENUFLECT, SALUTE, GREET and
+ ACKNOWLEDGE are synonymous.
+
+#. The first four (but not the last three) can then be followed by any of
+ the prepositions AT, TO or TOWARDS: words in apostrophes ``'...'`` are
+ matched literally, with the slash ``/`` separating alternatives.
+
+#. After that comes the name of an object which is currently in scope -- in
+ the same room as the player.
+
+#. If players type something that matches one of those patterns, the
+ interpreter triggers a ``Salute`` action, which by default is dealt with
+ by the ``SaluteSub`` routine.
+
+So, we're allowing BOW AT HAT and KOWTOW TOWARDS HAT, but not simply NOD
+HAT. We're allowing SALUTE HAT but not GREET TO HAT. It's not perfect,
+but it's a fair attempt at defining some new verbs to handle salutation.
+
+But suppose that we think of still other ways in which players might
+attempt this (remember, they don't know which verbs we've defined; they're
+just stabbing in the dark, trying out things that seem as though they ought
+to work). How about PAY HOMAGE TO HAT, or maybe WAVE AT HAT? They sound
+pretty reasonable, don't they? Except that, if we'd written::
+
+ Verb 'bow' 'nod' 'kowtow' 'genuflect' 'wave'
+ * 'at'/'to'/'towards' noun -> Salute;
+
+we'd have caused a compilation error: two different verb definitions refer
+to "wave". ``Grammar.h``, one of the library files whose contents a
+beginner might find useful to study, contains these lines::
+
+ Verb 'give' 'pay' 'offer' 'feed'
+ * held 'to' creature -> Give
+ * creature held -> Give reverse
+ * 'over' held 'to' creature -> Give;
+
+ Verb 'wave'
+ * -> WaveHands
+ * noun -> Wave;
+
+The problem is that the verbs PAY and WAVE are already defined by the
+library, and Inform's rule is that a verb can appear in only one ``Verb``
+definition. The wrong solution: edit ``Grammar.h`` to *physically* add
+lines to the existing definitions (it's almost never a good idea to make
+changes to the standard library files). The right solution: use ``Extend``
+to *logically* add those lines. If we write this in our source file::
+
+ Extend 'give'
+ * 'homage' 'to' noun -> Salute;
+
+ Extend 'wave'
+ * 'at' noun -> Salute;
+
+then the effect is exactly as if we'd edited ``Grammar.h`` to read like
+this::
+
+ Verb 'give' 'pay' 'offer' 'feed'
+ * held 'to' creature -> Give
+ * creature held -> Give reverse
+ * 'over' held 'to' creature -> Give
+ * 'homage' 'to' noun -> Salute;
+
+ Verb 'wave'
+ * -> WaveHands
+ * noun -> Wave
+ * 'at' noun -> Salute;
+
+and now players can PAY (or GIVE, or OFFER) HOMAGE to any object. (Because
+GIVE, PAY, OFFER and FEED are defined as synonyms, players can also FEED
+HOMAGE, but it's unlikely that anybody will notice this minor aberration;
+players are usually too busy trying to figure out *logical* possibilities.)
+
+.. rubric:: FireAt
+
+As usual, we'll first show you the default handler for this action::
+
+ [ FireAtSub;
+ if (noun == nothing)
+ print_ret "What, just fire off an arrow at random?";
+ if (BowOrArrow(second) == true)
+ print_ret "Unthinkable!";
+ ];
+
+.. note::
+
+ Some designers frown on the use of a rhetorical question like that,
+ since it may provoke a reply from the player. Admittedly the default
+ response from YES and NO covers the situation, but it might be better
+ design practice to reword the message as a statement rather than a
+ question.
+
+Here is the associated grammar::
+
+ Verb 'fire' 'shoot' 'aim'
+ * -> FireAt
+ * noun -> FireAt
+ * 'at' noun -> FireAt
+ * 'at' noun 'with' noun -> FireAt
+ * noun 'with' noun -> FireAt
+ * noun 'at' noun -> FireAt reverse;
+
+This is the most complex grammar that we'll write, and the first one
+offering several different options for the words which follow the initial
+verb. The first line of grammar::
+
+ * -> FireAt
+
+is going to let us type FIRE (or SHOOT, or AIM) by itself. The second
+line::
+
+ * noun -> FireAt
+
+supports FIRE BOW or FIRE ARROW (or something less sensible like
+FIRE TREE). The third line::
+
+ * 'at' noun -> FireAt
+
+accepts FIRE AT APPLE, FIRE AT TREE, and so on. Note that there's only one
+semicolon in all of the grammar, right at the very end.
+
+The first two statements in ``FireAtSub`` deal with the first line of
+grammar: FIRE (or SHOOT, or AIM) by itself. If the player types just that,
+both ``noun`` and ``second`` will contain ``nothing``, so we reject the
+attempt with the "at random?" message. Otherwise, we've got at least a
+``noun`` value, and possibly a ``second`` value also, so we make our
+standard check that ``second`` is something that can be fired, and then
+reject the attempt with the "Unthinkable!" message.
+
+There are a couple of reasons why you might find this grammar a bit tricky.
+The first is that on some lines the word ``noun`` appears twice: you need
+to remember that in this context ``noun`` is a parsing token which matches
+any single object visible to the player. Thus, the line::
+
+ * 'at' noun 'with' noun -> FireAt
+
+is matching FIRE AT :samp:`{some_visible_target}` WITH
+:samp:`{some_visible_weapon}`; perhaps confusingly, the value of the target
+object is then stored in variable ``noun``, and the value of the weapon
+object in variable ``second``.
+
+The second difficulty may be the final grammar line. Whereas on the
+preceding lines, the first ``noun`` matches a target object and the second
+``noun``, if present, matches a weapon object, that final line matches FIRE
+:samp:`{some_visible_weapon}` AT :samp:`{some_visible_target}` -- the two
+objects are mentioned in the wrong sequence. If we did nothing, our
+``FireAtSub`` would get pretty confused at this point, but we can swap the
+two objects back into the expected order by adding that ``reverse`` keyword
+at the end of the line, and then ``FireAtSub`` will work the same in all
+cases.
+
+Before leaving the ``FireAt`` action, we'll add one more piece of grammar::
+
+ Extend 'attack' replace
+ * noun -> FireAt;
+
+This uses the ``Extend`` directive which we've just met, this time with a
+``replace`` keyword. The effect is to substitute the new grammar defined
+here for that contained in ``Grammar.h``, so that ATTACK, KILL, MURDER and
+all the other violent synonyms now trigger our ``FireAt`` action instead of
+the Library's standard ``Attack`` action. We're doing this so that, in the
+Marketplace, KILL GESSLER and MURDER WALTER have the same unfortunate
+results as FIRE AT GESSLER and SHOOT WALTER.
+
+.. rubric:: Talk
+
+The final action that we define -- ``Talk`` -- provides a simple system of
+canned conversation, a low-key replacement for the standard ``Answer``,
+``Ask`` and ``Tell`` actions. The default ``TalkSub`` handler is closely
+based on ``TellSub`` (defined in library file ``verblibm.h``, should you be
+curious), and does three things:
+
+#. Deals with TALK TO ME or TALK TO MYSELF.
+
+#. Checks (a) whether the creature being talked to has a ``life``
+ property, (b) whether that property is prepared to process a ``Talk``
+ action, and (c) if the ``Talk`` processing returns ``true``. If all
+ three checks succeed then ``TalkSub`` need do nothing more; if one or
+ more of them fails then ``TalkSub`` simply...
+
+#. Displays a general "nothing to say" refusal to talk. ::
+
+ [ TalkSub;
+ if (noun == player) print_ret "Nothing you hear surprises you.";
+ if (RunLife(noun,##Talk) ~= false) return;
+ print_ret "At the moment, you can't think of anything to say.";
+ ];
+
+ .. note::
+
+ That second condition ``(RunLife(noun,##Talk) ~= false)`` is a bit of
+ a stumbling block, since it uses ``RunLife`` -- an undocumented
+ internal library routine -- to offer the ``Talk`` action to the NPC's
+ ``life`` property. We've decided to use it in exactly the same way
+ as the ``Tell`` action does, without worrying too much about how it
+ works (though it looks as though ``RunLife`` returns some ``true``
+ value if the ``life`` property has intercepted the action, ``false``
+ if it hasn't). The ``~=`` operator means "not equal to".
+
+The grammar is straightforward::
+
+ Verb 'talk' 't//' 'converse' 'chat' 'gossip'
+ * 'to'/'with' creature -> Talk
+ * creature -> Talk;
+
+Notice the use of ``'t//'`` to define T as a synonym for TALK, another way
+to make life a little easier for the player. (Actually, doing this
+introduces a minor problem: if the player types just T then the library
+prompts "Whom do you want to t to?" The fix for this involves enhancing an
+internal library routine called ``LanguageVerb`` -- not complex, but a
+little too heavy for our second game.)
+
+Here's the simplest ``Talk`` handler that we've seen -- it's from Gessler
+the governor. Any attempt to TALK TO GESSLER will provoke "You cannot
+bring yourself to speak to him". ::
+
+ life [;
+ Talk: print_ret "You cannot bring yourself to speak to him.";
+ ],
+
+Walter's ``Talk`` handler is only slightly more involved::
+
+ life [;
+ Talk:
+ if (location == marketplace)
+ print_ret "~Stay calm, my son, and trust in God.~";
+ print_ret "You point out a few interesting sights.";
+ ],
+
+And Helga's is the most sophisticated (though that isn't saying much)::
+
+ times_spoken_to 0, ! for counting the conversation topics
+ life [;
+ Talk:
+ self.times_spoken_to = self.times_spoken_to + 1;
+ switch (self.times_spoken_to) {
+ 1: score = score + 1;
+ print_ret "You warmly thank Helga for the apple.";
+ 2: print_ret "~See you again soon.~";
+ default:
+ return false;
+ }
+ ],
+
+This handler uses Helga's ``times_spoken_to`` property -- not a library
+property, it's one that we invented, like the ``mid_square.warnings_count``
+and ``pole.has_been_saluted`` properties -- to keep track of what's been
+said, permitting two snatches of conversation (and awarding a point) before
+falling back on the embarrassing silences implied by "You can't think of
+anything to say".
+
+That's the end of our little fable; you'll find a transcript and the full
+source in "William Tell" story on page 219. And now, it's time to meet --
+Captain Fate!