1
This is Info file inform.info, produced by Makeinfo-1.64 from the input
4
This is the Inform Designer's Manual, third edition, 4 September 1996,
5
as updated 16 May 1997. It was converted to Info by Christopher J.
6
Madsen <ac608@yfn.ysu.edu>.
8
Copyright 1996,1997 Graham Nelson and Christopher J. Madsen
10
Permission is granted to make and distribute copies of this manual
12
(a) distributed copies are not substantially different from those
13
archived by the author,
14
(b) this and other copyright messages are always retained in full, and
15
(c) no profit is involved.
18
File: inform, Node: Describing and Parsing, Next: Testing and Hacking, Prev: The Model World, Up: Top
20
Describing and Parsing
21
**********************
23
Language disguises thought... The tacit conventions on which the
24
understanding of everyday language depends are enormously
27
-- Ludwig Wittgenstein (1889-1951), Tractatus
31
* Describing Objects:: Describing objects and rooms
32
* Listing Objects:: Listing and grouping objects
33
* Parsing Nouns:: How nouns are parsed
34
* Plural Names:: Plural names for duplicated objects
35
* Parsing Verbs:: How verbs are parsed
36
* Grammar Tokens:: Tokens of grammar
37
* Scope:: Scope and what you can see
38
* Helping the Parser:: Helping the parser out of trouble
41
File: inform, Node: Describing Objects, Next: Listing Objects, Prev: Describing and Parsing, Up: Describing and Parsing
43
Describing objects and rooms
44
============================
46
And we were angry and poor and happy,
47
And proud of seeing our names in print.
49
-- G. K. Chesterton (1874-1936), A Song of Defeat
51
Talking to the player about the state of the world is much easier than
52
listening to his intentions for it. Despite this, the business of
53
description takes up a fair part of Chapter V since the designer of a
54
really complex game will eventually need to know almost every rule
55
involved. (Whereas nobody would want to know everything about the
58
To begin, the simplest description is the "short name" given to a
59
single object. For instance
63
may result in "an old brass lamp" being printed. There are four such
66
print (the) obj Print the object with its definite article
67
print (The) obj The same, but capitalised
68
print (a) obj Print the object with indefinite article
69
print (name) obj Print the object's short name alone
71
and these can be freely mixed into lists of things to print or
72
print_ret, as for example:
74
print_ret "The ogre declines to eat ", (the) noun, ".";
79
(By Gareth Rees.) When referring to animate objects, one usually needs
80
to use pronouns such as "his". Define new printing routines so that,
81
say, print "You throw the book at ", (PronounAcc) obj, "!"; will insert
82
the right accusative pronoun.
86
!!!! There is also a special syntax print object for printing object
87
names, but `do not use it without good reason': it doesn't understand
88
some of the features below and is not protected against crashing if you
89
mistakenly try to print the name for an out of range object number.
91
Inform tries to work out the right indefinite article for any object
92
automatically. In English-language games, it uses `an' when the short
93
name starts with a vowel and `a' when it does not (unless the name is
94
plural, when `some' is used in either case). You can override this by
95
setting article yourself. Here are some possibilities:
97
a / platinum bar, an / orange balloon, your / Aunt Jemima,
98
some bundles of / reeds, far too many / marbles, The / London Planetarium
100
If the object is given the attribute proper then its name is treated as
101
a proper noun with no indefinite article, so the value of article is
104
!! The article property can also hold a routine to print one.
106
Definite articles are always "the" (except for proper nouns). Thus
108
the platinum bar, Benjamin Franklin, Elbereth
110
are all printed by print (the) ...; the latter two objects being proper.
112
!! There's usually no need to worry about definite and indefinite
113
articles for room objects, as Inform never has cause to print them.
115
A single object whose name is plural, such as "grapes" or "marble
116
pillars", should be given the attribute pluralname. As a result the
117
library might say, e.g., "You can't open those" instead of "You can't
118
open that". It also affects the pronoun "them" and makes the usual
119
indefinite article "some".
121
!! You can give animate objects the attributes male, female or neuter
122
to help the parser understand pronouns properly. animate objects are
123
assumed to be male if you set neither alternative.
125
The short name of an object is normally the text given in double-quotes
126
at the head of its definition. This is very inconvenient to change
127
during play when, for example, "blue liquid" becomes "purple liquid" as
128
a result of a chemical reaction. A more flexible way to specify an
129
object's short name is with the short_name property. To print the name
130
of such an object, Inform does the following:
132
1. If the short_name is a string, it's printed and that's all.
134
2. If it is a routine, then it is called. If it returns true, that's
137
3. The text given in the header of the object definition is printed.
139
For example, the dye might be given:
142
[; switch(self.colour)
145
3: print "horrid sludge"; rtrue;
149
with "liquid" as the short name in its header. According to whether
150
its colour property is 1, 2 or 3, the printed result is "blue liquid",
151
"purple liquid" or "horrid sludge".
153
!! Alternatively, define the dye with short_name "blue liquid" and then
154
simply execute dye.short_name = "purple liquid"; when the time comes.
156
!! Rooms can also be given a short_name routine, which is useful to
157
code, say, a grid of four hundred similar locations called "Area 1" up
158
to "Area 400". (They can be represented by just one object in the
161
For many objects the indefinite article and short name will most often
162
be seen in inventory lists, such as
168
your satchel (which is open)
171
Some objects, though, ought to have fuller entries in an inventory: a
172
wine bottle should say how much wine is left, for instance. The invent
173
property is designed for this. The simplest way to use invent is as a
174
string. For instance, declaring a peculiar book with
176
invent "that harmless old book of Geoffrey's",
178
will make this the inventory line for the book. In the light of
179
events, it could later be changed to
181
geoffreys_book.invent = "that lethal old book of Geoffrey's";
183
!! Note that this string becomes the whole inventory entry: if the
184
object were an open container, its contents wouldn't be listed, which
185
might be unfortunate. In such circumstances it's better to write an
186
invent routine, and that's also the way to append text like
189
!! Each line of an inventory is produced in two stages. *First*, the
193
The global variable inventory_stage is set to 1.
196
The invent routine is called (if there is one). If it returns
200
The object's indefinite article and short-name are printed.
202
*Second*, little informative messages like "(which is open)" are
203
printed, and inventories are given for the contents of open containers:
206
The global variable inventory_stage is set to 2.
209
The invent routine is called (if there is one). If it returns
213
A message such as "(closed, empty and providing light)" is
214
printed, as appropriate.
217
If it is an open container, its contents are inventoried.
219
After each line is printed, linking text such as a new-line or a
220
comma is printed, according to the current "list style".
222
For example, here is the invent routine used by the matchbook in
226
[ i; if (inventory_stage==2)
228
if (i==0) print " (empty)";
229
if (i==1) print " (1 match left)";
230
if (i>1) print " (",i," matches left)";
237
Suppose you want to change the whole inventory line for an ornate box
238
but you can't use an invent string, or return true from stage 1,
239
because you still want stage 2d to happen properly (so that its
240
contents will be listed). How can you achieve this?
244
The largest and most complicated messages Inform ever prints on its own
245
initiative are room descriptions, printed when the Look action is
246
carried out (for instance, when the statement <Look>; triggers a room
247
description). What happens is: the room's short name is printed
248
(usually in bold-face) on a line of its own, then its description,
249
followed by a list of the objects residing there which aren't concealed
252
Chapter IV mentioned many different properties -- initial, when_on,
253
when_off and so on -- giving descriptions of what an object looks like
254
when in the same room as the player; some apply to doors, others to
255
switchable objects and so on. All of them can be routines to print
256
text, instead of being strings to print. The precise rules are given
259
But the whole system can be bypassed using the describe property.
260
If an object gives a describe routine then this takes priority over
261
everything: if it returns true, the library assumes that the object has
262
already been described, and prints nothing further. For example,
265
[; "^The platinum pyramid catches the light beautifully.";
268
means that even when the pyramid has been moved (i.e. held by the player
269
at some stage) it will always have its own line of room description.
271
!! Note the initial ^ (new-line) character. The library doesn't print
272
a skipped line itself before calling describe because it doesn't know
273
yet whether the routine will want to say anything. A describe routine
274
which prints nothing and returns true makes an object invisible, as if
277
!!!! The Look action does three things: it `notes arrival', prints the
278
room description then `scores arrival'. Only the printing rules are
279
given here (see *Note Constants and Scoring:: for the others), but
280
they're given in full. In what follows, the word `location' means the
281
room object if there's light to see by, and the special "Darkness"
282
object otherwise. First the top line:
285
A new-line is printed. The location's short name is printed (in
286
bold-face, if possible).
289
If the player is on a supporter, then " (on <something>)" is
290
printed; if inside anything else, then " (in <something>)".
293
" (as <something>)" is printed if this was requested by the game's
294
most recent call to ChangePlayer (for instance, " (as a
298
A new-line is printed.
300
Now the `long description'. This step is skipped if the player has
301
just moved of his own will into a location already visited, unless the
302
game is in "verbose" mode.
305
If the location has a describe property, then run it. If not,
306
look at the location's description property: if it's a string,
307
print it; if it's a routine, run it.
309
All rooms must provide either a describe property or a description
310
of themselves. Now for items nearby:
313
List any objects on the floor.
316
If the player is in or on something, list the other objects in
319
The library has now finished, but your game gets a chance to add a
323
Call the entry point LookRoutine.
325
!! The visited attribute is only given to a room after its description
326
has been printed for the first time (it happens during `scoring
327
arrival'). This is convenient for making the description different
328
after the first time.
330
!! `Listing objects' (as in 3a and 3b) is a complicated business.
331
Some objects are given a line or paragraph to themselves, others are
332
lumped together in a list at the end. The following objects are not
333
mentioned at all: the player, what the player is in or on (if anything)
334
and anything which is scenery or concealed. The remaining objects are
335
looked through (eldest first) as follows:
337
1. If the object has a describe routine, run it. If it returns true,
338
stop here and don't mention the object at all.
340
2. Work out the "description property" for the object:
341
a. For a container, this is when_open or when_closed;
343
b. Otherwise, for a switchable object this is when_on or
346
c. Otherwise, for a door this is when_open or when_closed;
348
d. Otherwise, it's initial.
350
3. If *either* the object doesn't have this property *or* the object
351
has been held by the player before (i.e., has moved) and the
352
property isn't when_off or when_closed *then* then the object will
353
be listed at the end.
355
4. Otherwise a new-line is printed and the property is printed (if
356
it's a string) or run (if it's a routine).
358
!! A supporter which is scenery won't be mentioned, but anything on top
359
of it which is not concealed will be.
361
!! Objects which have just been pushed into a new room are not listed
362
in that room's description on the turn in question. This is not because
363
of any rule about room descriptions, but because the pushed object is
364
moved into the new room only after the room description is made. This
365
means that when a wheelbarrow is pushed for a long distance, the player
366
does not have to keep reading "You can see a wheelbarrow here." every
367
move, as though that were a surprise.
369
!! You can use a library routine called Locale to perform `object
370
listing'. See *Note Objects and Routines:: for details: suffice to say
371
here that the process above is equivalent to executing
373
if (Locale(location, "You can see", "You can also see"))
376
Locale is useful for describing areas of a room which are sub-divided
377
off, such as the stage of a theatre.
382
The library implements "superbrief" and "verbose" modes for room
383
description (one always omits long room descriptions, the other never
384
does). How can verbose mode automatically print room descriptions
385
every turn? (Some of the later Infocom games did this.)
392
* `Balances' often uses short_name, especially for the white cubes
393
(whose names change) and lottery tickets (whose numbers are chosen
394
by the player). `Adventureland' uses short_name in simpler ways:
395
see the bear and the bottle, for instance.
397
* The scroll class of `Balances' uses invent.
399
* See the ScottRoom class of `Adventureland' for a radically
400
different way to describe rooms (in pidgin English, like
404
File: inform, Node: Listing Objects, Next: Parsing Nouns, Prev: Describing Objects, Up: Describing and Parsing
406
Listing and grouping objects
407
============================
409
As some day it may happen that a victim must be found
410
I've got a little list -- I've got a little list
411
Of society offenders who might well be underground,
412
And who never would be missed
413
Who never would be missed!
415
-- W. S. Gilbert (1836-1911), The Mikado
417
The library often needs to reel off a list of objects: when an Inv
418
(inventory) action takes place, for instance, or when describing the
419
contents of a container or the duller items in a room. Lists are
420
difficult to print out correctly `by hand', because there are many
421
cases to get right, especially when taking plurals into account.
422
Fortunately, the library's list-maker is available to the public. The
425
WriteListFrom(object, style);
427
where the list will start from the given object and go along its
428
siblings. Thus, to list all the objects inside X, list from child(X).
429
What the list looks like depends on the "style", which is a bitmap you
430
can make by adding some of the following constants:
432
NEWLINE_BIT New-line after each entry
433
INDENT_BIT Indent each entry according to depth
434
FULLINV_BIT Full inventory information after entry
435
ENGLISH_BIT English sentence style, with commas and `and'
436
RECURSE_BIT Recurse downwards with usual rules
437
ALWAYS_BIT Always recurse downwards
438
TERSE_BIT More terse English style
439
PARTINV_BIT Only brief inventory information after entry
440
DEFART_BIT Use the definite article in list
441
WORKFLAG_BIT At top level (only), only list objects
442
which have the workflag attribute
443
ISARE_BIT Prints " is " or " are " before list
444
CONCEAL_BIT Misses out concealed or scenery objects
446
The best way to use this is to experiment. For example, a `tall'
447
inventory is produced by:
449
WriteListFrom( child(player),
450
FULLINV_BIT + INDENT_BIT + NEWLINE_BIT + RECURSE_BIT );
454
WriteListFrom( child(player),
455
FULLINV_BIT + ENGLISH_BIT + RECURSE_BIT );
457
which produce effects like:
461
a bag (which is open)
465
four featureless white cubes
470
You are carrying a bag (which is open), inside which are three gold
471
coins, two silver coins and a bronze coin, four featureless white
472
cubes, a magic burin and a spell book.
474
except that the `You are carrying' part is not done by the list-maker,
475
and nor is the final full stop in the second example. The workflag is
476
an attribute which the library scribbles over from time to time as
477
temporary storage, but you can use it with care. In this case it makes
478
it possible to specify any reasonable list.
480
!!!! WORKFLAG_BIT and CONCEAL_BIT specify conflicting rules. If
481
they're both given, then what happens is: at the top level, but not
482
below, everything with workflag is included; on lower levels, but not
483
at the top, everything without concealed or scenery is included.
488
Write a DoubleInvSub action routine to produce an inventory like so:
490
You are carrying four featureless white cubes, a magic burin and a
491
spell book. In addition, you are wearing a purple cloak and a miner's
496
!! Finally, there is a neat way to customise the grouping together of
497
non-identical items in lists, considerably enhancing the presentation
498
of the game. If a collection of game objects -- say, all the edible
499
items in the game -- have a common non-zero value of the property
500
list_together, in the range 1 to 1000, they will always appear
501
adjacently in inventories, room descriptions and the like.
503
Alternatively, instead of being a small number the common value can
504
be a string such as "foodstuffs". If so then lists will cite, e.g.,
506
three foodstuffs (a scarlet fish, some lemmas and an onion)
515
in indented lists. This only happens when two or more are gathered
518
Finally, the common value can be a routine, such as:
521
[; if (inventory_stage==1) print "heaps of food, notably ";
522
else print ", which would do you no good";
525
Typically this might be part of a class definition from which all the
526
objects in question inherit. A list_together routine will be called
527
twice: once, with inventory_stage set to 1, as a preamble to the list
528
of items, and once (with 2) to print any postscript required. It is
529
allowed to change c_style (the current list style) without needing to
530
restore the old value and may, by returning 1 from stage 1, signal the
531
list-maker not to print a list at all. The simple example above
534
heaps of food, notably a scarlet fish, some lemmas
535
and an onion, which would do you no good
537
Such a routine may want to make use of the variables parser_one and
538
parser_two, which respectively hold the first object in the group and
539
the depth of recursion in the list (this might be needed to keep
540
indentation going properly). Applying x=NextEntry(x,parser_two); moves
541
x on from parser_one to the next item in the group. Another helpful
542
variable is listing_together, set up to the first object of a group
543
being listed or to 0 whenever no group is being listed. The following
544
list of 24 items shows some possible effects (see the example game
547
You can see a plastic fork, knife and spoon, three hats (a fez, a Panama
548
and a sombrero), the letters X, Y, Z, P, Q and R from a Scrabble set, a
549
defrosting Black Forest gateau, Punch magazine, a recent issue of the
550
Spectator, a die and eight coins (four silver, one bronze and three gold)
556
Implement the Scrabble pieces.
563
Implement the three denominations of coin.
570
Implement the I Ching in the form of six coins, three gold (goat,
571
deer and chicken), three silver (robin, snake and bison) which can be
572
thrown to reveal gold and silver trigrams.
579
* A good example of WriteListFrom in action is the definition of
580
CarryingClass from the example game `The Thief', by Gareth Rees.
581
This alters the examine description of a character by appending a
582
list of what that person is carrying and wearing.
584
* Denominations of coin are also in evidence in `Balances'.
587
File: inform, Node: Parsing Nouns, Next: Plural Names, Prev: Listing Objects, Up: Describing and Parsing
592
The Naming of Cats is a difficult matter,
593
It isn't just one of your holiday games;
594
You may think at first I'm as mad as a hatter
595
When I tell you, a cat must have THREE DIFFERENT NAMES.
597
-- T. S. Eliot (1888-1965), The Naming of Cats
599
Bulldust, coolamon, dashiki, fizgig, grungy, jirble, pachinko,
600
poodle-faker, sharny, taghairm
602
-- Catachrestic words from Chambers English Dictionary
604
Suppose we have a tomato defined with
606
name "fried" "green" "tomato",
608
but which is going to redden later and need to be referred to as "red
609
tomato". It's perfectly straightforward to alter the name property of
610
an object, which is a word array of dictionary words. For example,
613
for (i=0:2*i<obj.#name:i++) print (address) (obj.&name)-->i, "^";
616
prints out the list of dictionary words held in name for a given
617
object. It's perfectly possible to write to this, so we could just set
619
(tomato.&name)-->1 = 'red';
621
but this is not a flexible or elegant solution, and it's time to begin
622
delving into the parser.
624
!! Note that we can't change the size of the name array. To simulate
625
this, we could define the object with name set to, say, 30 copies of an
626
`untypeable word' (see below) such as 'blank.'.
628
The Inform parser is designed to be as "open-access" as possible,
629
because a parser cannot ever be general enough for every game without
630
being highly modifiable. The first thing it does is to read in text
631
from the keyboard and break it up into a stream of words: so the text
632
"wizened man, eat the grey bread" becomes
634
wizened / man / , / eat / the / grey / bread
636
and these words are numbered from 1. At all times the parser keeps a
637
"word number" marker to keep its place along this line, and this is
638
held in the variable wn. The routine NextWord() returns the word at
639
the current position of the marker, and moves it forward, i.e. adds 1
640
to wn. For instance, the parser may find itself at word 6 and trying
641
to match "grey bread" as the name of an object. Calling NextWord()
642
gives the value 'grey' and calling it again gives 'bread'.
644
Note that if the player had mistyped "grye bread", "grye" being a
645
word which isn't mentioned anywhere in the program or created by the
646
library, NextWord() returns 0 for `misunderstood word'. Writing
647
something like if (w=='grye') ... somewhere in the program makes Inform
648
put "grye" into the dictionary automatically.
650
!! Remember that the game's dictionary only has 9-character resolution.
651
(And only 6 if Inform has been told to compile an early-model story
652
file: see *Note Run-Time Limitations::.) Thus the values of
653
'polyunsaturate' and 'polyunsaturated' are equal. Also, upper case and
654
lower case letters are considered the same. Words are permitted to
655
contain numerals or symbols (but not at present to contain accented
658
!!!! A dictionary word can even contain spaces, full stops or commas.
659
If so it is `untypeable'. For instance, 'in,out' is an untypeable word
660
because if the player does type it then the parser cuts it into three,
661
never checking the dictionary for the entire word. Thus the constant
662
'in,out' can never be anything that NextWord returns. This can
663
actually be useful (as it was in *note Living Creatures::.).
665
!! It can also be useful to check for numbers. The library routine
666
TryNumber(wordnum) tries to parse the word at wordnum as a number
667
(recognising decimal numbers and English ones from "one" to "twenty"),
668
returning -1000 if it fails altogether, or else the number. Values
669
exceeding 10000 are rounded down to 10000.
671
!!!! Sometimes there is no alternative but to actually look at the
672
player's text one character at a time (for instance, to check a
673
20-digit phone number). The routine WordAddress(wordnum) returns a
674
byte array of the characters in the word, and WordLength(wordnum) tells
675
you how many characters there are in it. Thus in the above example,
677
thetext = WordAddress(4);
678
print WordLength(4), " ", (char) thetext->0, (char) thetext->2;
680
prints the text "3 et".
682
An object can affect how its name is parsed by giving a parse_name
683
routine. This is expected to try to match as many words as possible
684
starting from the current position of wn, reading them in one at a time
685
using the NextWord() routine. Thus it must not stop just because the
686
first word makes sense, but must keep reading and find out how many
687
words in a row make sense. It should return:
689
0 if the text didn't make any sense at all,
690
k if k words in a row of the text seem to refer to the object, or
691
-1 to tell the parser it doesn't want to decide after all.
693
The word marker wn can be left anywhere afterwards. For example:
695
Object -> thing "weird thing"
697
[ i; while (NextWord()=='weird' or 'thing') i++;
701
This definition duplicates (very nearly) the effect of having defined:
703
Object -> thing "weird thing"
704
with name "weird" "thing";
706
Which isn't very useful. But the tomato can now be coded up with
709
[ i j; if (self has general) j='red'; else j='green';
710
while (NextWord()=='tomato' or 'fried' or j) i++;
714
so that "green" only applies until its general attribute has been set,
715
whereupon "red" does.
720
Rewrite this to insist that the adjectives must come before the
721
noun, which must be present.
728
Create a musician called Princess who, when kissed, is transformed
729
into "/?%?/ (the artiste formerly known as Princess)".
736
(Cf. `Cafe Inform'.) Construct a drinks machine capable of serving
737
cola, coffee or tea, using only one object for the buttons and one for
742
!! parse_name is also used to spot plurals: see *Note Plural Names::.
744
Suppose that an object doesn't have a parse_name routine, or that it
745
has but it returned -1. The parser then looks at the name words. It
746
recognises any arrangement of some or all of these words as a match
747
(the more words, the better). Thus "fried green tomato" is understood,
748
as are "fried tomato" and "green tomato". On the other hand, so are
749
"fried green" and "green green tomato green fried green". This method
750
is quick and good at understanding a wide variety of sensible inputs,
751
though bad at throwing out foolish ones.
753
However, you can affect this by using the ParseNoun entry point.
754
This is called with one argument, the object in question, and should
755
work exactly as if it were a parse_name routine: i.e., returning -1, 0
756
or the number of words matched as above. Remember that it is called
757
very often and should not be horribly slow. For example, the following
758
duplicates what the parser usually does:
761
while (IsAWordIn(NextWord(),obj,name) == 1) n++; return n;
763
[ IsAWordIn w obj prop k l m;
764
k=obj.∝ l=(obj.#prop)/2;
770
In this example IsAWordIn just checks to see if w is one of the entries
771
in the word array obj.&prop.
776
Many adventure-game parsers split object names into `adjectives' and
777
`nouns', so that only the pattern <0 or more adjectives> <1 or more
778
nouns> is recognised. Implement this.
785
During debugging it sometimes helps to be able to refer to objects
786
by their internal numbers, so that "put object 31 on object 5" would
787
work. Implement this.
794
How could the word "#" be made a wild-card, meaning "match any
802
And how could "*" be a wild-card for "match any collection of
810
There is no problem with calling a container "hole in wall", because
811
the parser will understand "put apple in hole in wall" as "put (apple)
812
in (hole in wall)". But create a fly in amber, so that "put fly in
813
amber in hole in wall" works properly and isn't misinterpreted as "put
814
(fly) in (amber in hole in wall)". (Warning: you may need to know
815
about the BeforeParsing entry point (*note Parsing Verbs::.) and the
816
format of the parse buffer (see *note Grammar Tokens::.).)
823
* Straightforward parse_name examples are the chess-pieces object
824
and the kittens class of `Alice Through The Looking-Glass'.
825
Lengthier ones are found in `Balances', especially in the white
829
File: inform, Node: Plural Names, Next: Parsing Verbs, Prev: Parsing Nouns, Up: Describing and Parsing
831
Plural names for duplicated objects
832
===================================
836
-- Petronius (?-c. 66), Cena Trimalchionis
838
A notorious problem for adventure game parsers is to handle a
839
collection of, say, ten gold coins, allowing the player to use them
840
independently of each other, while gathering them together into groups
841
in descriptions and inventories. This is relatively easy in Inform,
842
and only in really hard cases do you have to provide code. Two
843
problems must be overcome: firstly, the game has to be able to talk to
844
the player in plurals, and secondly vice versa. First, then, game to
848
with name "gold" "coin",
849
short_name "gold coin",
852
(and similar silver and bronze coin classes here)
856
has container open openable;
864
Now we have a bag of six coins. The player looking inside the bag will
868
In the bag are three gold coins, two silver coins and a bronze coin.
870
How does the library know that the three gold coins are the same as each
871
other, but the others different? It doesn't look at the classes but the
872
names. It will only group together things which:
874
a. have a plural set,
876
b. are `indistinguishable' from each other.
878
Indistinguishable means they have the same name words as each other,
879
possibly in a different order, so that nothing the player can type will
882
!! Actually, the library is cleverer than this. What it groups
883
together depends slightly on the context of the list it's writing out.
884
When it's writing a list which prints out details of which objects are
885
providing light, for instance (like an inventory), it won't group
886
together two objects if one is lit but the other isn't. Similarly for
887
objects with visible possessions or which can be worn.
889
!!!! This all gets even more complicated when the objects have a
890
parse_name routine supplied, because then the library can't use the name
891
fields to tell them apart. If they have different parse_name routines,
892
it decides that they're different. But if they have the same parse_name
893
routine, there is no alternative but to ask them. What happens is that
895
1. A variable called parser_action is set to ##TheSame;
896
2. Two variables, called parser_one and parser_two are set to
897
the two objects in question;
898
3. Their parse_name routine is called. If it returns:
899
-1 the objects are declared ``indistinguishable",
900
-2 they are declared different.
901
4. Otherwise, the usual rules apply and the library looks at
902
the ordinary name fields of the objects.
904
##TheSame is a fake action. The implementation of the `Spellbreaker
905
cubes' in the `Balances' game is an example of such a routine, so that
906
if the player writes the same name on several of the cubes, they become
907
grouped together. Note that this whole set-up is such that if the
908
author of a parse_name routine has never read this paragraph, it doesn't
909
matter and the usual rules take their course.
911
!!!! You may even want to provide a parse_name routine just to speed up
912
the process of telling two objects apart -- if there were 30 gold coins
913
the parser would be doing a lot of work comparing all their names, but
914
you can make the decision much faster.
916
Secondly, the player talking to the computer. This goes a little
917
further than just copies of the same object: many games involve
918
collecting a number of similar items, say a set of nine crowns in
919
different colours. Then you'd want the parser to recognise things like:
921
> drop all of the crowns except green
922
> drop the three other crowns
924
Putting the word "crowns" in their name lists is not quite right,
925
because the parser will still think that "crowns" might refer to a
926
specific item. Instead, put in the word "crowns//p". The //p marks
927
out the dictionary word "crowns" as one that can refer to more than one
928
game object at once. (So that you shouldn't set this for the word
929
"grapes" if a bunch of grapes was a single game object; you should give
930
that object the pluralname attribute instead.) For example the GoldCoin
934
with name "gold" "coin" "coins//p",
935
short_name "gold coin",
938
and now when the player types "take coins", the parser interprets this
939
as "take all the coins within reach".
941
!!!! The only snag is that now the word "coins" is marked as //p
942
everywhere in the game, in all circumstances. Here is a more
943
complicated way to achieve the same result, but strictly in context of
944
these objects alone. We need to make the parse_name routine tell the
945
parser that yes, there was a match, but that it was a plural. The way
946
to do this is to set parser_action to ##PluralFound, another fake
947
action. So, for example:
954
if (j=='crown' or self.name) i++;
957
{ parser_action=##PluralFound; i++; }
963
This code assumes that the crown objects have just one name each, their
969
Write a `cherub' class so that if the player tries to call them
970
"cherubs", a message like "I'll let this go by for now, but the plural
971
of cherub is cherubim" appears.
978
* See the coinage of `Balances'.
981
File: inform, Node: Parsing Verbs, Next: Grammar Tokens, Prev: Plural Names, Up: Describing and Parsing
986
Grammar, which can govern even kings.
988
-- Moliere (1622-1673), Les Femmes savantes
990
The parser's fundamental method is simple. Given a stream of text like
992
saint / peter / , / take / the / keys / from / paul
994
it first calls the entry point BeforeParsing (in case you want to
995
meddle with the text stream before it gets underway). It then works
996
out who is being addressed, if anyone, by looking for a comma, and
997
trying out the text up to there as a noun (anyone animate or anything
998
talkable will do): in this case St Peter. This person is called the
999
"actor", since he is going to perform the action, and is usually the
1000
player himself (thus, typing "myself, go north" is equivalent to typing
1001
"go north"). The next word, in this case 'take', is the "verb word".
1002
An Inform verb usually has several English verb words attached, which
1003
are called synonyms of each other: for instance, the library is set up
1005
`take' = `carry' = `hold'
1006
all referring to the same Inform verb.
1008
!! The parser sets up global variables actor and verb_word while
1009
working. (In the example above, their values would be the St Peter
1010
object and 'take', respectively.)
1012
!!!! It isn't quite that simple: names of direction objects are treated
1013
as implicit "go" commands, so that "n" is acceptable as an alternative
1014
to "go north". There are also "again", "oops" and "undo" to grapple
1017
!! Also, a major feature (the grammar property for the person being
1018
addressed) has been missed out of this description: see the latter half
1019
of *Note Living Creatures:: for details.
1021
Teaching the parser a new synonym is easy. Like all of the directives
1022
in this section, the following must appear after the inclusion of the
1023
library file Grammar:
1025
Verb "steal" "acquire" "grab" = "take";
1027
This creates another three synonyms for "take".
1029
!! One can also prise synonyms apart, as will appear later.
1031
The parser is now up to word 5; i.e., it has "the keys from paul" left
1032
to understand. Apart from a list of English verb-words which refer to
1033
it, an Inform verb also has a "grammar". This is a list of 1 or more
1034
"lines", each a pattern which the rest of the text might match. The
1035
parser tries the first, then the second and so on, and accepts the
1036
earliest one that matches, without ever considering later ones.
1038
A line is itself a row of "tokens". Typical tokens might mean `the
1039
name of a nearby object', `the word from' or `somebody's name'. To
1040
match a line, the parser must match against each token in sequence.
1041
For instance, the line of 3 tokens
1043
<a noun> <the word from> <a noun>
1045
matches the text. Each line has an action attached, which in this case
1046
is Remove: so the parser has ground up the original text into just four
1047
numbers, ending up with
1050
action = Remove noun = gold_keys second = st_paul
1052
What happens then is that the St Peter's orders routine (if any) is
1053
sent the action, and may if it wishes cooperate. If the actor had been
1054
the player, then the action would have been processed in the usual way.
1056
!! The action for the line which is currently being worked through is
1057
stored in the variable action_to_be; or, at earlier stages when the
1058
verb hasn't been deciphered yet, it holds the value NULL.
1060
The Verb directive creates Inform verbs, giving them some English verb
1061
words and a grammar. The library's Grammar file consists almost
1062
exclusively of Verb directives: here is an example simplified from one
1065
Verb "take" "get" "carry" "hold"
1068
* multiinside "from" noun -> Remove
1069
* "in" noun -> Enter
1070
* multiinside "off" noun -> Remove
1071
* "off" held -> Disrobe
1072
* "inventory" -> Inv;
1074
(You can look at the grammar being used in a game with the debugging
1075
verb "showverb": see *Note Debugging:: for details.) Each line of
1076
grammar begins with a *, gives a list of tokens as far as -> and then
1077
the action which the line produces. The first line can only be matched
1078
by something like "get out", the second might be matched by
1081
get all the fruit except the apple
1083
and so on. A full list of tokens will be given later: briefly, `"out"'
1084
means the literal word "out", `multi' means one or more objects nearby,
1085
`noun' means just one and `multiinside' means one or more objects
1086
inside the second noun. In this book, grammar tokens are written in
1087
the style `noun' to prevent confusion (as there is also a variable
1090
!!!! Since this book was first written, the library has been improved
1091
so that "take" and "get" each have their own independent grammars. But
1092
for the sake of example, suppose they share the grammar written out
1093
above. Sometimes this has odd results: "get in bed" is correctly
1094
understood as a request to enter the bed, "take in washing" is
1095
misunderstood as a request to enter the washing. You might avoid this
1096
by using Extend only to separate them into different grammars, or you
1097
could fix the Enter action to see if the variable verb_word=='take' or
1100
!! Some verbs are meta - they are not really part of the game: for
1101
example, "save", "score" and "quit". These are declared using Verb
1107
and any debugging verbs you create would probably work better this way,
1108
since meta-verbs are protected from interference by the game and take
1111
After the -> in each line is the name of an action. Giving a name in
1112
this way is what creates an action, and if you give the name of one
1113
which doesn't already exist then you must also write a routine to
1114
execute the action, even if it's one which doesn't do very much. The
1115
name of the routine is always the name of the action with Sub appended.
1118
[ XyzzySub; "Nothing happens."; ];
1119
Verb "xyzzy" * -> Xyzzy;
1121
will make a new magic-word verb "xyzzy", which always says "Nothing
1122
happens" -- always, that is, unless some before rule gets there first,
1123
as it might do in certain magic places. Xyzzy is now an action just as
1124
good as all the standard ones: ##Xyzzy gives its action number, and you
1125
can write before and after rules for it in Xyzzy: fields just as you
1126
would for, say, Take.
1128
!! Finally, the line can end with the word reverse. This is only
1129
useful if there are objects and numbers in the line which occur in the
1130
wrong order. An example from the library's grammar:
1132
Verb "show" "present" "display"
1133
* creature held -> Show reverse
1134
* held "to" creature -> Show;
1136
The point is that the Show action expects the first parameter to be an
1137
item, and the second to be a person. When the text "show him the
1138
shield" is typed in, the parser must reverse the two parameters "him"
1139
and "the shield" before causing a Show action. On the other hand, in
1140
"show the shield to him" the parameters are in the right order already.
1142
The library defines grammars for the 100 or so English verbs most often
1143
used by adventure games. However, in practice you very often need to
1144
alter these, usually to add extra lines of grammar but sometimes to
1145
remove existing ones. For example, consider an array of 676 labelled
1146
buttons, any of which could be pushed: it's hardly convenient to define
1147
676 button objects. It would be more sensible to create a grammar line
1148
which understands things like
1150
``button j16", ``d11", ``a5 button"
1152
(it's easy enough to write code for a token to do this), and then to
1153
add it to the grammar for the "press" verb. The Extend directive is
1154
provided for exactly this purpose:
1156
Extend "push" * Button -> PushButton;
1158
The point of Extend is that it is against the spirit of the Library to
1159
alter the standard library files -- including the grammar table --
1160
unless absolutely necessary.
1162
!!!! Another method would be to create a single button object with a
1163
parse_name routine which carefully remembers what it was last called,
1164
so that the object always knows which button it represents. See
1165
`Balances' for an example.
1167
Normally, extra lines of grammar are added at the bottom of those
1168
already there. This may not be what you want. For instance, "take"
1173
quite early on. So if you want to add a grammar line which diverts
1174
"take something-edible" to a different action, like so:
1178
(`edible' being a token matching anything which has the attribute
1179
edible) then it's no good adding this at the bottom of the Take
1180
grammar, because the earlier line will always be matched first. Thus,
1181
you really want to insert your line at the top, not the bottom, in this
1182
case. The right command is
1187
You might even want to over-ride the old grammar completely, not just
1188
add a line or two. For this, use
1190
Extend "push" replace
1191
* Button -> PushButton;
1193
and now "push" can be used only in this way. To sum up, Extend can take
1196
replace completely replace the old grammar with this one;
1197
first insert the new grammar at the top of the old one;
1198
last insert the new grammar at the bottom of the old one;
1200
with last being the default (which doesn't need to be said explicitly).
1202
!! In library grammar, some verbs have many synonyms: for instance,
1204
"attack" "break" "smash" "hit" "fight" "wreck" "crack"
1205
"destroy" "murder" "kill" "torture" "punch" "thump"
1207
are all treated as identical. But you might want to distinguish between
1208
murder and lesser crimes. For this, try
1210
Extend only "murder" "kill" replace * animate -> Murder;
1212
The keyword only tells Inform to extract the two verbs "murder" and
1213
"kill". These then become a new verb which is initially an identical
1214
copy of the old one, but then replace tells Inform to throw that away
1215
in favour of an entirely new grammar. Similarly,
1217
Extend only "get" * "with" "it" -> Sing;
1219
makes "get" behave exactly like "take" (as usual) except that it also
1220
recognises "with it", so that "get with it" makes the player sing but
1221
"take with it" doesn't. Other good pairs to separate might be "cross"
1222
and "enter", "drop" and "throw", "give" and "feed", "swim" and "dive",
1223
"kiss" and "hug", "cut" and "prune".
1225
!!!! Bear in mind that once a pair has been split apart like this, any
1226
subsequent extension made to one will not be made to the other.
1228
!!!! There are (a few) times when verb definition commands are not
1229
enough. For example, in the original `Advent' (or `Colossal Cave'),
1230
the player could type the name of a not-too-distant place which had
1231
previously been visited, and be taken there. There are several ways to
1232
code this -- say, with 60 rather similar verb definitions, or with a
1233
single "travel" verb which has 60 synonyms, whose action routine looks
1234
at the parser's verb_word variable to see which one was typed, or even
1235
by restocking the compass object with new directions in each room --
1236
but here's another. The library will call the UnknownVerb routine (if
1237
you provide one) when the parser can't even get past the first word.
1238
This has two options: it can return false, in which case the parser
1239
just goes on to complain as it would have done anyway. Otherwise, it
1240
can return a verb word which is substituted for what the player
1241
actually typed. Here is a foolish example:
1244
if (w=='shazam') { print "Shazam!^"; return 'inventory'; }
1248
which responds to the magic word "shazam" by printing Shazam! and then,
1249
rather disappointingly, taking the player's inventory. But in the
1250
example above, it could be used to look for the word w through the
1251
locations of the game, store the place away in some global variable,
1252
and then return 'go'. The GoSub routine could then be fixed to look at
1258
Why is it usually a bad idea to print text out in an UnknownVerb
1263
!!!! If you allow a flexible collection of verbs (say, names of spells
1264
or places) then you may want a single `dummy' verb to stand for
1265
whichever is being typed. This may make the parser produce strange
1266
questions because it is unable to sensibly print the verb back at the
1267
player, but you can fix this using the PrintVerb entry point.
1272
Implement the Crowther and Woods feature of moving from one room to
1273
another by typing its name, using a dummy verb.
1280
Implement a lamp which, when rubbed, produces a genie who casts a
1281
spell over the player to make him confuse the words "white" and "black".
1288
* `Advent' makes a string of simple Verb definitions; `Alice Through
1289
The Looking-Glass' uses Extend a little.
1291
* `Balances' has a large extra grammar and also uses the UnknownVerb
1292
and PrintVerb entry points.
1295
File: inform, Node: Grammar Tokens, Next: Scope, Prev: Parsing Verbs, Up: Describing and Parsing
1300
The complete list of grammar tokens is as follows:
1301
"<word>" that literal word only
1302
noun any object in scope
1303
held object held by the player
1304
multi one or more objects in scope
1305
multiheld one or more held objects
1306
multiexcept one or more in scope, except the other
1307
multiinside one or more in scope, inside the other
1308
<attribute> any object in scope which has the attribute
1309
creature an object in scope which is animate
1310
noun = <routine> any object in scope passing the given test
1311
scope = <routine> an object in this definition of scope
1312
number a number only
1313
<routine> any text accepted by the given routine
1314
topic any text at all
1315
special any single word or number
1317
These tokens are all described in this section except for `scope =
1318
<Routine>', which is postponed to the next.
1320
`"<word>"' This matches only the literal word given, normally a
1321
preposition such as "into". Whereas most tokens produce a "parameter"
1322
(an object or group of objects, or a number), this token doesn't.
1323
There can therefore be as many or as few of them on a grammar line as
1326
It often happens that several prepositions really mean the same
1327
thing for a given verb: "in", "into" and "inside" are often equally
1328
sensible. As a convenient shorthand you can write a series of
1329
prepositions with slash marks / in between, to mean "one of these
1330
words". For example:
1332
* noun "in"/"into"/"inside" noun -> Insert|
1334
prepositions (Note that / can only be used with prepositions.)
1336
!! Prepositions like this are unfortunately sometimes called
1337
`adjectives' inside the parser source code, and in Infocom hackers'
1338
documents: the usage is traditional but has been avoided in this manual.
1340
`noun' The definition of "in scope" will be given in the next section.
1341
Roughly, it means "visible to the player at the moment".
1343
`held' Convenient for two reasons. Firstly, many actions only sensibly
1344
apply to things being held (such as Eat or Wear), and using this token
1345
in the grammar you can make sure that the action is never generated by
1346
the parser unless the object is being held. That saves on always
1347
having to write "You can't eat what you're not holding" code.
1348
Secondly, suppose we have grammar
1353
and the player types "eat the banana" while the banana is, say, in
1354
plain view on a shelf. It would be petty of the game to refuse on the
1355
grounds that the banana is not being held. So the parser will generate
1356
a Take action for the banana and then, if the Take action succeeds, an
1357
Eat action. Notice that the parser does not just pick up the object,
1358
but issues an action in the proper way -- so if the banana had rules
1359
making it too slippery to pick up, it won't be picked up. This is
1360
called "implicit taking".
1362
The `multi-' tokens indicate that a list of one or more objects can go
1363
here. The parser works out all the things the player has asked for,
1364
sorting out plural nouns and words like "except" by itself, and then
1365
generates actions for each one. A single grammar line can only contain
1366
one `multi-' token: so "hit everything with everything" can't be parsed
1367
(straightforwardly, that is: you can parse anything with a little more
1368
effort). The reason not all nouns can be multiple is that too helpful
1369
a parser makes too easy a game. You probably don't want to allow
1370
"unlock the mystery door with all the keys" -- you want the player to
1371
suffer having to try them one at a time, or else to be thinking.
1373
`multiexcept' Provided to make commands like "put everything in the
1374
rucksack" parsable: the "everything" is matched by all of the player's
1375
possessions except the rucksack. This stops the parser from generating
1376
an action to put the rucksack inside itself.
1378
`multiinside' Similarly, this matches anything inside the other
1379
parameter on the line, and is good for parsing commands like "remove
1380
everything from the cupboard".
1382
`<attribute>' This allows you to sort out objects according to
1383
attributes that they have:
1385
Verb "use" "employ" "utilise"
1389
* enterable -> Enter;
1391
though the library grammar does not contain such an appallingly
1392
convenient verb! Since you can define your own attributes, it's easy
1393
to make a token matching only your own class of object.
1395
`creature' Same as `animate' (a hangover from older editions of
1398
`noun = <Routine>' The last and most powerful of the "a nearby object
1399
satisfying some condition" tokens. When determining whether an object
1400
passes this test, the parser sets the variable noun to the object in
1401
question and calls the routine. If it returns true, the parser accepts
1402
the object, and otherwise it rejects it. For example, the following
1403
should only apply to animals kept in a cage:
1406
if (noun in wicker_cage) rtrue; rfalse;
1408
Verb "free" "release"
1409
* noun=CagedCreature -> FreeAnimal;
1411
So that only nouns which pass the CagedCreature test are allowed. The
1412
CagedCreature routine can appear anywhere in the code, though it's
1413
tidier to keep it nearby.
1415
`scope = <Routine>' An even more powerful token, which means "an object
1416
in scope" where scope is redefined specially. See the next section.
1418
`number' Matches any decimal number from 0 upwards (though it
1419
rounds off large numbers to 10000), and also matches the numbers "one"
1420
to "twenty" written in English. For example:
1423
* number -> TypeNum;
1425
causes actions like Typenum 504 when the player types "type 504". Note
1426
that noun is set to 504, not to an object.
1431
(A beautiful feature stolen from David M. Baggett's game `The Legend
1432
Lives', which uses it to great effect.) Some games produce footnotes
1433
every now and then. Arrange matters so that these are numbered [1],
1434
[2] and so on in order of appearance, to be read by the player when
1435
"footnote 1" is typed.
1439
!! The entry point ParseNumber allows you to provide your own
1440
number-parsing routine, which opens up many sneaky possibilities --
1441
Roman numerals, coordinates like "J4", very long telephone numbers and
1442
so on. This takes the form
1444
[ ParseNumber buffer length;
1445
...returning 0 if no match is made, or the number otherwise...
1448
and examines the supposed `number' held at the byte address buffer, a
1449
row of characters of the given length. If you provide a ParseNumber
1450
routine but return 0 from it, then the parser falls back on its usual
1451
number-parsing mechanism to see if that does any better.
1453
!!!! Note that ParseNumber can't return 0 to mean the number zero.
1454
Probably "zero" won't be needed too often, but if it is you can always
1455
return some value like 1000 and code the verb in question to understand
1456
this as 0. (Sorry: this was a poor design decision made too long ago
1459
`<Routine>' The most flexible token is simply the name of a "general
1460
parsing routine". This looks at the word stream using NextWord and wn
1461
(*note Parsing Nouns::.) and should return:
1463
-1 if the text isn't understood,
1464
0 if it's understood but no parameter results,
1465
1 if a number results, or
1466
n if the object n results.
1468
In the case of a number, the actual value should be put into the
1469
variable parsed_number. On an unsuccessful match (returning -1) it
1470
doesn't matter what the final value of wn is. On a successful match it
1471
should be left pointing to the next thing `after' what the routine
1472
understood. Since NextWord moves wn on by one each time it is called,
1473
this happens automatically unless the routine has read too far. For
1477
w=NextWord(); if (w=='on' or 'at' or 'in') return 0;
1481
makes a token which accepts any of the words "on", "at" or "in" as
1482
prepositions (not translating into objects or numbers). Similarly,
1484
[ Anything w; while (w~=-1) w=NextWordStopped(); return 0; ];
1486
accepts the entire rest of the line (ignoring it). NextWordStopped is
1487
a form of NextWord which returns -1 once the original word stream has
1490
`topic' This token matches as much text as possible. It should either
1491
be at the end of its grammar line, or be followed by a preposition.
1492
(The only way it can fail to match is if it finds no text at all.) The
1493
library's grammar uses this token for topics of conversation and topics
1494
looked up in books (see *Note Reading Matter:: and *note Living
1495
Creatures::.), hence the name. The parser ignores the text for now
1496
(your own code will have to think about it later), and simply sets the
1497
variables consult_from to the number of the first word of the matched
1498
text and consult_words to the number of words.
1500
`special' Obsolete and best avoided.
1505
Write a token to detect low numbers in French, "un" to "cinq".
1512
Write a token to detect floating-point numbers like "21", "5.4623",
1513
"two point oh eight" or "0.01", rounding off to two decimal places.
1520
Write a token to match a phone number, of any length from 1 to 30
1521
digits, possibly broken up with spaces or hyphens (such as "01245 666
1522
737" or "123-4567").
1529
(Adapted from code in Andrew Clover's `timewait.h' library
1530
extension.) Write a token to match any description of a time of day,
1531
such as "quarter past five", "12:13 pm", "14:03", "six fifteen" or
1539
Code a spaceship control panel with five sliding controls, each set
1540
to a numerical value, so that the game looks like:
1544
There is a control panel here, with five slides, each of which can be
1545
set to a numerical value.
1546
>push slide one to 5
1547
You set slide one to the value 5.
1548
>examine the first slide
1549
Slide one currently stands at 5.
1551
You set slide four to the value 6.
1555
!!!! General parsing routines sometimes need to get at the raw text
1556
originally typed by the player. Usually WordAddress and WordLength
1557
(*note Parsing Nouns::.) are adequate. If not, it's helpful to know
1558
that the parser keeps a string array called buffer holding:
1560
buffer->0 = <maximum number of characters which can fit in buffer>
1561
buffer->1 = <the number n of characters typed>
1562
buffer->2...buffer->(n+1) = <the text typed>
1564
and, in parallel with this, another one called parse holding:
1566
parse->0 = <maximum number of words which can fit in buffer>
1567
parse->1 = <the number m of words typed>
1568
parse->2... = <a four-byte block for each word, as follows>
1569
block-->0 = <the dictionary entry if word is known, 0 otherwise>
1570
block->2 = <number of letters in the word>
1571
block->3 = <index to first character in the buffer>
1573
(However, for version 3 games the format is slightly different: in
1574
buffer the text begins at byte 1, not at byte 2, and its end is
1575
indicated with a zero terminator byte.) Note that the raw text is
1576
reduced to lower case automatically, even if within quotation marks.
1577
Using these buffers directly is perfectly safe but not recommended
1578
unless there's no other way, as it tends to make code rather illegible.
1583
Try to implement the parser's routines NextWord, WordAddress and
1591
(Difficult.) Write a general parsing routine accepting any amount
1592
of text (including spaces, full stops and commas) between double-quotes
1600
How would you code a general parsing routine which never matches
1608
Why would you code a general parsing routine which never matches
1616
An apparent restriction of the parser is that it only allows two
1617
parameters (noun and second). Write a general parsing routine to
1618
accept a third. (This final exercise with general parsing routines is
1619
easier than it looks: see the specification of the NounDomain library
1620
routine in *Note Objects and Routines::.)