Prev: 6E82 Up: Map Next: 6F27
6E8E: Turn the next word of the input into a token
The tokeniser. Starting at HL in the input buffer, it skips spaces, finds the next word or punctuation mark, and returns its class in A and a two-byte token in B (high) and C (low). HL is left after the word, ready for the next call. The address of the start of the word is stored at B5CB so that an 'I don't know the word' message can quote it.
Input A BC
End of line (ENTER) $C0 $C000
Full stop $B0 $B000
Comma $A0 $A000
Double quote $90 9000
A dictionary word its class class in the top nibble of B, then the 12-bit offset of the word from 6000
An unknown word $D0 undefined
The search works like this:
1. 6F3E copies the typed letters (keeping only their low five bits, so case does not matter) into the buffer at 7071 and their count into 7081. It then uses the letter index at 6000 to find the first dictionary word beginning with the same letter, and unpacks that word into the buffer at 7082 (count in 7092). If there are no words for that letter, the word is unknown.
2. 6FB1 compares the typed letters with the dictionary word, over the length of the shorter of the two.
3. If they differ, 6F69 unpacks the next word in the dictionary and the comparison is repeated. The search gives up (unknown word) as soon as it reaches a word with a different first letter.
4. If they agree, the lengths decide (6EB7). If the dictionary word is at least as long as what was typed, it is accepted. So any abbreviation matches the first word that starts with those letters: this is why N means NORTH, but also why EX finds EXAMINE and not EXCEPT. If the player typed MORE letters than the dictionary word has, and the dictionary word is 1-3 letters long, it is rejected and the search moves on (so typing EASTWARD does not match E). If the dictionary word is 4 letters or longer, the game looks at the following dictionary word (6F6D, without moving the current position); if that one also matches the typed letters, the search moves on to it, otherwise the current word is accepted. So extra letters after a long enough word are ignored: SWORDS finds SWORD, and TROLLS finds TROLLS rather than TROLL.
5. For the accepted word (6EE2), the end of the word is found. If bit 6 of the last letter is set, the word is a synonym and the next two bytes give the offset of the real word; HL is switched to that word, so for example HIT is returned as ATTACK. The class is then assembled from bits 5 and 6 of the real word's first two bytes (see 6040), and $A000 is added to the word's address to turn it into an offset from 6000 (because 6000 + $A000 = $10000).
Input
HL Position in the input buffer
Output
A Word class
BC Token
HL Position after the word
6E8E PUSH DE Save DE
6E8F LD A,(HL) Skip spaces
6E90 INC HL Increment HL
6E91 CP $20 Is it " "?
6E93 JR Z,$6E8F If yes, go to 6E8F
6E95 DEC HL Decrement HL
6E96 LD ($B5CB),HL Remember where the word starts
6E99 CP $0D End of the line?
6E9B JR Z,$6ED5 If yes, go to 6ED5
6E9D CALL $6F27 Punctuation?
6EA0 JR Z,$6EDA If the routine returned with Z set, go to 6EDA
6EA2 CALL $6F3E Copy the typed word and find the first dictionary word with the same first letter
6EA5 JR NZ,$6EB3 No words start with this letter: unknown word
6EA7 PUSH HL Save HL
6EA8 CALL $6FB1 Compare the typed word with the dictionary word
6EAB JR Z,$6EB7 If the routine returned with Z set, go to 6EB7
6EAD CALL $6F69 Different: try the next dictionary word
6EB0 JR Z,$6EA8 If the routine returned with Z set, go to 6EA8
6EB2 POP HL Restore HL
6EB3 LD A,$D0 Class $D0: unknown word
6EB5 JR $6ED7 Continue at 6ED7
6EB7 LD A,($7081) Letters agree. Is the dictionary word at least as long as the typed word?
6EBA LD B,A B = A
6EBB LD A,($7092) A = the dictionary word length
6EBE CP B Compare with B
6EBF JR NC,$6EE2 If carry clear, go to 6EE2
6EC1 CP $04 No: reject dictionary words of 1-3 letters
6EC3 JR C,$6EAD If A < 4, go to 6EAD
6EC5 PUSH IX Save IX
6EC7 CALL $6F6D Otherwise, does the next dictionary word also fit?
6ECA JR NZ,$6EE0 If the routine returned with Z reset, go to 6EE0
6ECC CALL $6FB1 Call: Compare the typed word with a dictionary word (6FB1)
6ECF JR NZ,$6EE0 If the routine returned with Z reset, go to 6EE0
6ED1 POP IX Restore IX
6ED3 JR $6EAD Continue at 6EAD
6ED5 LD A,$C0 End of line: class $C0
6ED7 LD BC,$0000 BC = 0
6EDA POP DE Put the class into the top of B and return it in A
6EDB LD D,A D = A
6EDC ADD A,B Add A,B
6EDD LD B,A B = A
6EDE LD A,D A = D
6EDF RET Done
6EE0 POP IX Restore IX
6EE2 LD IX,($B607) Accept the dictionary word at (B607): find its last letter
6EE6 PUSH IX Save IX
6EE8 XOR A A = 0
6EE9 INC IX Increment IX
6EEB INC A Increment A
6EEC BIT 7,(IX-$01) Test bit 7 of (IX-$01)
6EF0 JR Z,$6EE9 If the bit is clear, go to 6EE9
6EF2 CP $02 Compare with 2
6EF4 JR Z,$6EE9 If yes, go to 6EE9
6EF6 CP $03 Compare with 3
6EF8 JR NZ,$6F00 If no, go to 6F00
6EFA BIT 7,(IX-$02) Test bit 7 of (IX-$02)
6EFE JR NZ,$6EE9 If the bit is set, go to 6EE9
6F00 BIT 6,(IX-$01) Is it a synonym?
6F04 JR Z,$6F11 If the bit is clear, go to 6F11
6F06 LD L,(IX+$00) Yes: switch to the word it stands for
6F09 LD H,(IX+$01) H = (IX+1)
6F0C LD DE,$6000 DE = Dictionary letter index (6000)
6F0F ADD HL,DE Add HL,DE
6F10 EX (SP),HL Swap HL with the value on top of the stack
6F11 POP HL Restore HL
6F12 LD A,(HL) Build the class from bits 5-6 of the first two bytes
6F13 RLCA Rotate A left
6F14 AND $C0 Keep only the bits of $C0
6F16 LD B,A B = A
6F17 INC HL Increment HL
6F18 LD A,(HL) A = (HL)
6F19 RRCA Rotate A right
6F1A AND $30 Keep only the bits of $30
6F1C ADD A,B Add A,B
6F1D DEC HL Decrement HL
6F1E LD DE,$A000 Turn the address into an offset from 6000
6F21 ADD HL,DE Add HL,DE
6F22 PUSH HL Save HL
6F23 POP BC Restore BC
6F24 POP HL Restore HL
6F25 JR $6EDA Continue at 6EDA
Prev: 6E82 Up: Map Next: 6F27