![]() |
How a sentence is understood |
A command goes through six hands between the keyboard and the thing being done: the line reader (READ_LINE), the tokeniser (TOKENISE), the parser's state machine (PARSE_COMMAND), the pattern matcher (MATCH_PATTERN), the object matcher (MATCH_AND_TRY) and the one routine that does anything for anyone (DO_ACTION). The overview says what each is for; this page follows one real line through all of them, with what each left in its buffers.
Typed at the first prompt of a game, in Bag End, where Thorin and Gandalf are and the player holds the curious map (Gandalf's first step gives it):
SAY TO THORIN "QUICKLY OPEN THE CHEST" THEN READ THE CURIOUS MAP AND DROP IT
It has an order in quotes with an adverb in it, THEN, two verbs that are synonyms (SAY, READ), an adjective, AND in front of a verb, and IT. The game was run in SkoolKit's simulator when this page was built, the line put into the input buffer as scripts/hobbit_drive.py does, and every table below was read from the machine by a probe on the address named, just before the instruction there ran. What the game printed, from PRINT_CHAR past its gate (the player's commands, then the rest of the world's turns, Thorin's among them):
you talk to thorin. you examine the curious map. there seem to be some symbols on it but you cannot read them. you drop the curious map.
gandalf opens the round green door. thorin opens the wooden chest. gandalf goes east. thorin says " hurry up ".
READ_LINE takes keys into INPUT_LINE as plain ASCII, echoing them, and ends the line with a carriage return ($0D). Nothing is done to the words yet. The cursor is only registers -- HL walking the line, B counting the room left, 128 to start -- which is how a command can be put in from outside (see the notes' driving.md).
The main loop calls TOKENISE once per word, from $6D31, and keeps each two-byte token in TOKENS. A full stop, a comma or a quote is a token by itself (PUNCTUATION_TOKEN). Anything else is copied as letter codes -- the low five bits of each character, so A is 1 -- into TYPED_LETTERS ($707A), up to the first character below $40, and looked up by MATCH_WORD: the first letter picks a bucket from WORD_INDEX, and each entry in it is unpacked and compared by LETTERS_AGREE over the shorter of the two lengths, until one agrees. The table is each call, with the candidates it unpacked (read at $6F72, where each one starts) and the token it returned (in B and C at $6D34):
| Typed | Letter codes | Candidates tried | Entry taken | Class | Token |
|---|---|---|---|---|---|
| SAY | 19 1 25 | 4: S, SAND, SAVE, SAY | SAY ($6584) → TALK | $3 verb | 36 90 |
| TO | 20 15 | 15: TAKE, TALK ... (11 more) ... TIE, TO | TO ($66D1) | $7 preposition | 76 D1 |
| THORIN | 20 8 15 18 9 14 | 10: TAKE, TALK ... (6 more) ... THIN, THORIN | THORIN ($66B4) | $5 noun | 56 B4 |
| " | - | - | - | $9 quantifier, pronoun or game command | 90 00 |
| QUICKLY | 17 21 9 3 11 12 25 | 1: QUICKLY | QUICKLY ($650C) | $0 adverb | 05 0C |
| OPEN | 15 16 5 14 | 8: OF, OFF ... (4 more) ... ONTO, OPEN | OPEN ($64B4) | $3 verb | 34 B4 |
| THE | 20 8 5 | 5: TAKE, TALK, TANGLED, THAT, THE | THE ($669F) | $8 article or the like | 86 9F |
| CHEST | 3 8 5 19 20 | 12: CACHE, CAMP ... (8 more) ... CELLAR, CHEST | CHEST ($6122) | $5 noun | 51 22 |
| " | - | - | - | $9 quantifier, pronoun or game command | 90 00 |
| THEN | 20 8 5 14 | 6: TAKE, TALK ... (2 more) ... THE, THEN | THEN ($66A2) | $B then | B6 A2 |
| READ | 18 5 1 4 | 3: RAVENHILL, RAVINE, READ | READ ($6530) → EXAMINE | $3 verb | 32 3E |
| THE | 20 8 5 | 5: TAKE, TALK, TANGLED, THAT, THE | THE ($669F) | $8 article or the like | 86 9F |
| CURIOUS | 3 21 18 9 15 21 19 | 22: CACHE, CAMP ... (18 more) ... CUPBOARD, CURIOUS | CURIOUS ($6163) | $6 adjective | 61 63 |
| MAP | 13 1 16 | 3: MAGIC, MAN, MAP | MAP ($642C) | $5 noun | 54 2C |
| AND | 1 14 4 | 7: A, ACROSS ... (3 more) ... AN, AND | AND ($605B) | $A and | A0 5B |
| DROP | 4 18 15 16 | 19: D, DALE ... (15 more) ... DRINK, DROP | DROP ($61E8) | $3 verb | 31 E8 |
| IT | 9 20 | 8: I, IN ... (4 more) ... IS, IT | IT ($639E) | $9 quantifier, pronoun or game command | 93 9E |
| (end) | - | - | - | $C end of the line | C0 00 |
Two things happen here that nothing downstream ever sees. A synonym is resolved: SAY's entry ends with a link to TALK, and READ's to EXAMINE, and the token carries the word linked to, so from here on the game only knows TALK and EXAMINE. And the buckets are only grouped by initial letter, not sorted, so a common word can be found late: CURIOUS was the 22nd C-word unpacked.
The same routine, called on single words on a fresh machine, shows its rules for short and long words: a typed word may be shorter than the entry (an abbreviation, taken as soon as the letters agree, so the first in the bucket wins), or longer, but only if the entry has four letters or more and the next candidate does not also agree:
| Typed | Candidates | Last candidate | Token | Why |
|---|---|---|---|---|
| EXAM | 14 | EXAMINE | EXAMINE (token $323E) | shorter than the entry: an abbreviation |
| INV | 6 | INVENTORY | INVENTORY (token $3392) | the same |
| CUR | 22 | CURIOUS | CURIOUS (token $6163) | an abbreviation takes the first entry that agrees, in bucket order |
| SWORDS | 46 | SWORD | SWORD (token $5680) | longer than the entry, which has five letters, and nothing after it agrees as well |
| INT | 5 | INTO | INTO (token $138E) | IN agrees but is too short to be stretched (under four letters); INTO then takes it as an abbreviation |
| MAPS | 10 | the last, MOUNTAINS; then the bucket ended | not a word ($D0) | longer than MAP, which has only three letters |
| EXAMINING | 16 | the last, EYES; then the bucket ended | not a word ($D0) | its seventh letter disagrees with EXAMINE's |
| XYZZY | 0 | no word begins with that letter | not a word ($D0) | no word begins with X |
So the tokens for the whole line, as the parser finds them in TOKENS at $6D8A: the class in the top nibble, the dictionary offset from $6000 below. The main loop has made one change: at the closing quote it put a full-stop token first ($B0 $00), so that what is said ends as a sentence.
| At | Token | Class | Word |
|---|---|---|---|
| $709C | 36 90 | $3 | TALK |
| $709E | 76 D1 | $7 | TO |
| $70A0 | 56 B4 | $5 | THORIN |
| $70A2 | 90 00 | $9 | (a quote) |
| $70A4 | 05 0C | $0 | QUICKLY |
| $70A6 | 34 B4 | $3 | OPEN |
| $70A8 | 86 9F | $8 | THE |
| $70AA | 51 22 | $5 | CHEST |
| $70AC | B0 00 | $B | (a full stop, put in by the main loop) |
| $70AE | 90 00 | $9 | (a quote) |
| $70B0 | B6 A2 | $B | THEN |
| $70B2 | 32 3E | $3 | EXAMINE |
| $70B4 | 86 9F | $8 | THE |
| $70B6 | 61 63 | $6 | CURIOUS |
| $70B8 | 54 2C | $5 | MAP |
| $70BA | A0 5B | $A | AND |
| $70BC | 31 E8 | $3 | DROP |
| $70BE | 93 9E | $9 | IT |
| $70C0 | C0 00 | $C | (the end) |
The class is two bits of the entry's first byte and two of its second. CLASS_DISPATCH ($75C1) turns it into an index into PARSER_CLASSES and jumps there; the handlers are the parser. Read from the game (the word counts from the dictionary, synonyms included):
| Class | Words of | Handler | Words | Some of them |
|---|---|---|---|---|
| $0 | adverb | PARSE_ADVERB | 13 | CAREFULLY, FEEBLY, FORCEFULLY, PLEASE, QUICKLY, QUIET, ... |
| $1 | in or into | PARSE_IN | 2 | IN, INTO |
| $2 | direction | PARSE_DIRECTION | 19 | DOWN, EAST, NORTH, NORTHEAST, NORTHWEST, SOUTH, ... |
| $3 | verb | PARSE_VERB | 59 | ATTACK, BURN, CARRY, CLIMB, CLOSE, CROSS, ... |
| $4 | verb of motion | PARSE_GO | 2 | GO, RUN |
| $5 | noun | PARSE_NOUN | 121 | ARM, ARROW, AXE, BARD, BARREL, BAY, ... |
| $6 | adjective | PARSE_ADJECTIVE | 96 | BACK, BARREN, BEORNS, BEWITCHED, BIG, BLACK, ... |
| $7 | preposition | PARSE_PREPOSITION | 16 | ACROSS, AFTER, AT, FOR, FROM, INSIDE, ... |
| $8 | article or the like | PARSE_ARTICLE | 11 | A, ALREADY, AN, ANOTHER, ARE, CAN, ... |
| $9 | quantifier, pronoun or game command | PARSE_SPECIAL | 14 | ALL, EXCEPT, HELP, IT, LOAD, NOPRINT, ... |
| $A | and | PARSE_AND | 1 | AND |
| $B | then | PARSE_THEN | 1 | THEN |
| $C | end of the line | PARSE_END | - | - |
PARSE_COMMAND parses one command and returns to the main loop, which obeys it and calls it again while there is more on the line. It takes tokens through NEXT_TOKEN; register E says what may come next, each handler setting and clearing its bits. A handler that wants to know what follows reads on itself, so not every token goes through the class dispatch: a preposition looks for another preposition, an adjective for the noun after it. The words go into a 24-byte frame at COMMAND_FRAME (more frames, for a sentence that needs them, lie below it, from FRAMES): the verb, an adverb or a direction, and two noun phrases of two prepositions, the noun and two adjectives, each a two-byte word reference, low byte first. Articles are noted and dropped.
Each command below is one call of PARSE_COMMAND: every token read, by which routine (the caller of NEXT_TOKEN), E as it was then, and where the class dispatch sent it; then the frame as OBEY found it at $6D96.
| Token | Class | Read by | E | Dispatched to |
|---|---|---|---|---|
| TALK | $3 | PARSE_COMMAND (PARSE_NEXT_WORD) | $FF: verb, adverb, article, 1st phrase free, 2nd phrase free | PARSE_VERB |
| TO | $7 | PARSE_COMMAND (PARSE_NEXT_WORD) | $FD: adverb, article, 1st phrase free, 2nd phrase free | PARSE_PREPOSITION |
| THORIN | $5 | PARSE_PREPOSITION | $FD: adverb, article, 1st phrase free, 2nd phrase free | - |
| (quote) | $9 | PARSE_COMMAND (PARSE_NEXT_WORD) | $BD: adverb, article, 2nd phrase free | PARSE_SPECIAL |
| QUICKLY | $0 | PARSE_COMMAND (PARSE_NEXT_WORD) | $FF: verb, adverb, article, 1st phrase free, 2nd phrase free | PARSE_ADVERB |
| OPEN | $3 | PARSE_COMMAND (PARSE_NEXT_WORD) | $FB: verb, article, 1st phrase free, 2nd phrase free | PARSE_VERB |
| THE | $8 | PARSE_COMMAND (PARSE_NEXT_WORD) | $F9: article, 1st phrase free, 2nd phrase free | PARSE_ARTICLE |
| CHEST | $5 | PARSE_COMMAND (PARSE_NEXT_WORD) | $E9: 1st phrase free, 2nd phrase free | PARSE_NOUN |
| (full stop) | $B | PARSE_COMMAND (PARSE_NEXT_WORD) | $B9: article, 2nd phrase free | PARSE_THEN |
| (quote) | $9 | PARSE_COMMAND (PARSE_NEXT_WORD) | $FF: verb, adverb, article, 1st phrase free, 2nd phrase free | PARSE_SPECIAL |
| THEN | $B | PARSE_COMMAND (PARSE_NEXT_WORD) | $BD: adverb, article, 2nd phrase free | PARSE_THEN |
The frame, as OBEY found it:
| Offset | Field | Bytes | Words |
|---|---|---|---|
| 0-1 | verb | 90 06 | TALK |
| 2-3 | adverb or direction | 00 00 | - |
| 4-7 | phrase 1: prepositions | D1 06 00 00 | TO |
| 8-9 | phrase 1: noun | B4 06 | THORIN |
| 10-13 | phrase 1: adjectives | 00 00 00 00 | - |
| 14-17 | phrase 2: prepositions | 00 00 00 00 | - |
| 18-19 | phrase 2: noun | 00 00 | - |
| 20-23 | phrase 2: adjectives | 00 00 00 00 | - |
The quote is a class $9 token with no word, which PARSE_SPECIAL finds in slot 0 of SPECIAL_WORDS: its handler is SPECIAL_QUOTE. At the opening quote it calls ORDER_BEGINS, which keeps the sentence so far aside and parses what follows in a fresh frame with IS_ORDER set -- QUICKLY, OPEN, THE, CHEST, and the full stop the main loop added, which ends the order as THEN would but, inside quotes, carries straight on. At the closing quote SPECIAL_QUOTE files each frame parsed since into a free slot of ORDERS, marked $FF, puts the first sentence back and goes on. The THEN after it ends the command. So the frame OBEY gets holds only TALK TO THORIN; the order is in ORDERS slot 0, as it was at $6D96:
| Byte | Field | Bytes | Words |
|---|---|---|---|
| 0 | whose | FF | not yet given ($FF: waiting) |
| 1-2 | verb | B4 04 | OPEN |
| 3-4 | adverb | 0C 05 | QUICKLY |
| 9-10 | phrase 1: noun | 22 01 | CHEST |
| 11-14 | phrase 1: adjectives | 00 00 00 00 | - |
| Token | Class | Read by | E | Dispatched to |
|---|---|---|---|---|
| EXAMINE | $3 | PARSE_COMMAND (PARSE_NEXT_WORD) | $FF: verb, adverb, article, 1st phrase free, 2nd phrase free | PARSE_VERB |
| THE | $8 | PARSE_COMMAND (PARSE_NEXT_WORD) | $FD: adverb, article, 1st phrase free, 2nd phrase free | PARSE_ARTICLE |
| CURIOUS | $6 | PARSE_COMMAND (PARSE_NEXT_WORD) | $ED: adverb, 1st phrase free, 2nd phrase free | PARSE_ADJECTIVE |
| MAP | $5 | PARSE_ADJECTIVE | $ED: adverb, 1st phrase free, 2nd phrase free | - |
| AND | $A | PARSE_COMMAND (PARSE_NEXT_WORD) | $BD: adverb, article, 2nd phrase free | PARSE_AND |
| DROP | $3 | PARSE_AND | $B5: adverb, article, 2nd phrase free; just after AND | - |
| DROP | $3 | PARSE_COMMAND (PARSE_NEXT_WORD) | $F7: verb, adverb, article, 1st phrase free, 2nd phrase free; just after AND | PARSE_VERB |
The frame, as OBEY found it:
| Offset | Field | Bytes | Words |
|---|---|---|---|
| 0-1 | verb | 3E 02 | EXAMINE |
| 2-3 | adverb or direction | 00 00 | - |
| 4-7 | phrase 1: prepositions | 00 00 00 00 | - |
| 8-9 | phrase 1: noun | 2C 04 | MAP |
| 10-13 | phrase 1: adjectives | 63 01 00 00 | CURIOUS |
| 14-17 | phrase 2: prepositions | 00 00 00 00 | - |
| 18-19 | phrase 2: noun | 00 00 | - |
| 20-23 | phrase 2: adjectives | 00 00 00 00 | - |
AND is where the machine looks ahead. PARSE_AND passes over any more ANDs and saves a checkpoint (AND_TOKENS: the place in TOKENS, E, the frame), then ends this part as THEN would and starts a new noun phrase. The next token is DROP, a verb, and PARSE_VERB finds E's bit 3 clear -- just after AND -- so the AND joined two commands, not two noun phrases: it goes back to the checkpoint and ends the command there. DROP IT is left in TOKENS for the next call, after this command has been done.
| Token | Class | Read by | E | Dispatched to |
|---|---|---|---|---|
| DROP | $3 | PARSE_COMMAND (PARSE_NEXT_WORD) | $FF: verb, adverb, article, 1st phrase free, 2nd phrase free | PARSE_VERB |
| IT | $9 | PARSE_COMMAND (PARSE_NEXT_WORD) | $FD: adverb, article, 1st phrase free, 2nd phrase free | PARSE_SPECIAL |
| (end) | $C | PARSE_COMMAND (PARSE_NEXT_WORD) | $BD: adverb, article, 2nd phrase free | PARSE_END |
The frame, as OBEY found it:
| Offset | Field | Bytes | Words |
|---|---|---|---|
| 0-1 | verb | E8 01 | DROP |
| 2-3 | adverb or direction | 00 00 | - |
| 4-7 | phrase 1: prepositions | 00 00 00 00 | - |
| 8-9 | phrase 1: noun | 2C 04 | MAP |
| 10-13 | phrase 1: adjectives | 63 01 00 00 | CURIOUS |
| 14-17 | phrase 2: prepositions | 00 00 00 00 | - |
| 18-19 | phrase 2: noun | 00 00 | - |
| 20-23 | phrase 2: adjectives | 00 00 00 00 | - |
IT is a special word too. WORD_IT copies the six bytes kept at IT_NAME ($B6E0) -- the name of the last target, set when the command before was matched: CURIOUS MAP -- into the phrase as if they had been typed, and files it. So the frame is exactly what DROP THE CURIOUS MAP would give.
There is no table of verbs. OBEY calls PARSE_ACTION, which calls MATCH_PATTERN: it gathers a probe at $7958 -- the verb, then up to two words picked from the frame's phrases, their prepositions or particles -- and compares it with each 8-byte pattern in ACTION_PATTERNS by NAME_MATCHES, the same comparison the objects' names are matched with, so the order of the two picked words does not matter. The action code is the pattern's place in the list. For the three commands (read at $79C4 and $79E9):
| Command | Probe, pattern and flags |
|---|---|
| 1 | probe [TALK, TO, -]; pattern 53 at $ACF3, TALK TO; flags $28 $44 |
| 2 | probe [EXAMINE, -, -]; pattern 28 at $AC2B, EXAMINE; flags $08 $40 |
| 3 | probe [DROP, -, -]; pattern 13 at $ABB3, DROP; flags $08 $08 |
Each pattern's four word references carry four flag bits each, which PATTERN_FLAGS gathers into two bytes, FLAGS_FIRST_WORDS ($B71D) and FLAGS_LAST_WORDS ($B71E). What they mean is read from the code that tests them: in the first, bit 3 the pattern has a target and bit 2 an instrument (PARSE_ACTION and WOULD_WORK), bit 4 it is not narrated (NARRATE_ACTION), bit 5 the target's phrase is the one with the particle (ASSIGN_PHRASES), bit 7 the target is a place and bit 0 PATTERN_OPTION (PATTERN_OPTIONS); in the second, bits 2-3 and 0-1 are the kinds of object the target and the instrument may be (the mode FIND_NAMED_OBJECT searches in: things, characters, or either) and bit 6 the action needs light. Every pattern in the game, with those decoded (the code links to the Actions page, which has each one's handlers and the objects that carry their own):
| Code | Words | Last word | Flags | Target | Instrument | Target phrase | Options | Ordinary handler |
|---|---|---|---|---|---|---|---|---|
| 1 | NORTH | GO | $00 $00 | - | - | - | - | MOVE |
| 2 | SOUTH | GO | $00 $00 | - | - | - | - | MOVE |
| 3 | EAST | GO | $00 $00 | - | - | - | - | MOVE |
| 4 | WEST | GO | $00 $00 | - | - | - | - | MOVE |
| 5 | NORTHEAST | GO | $00 $00 | - | - | - | - | MOVE |
| 6 | NORTHWEST | GO | $00 $00 | - | - | - | - | MOVE |
| 7 | SOUTHEAST | GO | $00 $00 | - | - | - | - | MOVE |
| 8 | SOUTHWEST | GO | $00 $00 | - | - | - | - | MOVE |
| 9 | UP | GO | $00 $00 | - | - | - | - | MOVE |
| 10 | DOWN | GO | $00 $00 | - | - | - | - | MOVE |
| 11 | STRIKE WITH | - | $0E $40 | things | things | - | needs light | objects' own only |
| 12 | CLOSE | - | $08 $40 | things | - | - | needs light | objects' own only |
| 13 | DROP | - | $08 $08 | either | - | - | - | DO_DROP |
| 14 | DROP IN | - | $0C $40 | things | things | - | needs light | objects' own only |
| 15 | ATTACK WITH | - | $0E $44 | characters | things | - | needs light | DO_ATTACK |
| 16 | OPEN | - | $08 $40 | things | - | - | needs light | objects' own only |
| 17 | PUT IN | - | $0C $40 | things | things | - | needs light | objects' own only |
| 18 | PUT ON | - | $0C $40 | things | things | - | needs light | objects' own only |
| 19 | TAKE | - | $08 $40 | things | - | - | needs light | DO_TAKE |
| 20 | TAKE OUT OF | - | $0C $40 | things | things | - | needs light | objects' own only |
| 21 | TAKE FROM | - | $0C $40 | things | things | - | needs light | objects' own only |
| 22 | TAKE OFF | - | $29 $40 | things | - | with the particle | needs light, PATTERN_OPTION | objects' own only |
| 23 | LOOK | - | $10 $40 | - | - | - | not narrated, needs light | DO_LOOK |
| 24 | LOOK THROUGH | - | $28 $00 | things | - | with the particle | - | objects' own only |
| 25 | LOOK ACROSS | - | $28 $00 | things | - | with the particle | - | objects' own only |
| 26 | INVENTORY | - | $10 $40 | - | - | - | not narrated, needs light | DO_INVENTORY |
| 27 | EAT | - | $08 $00 | things | - | - | - | objects' own only |
| 28 | EXAMINE | - | $08 $40 | things | - | - | needs light | DO_EXAMINE |
| 29 | GIVE TO | - | $0C $61 | things | characters | - | needs light | DO_GIVE |
| 30 | GO THROUGH | - | $28 $00 | things | - | with the particle | - | objects' own only |
| 31 | ENTER | - | $88 $00 | things | - | - | the target is a place | DO_ENTER |
| 32 | GO INTO | - | $A8 $00 | things | - | with the particle | the target is a place | DO_ENTER |
| 33 | DRINK | - | $08 $00 | things | - | - | - | objects' own only |
| 34 | EMPTY | - | $08 $00 | things | - | - | - | objects' own only |
| 35 | FILL WITH | - | $0C $40 | things | things | - | needs light | objects' own only |
| 36 | RUN | - | $00 $00 | - | - | - | - | DO_RUN |
| 37 | LOCK WITH | - | $0C $40 | things | things | - | needs light | objects' own only |
| 38 | UNLOCK WITH | - | $0C $40 | things | things | - | needs light | objects' own only |
| 39 | FOLLOW | - | $09 $04 | characters | - | - | PATTERN_OPTION | DO_FOLLOW |
| 40 | WEAR | - | $08 $00 | things | - | - | - | objects' own only |
| 41 | THROW | - | $08 $00 | things | - | - | - | objects' own only |
| 42 | THROW AT | - | $0C $02 | things | either | - | - | DO_THROW_AT |
| 43 | THROW ACROSS | - | $0C $40 | things | things | - | needs light | objects' own only |
| 44 | THROW THROUGH | - | $0C $40 | things | things | - | needs light | objects' own only |
| 45 | BURN | - | $08 $04 | characters | - | - | - | DO_BURN |
| 46 | TIE TO | - | $0C $40 | things | things | - | needs light | DO_TIE |
| 47 | CUT | - | $08 $00 | things | - | - | - | objects' own only |
| 48 | CAPTURE | - | $08 $04 | characters | - | - | - | DO_CAPTURE |
| 49 | PULL | - | $08 $00 | things | - | - | - | objects' own only |
| 50 | SWIM | - | $08 $40 | things | - | - | needs light | objects' own only |
| 51 | UNTIE | - | $08 $48 | either | - | - | needs light | DO_UNTIE |
| 52 | CLIMB | - | $08 $40 | things | - | - | needs light | objects' own only |
| 53 | TALK TO | - | $28 $44 | characters | - | with the particle | needs light | DO_TALK |
| 54 | CLIMB INTO | - | $28 $40 | things | - | with the particle | needs light | objects' own only |
| 55 | CLIMB OUT OF | - | $28 $80 | things | - | with the particle | - | DO_CLIMB_OUT |
| 56 | JUMP ONTO | - | $29 $00 | things | - | with the particle | PATTERN_OPTION | objects' own only |
| 57 | DIG | - | $08 $40 | things | - | - | needs light | objects' own only |
| 58 | SHOOT | - | $08 $44 | characters | - | - | needs light | DO_SHOOT |
| 59 | CARRY | - | $08 $48 | either | - | - | needs light | DO_TAKE |
The ten directions are the patterns with GO as the last word, so NORTH and GO NORTH are one action. Two flags are not accounted for by the table: bit 5 of the second byte, set for GIVE TO alone, which ASSIGN_PHRASES reads when no particle was typed; and bit 7 of the second byte, set for CLIMB OUT OF alone, which NARRATE_ACTION reads to put both particle words before the object.
A name is not turned into an object up front. ASSIGN_PHRASES decides which phrase is the target and which the instrument -- by where the preposition the pattern wants turns up, not by order -- and copies their nouns and adjectives to TARGET_NAME and INSTRUMENT_NAME, and the target's to IT_NAME ($B6E0) for IT. Then MATCH_AND_TRY goes through the objects whose name fits, in reach of the actor (FIND_NAMED_OBJECT, IN_REACH), and for each one runs the action through DO_ACTION with DOING_IT ($B6FA) clear: a test. Every handler makes its checks and then calls FOR_REAL, which in a test sets SUCCEEDED ($B6FB) and returns from the handler, so nothing changes and nothing is printed. The first object that would work is kept. OBEY then tests it once more, narrates it (NARRATE_ACTION), sets DOING_IT and runs DO_ACTION for real. For the three commands (fits read at $9E0F, tests at $7AED and $7AF0, the handler at $958C):
| Stage | What the machine held |
|---|---|
| target's name (TARGET_NAME) | THORIN |
| objects whose name fits | thorin ($3F) |
| of those, in the actor's reach | thorin |
| tested by MATCH_AND_TRY, DOING_IT = 0 | thorin: SUCCEEDED = 1 |
| tested by OBEY, DOING_IT = 0 | thorin: SUCCEEDED = 1 |
| for real: the handler DO_ACTION runs | DO_TALK, from ACTION_TABLE, the ordinary handler |
you talk to thorin.
| Stage | What the machine held |
|---|---|
| target's name (TARGET_NAME) | CURIOUS MAP |
| objects whose name fits | curious map ($03) |
| of those, in the actor's reach | curious map |
| tested by MATCH_AND_TRY, DOING_IT = 0 | curious map: SUCCEEDED = 1 |
| tested by OBEY, DOING_IT = 0 | curious map: SUCCEEDED = 1 |
| for real: the handler DO_ACTION runs | ELROND_READS_MAP, from its own record ($C1E2) |
you examine the curious map. there seem to be some symbols on it but you cannot read them.
| Stage | What the machine held |
|---|---|
| target's name (TARGET_NAME) | CURIOUS MAP |
| objects whose name fits | curious map ($03) |
| of those, in the actor's reach | curious map |
| tested by MATCH_AND_TRY, DOING_IT = 0 | curious map: SUCCEEDED = 1 |
| tested by OBEY, DOING_IT = 0 | curious map: SUCCEEDED = 1 |
| for real: the handler DO_ACTION runs | DO_DROP, from ACTION_TABLE, the ordinary handler |
you drop the curious map.
The map's EXAMINE is the map's own: its record carries a handler for action 28, and DO_ACTION asks the object before it looks in ACTION_TABLE (see the overview). Here the player is not Elrond, so it only says the symbols cannot be read.
TALK TO's handler, DO_TALK, decides how many of the sentences in ORDERS the character takes: a random number up to its limit (6 for Thorin), and ASSIGN_ORDERS gives it that many of those waiting and throws the rest away. Here it was called with 3, and 1 was waiting, so slot 0's first byte became Thorin's number, $3F. On his turn in the world's turn that followed, TAKE_ORDER freed the slot and parsed the frame the way the player's are: pattern 16 (OPEN), target CHEST, which fitted wooden chest; tested, it would work, and he did it:
thorin opens the wooden chest.
The adverb was parsed and kept at offset 2 of the frame, and played no part: MATCH_PATTERN's probe is the verb and the phrases' prepositions, not offset 2 (read), so QUICKLY OPEN THE CHEST is OPEN THE CHEST. How the characters' turns work is on How the characters live.