DM4 §18: Making conversation

## §18 Making conversation

To listen is far harder than to speak. This section overlaps with Chapter IV, the chapter on parsing text, and the later exercises are among the hardest in the book. As the following summary table shows, the simpler ways for the player to speak to people were covered in the previous section: this section is about “orders”.

Example command | Rule | `action` | `noun` | `second` | consult
“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
“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

Here we're supposing that the game's dictionary includes “troll”, “orc” and so forth, but not “wyvern”, which is why “ask orc about wyvern” results in the action `Ask orc 0`. The notation `NotU...` is an abbreviation for `NotUnderstood`, of which more later. The two numbers in the “consult” column are the values of `consult_from` and `consult_words`, in cases where they are set.

· · · · ·

When the player types in something like “pilot, fly south”, addressing an object which has `animate` or at least `talkable`, the result is called an ‘order’.

The order is sent to the pilot's `orders` property, which may if it wishes comply or react in some other way. Otherwise, the standard game rules will simply print something like “The pilot has better things to do.” The ‘Ruins’ 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 of an `orders` rule is run when the parser couldn't understand what the player typed: e.g., “pilot, fly somersaults”.

▲ The Inform library regards the words “yes” and “no” as being verbs, so it parses “delores, yes” into 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`.

▲ When a `NotUnderstood` order is being passed to `orders`, the library sets up some variables to help you parse by hand if you need to. The actual order, say “fly somersaults”, becomes a sort of consultation topic, with `consult_from` and `consult_words` set to the first word number and the number of words. The variable `etype` holds the parser error that would have been printed out, had it been a command by the player himself. See §33: for instance, the value `CANTSEE_PE` would mean “the pilot can't see any such object”.

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

• EXERCISE 27
(Cf. ‘Starcross’.) Construct a computer responding to “computer, theta is 180”.

• EXERCISE 28
For many designers, `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’.”?

· · · · ·

When the player issues a request to an `animate` or `talkable` object, they're normally parsed in the standard way. “avon, take the bracelet” results in the order `Take bracelet` being sent to Kerr Avon, just as typing “take the bracelet” results in the action `Take bracelet` passing to the player. The range of text understood is the same, whether or not the person addressed is Avon. Sometimes, though, one would rather that different people understood entirely different grammars.

For instance, consider Zen, the flight computer of an alien spacecraft. It's inappropriate to tell Zen to 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”

For such commands, an `animate` or `talkable` object can if it likes provide a `grammar` property. This is called at a time when the parser has worked out the object being addressed and has set the variables `verb_wordnum` and `verb_word` to the word number of the ‘verb’ and its dictionary entry, respectively. For example, in “orac, operate the teleport” `verb_wordnum` would be 3, because the comma counts as a word on its own, and `verb_word` would be `'operate'`.

Once called, the `grammar` routine can reply to the parser by returning:

`false`
  Meaning “carry on as usual”.
`true`
  Meaning “you can stop parsing now because I have done it all, and put the resulting order into the variables `action`, `noun` and `second`”.
`'verb'`
  Meaning “don't use the standard game grammar: use the grammar lines for this verb instead”.
`-'verb'`
  Meaning “use the grammar lines for this verb, and if none of them match, use the standard game grammar as usual”.

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

•▲ EXERCISE 29
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 30
Another of Charlotte's rules is that if you say a number, she has to clap that many times. Can you play?

•▲ EXERCISE 31
Regrettably, Dyslexic Dan has always mixed up the words “take” and “drop”. Implement him anyway.

· · · · ·

