Contents
Back
Forward

16. Living creatures and conversation


To know how to live is my trade and my art.

...Michel de Montaigne (1533--1592), Essays


Everything that can be said can be said clearly.

...Ludwig Wittgenstein (1889--1951), Tractatus

This rummage through special kinds of objects finishes up with the most sophisticated kind: living ones. Note that the finer points of this section, on the arts of conversation, require some knowledge of Chapter V.

Animate objects, such as sea monsters, mad aunts or nasty little dwarves, have a property called life. This behaves somewhat like a before or after routine, but only applies to the following actions:

Attack
The player is making hostile advances...

Kiss
...or excessively friendly ones...

WakeOther
...or simply trying to rouse the creature from sleep.

ThrowAt
The player asked to throw noun at the creature.

Give
The player asked to give noun to the creature...

Show
...or, tantalisingly, just to show it.

Ask
The player asked about something. Just as with a "consult'' topic (see Section 15 passim), the variables consult_from and consult_words are set up to indicate which words the object might like to think about. (In addition, second holds the dictionary value for the first word which isn't 'the', but this is much cruder.)

Tell
Likewise, the player is trying to tell the creature about something. The topic is set up just as for Ask (that is, consult_from and consult_words are set, and second also holds the first interesting word).
Answer
This can happen in two ways. One is if the player types "answer <some text> to troll" or "say <some text> to troll''; the other is if he gives an order which the parser can't sort out, such as "troll, og south", and which the orders property hasn't handled already. Once again, variables are set as if it were a "consult'' topic. (In addition, noun is set to the first word, and an attempt to read the text as a number is stored in the variable special_number: for instance, "computer, 143" will cause special_number to be set to 143.)

Order
This catches any 'orders' which aren't handled by the orders property (see below); action, noun and second are set up as usual.

If the life routine doesn't exist, or returns false, events take their usual course. life routines tend to be quite lengthy, even for relatively static characters such as the priest who stands in the 'Ruins' Shrine:

Object -> priest "mummified priest"
  with name "mummified" "priest",
       description
          "He is desiccated and hangs together only by will-power.  Though
           his first language is presumably local Mayan, you have the curious
           instinct that he will understand your speech.",
       initial "Behind the slab, a mummified priest stands waiting, barely
           alive at best, impossibly venerable.",
       life
       [; Answer: "The priest coughs, and almost falls apart.";
          Ask:     switch(second)
                   {   'dictionary', 'book':
                            if (dictionary has general)
                                "~The ~bird~ glyph... very funny.~";
                           "~A dictionary? Really?~";
                       'glyph', 'glyphs', 'mayan', 'dialect':
                           "~In our culture, the Priests are ever literate.~";
                       'king', 'tomb', 'shrine', 'temple', 'altar', 'slab':
                           "~The King (life! prosperity! happiness!) is buried
                            deep under this Shrine, where you will never go.~";
                   }
                   "~You must find your own answer.~";
          Tell:   "The priest has no interest in your sordid life.";
          Attack, Kiss:  remove self;
                  "The priest desiccates away into dust until nothing
                   remains, not a breeze nor a bone.";
          ThrowAt: move noun to location; <<Attack self>>;
          Show, Give:
                   if (noun==dictionary && dictionary hasnt general)
                   {   give dictionary general;
                      "The priest reads a little of the book, laughing
                       in a hollow, whispering way.  Unable to restrain
                       his mirth, he scratches in a correction somewhere
                       before returning the book.";
                   }
                  "The priest is not very interested in earthly things.";
       ],
  has  animate;
(Some of the Ask topics are omitted for brevity.) Of course an animate object still has before and after routines like any other, so you can trap many other kinds of behaviour. Animate creatures can also react_before and react_after, and it's here that these properties really come into their own:
       react_before
       [; Drop: if (noun==satellite_gadget)
             print "~I wouldn't do that, Mr Bond,~ says Blofeld.^^";
          Shoot: remove beretta;
            "As you draw, Blofeld snaps his fingers and a giant
             magnet snatches the gun from your hand.  It hits the
             ceiling with a clang.  Blofeld silkily strokes his cat.";
       ];
