- return;
-}
-#define SAVARR(ARR,N) fSAVARR(ARR,N)
-
-#undef SAVWRD
-#define WORD (*wORD)
-void fSAVWRD(long OP, long *wORD) {
-static long BUF[250], CKSUM = 0, H1, HASH = 0, N = 0, STATE = 0;
-
-/* If OP<0, start writing a file, using word to initialise encryption; save
- * word in the file. If OP>0, start reading a file; read the file to find
- * the value with which to decrypt the rest. In either case, if a file is
- * already open, finish writing/reading it and don't start a new one. If OP=0,
- * read/write a single word. Words are buffered in case that makes for more
- * efficient disk use. We also compute a simple checksum to catch elementary
- * poking within the saved file. When we finish reading/writing the file,
- * we store zero into WORD if there's no checksum error, else nonzero. */
-
- if(OP != 0){long ifvar; ifvar=(STATE); switch (ifvar<0? -1 : ifvar>0? 1 :
- 0) { case -1: goto L30; case 0: goto L10; case 1: goto L30; }}
- if(STATE == 0)return;
- if(N == 250)SAVEIO(1,STATE > 0,BUF);
- N=MOD(N,250)+1;
- H1=MOD(HASH*1093L+221573L,1048576L);
- HASH=MOD(H1*1093L+221573L,1048576L);
- H1=MOD(H1,1234)*765432+MOD(HASH,123);
- N--;
- if(STATE > 0)WORD=BUF[N]+H1;
- BUF[N]=WORD-H1;
- N++;
- CKSUM=MOD(CKSUM*13+WORD,1000000000L);
- return;
-
-L10: STATE=OP;
- SAVEIO(0,STATE > 0,BUF);
- N=1;
- if(STATE > 0) goto L15;
- HASH=MOD(WORD,1048576L);
- BUF[0]=1234L*5678L-HASH;
-L13: CKSUM=BUF[0];
- return;
-
-L15: SAVEIO(1,true,BUF);
- HASH=MOD(1234L*5678L-BUF[0],1048576L);
- goto L13;
-
-L30: if(N == 250)SAVEIO(1,STATE > 0,BUF);
- N=MOD(N,250)+1;
- if(STATE > 0) goto L32;
- N--; BUF[N]=CKSUM; N++;
- SAVEIO(1,false,BUF);
-L32: N--; WORD=BUF[N]-CKSUM; N++;
- SAVEIO(-1,STATE > 0,BUF);
- STATE=0;
- return;
-}
-
-
-
-
-
-/* Data struc. routines (VOCAB, DSTROY, JUGGLE, MOVE, PUT, CARRY, DROP, ATDWRF)
- */
-
-#undef WORD
-#define SAVWRD(OP,WORD) fSAVWRD(OP,&WORD)
-
-long VOCAB(long ID, long INIT) {
-long I, LEXEME;
-
-/* Look up ID in the vocabulary (ATAB) and return its "definition" (KTAB), or
- * -1 if not found. If INIT is positive, this is an initialisation call setting
- * up a keyword variable, and not finding it constitutes a bug. It also means
- * that only KTAB values which taken over 1000 equal INIT may be considered.
- * (Thus "STEPS", which is a motion verb as well as an object, may be located
- * as an object.) And it also means the KTAB value is taken modulo 1000. */
-
- /* 1 */ for (I=1; I<=TABSIZ; I++) {
- if(KTAB[I] == -1) goto L2;
- if(INIT >= 0 && KTAB[I]/1000 != INIT) goto L1;
- if(ATAB[I] == ID) goto L3;
-L1: /*etc*/ ;
- } /* end loop */
- BUG(21);
-
-L2: LEXEME= -1;
- if(INIT < 0)return(LEXEME);
- BUG(5);
-
-L3: LEXEME=KTAB[I];
- if(INIT >= 0)LEXEME=MOD(LEXEME,1000);
- return(LEXEME);
-}
-
-void DSTROY(long object)
-/* Permanently eliminate "object" by moving to a non-existent location. */
-{
- MOVE(object,0);
-}
-
-void JUGGLE(long object)
+ // If execution reaches here, we didn't find the word.
+ return(WORD_NOT_FOUND);
+}
+
+long get_vocab_id(const char* word)
+// Search the vocab categories in order for the supplied word.
+{
+ long ref_num;
+
+ ref_num = get_motion_vocab_id(word);
+ if (ref_num != WORD_NOT_FOUND)
+ return(ref_num + 0); // FIXME: replace with a proper hash
+
+ ref_num = get_object_vocab_id(word);
+ if (ref_num != WORD_NOT_FOUND)
+ return(ref_num + 1000); // FIXME: replace with a proper hash
+
+ ref_num = get_action_vocab_id(word);
+ if (ref_num != WORD_NOT_FOUND)
+ return(ref_num + 2000); // FIXME: replace with a proper hash
+
+ ref_num = get_special_vocab_id(word);
+ if (ref_num != WORD_NOT_FOUND)
+ return(ref_num + 3000); // FIXME: replace with a proper hash
+
+ // Check for the reservoir magic word.
+ if (strcasecmp(word, game.zzword) == 0)
+ return(PART + 2000); // FIXME: replace with a proper hash
+
+ return(WORD_NOT_FOUND);
+}
+
+void juggle(long object)