00001
00002
00003
00004 #include <stdio.h>
00005 #include <string.h>
00006 #include <ctype.h>
00007 #include <stdlib.h>
00008 #include "advent.h"
00009 #include "advdec.h"
00010
00011 #define ALL 109
00012
00013 #define ENTER 3
00014 #define CRAWL 17
00015 #define JUMP 39
00016 #define CLIMB 56
00017 #define XYZZY 62
00018 #define PLUGH 65
00019 #define PLOVER 71
00020 #define PHUCE 82
00021
00022 _PROTOTYPE(static void getwords, (void));
00023 _PROTOTYPE(static void clrlin, (void));
00024 _PROTOTYPE(static void doobj, (int *));
00025 _PROTOTYPE(static boolean doiobj, (void));
00026 _PROTOTYPE(static boolean do_scoop_up, (void));
00027 _PROTOTYPE(static boolean check_next, (void));
00028
00029 static char buffer[INPUTBUFLEN] = {'\0', '\0', '\0', '\0'};
00030 static char *txt[MAXWORDS] = {buffer, buffer, buffer, buffer};
00031 static char *cindex = buffer;
00032 static boolean pflag;
00033 static int vrbkey, words[MAXWORDS] = {0, 0, 0, 0}, word, wdx = 0;
00034 static int takdir[20] = {2, 6, 9, 10, 11, 13, 14, 17, 23, 25,
00035 33, 34, 36, 37, 39, 78, 79, 80, 89, -1};
00036
00037 static int vkey[60] = {
00038 0, 199, 9, 0, 130, 0, 197, 0, 0, 243,
00039 0, 0, 89, 140, 0, 5, 0, 227, 0, 0,
00040 0, 31, 42, 0, 0, 0, 0, 172, 1, 0,
00041 0, 0, 254, 0, 69, 0, 0, 92, 0, 0,
00042 138, 137, 149, 239, 45, 74, 183, 0, 0, 112,
00043 241, 0, 114, 0, 30, 0, 0, 0, 0, 0
00044 };
00045
00046 static int ptab[260] = {
00047 0, 3028, 3065, 3009, -3005, 5071, 5070, 5058, -5020, 19055,
00048 19108, 19038, 19020, 19071, 19070, 19058, 19004, 19048, 19091, 19094,
00049 19112, 19002, 19118, 2062, 2066, 2047, 2067, 2053, 2065, -2010,
00050 -3114, 4034, 4011, 4101, 4035, 4099, 4098, 4017, 4104, 4014,
00051 4015, -4087, 3083, 3085, -3081, 5055, 5108, 5020, 5071, 5070,
00052 5058, 5004, 5048, 5091, 5112, 5099, 5118, 19055, 19108, 19020,
00053 19071, 19070, 19058, 19004, 19048, 19091, 19112, 19099,-19118, 3028,
00054 3065, 3009, 3005, -3018, 19055, 19108, 19038, 19020, 19071, 19070,
00055 19058, 19004, 19004, 19048, 19091, 19094, 19112, 19002,-19118, 3028,
00056 3065, -3018, 19055, 19108, 19038, 19020, 19071, 19070, 19058, 19004,
00057 19048, 19091, 19094, 19112, 19118, 2062, 2066, 2047, 2067, 2053,
00058 2065, -2010, 3102, -3090, 19055, 19108, 19020, 19071, 19070, 19058,
00059 19004, 19048, 19091, 19014, 19015, 19112, 19118, 19120, 19120, -9999,
00060 3090, 3102, 3028, 3057, 3065, 3009, -3005,-29999, 2052, -2068,
00061 2024, 2065, 2091, 2042, 2073, 5071, 5070, 5058, -5020, 30999,
00062 2062, 2066, 2047, 2067, 2053, 2065, 2010, 2073, 19055, 19108,
00063 19038, 19020, 19071, 19070, 19058, 19004, 19048, 19091, 19094, 19112,
00064 19002,-19118, 2014, 2015, 2013, 2999, 5014, 5015, 5013, 5999,
00065 5110, 5113, -5999, 5055, 5108, 5020, 5071, 5070, 5058, 5004,
00066 5048, 5091, 5014, 5015, 5112, 5099, -5118, 3102, -3090, 6066,
00067 6047, 6067, 6053, 6072, 6073, 5055, 5108, 5020, 5071, 5070,
00068 5004, 5004, 5048, 5091, 5112, 5099, 5118, 19055, 19108, 19020,
00069 19071, 19070, 19058, 19004, 19048, 19091,-19118, 4034, 4011, 4101,
00070 4035, 4099, 4098, 4017, 4104, 4027, 4087, 9999,-30999, 2002,
00071 -6002, 3102, -3090, 9999, 4034, 4011, 4101, 4035, 4099, 4087,
00072 4098, 4017, 4104, -4027, -5999, 0, 0, 0, 0, 0,
00073 };
00074
00075 static int adjkey[40] = {
00076 0, 15, 38, 64, 4, 63, 1, 61, 62, 67,
00077 9, 27, 53, 46, 47, 60, 31, 39, 40, 6,
00078 43, 26, 32, 28, 34, 50, 49, 45, 44, 10,
00079 20, 25, 21, 36, 37, 30, 33, 0, 0, 0
00080 };
00081
00082 static int adjtab[70] = {
00083 0, 5, 98, -83, 2, -90, 66, 41, -90, -39,
00084 41, 14, 15, 50, -11, 50, 64, 56, 72, -74,
00085 -19, 119, 59, 73, -118, -119, -70, -41, 95, -118,
00086 -118, -58, -71, -120, 110, -108, -120, -73, -62, -60,
00087 110, 54, -63, -67, -41, -27, -47, 52, -75, -69,
00088 65, 112, -3, 41, 72, 90, 20, 101, 107, -118,
00089 -55, -10, -38, -4, 48, 9, -71, -39, 0, 0
00090 };
00091
00092
00093
00094
00095 int english()
00096 {
00097
00098 char *ch_ptr, *word1, *word2;
00099 int type, val, type2, val2, adj, k, kk;
00100 static int iwest = 0;
00101
00102 if (!(words[++wdx])) {
00103 getwords();
00104 wdx = 0;
00105 }
00106 pflag = FALSE;
00107 word = words[wdx];
00108 if (word < 0) {
00109 printf("I didn't understand the word \"%s\"\n", txt[wdx]);
00110 words[wdx+1] = 0;
00111 return (FALSE);
00112 }
00113 type2 = val2 = -1;
00114 type = CLASS(word);
00115 clrlin();
00116 val = VAL(word);
00117 if (words[wdx + 1] && CLASS(words[wdx + 1]) != CONJUNCTION) {
00118
00119
00120 if (type == ACTION && (val == SAY || val == YELL)) {
00121 word = words[++wdx];
00122 if (!(word == XYZZY || word == PLUGH
00123 || word == PLOVER || word == PHUCE)) {
00124 if (val == SAY)
00125 printf("Okay, \"%s\".\n", txt[wdx]);
00126 else {
00127 for (ch_ptr = txt[wdx]; *ch_ptr; ch_ptr++)
00128 if (islower(*ch_ptr))
00129 *ch_ptr = toupper(*ch_ptr);
00130 printf("Okay, \"%s\"!!!!!\n", txt[wdx]);
00131 }
00132 return (FALSE);
00133 }
00134 } else {
00135 word1 = txt[wdx];
00136 word2 = txt[wdx + 1];
00137
00138
00139
00140 if (word == ENTER) {
00141 if (CLASS(words[wdx + 1]) == NOUN && VAL(words[wdx + 1]) == BOAT)
00142 word = TAKE + 2000;
00143 else if ((strcmp(word2, "stream") == 0)
00144 || (strcmp(word2, "water") == 0)
00145 || (strcmp(word2, "reservoir") == 0)
00146 || (strcmp(word2, "ocean") == 0)
00147 || (strcmp(word2, "sea") == 0)
00148 || (strcmp(word2, "pool") == 0)) {
00149 rspeak(liqloc(g.loc) == WATER ? 70 : 43);
00150 wdx++;
00151 return (FALSE);
00152 }
00153 } else {
00154 type2 = CLASS(words[wdx + 1]);
00155 val2 = VAL(words[wdx + 1]);
00156
00157
00158
00159
00160 if (strcmp(word1, "leave") == 0 && type2 == NOUN) {
00161 if (!hinged(val2) || g.fixed[val2])
00162 word = LEAVE + 2000;
00163
00164
00165
00166 } else if (strcmp(word1, "light") == 0
00167 && VAL(words[wdx + 1]) == LAMP) {
00168 word = ON + 2000;
00169
00170
00171
00172 } else if ((strcmp(word1, "water") == 0 || strcmp(word1, "oil") == 0)
00173 && (strcmp(word2, "plant") == 0 || strcmp(word2, "door") == 0
00174 || strcmp(word2, "sword") == 0 || strcmp(word2, "anvil") == 0)
00175 && at(val2)) {
00176 words[wdx + 1] = word;
00177 txt[wdx + 1] = txt[wdx];
00178 word = POUR + 2000;
00179 }
00180 }
00181 }
00182
00183 }
00184
00185
00186 do {
00187 switch (CLASS(word)) {
00188 case MOTION:
00189 {
00190 boolean do_part2;
00191 int i;
00192
00193 do_part2 = FALSE;
00194 type = CLASS(verbs[vrbx]);
00195 val = VAL(verbs[vrbx]);
00196 if (!vrbx)
00197 do_part2 = TRUE;
00198 else {
00199 if (type > ACTION) {
00200 rspeak(confuz());
00201 return (FALSE);
00202 }
00203 }
00204 if (type == ACTION) {
00205 if (val == GO)
00206 do_part2 = TRUE;
00207 else {
00208 if (val == TAKE) {
00209 for (i = 0; i < 20; i++)
00210 if (takdir[i] == val)
00211 do_part2 = TRUE;
00212 }
00213 if (!do_part2) {
00214 word = vocab(txt[wdx], 1);
00215 if (word)
00216 words[wdx--] = word;
00217 }
00218 }
00219 } else if (type != CRAWL && type != JUMP
00220 && type != CLIMB)
00221 do_part2 = TRUE;
00222 if (do_part2) {
00223 verbs[1] = word;
00224 vrbx = 1;
00225 if (strcmp(txt[wdx], "west") == 0) {
00226 iwest++;
00227 if (iwest == 10)
00228 rspeak(17);
00229 }
00230 }
00231 break;
00232 }
00233 case NOUN:
00234 if (pflag) {
00235 if (!doiobj())
00236 return (FALSE);
00237 } else {
00238 word = VAL(word);
00239 if (word == ALL) {
00240 if (!do_scoop_up())
00241 return (FALSE);
00242 } else {
00243 doobj(&word);
00244 if (word > 0) {
00245 objs[++objx] = word;
00246 otxt[objx] = txt[wdx];
00247 } else {
00248 clrlin();
00249 pflag = FALSE;
00250 wdx++;
00251 while (words[wdx]) {
00252 if (CLASS(words[wdx]) == CONJUNCTION)
00253 break;
00254 wdx++;
00255 }
00256 if (words[wdx] == 0)
00257 return (FALSE);
00258 }
00259 }
00260 }
00261 break;
00262 case ACTION:
00263 if (vrbx == 0)
00264 vrbx++;
00265 else {
00266 if (VAL(verbs[vrbx]) == TAKE) {
00267 val = VAL(word);
00268 if (val == DRINK || val == INVENTORY
00269 || val == SCORE || val == NOTHING
00270 || val == LOOK);
00271 else if (val == GO && (
00272 strcmp(txt[wdx], "walk") == 0
00273 || strcmp(txt[wdx], "run") == 0
00274 || strcmp(txt[wdx], "hike") == 0));
00275 else {
00276 rspeak(confuz());
00277 return (FALSE);
00278 }
00279 } else if (objx || CLASS(words[wdx - 1]) == CONJUNCTION) {
00280 rspeak(confuz());
00281 return (FALSE);
00282 }
00283 }
00284 verbs[vrbx] = word;
00285 vtxt[vrbx] = txt[wdx];
00286 break;
00287 case MISC:
00288 if (vrbx) {
00289 rspeak(confuz());
00290 return (FALSE);
00291 }
00292 verbs[1] = word;
00293 vrbx = 1;
00294 break;
00295 case PREPOSITION:
00296 if (CLASS(verbs[vrbx]) != ACTION || iobx) {
00297 rspeak(confuz());
00298 return (FALSE);
00299 }
00300 vrbkey = vkey[VAL(verbs[vrbx])];
00301 if (!vrbkey) {
00302 rspeak(confuz());
00303 return (FALSE);
00304 }
00305 prep = VAL(word);
00306 pflag = TRUE;
00307 break;
00308 case ADJACTIVE:
00309
00310
00311
00312 adj = VAL(word);
00313 if (!check_next())
00314 return (FALSE);
00315 else if (CLASS(word) == CONJUNCTION) {
00316 printf("%s what?\n", txt[wdx - 1]);
00317 return (FALSE);
00318 } else {
00319 if (CLASS(word) != NOUN)
00320 word = vocab(txt[wdx], NOUN);
00321 if (word == -1 || CLASS(word) != NOUN || VAL(word) == ALL) {
00322 rspeak(confuz());
00323 return (FALSE);
00324 }
00325 words[wdx] = word;
00326 kk = VAL(word);
00327 for (k = adjkey[adj]; adjtab[k] >= 0; k++) {
00328 if (kk == abs(adjtab[k]))
00329 break;
00330 }
00331 if (adjtab[k] < 0) {
00332 rspeak(confuz());
00333 return (FALSE);
00334 }
00335 }
00336 break;
00337 case CONJUNCTION:
00338 if (!check_next())
00339 return (FALSE);
00340 switch (CLASS(word)) {
00341 case MOTION:
00342 case ACTION:
00343 case MISC:
00344 words[wdx--] = 0;
00345 break;
00346 case NOUN:
00347 case ADJACTIVE:
00348 break;
00349 case PREPOSITION:
00350 case CONJUNCTION:
00351 rspeak(confuz());
00352 return (FALSE);
00353 default:
00354 bug(33);
00355 }
00356 break;
00357 default:
00358 bug(33);
00359 }
00360 word = words[++wdx];
00361 if (word < 0) {
00362 if (pct(50))
00363 printf("I don't understand the word %s?\n", txt[wdx]);
00364 else
00365 printf("Mumble ? %s\n", txt[wdx]);
00366
00367 words[wdx+1] = 0;
00368 return (FALSE);
00369 }
00370 type = CLASS(word);
00371 if (type == NOUN) {
00372
00373
00374
00375
00376 if ((pflag ? iobx : objx)
00377 && CLASS(words[wdx - 1]) != CONJUNCTION) {
00378 val = VAL(verbs[vrbx]);
00379 if (!living(objs[objx]) || (val != THROW && val != FEED)) {
00380 rspeak(confuz());
00381 return (FALSE);
00382 }
00383 iobx++;
00384 iobjs[iobx] = objs[objx];
00385 objs[objx] = 0;
00386 objx++;
00387 }
00388 }
00389 } while (word);
00390
00391 if (verbs[1] == 0) {
00392 if (objs[1] == 0) {
00393 rspeak(confuz());
00394 clrlin();
00395 } else if (objs[2])
00396 printf("What do you want to do with them?\n");
00397 else
00398 printf("What do you want to do with %s?\n", otxt[1]);
00399 return (FALSE);
00400 } else if (objx > 1 && iobx > 1) {
00401 rspeak(confuz());
00402 return (FALSE);
00403 }
00404 return (TRUE);
00405
00406 }
00407
00408
00409
00410
00411
00412 static void getwords()
00413 {
00414 static int wdx = 0;
00415 int i, term_loc;
00416 char terminator;
00417
00418 if (*cindex == '\0') {
00419 while (!*ask("\n> ", buffer, sizeof(buffer))) ;
00420 for (cindex = buffer; *cindex; cindex++)
00421 if (isupper(*cindex))
00422 *cindex = tolower(*cindex);
00423 cindex = buffer;
00424 }
00425 wdx = 0;
00426 buffer[sizeof(buffer)-1] = '\0';
00427 for (i = 0; i < MAXWORDS; i++) {
00428 txt[i] = &buffer[sizeof(buffer)-1];
00429 words[i] = 0;
00430 }
00431 do {
00432 while (*cindex == ' ')
00433 cindex++;
00434 txt[wdx] = cindex;
00435 term_loc = strcspn(cindex, " ,.;\n");
00436 cindex += term_loc;
00437 terminator = *cindex;
00438 *cindex++ = '\0';
00439 if ((strcmp(txt[wdx], "a") != 0)
00440 && (strcmp(txt[wdx], "the") != 0)
00441 && (strcmp(txt[wdx], "an") != 0)) {
00442 words[wdx] = vocab(txt[wdx], 0);
00443 wdx++;
00444 }
00445 if (terminator == ',') {
00446 txt[wdx] = "and";
00447 words[wdx] = vocab(txt[wdx], 0);
00448 wdx++;
00449 }
00450 }
00451 while ((terminator != ';') && (terminator != '.')
00452 && (terminator != '\0') && (terminator != '\n'));
00453 if (terminator == '\0')
00454 cindex--;
00455 return;
00456 }
00457
00458
00459
00460
00461
00462 static void clrlin()
00463 {
00464 int i;
00465
00466 for (i = 0; i < MAXWORDS; i++) {
00467 verbs[i] = 0;
00468 vtxt[i] = &buffer[sizeof(buffer)-1];
00469 }
00470
00471 for (i = 0; i < MAXITEMS; i++) {
00472 objs[i] = 0;
00473 otxt[i] = &buffer[sizeof(buffer)-1];
00474 iobjs[i] = 0;
00475 iotxt[i] = &buffer[sizeof(buffer)-1];
00476 }
00477 vrbx = 0;
00478 objx = 0;
00479 iobx = 0;
00480 prep = 0;
00481 }
00482
00483
00484
00485
00486 static void doobj(object)
00487 int *object;
00488 {
00489 int msg;
00490
00491 if (holding(*object))
00492 return;
00493 if (blind()) {
00494 printf("I see no %s here.\n", txt[wdx]);
00495 *object = 0;
00496 return;
00497 }
00498
00499 if (g.fixed[*object] == g.loc || athand(*object))
00500 return;
00501 else if (here(*object)) {
00502 msg = plural(*object) ? 373 : 335;
00503 *object = 0;
00504 rspeak(msg);
00505 }
00506
00507 else if (*object == GRATE) {
00508 if (g.loc == 1 || g.loc == 4 || g.loc == 7) {
00509 verbs[1] = DEPRESSION;
00510 vrbx = 1;
00511 return;
00512 } else if (g.loc > 9 && g.loc < 15) {
00513 verbs[1] = ENTRANCE;
00514 vrbx = 1;
00515 return;
00516 }
00517 }
00518
00519 else if (dcheck() && g.dflag >= 2) {
00520 *object = DWARF;
00521 }
00522
00523 else if (liqloc(g.loc) == *object
00524 || (liq(BOTTLE) == *object && athand(BOTTLE))
00525 || (liq(CASK) == *object && athand(CASK)));
00526 else if (*object == PLANT && at(PLANT2) &&
00527 g.prop[PLANT2] == 0) {
00528 *object = PLANT2;
00529 } else if (*object == ROCKS && at(CARVNG)) {
00530 *object = CARVNG;
00531 }
00532
00533 else if (*object == KNIFE && g.knfloc == g.loc) {
00534 rspeak(116);
00535 g.knfloc = -1;
00536 }
00537
00538 else if (*object == ROD && athand(ROD2)) {
00539 *object = ROD2;
00540 } else if (*object == DOOR && (at(SAFE) || at(TDOOR)
00541 || at(TDOOR2) || at(PDOOR))) {
00542 if (at(TDOOR2))
00543 *object = TDOOR2;
00544 else if (at(PDOOR))
00545 *object = PDOOR;
00546 else if (at(SAFE))
00547 *object = SAFE;
00548 else
00549 *object = TDOOR;
00550 } else if (*object == BOOK && athand(BOOK2)) {
00551 *object = BOOK2;
00552 } else if (!(verbs[vrbx] == FIND || verbs[vrbx] == INVENTORY)) {
00553 *object = 0;
00554 printf("I see no %s here.\n", txt[wdx]);
00555 }
00556 return;
00557 }
00558
00559 static boolean doiobj()
00560 {
00561 char dk[INPUTBUFLEN], dkk[INPUTBUFLEN];
00562 int kk;
00563 boolean ok;
00564
00565
00566 ok = TRUE;
00567 word = VAL(word);
00568 if (word != ALL) {
00569 doobj(&word);
00570 if (word > 0) {
00571 iobjs[++iobx] = word;
00572 iotxt[iobx] = txt[wdx];
00573 } else
00574 ok = FALSE;
00575 }
00576 kk = abs(ptab[vrbkey]) / 1000;
00577 if (kk == prep) {
00578
00579
00580
00581 if (word == 0 || CLASS(word) == CONJUNCTION) {
00582
00583
00584 pflag = FALSE;
00585 strcpy(dk, txt[--wdx]);
00586 strcpy(dkk, vtxt[vrbx]);
00587 ok = FALSE;
00588 if ((strcmp(dk, "on") == 0
00589 || strcmp(dk, "off") == 0)
00590 && (strcmp(dkk, "turn") == 0
00591 || objs[objx] == LAMP))
00592 ok = TRUE;
00593 if (strcmp(dkk, "take") == 0
00594 || strcmp(dkk, "put") == 0)
00595 ok = TRUE;
00596 if (strcmp(dk, "up") == 0
00597 && strcmp(dkk, "pick") == 0)
00598 ok = TRUE;
00599 if (strcmp(dk, "down") == 0
00600 && (strcmp(dkk, "put") == 0 || verbs[vrbx] == THROW) )
00601 ok = TRUE;
00602 } else {
00603
00604
00605 kk = abs(ptab[vrbkey]) % 1000;
00606 if (kk == word && kk == ALL) {
00607 if (!do_scoop_up())
00608 return (FALSE);
00609 } else if (!(kk == word || kk == 999)) {
00610 vrbkey++;
00611 ok = ptab[vrbkey - 1] < 0 ? FALSE : TRUE;
00612 }
00613 }
00614 }
00615 return (ok);
00616 }
00617
00618 static boolean do_scoop_up()
00619 {
00620 int i, val;
00621
00622 val = VAL(verbs[vrbx]);
00623 if (val == DROP || val == PUT || val == LEAVE) {
00624 for (i = 1; i < MAXOBJ; i++) {
00625 if (!athand(i) || g.fixed[i])
00626 continue;
00627 if (i > WATER && i <= WINE + 1)
00628 continue;
00629 if (toting(i)) {
00630 objs[++objx] = i;
00631 otxt[objx] = "BUG???";
00632 if (objx >= 44)
00633 break;
00634 }
00635 }
00636 }
00637 if (val == TAKE || val == PICK || val == GET) {
00638 if (blind()) {
00639 rspeak(357);
00640 return (FALSE);
00641 } else {
00642 for (i = 1; i < MAXOBJ; i++) {
00643 if (!athand(i) || g.fixed[i])
00644 continue;
00645 if (i > WATER && i <= WINE + 1)
00646 continue;
00647 if (!toting(i)) {
00648 objs[++objx] = i;
00649 otxt[objx] = "BUG???";
00650 if (objx >= 44)
00651 break;
00652 }
00653 }
00654 }
00655 }
00656 return (TRUE);
00657 }
00658
00659 static boolean check_next()
00660 {
00661
00662 word = words[wdx + 1];
00663 if (word > 0)
00664 return (TRUE);
00665 else if (word == 0)
00666 rspeak(confuz());
00667 else {
00668 if (pct(50))
00669 printf("I don't understand the word %s?\n", txt[wdx]);
00670 else
00671 printf("Mumble ? %s\n", txt[wdx]);
00672 words[wdx+1] = 0;
00673 }
00674
00675 return (FALSE);
00676 }