If Blofeld moves from place to place, these rules move with him.

??EXERCISE 18:
(link to
the answer)
Arrange for a bearded psychiatrist to place the player under observation, occasionally mumbling insights such as "Subject puts green cone on table. Interesting.''

Another example is the coiled snake from 'Balances', which shows that even the tiniest life routine can be adequate for an animal:

Object -> snake "hissing snake"
  with name "hissing" "snake",
       initial "Tightly coiled at the edge of the chasm is a hissing snake.",
       life [; "The snake hisses angrily!"; ],
  has  animate;

/\ When writing general code to deal with animate creatures, it's sometimes convenient to have a system worked out for printing pronouns such as "her'' and "He''. See Section 22 for one way to do this.

Sometimes creatures should be transparent, sometimes not. Consider these two cases of animate characters, for instance:

-- an urchin with something bulging inside his jacket pocket;

-- a hacker who has a bunch of keys hanging off his belt.

The hacker is transparent, the urchin not. That way the parser prevents the player from referring to whatever the urchin is hiding, even if the player has played the game before, and knows what is in there and what it's called. But the player can look at and be tantalised by the hacker's keys.

When the player types in something like "pilot, fly south'', the result is called an 'order': this is the corresponding idea to an 'action'. (Indeed, if the player types "me, go south'' an ordinary Go s_obj action is produced.)

The order is sent to the pilot's orders property, which may if it wishes obey or react in some other way. Otherwise, the standard game rules will simply print something like "The pilot has better things to do.'' The above priest is especially unhelpful:

       orders
       [;  Go: "~I must not leave the Shrine.~";
           NotUnderstood: "~You speak in riddles.~";
           default: "~It is not your orders I serve.~";
       ];
(The NotUnderstood clause is run when the parser couldn't understand what the player typed: e.g., "priest, go onrth''.)

/\ Something to bear in mind is that because the library regards the words "yes'' and "no'' as being verbs in Inform, it understands "delores, yes'' as being a Yes order. (This can be a slight nuisance, as "say yes to delores'' is treated differently: it gets routed through the life routine as an Answer.)

/\/\ If the orders property returns false (or if there wasn't an orders property in the first place), the order is sent either to the Order: part of the life property (if it's understood) or to the Answer: part (if it isn't). (This is how all orders used to be processed, and it's retained to avoid making reams of old Inform code go wrong.) If these also return false, a message like "X has better things to do'' or "There is no reply'' is finally printed.

To clarify the various kinds of conversation:
Command rule action noun second consult
"orc, take axe'' order Take axe 0
"orc, yes'' order Yes 0 0
"ask orc for the shield'' order Give shield player
"orc, troll'' order NotU... 'troll' orc 3 1
"say troll to orc'' life Answer 'troll' orc 2 1
"answer troll to orc'' life Answer 'troll' orc 2 1
"orc, tell me about coins'' life Ask orc 'coins' 6 1
"ask orc about the big troll'' life Ask orc 'big' 4 3
"ask orc about wyvern'' life Ask orc 0 4 1
"tell orc about lost troll'' life Tell orc 'lost' 4 2
where "wyvern'' is a word not mentioned anywhere in the program, which is why its value is 0.

??EXERCISE 19:
(link to
the answer)
In some ways, Answer and Tell are just too much trouble. How can you make attempts to use these produce a message saying "To talk to someone, try 'someone, something'.''?

Some objects are not alive as such, but can be spoken to: microphones, tape recorders, voice-activated computers and so on. It would be a nuisance to implement these as animate, since they have none of the other characteristics of life: instead, they can be given just the attribute talkable and orders and life properties to deal with the resulting conversation.