▲ When devising unusual grammars, you sometimes want to define grammar lines that the player can only use when talking to other people. The vile trick to achieve this is to attach these grammar lines to an “untypeable verb”, such as `'comp,'`. This can never match what the player typed because the parser automatically separates the text “comp,” into two words, “comp” and “,”, with a space between them. The same will happen with any word of up to 7 letters followed by a comma or full stop. For instance, here's one way to solve the ‘Starcross’ computer exercise, using an untypeable verb:

    [ Control;
      switch (NextWord()) {
          'theta': parsed_number = 1; return GPR_NUMBER;
          'phi':   parsed_number = 2; return GPR_NUMBER;
          'range': parsed_number = 3; return GPR_NUMBER;
          default: return GPR_FAIL;
      }
    ];
    Verb 'comp,' * Control 'is' number -> SetTo;

(Here, `Control` is a “general parsing routine”: see §31.) The computer itself then needs these properties:

    grammar [; return 'comp,'; ],
    orders [;
        SetTo:
            switch (noun) {
                1: print "~Theta"; 2: print "~Phi"; 3: print "~Range";
            }
            " set to ", second, ".~";
        default: "~Does not compute!~";
    ];

This may not look easier, but it's much more flexible, as the exercises below may demonstrate.

•▲▲ EXERCISE 32
How can you make a grammar extension to an ordinary verb that will apply only to Dan?

•▲ EXERCISE 33
Make an alarm clock responding to “alarm, off”, “alarm, on” and “alarm, half past seven” (the latter to set its alarm time).

•▲ EXERCISE 34
Implement a tricorder (from Star Trek) which analyses nearby objects on a request like “tricorder, the quartz stratum”.

•▲ EXERCISE 35
And, for good measure, a replicator responding to commands like “replicator, tea earl grey” and “replicator, aldebaran brandy”.

•▲▲ EXERCISE 36
And a communications badge in contact with the ship's computer, which answers questions like “computer, where is Admiral Blank”. (This is best done with “scope hacking”, for which see §32.)

•▲▲ EXERCISE 37
Finally, construct the formidable flight computer Zen. (Likewise.)

▲▲ To trump one vile trick with another, untypeable verbs are also sometimes used 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. For instance, there's no `ThrownAtSub`, because `ThrownAt` is a fake. A fake fake action is a half-measure: it's a full action in every respect, including having an action routine, except that it can never be generated by the parser. The following grammar line creates three of them, called `Prepare`, `Simmer` and `Cook`:

    Verb 'fakes.' * -> Prepare * -> Simmer * -> Cook;

The author is indebted for this terminology to an algebraic geometry seminar by Peter Kronheimer on fake and fake fake K3 surfaces.

· · · · ·

▲ Difficult “someone on the other end of a phone” situations turn up quite often in one form or another (see, for instance, the opening scene of ‘Seastalker’) and often a quite simple solution is fine. If you just want to make something like “michael, tell me about the crystals” work, when Michael is at the other end of the line, give the phone the talkable attribute and make the word 'michael' one of its names. If several people are on the phone at different times, you can always give the phone a `parse_name` property (see §28) to respond to different names at different times.

•▲ EXERCISE 38
Via the main screen of the Starship Enterprise, Captain Jean-Luc Picard wants to see and talk to Noslen Maharg, the notorious tyrant, who is down on the planet Mrofni. Make it so.

•▲▲ EXERCISE 39
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 to “martha, look”, “ask martha about…”, “say yes to martha”, “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 I’, 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 animals and dwarves of ‘Advent’. •Following people means being able to refer to them after they've left the room: see the library extension `"follower.h"` by Gareth Rees, Andrew Clover and Neil James Brown. •A wandering character with a destination to aim for needs to be able to navigate from room to room, and possibly through doors. Ideally, a designer should be able to make a simple instruction like “head for the West Ballroom” without specifying any route. Two independent library extensions allow this: `"MoveClass.h"`, by Neil James Brown and Alan Trewartha, is compatible with `"follower.h"` and is especially strong on handling doors. Volker Lanz's `"NPCEngine"` is designed for what might be called detective-mystery situations, in which the people inside a country house are behaving independently in ways which must frequently be described to the player. •Irene Callaci's `"AskTellOrder.h"` library extension file automatically handles commands in the form “ask/tell someone to do something”.