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
true
action
,
noun
and second
”.'verb'
-'verb'
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”.