??EXERCISE 20:
(link to
the answer)
(Cf. 'Starcross'.) Construct a computer responding to "computer, theta is 180''.

/\ The rest of this section starts to overlap much more with Chapter V, and assumes a little familiarity with the parser.

/\ The NotUnderstood clause of orders is run when the parser has got stuck parsing an order like "pilot, fly somersaults''. The variable etype holds the parser error that would have been printed out, had it been a command by the player himself. See Section 29: for instance, CANTSEE_PE would mean "the pilot can't see any such object''.

/\ When the player issues requests to an animate or talkable object, they're normally parsed exactly as if they were commands by the player himself (except that the actor is now the person being spoken to). But sometimes one would rather they were parsed by an entirely different grammar. For instance, consider Zen, the flight computer of an alien spacecraft. It's inappropriate to tell Zen to (say) pick up a teleport bracelet and the crew tend to give commands more like:
"Zen, set course for Centauro''
"Zen, speed standard by six''
"Zen, scan 360 orbital''
"Zen, raise the force wall''
"Zen, clear the neutron blasters for firing''
This could mostly be implemented by adding verbs like "raise'' to the usual game grammar (see the 'Starcross' computer exercise above), or by carefully trapping the Answer rule. But this is a nuisance, especially if about half the commands you want are recognised as orders in the usual grammar but the other half aren't.

An animate or talkable object can therefore provide a grammar routine (if it likes). This is called at a time when the parser has worked out the object that is being addressed and has set the variables verb_num and verb_word (to the number of the 'verb' and its dictionary entry, respectively: for example, in "orac, operate the teleport'' verb_num would be 3 (because the comma counts as a word on its own) and verb_word would be 'operate'). The grammar routine can reply by returning:

0. -- The parser carries on as usual.

1. -- The grammar routine is saying it has done all the parsing necessary itself, by hand (i.e., using NextWord, TryNumber, NounDomain and the like): the variables action, noun and second must be set up to contain the resulting order.

'verb' -- The parser ignores the usual grammar and instead works through the grammar lines for the given verb (see below).

-'verb' -- Ditto, except that if none of those grammar lines work then the parser goes back and tries the usual grammar as well.

In addition, the grammar routine is free to do some partial parsing of the early words provided it moves on verb_num accordingly to show how much it's got through.

??/\EXERCISE 21:
(link to
the answer)
Implement Charlotte, a little girl who's playing Simon Says (a game in which she only follows your instructions if you remember to say "Simon says'' in front of them: so she'll disobey "charlotte, wave'' but obey "charlotte, simon says wave'').

??/\EXERCISE 22:
(link to
the answer)
Another of Charlotte's rules is that if you say a number, she has to clap that many times. Can you play?

??/\EXERCISE 23:
(link to
the answer)
Regrettably, Dyslexic Dan has always mixed up the words "take'' and "drop''. Implement him anyway.

/\ It's useful to know that if the player types a comma or a full stop, then the parser cuts these out as separate words. Because of this, a dictionary word containing up to 7 letters and then a comma or a full stop can never be matched by what the player types. Such a word is called an "untypeable verb'', and it's useful to help a grammar routine to shunt parsing into a piece of game grammar which the player can never use. For instance, here's a way to implement the 'Starcross' computer which doesn't involve creating foolish new actions. We create grammar:
[ Control;
  switch(NextWord())
  {   'theta': parsed_number=1; return 1;
      'phi':   parsed_number=2; return 1;
      'range': parsed_number=3; return 1;
      default: return -1;
  }
];
Verb "comp," * Control "is" number -> SetTo;
And the computer itself needs properties
       grammar [; return 'comp,'; ],
       orders
       [;  SetTo:
               switch(noun)
               {   1: print "~Theta"; 2: print "~Phi"; 3: print "~Range"; }
               print_ret " set to ", second, ".~";
           default: "~Does not compute!~";
       ];
