1 /* program ENGLISH.C */
22 _PROTOTYPE(static void getwords
, (void));
23 _PROTOTYPE(static void clrlin
, (void));
24 _PROTOTYPE(static void doobj
, (int *));
25 _PROTOTYPE(static boolean doiobj
, (void));
26 _PROTOTYPE(static boolean do_scoop_up
, (void));
27 _PROTOTYPE(static boolean check_next
, (void));
29 static char buffer
[INPUTBUFLEN
] = {'\0', '\0', '\0', '\0'};
30 static char *txt
[MAXWORDS
] = {buffer
, buffer
, buffer
, buffer
};
31 static char *cindex
= buffer
;
33 static int vrbkey
, words
[MAXWORDS
] = {0, 0, 0, 0}, word
, wdx
= 0;
34 static int takdir
[20] = {2, 6, 9, 10, 11, 13, 14, 17, 23, 25,
35 33, 34, 36, 37, 39, 78, 79, 80, 89, -1};
37 static int vkey
[60] = {
38 0, 199, 9, 0, 130, 0, 197, 0, 0, 243,
39 0, 0, 89, 140, 0, 5, 0, 227, 0, 0,
40 0, 31, 42, 0, 0, 0, 0, 172, 1, 0,
41 0, 0, 254, 0, 69, 0, 0, 92, 0, 0,
42 138, 137, 149, 239, 45, 74, 183, 0, 0, 112,
43 241, 0, 114, 0, 30, 0, 0, 0, 0, 0
46 static int ptab
[260] = {
47 0, 3028, 3065, 3009, -3005, 5071, 5070, 5058, -5020, 19055,
48 19108, 19038, 19020, 19071, 19070, 19058, 19004, 19048, 19091, 19094,
49 19112, 19002, 19118, 2062, 2066, 2047, 2067, 2053, 2065, -2010,
50 -3114, 4034, 4011, 4101, 4035, 4099, 4098, 4017, 4104, 4014,
51 4015, -4087, 3083, 3085, -3081, 5055, 5108, 5020, 5071, 5070,
52 5058, 5004, 5048, 5091, 5112, 5099, 5118, 19055, 19108, 19020,
53 19071, 19070, 19058, 19004, 19048, 19091, 19112, 19099,-19118, 3028,
54 3065, 3009, 3005, -3018, 19055, 19108, 19038, 19020, 19071, 19070,
55 19058, 19004, 19004, 19048, 19091, 19094, 19112, 19002,-19118, 3028,
56 3065, -3018, 19055, 19108, 19038, 19020, 19071, 19070, 19058, 19004,
57 19048, 19091, 19094, 19112, 19118, 2062, 2066, 2047, 2067, 2053,
58 2065, -2010, 3102, -3090, 19055, 19108, 19020, 19071, 19070, 19058,
59 19004, 19048, 19091, 19014, 19015, 19112, 19118, 19120, 19120, -9999,
60 3090, 3102, 3028, 3057, 3065, 3009, -3005,-29999, 2052, -2068,
61 2024, 2065, 2091, 2042, 2073, 5071, 5070, 5058, -5020, 30999,
62 2062, 2066, 2047, 2067, 2053, 2065, 2010, 2073, 19055, 19108,
63 19038, 19020, 19071, 19070, 19058, 19004, 19048, 19091, 19094, 19112,
64 19002,-19118, 2014, 2015, 2013, 2999, 5014, 5015, 5013, 5999,
65 5110, 5113, -5999, 5055, 5108, 5020, 5071, 5070, 5058, 5004,
66 5048, 5091, 5014, 5015, 5112, 5099, -5118, 3102, -3090, 6066,
67 6047, 6067, 6053, 6072, 6073, 5055, 5108, 5020, 5071, 5070,
68 5004, 5004, 5048, 5091, 5112, 5099, 5118, 19055, 19108, 19020,
69 19071, 19070, 19058, 19004, 19048, 19091,-19118, 4034, 4011, 4101,
70 4035, 4099, 4098, 4017, 4104, 4027, 4087, 9999,-30999, 2002,
71 -6002, 3102, -3090, 9999, 4034, 4011, 4101, 4035, 4099, 4087,
72 4098, 4017, 4104, -4027, -5999, 0, 0, 0, 0, 0,
75 static int adjkey
[40] = {
76 0, 15, 38, 64, 4, 63, 1, 61, 62, 67,
77 9, 27, 53, 46, 47, 60, 31, 39, 40, 6,
78 43, 26, 32, 28, 34, 50, 49, 45, 44, 10,
79 20, 25, 21, 36, 37, 30, 33, 0, 0, 0
82 static int adjtab
[70] = {
83 0, 5, 98, -83, 2, -90, 66, 41, -90, -39,
84 41, 14, 15, 50, -11, 50, 64, 56, 72, -74,
85 -19, 119, 59, 73, -118, -119, -70, -41, 95, -118,
86 -118, -58, -71, -120, 110, -108, -120, -73, -62, -60,
87 110, 54, -63, -67, -41, -27, -47, 52, -75, -69,
88 65, 112, -3, 41, 72, 90, 20, 101, 107, -118,
89 -55, -10, -38, -4, 48, 9, -71, -39, 0, 0
93 Analyze a two word sentence
98 char *ch_ptr
, *word1
, *word2
;
99 int type
, val
, type2
, val2
, adj
, k
, kk
;
100 static int iwest
= 0;
102 if (!(words
[++wdx
])) {
108 if (word
< 0) { /* check first word */
109 printf("I didn't understand the word \"%s\"\n", txt
[wdx
]);
111 return (FALSE
); /* didn't know it */
117 if (words
[wdx
+ 1] && CLASS(words
[wdx
+ 1]) != CONJUNCTION
) {
119 /* 'SAY' or 'CALL'. If no next word, pass on to higher powers. */
120 if (type
== ACTION
&& (val
== SAY
|| val
== YELL
)) {
122 if (!(word
== XYZZY
|| word
== PLUGH
123 || word
== PLOVER
|| word
== PHUCE
)) {
125 printf("Okay, \"%s\".\n", txt
[wdx
]);
127 for (ch_ptr
= txt
[wdx
]; *ch_ptr
; ch_ptr
++)
128 if (islower(*ch_ptr
))
129 *ch_ptr
= toupper(*ch_ptr
);
130 printf("Okay, \"%s\"!!!!!\n", txt
[wdx
]);
136 word2
= txt
[wdx
+ 1];
138 /* Special stuff for 'ENTER'. Can't go into water. 'ENTER
139 BOAT' means 'TAKE BOAT' */
141 if (CLASS(words
[wdx
+ 1]) == NOUN
&& VAL(words
[wdx
+ 1]) == BOAT
)
143 else if ((strcmp(word2
, "stream") == 0)
144 || (strcmp(word2
, "water") == 0)
145 || (strcmp(word2
, "reservoir") == 0)
146 || (strcmp(word2
, "ocean") == 0)
147 || (strcmp(word2
, "sea") == 0)
148 || (strcmp(word2
, "pool") == 0)) {
149 rspeak(liqloc(g
.loc
) == WATER
? 70 : 43);
154 type2
= CLASS(words
[wdx
+ 1]);
155 val2
= VAL(words
[wdx
+ 1]);
157 /* 'LEAVE' is motion verb, unsless leaving an object.
158 E.G., 'LEAVE BOAT' or 'LEAVE BOTTLE'. BUt make sure
159 to leave ('DROP') only totable objects. */
160 if (strcmp(word1
, "leave") == 0 && type2
== NOUN
) {
161 if (!hinged(val2
) || g
.fixed
[val2
])
164 /* IF 'LIGHT LAMP', Light must be taken as an
165 action verb, not a noun. */
166 } else if (strcmp(word1
, "light") == 0
167 && VAL(words
[wdx
+ 1]) == LAMP
) {
170 /* 'WATER PLANT' becomes 'POUR WATER', If we are at
171 plant. 'OIL DOOR' becomes 'POUR OIL', etc., etc. */
172 } else if ((strcmp(word1
, "water") == 0 || strcmp(word1
, "oil") == 0)
173 && (strcmp(word2
, "plant") == 0 || strcmp(word2
, "door") == 0
174 || strcmp(word2
, "sword") == 0 || strcmp(word2
, "anvil") == 0)
176 words
[wdx
+ 1] = word
;
177 txt
[wdx
+ 1] = txt
[wdx
];
184 /* This is the 'inner' loop. Dispatching of all word in a clause
185 after the first comes through here. */
187 switch (CLASS(word
)) {
194 type
= CLASS(verbs
[vrbx
]);
195 val
= VAL(verbs
[vrbx
]);
204 if (type
== ACTION
) {
209 for (i
= 0; i
< 20; i
++)
210 if (takdir
[i
] == val
)
214 word
= vocab(txt
[wdx
], 1);
219 } else if (type
!= CRAWL
&& type
!= JUMP
225 if (strcmp(txt
[wdx
], "west") == 0) {
246 otxt
[objx
] = txt
[wdx
];
252 if (CLASS(words
[wdx
]) == CONJUNCTION
)
266 if (VAL(verbs
[vrbx
]) == TAKE
) {
268 if (val
== DRINK
|| val
== INVENTORY
269 || val
== SCORE
|| val
== NOTHING
271 else if (val
== GO
&& (
272 strcmp(txt
[wdx
], "walk") == 0
273 || strcmp(txt
[wdx
], "run") == 0
274 || strcmp(txt
[wdx
], "hike") == 0));
279 } else if (objx
|| CLASS(words
[wdx
- 1]) == CONJUNCTION
) {
285 vtxt
[vrbx
] = txt
[wdx
];
296 if (CLASS(verbs
[vrbx
]) != ACTION
|| iobx
) {
300 vrbkey
= vkey
[VAL(verbs
[vrbx
])];
309 /* Adjective handler. Scarf the next word, make sure it is
310 a valid object for this object. Then call getobj to see
311 if it is really there, Then link into object code. */
315 else if (CLASS(word
) == CONJUNCTION
) {
316 printf("%s what?\n", txt
[wdx
- 1]);
319 if (CLASS(word
) != NOUN
)
320 word
= vocab(txt
[wdx
], NOUN
);
321 if (word
== -1 || CLASS(word
) != NOUN
|| VAL(word
) == ALL
) {
327 for (k
= adjkey
[adj
]; adjtab
[k
] >= 0; k
++) {
328 if (kk
== abs(adjtab
[k
]))
340 switch (CLASS(word
)) {
363 printf("I don't understand the word %s?\n", txt
[wdx
]);
365 printf("Mumble ? %s\n", txt
[wdx
]);
372 /* It's not the first: Make sure he included a comma or
373 'and'. Differenctiate between direct & indirect objects.
374 Check for special case of multiple ofjects: 'feed bear
375 honey' or 'throw troll nugget'. */
376 if ((pflag
? iobx
: objx
)
377 && CLASS(words
[wdx
- 1]) != CONJUNCTION
) {
378 val
= VAL(verbs
[vrbx
]);
379 if (!living(objs
[objx
]) || (val
!= THROW
&& val
!= FEED
)) {
384 iobjs
[iobx
] = objs
[objx
];
396 printf("What do you want to do with them?\n");
398 printf("What do you want to do with %s?\n", otxt
[1]);
400 } else if (objx
> 1 && iobx
> 1) {
409 retrieve input line (max INPUTBUFLEN chars), convert to lower case
410 & rescan for first two words (max. WORDSIZE-1 chars).
412 static void getwords()
418 if (*cindex
== '\0') {
419 while (!*ask("\n> ", buffer
, sizeof(buffer
))) ;
420 for (cindex
= buffer
; *cindex
; cindex
++)
421 if (isupper(*cindex
))
422 *cindex
= tolower(*cindex
);
426 buffer
[sizeof(buffer
)-1] = '\0';
427 for (i
= 0; i
< MAXWORDS
; i
++) {
428 txt
[i
] = &buffer
[sizeof(buffer
)-1];
432 while (*cindex
== ' ')
435 term_loc
= strcspn(cindex
, " ,.;\n");
437 terminator
= *cindex
;
439 if ((strcmp(txt
[wdx
], "a") != 0)
440 && (strcmp(txt
[wdx
], "the") != 0)
441 && (strcmp(txt
[wdx
], "an") != 0)) {
442 words
[wdx
] = vocab(txt
[wdx
], 0);
445 if (terminator
== ',') {
447 words
[wdx
] = vocab(txt
[wdx
], 0);
451 while ((terminator
!= ';') && (terminator
!= '.')
452 && (terminator
!= '\0') && (terminator
!= '\n'));
453 if (terminator
== '\0')
458 /* CLRIN, clears out all surrent syntax args in preparation for
466 for (i
= 0; i
< MAXWORDS
; i
++) {
468 vtxt
[i
] = &buffer
[sizeof(buffer
)-1];
471 for (i
= 0; i
< MAXITEMS
; i
++) {
473 otxt
[i
] = &buffer
[sizeof(buffer
)-1];
475 iotxt
[i
] = &buffer
[sizeof(buffer
)-1];
484 Routine to process an object.
486 static void doobj(object
)
491 if (holding(*object
))
494 printf("I see no %s here.\n", txt
[wdx
]);
498 /* Is object here? if so, transitive */
499 if (g
.fixed
[*object
] == g
.loc
|| athand(*object
))
501 else if (here(*object
)) {
502 msg
= plural(*object
) ? 373 : 335;
506 /* Did he give grate as destination? */
507 else if (*object
== GRATE
) {
508 if (g
.loc
== 1 || g
.loc
== 4 || g
.loc
== 7) {
509 verbs
[1] = DEPRESSION
;
512 } else if (g
.loc
> 9 && g
.loc
< 15) {
518 /* Is it a dwarf he is after? */
519 else if (dcheck() && g
.dflag
>= 2) {
522 /* Is he trying to get/use a liquid? */
523 else if (liqloc(g
.loc
) == *object
524 || (liq(BOTTLE
) == *object
&& athand(BOTTLE
))
525 || (liq(CASK
) == *object
&& athand(CASK
)));
526 else if (*object
== PLANT
&& at(PLANT2
) &&
527 g
.prop
[PLANT2
] == 0) {
529 } else if (*object
== ROCKS
&& at(CARVNG
)) {
532 /* Is he trying to grab a knife? */
533 else if (*object
== KNIFE
&& g
.knfloc
== g
.loc
) {
537 /* Is he trying to get at dynamite? */
538 else if (*object
== ROD
&& athand(ROD2
)) {
540 } else if (*object
== DOOR
&& (at(SAFE
) || at(TDOOR
)
541 || at(TDOOR2
) || at(PDOOR
))) {
550 } else if (*object
== BOOK
&& athand(BOOK2
)) {
552 } else if (!(verbs
[vrbx
] == FIND
|| verbs
[vrbx
] == INVENTORY
)) {
554 printf("I see no %s here.\n", txt
[wdx
]);
559 static boolean
doiobj()
561 char dk
[INPUTBUFLEN
], dkk
[INPUTBUFLEN
];
565 /* checks object is valid for this preposition */
571 iobjs
[++iobx
] = word
;
572 iotxt
[iobx
] = txt
[wdx
];
576 kk
= abs(ptab
[vrbkey
]) / 1000;
578 /* preprosition is valid with this verb now check object of
581 if (word
== 0 || CLASS(word
) == CONJUNCTION
) {
582 /* no object following prepresition: check special cases */
585 strcpy(dk
, txt
[--wdx
]);
586 strcpy(dkk
, vtxt
[vrbx
]);
588 if ((strcmp(dk
, "on") == 0
589 || strcmp(dk
, "off") == 0)
590 && (strcmp(dkk
, "turn") == 0
591 || objs
[objx
] == LAMP
))
593 if (strcmp(dkk
, "take") == 0
594 || strcmp(dkk
, "put") == 0)
596 if (strcmp(dk
, "up") == 0
597 && strcmp(dkk
, "pick") == 0)
599 if (strcmp(dk
, "down") == 0
600 && (strcmp(dkk
, "put") == 0 || verbs
[vrbx
] == THROW
) )
603 /* object follows preposition See if it's plausible. */
605 kk
= abs(ptab
[vrbkey
]) % 1000;
606 if (kk
== word
&& kk
== ALL
) {
609 } else if (!(kk
== word
|| kk
== 999)) {
611 ok
= ptab
[vrbkey
- 1] < 0 ? FALSE
: TRUE
;
618 static boolean
do_scoop_up()
622 val
= VAL(verbs
[vrbx
]);
623 if (val
== DROP
|| val
== PUT
|| val
== LEAVE
) {
624 for (i
= 1; i
< MAXOBJ
; i
++) {
625 if (!athand(i
) || g
.fixed
[i
])
627 if (i
> WATER
&& i
<= WINE
+ 1)
631 otxt
[objx
] = "BUG???";
637 if (val
== TAKE
|| val
== PICK
|| val
== GET
) {
642 for (i
= 1; i
< MAXOBJ
; i
++) {
643 if (!athand(i
) || g
.fixed
[i
])
645 if (i
> WATER
&& i
<= WINE
+ 1)
649 otxt
[objx
] = "BUG???";
659 static boolean
check_next()
662 word
= words
[wdx
+ 1];
669 printf("I don't understand the word %s?\n", txt
[wdx
]);
671 printf("Mumble ? %s\n", txt
[wdx
]);