| ||||||||||||||||||||||||||||||||||||||||||||||||
Contents Back Forward |
| |||||||||||||||||||||||||||||||||||||||||||||||
The complete list of grammar tokens is as
follows:
These tokens are all described in this section except for
It often happens that several prepositions really mean the same thing for a given verb: "in", "into" and "inside" are often equally sensible. As a convenient shorthand you can write a series of prepositions with slash marks / in between, to mean "one of these words". For example: * noun "in"/"into"/"inside" noun -> Insert(Note that / can only be used with prepositions.)
| ||||||||||||||||||||||||||||||||||||||||||||||||
Prepositions like this are unfortunately sometimes called 'adjectives' inside the parser source code, and in Infocom hackers' documents: the usage is traditional but has been avoided in this manual. | ||||||||||||||||||||||||||||||||||||||||||||||||
Verb "eat" * held -> Eat;and the player types "eat the banana'' while the banana is, say, in plain view on a shelf. It would be petty of the game to refuse on the grounds that the banana is not being held. So the parser will generate a Take action for the banana and then, if the Take action succeeds, an Eat action. Notice that the parser does not just pick up the object, but issues an action in the proper way -- so if the banana had rules making it too slippery to pick up, it won't be picked up. This is called "implicit taking''.
The
Verb "use" "employ" "utilise" * edible -> Eat * clothing -> Wear ...and so on... * enterable -> Enter;though the library grammar does not contain such an appallingly convenient verb! Since you can define your own attributes, it's easy to make a token matching only your own class of object.
[ CagedCreature; if (noun in wicker_cage) rtrue; rfalse; ]; Verb "free" "release" * noun=CagedCreature -> FreeAnimal;So that only nouns which pass the CagedCreature test are allowed. The CagedCreature routine can appear anywhere in the code, though it's tidier to keep it nearby.
Verb "type" * number -> TypeNum;causes actions like Typenum 504 when the player types "type 504''. Note that noun is set to 504, not to an object.
| ||||||||||||||||||||||||||||||||||||||||||||||||
EXERCISE 68: (link to the answer) | ||||||||||||||||||||||||||||||||||||||||||||||||
(A beautiful feature stolen from David M. Baggett's game
'The Legend Lives', which uses it to great effect.) Some games produce
footnotes every now and then. Arrange matters so that these are
numbered [1], [2] and so on in order of appearance, to be read by the
player when "footnote 1'' is typed.
| ||||||||||||||||||||||||||||||||||||||||||||||||
The entry point ParseNumber allows you to provide your own
number-parsing routine, which opens up many sneaky possibilities --
Roman numerals, coordinates like "J4", very long telephone numbers
and so on. This takes the form
[ ParseNumber buffer length; ...returning 0 if no match is made, or the number otherwise... ];and examines the supposed 'number' held at the byte address buffer, a row of characters of the given length. If you provide a ParseNumber routine but return 0 from it, then the parser falls back on its usual number-parsing mechanism to see if that does any better. | ||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||
Note that ParseNumber can't return 0 to mean the number zero. Probably "zero'' won't be needed too often, but if it is you can always return some value like 1000 and code the verb in question to understand this as 0. (Sorry: this was a poor design decision made too long ago to change now.) | ||||||||||||||||||||||||||||||||||||||||||||||||
-1 if the text isn't understood,In the case of a number, the actual value should be put into the variable parsed_number. On an unsuccessful match (returning -1) it doesn't matter what the final value of wn is. On a successful match it should be left pointing to the next thing after what the routine understood. Since NextWord moves wn on by one each time it is called, this happens automatically unless the routine has read too far. For example: [ OnAtorIn w; w=NextWord(); if (w=='on' or 'at' or 'in') return 0; return -1; ];makes a token which accepts any of the words "on", "at" or "in" as prepositions (not translating into objects or numbers). Similarly, [ Anything w; while (w~=-1) w=NextWordStopped(); return 0; ];accepts the entire rest of the line (ignoring it). NextWordStopped is a form of NextWord which returns -1 once the original word stream has run out.
| ||||||||||||||||||||||||||||||||||||||||||||||||
EXERCISE 69: (link to the answer) | ||||||||||||||||||||||||||||||||||||||||||||||||
Write a token to detect low numbers in French, "un''
to "cinq''.
| ||||||||||||||||||||||||||||||||||||||||||||||||
EXERCISE 70: (link to the answer) | ||||||||||||||||||||||||||||||||||||||||||||||||
Write a token to detect floating-point numbers
like "21'', "5.4623'', "two point oh eight'' or "0.01'',
rounding off to two
decimal places.
| ||||||||||||||||||||||||||||||||||||||||||||||||
EXERCISE 71: (link to the answer) | ||||||||||||||||||||||||||||||||||||||||||||||||
Write a token to match a phone number,
of any length from 1 to 30 digits, possibly broken up
with spaces or hyphens (such as "01245 666
737'' or "123-4567'').
| ||||||||||||||||||||||||||||||||||||||||||||||||
EXERCISE 72: (link to the answer) | ||||||||||||||||||||||||||||||||||||||||||||||||
(Adapted from code in Andrew Clover's
'timewait.h' library extension.)
Write a token to match any description of a time of day,
such as "quarter past five'', "12:13 pm'', "14:03'',
"six fifteen'' or "seven o'clock''.
| ||||||||||||||||||||||||||||||||||||||||||||||||
EXERCISE 73: (link to the answer) | ||||||||||||||||||||||||||||||||||||||||||||||||
Code a spaceship control panel with five
sliding controls, each set to a numerical value, so that
the game looks like:
>look Machine Room There is a control panel here, with five slides, each of which can be set to a numerical value. >push slide one to 5 You set slide one to the value 5. >examine the first slide Slide one currently stands at 5. >set four to six You set slide four to the value 6.
| ||||||||||||||||||||||||||||||||||||||||||||||||
General parsing routines sometimes need to get at the raw
text originally typed by the player. Usually WordAddress and
WordLength (see Section 24) are adequate. If not, it's helpful to know
that the parser keeps a string array called buffer holding:
buffer->0 = <maximum number of characters which can fit in buffer>and, in parallel with this, another one called parse holding: parse->0 = <maximum number of words which can fit in buffer>(However, for version 3 games the format is slightly different: in buffer the text begins at byte 1, not at byte 2, and its end is indicated with a zero terminator byte.) Note that the raw text is reduced to lower case automatically, even if within quotation marks. Using these buffers directly is perfectly safe but not recommended unless there's no other way, as it tends to make code rather illegible. | ||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||
EXERCISE 74: (link to the answer) | ||||||||||||||||||||||||||||||||||||||||||||||||
Try to implement the parser's routines NextWord,
WordAddress and WordLength.
| ||||||||||||||||||||||||||||||||||||||||||||||||
EXERCISE 75: (link to the answer) | ||||||||||||||||||||||||||||||||||||||||||||||||
(Difficult.) Write a general parsing routine accepting
any amount of text (including spaces, full stops and commas)
between double-quotes as a single token.
| ||||||||||||||||||||||||||||||||||||||||||||||||
EXERCISE 76: (link to the answer) | ||||||||||||||||||||||||||||||||||||||||||||||||
How would you code a general parsing routine which
never matches anything?
| ||||||||||||||||||||||||||||||||||||||||||||||||
EXERCISE 77: (link to the answer) | ||||||||||||||||||||||||||||||||||||||||||||||||
Why would you code a general parsing routine which
never matches anything?
| ||||||||||||||||||||||||||||||||||||||||||||||||
EXERCISE 78: (link to the answer) | ||||||||||||||||||||||||||||||||||||||||||||||||
An apparent restriction of the parser is that it only allows two parameters (noun and second). Write a general parsing routine to accept a third. (This final exercise with general parsing routines is easier than it looks: see the specification of the NounDomain library routine in Appendix A9.) |