This may not look easier, but it's much more flexible, as the exercises below will hopefully demonstrate.

/\/\ Another use for untypeable verbs is to create what might be called 'fake fake actions'. Recall that a fake action is one which is never generated by the parser, and has no action routine. Sometimes (very rarely) you want a proper action but which still can't be generated by the parser: the following example creates three.
Verb "actions." * -> Prepare * -> Simmer * -> Cook;
The parser never uses "actions.'' in its ordinary grammar, so this definition has the sole effect of creating three new actions: Prepare, Simmer and Cook.

??/\/\EXERCISE 24:
(link to
the answer)
How can you make a grammar extension to an ordinary verb that will apply only to Dan?

??/\EXERCISE 25:
(link to
the answer)
Make an alarm clock responding to "alarm, off'', "alarm, on'' and "alarm, half past seven'' (the latter to set its alarm time).

??/\EXERCISE 26:
(link to
the answer)
Implement a tricorder (from Star Trek) which analyses nearby objects on a request like "tricorder, the quartz stratum''.

??/\EXERCISE 27:
(link to
the answer)
And, for good measure, a replicator responding to commands like "replicator, tea earl grey'' and "replicator, aldebaran brandy''.

??/\/\EXERCISE 28:
(link to
the answer)
And a communications badge in contact with the ship's computer, which answers questions like "computer, where is Admiral Lebling''.

??/\/\EXERCISE 29:
(link to
the answer)
Finally, construct the formidable flight computer Zen.

The next two exercises really belong to Section 28, but are too useful (for the "someone on the other end of a phone'' situation) to bury far away. Note that an alternative to these scope-hacking tricks, if you just want to implement something like "michael, tell me about the crystals'' (when Michael is at the other end of the line), is to make the phone a talkable object and make the word 'michael' refer to the phone (using a parse_name routine).

For more on scope hacking, see Section 28. Note that the variable scope_reason is always set to the constant value TALKING_REASON when the game is trying to work out who you wish to talk to: so it's quite easy to make the scope different for conversational purposes.

??/\EXERCISE 30:
(link to
the answer)
Via the main screen of the Starship Enterprise, Captain Picard wants to see and talk to Noslen Maharg, the notorious tyrant, who is down on the planet Mrofni. Make it so.

??/\/\EXERCISE 31:
(link to
the answer)
Put the player in telepathic contact with Martha, who is in a sealed room some distance away, but who has a talent for telekinesis. Martha should respond well to "martha, look'', "ask martha about...'', "say yes to martha'', "ask martha for red ball'', "martha, give me the red ball'' and the like.

*REFERENCES:
A much fuller example of a 'non-player character' is given in the example game 'The Thief', by Gareth Rees (though it's really an implementation of the gentleman in 'Zork', himself an imitation of the pirate in 'Advent'). The thief is capable of walking around, being followed, stealing things, picking locks, opening doors and so on.
Other good definitions of animate objects to look at are Christopher in 'Toyshop', who will stack up building blocks on request; the kittens in 'Alice Through The Looking-Glass'; the barker in 'Balances', and the cast of 'Advent': the little bird, the snake, bear and dragon, the pirate and of course the threatening little dwarves.
Following people means being able to refer to them after they've left the room: see 'Follow my leader', also by Mr Rees, or the library extension "follower.h'' by Andrew Clover.
See the Inform home page for a way round the Yes awkwardness.
For parsing topics of conversation in advanced ways, see the example game 'Encyclopaedia Frobozzica' by Gareth Rees.
To see how much a good set of characters can do for a game, try playing the prologue of 'Christminster'.


Contents / Back / Forward
Chapter I / Chapter II / Chapter III / Chapter IV / Chapter V / Chapter VI / Appendix
Mechanically translated to HTML from third edition as revised 16 May 1997. Copyright © Graham Nelson 1993, 1994, 1995, 1996, 1997: all rights reserved.