|
|
1.1 ! root 1: /* Adventure (3/6/79 17:32:41 1.20) ! 2: Current limits: ! 3: 999 lines, linsiz of message text (lines). ! 4: 750 travel options (travel, trvsiz). ! 5: 300 vocabulary words (ktab, atab, tabsiz). ! 6: 150 locations (ltext, stext, key, cond, abb, atloc, locsiz). ! 7: 100 objects (plac, place, fixd, fixed, rlink (twice), ptext, ! 8: prop). ! 9: 35 "action" verbs (actspk, vrbsiz). ! 10: 205 random messages (rtext, rtxsiz). ! 11: 12 different player classifications (ctext, cval, clsmax). ! 12: 20 hints, less 3 (hintlc, hinted, hints, hntsiz). ! 13: 35 magic messages (mtext, magsiz). ! 14: there are also limits which cannot be exceeded due to the ! 15: structure of the database. (e.g., the vocabulary uses ! 16: n/1000 to determine word type, so there can't be more ! 17: than 1000 words.) these upper limits are: ! 18: 1000 non-synonymous vocabulary words ! 19: 300 locations ! 20: 100 objects ! 21: */ ! 22: #include <stdio.h> ! 23: #include <signal.h> ! 24: ! 25: long longabs(x) ! 26: long x; ! 27: { ! 28: return x<0? -x: x; ! 29: } ! 30: ! 31: long getl (file) ! 32: register FILE *file; ! 33: { ! 34: long l; ! 35: l = getw (file); ! 36: l <<= 16; ! 37: l |= getw (file); ! 38: return l; ! 39: } ! 40: ! 41: putl (l, file) ! 42: long l; ! 43: register FILE *file; ! 44: { ! 45: putw ((int) (l >> 16), file); ! 46: putw ((int) l, file); ! 47: } ! 48: ! 49: FILE *caves, *suspfd; ! 50: long tvec, xtime, time(); ! 51: long ftell(); ! 52: struct passwd *pwbuf; ! 53: char suspbeg; /* Start of variables to write during suspension */ ! 54: char tkword[10]; ! 55: char wd2x[5]; ! 56: char wd2[5]; ! 57: char wd1x[5]; ! 58: char wd1[5]; ! 59: char atab[300+1][6]; ! 60: char linebuf[100]; /* For reading cave description, etc */ ! 61: char chr; ! 62: char *cp1, *cp2; ! 63: int rtext[205]; ! 64: long newloc = 0L; ! 65: long lines[1000]; /* Assumed initialized to zero */ ! 66: int blklin = 1; ! 67: int dseen[6]; ! 68: int odloc[6]; ! 69: int dloc[6]; ! 70: int tk[20+1]; ! 71: int hinted[20+1]; ! 72: int hinted[20+1]; /* Assumed initialized to 0 */ ! 73: int hints[12+1][4+1]; /* Assumed initialized to 0 */ ! 74: int cval[12+1]; /* Assumed initialized to 0 */ ! 75: int ctext[12+1]; /* Assumed initialized to 0 */ ! 76: int actspk[35+1]; /* Assumed initialized to 0 */ ! 77: int prop[100+1]; /* Assumed initialized to 0 */ ! 78: int fixd[100+1]; /* Assumed initialized to 0 */ ! 79: int plac[100+1]; /* Assumed initialized to 0 */ ! 80: int cond[150+1]; /* Assumed initialized to 0 */ ! 81: int key[150+1]; /* Assumed initialized to 0 */ ! 82: int stext[150+1]; /* Assumed initialized to 0 */ ! 83: int ltext[150+1]; /* Assumed initialized to 0 */ ! 84: long travel[750+1]; /* Assumed initialized to 0 */ ! 85: int hintlc[21+1]; /* Assumed initialized to zero */ ! 86: int abb[150+1]; ! 87: int holdng; ! 88: int fixed[100+1]; ! 89: int place[100+1]; ! 90: int rlink[200+1]; ! 91: int atloc[150+1]; ! 92: int tabsiz = 300; ! 93: int ktab[300+1]; ! 94: int ptext[100+1]; ! 95: #ifdef INITBUG ! 96: int clssiz = 12; ! 97: int linsiz = 999; ! 98: int vrbsiz = 35; ! 99: #endif INITBUG ! 100: int trvsiz = 750; ! 101: int locsiz = 150; ! 102: int rtxsiz = 205; ! 103: int clsmax = 12; ! 104: int hntsiz = 20; ! 105: int wzdark; ! 106: int lmwarn; ! 107: int closng; ! 108: int panic; ! 109: int closed; ! 110: int gaveup; ! 111: int scorng; ! 112: int yea; ! 113: long ll; ! 114: ! 115: #ifdef unix ! 116: #include <pwd.h> ! 117: #define GETPWUID() pwbuf=getpwuid(getuid());cp2=pwbuf->pw_dir;while(*cp1++ = *cp2++);cp1--; ! 118: #define HOURS "Colossal Cave is always open\n" ! 119: #ifndef CAVE ! 120: #define CAVE "/usr/games/lib/cave" ! 121: #endif CAVE ! 122: #define SUSPREAD "r" ! 123: #define SUSPWRITE "w" ! 124: #endif ! 125: #ifdef gcos ! 126: #define CLOSED "Colossal Cave is closed weekdays between 8 AM and 6 PM.\n" ! 127: #define GETPWUID() if(lmsgrd()<3){printf(CLOSED);return(0);}fprompt("\r\n"); ! 128: #define HOURS CLOSED ! 129: #define CAVE "cc/adve/cave$abracadabra" ! 130: #define SUSPREAD "ri" ! 131: #define SUSPWRITE "wi" ! 132: #endif ! 133: ! 134: #define abbnum ints[0] ! 135: #define iy ints[1] ! 136: #define axe ints[2] ! 137: #define back ints[3] ! 138: #define batter ints[4] ! 139: #define bear ints[5] ! 140: #define bird ints[6] ! 141: #define bonus ints[7] ! 142: #define bottle ints[8] ! 143: #define cage ints[9] ! 144: #define cave ints[10] ! 145: #define ccode ints[11] ! 146: #define ch ints[12] ! 147: #define chain ints[13] ! 148: #define chasm ints[14] ! 149: #define chest ints[15] ! 150: #define chloc ints[16] ! 151: #define chloc2 ints[17] ! 152: #define clam ints[18] ! 153: #define clock1 ints[19] ! 154: #define clock2 ints[20] ! 155: #define clsses ints[21] ! 156: #define coins ints[22] ! 157: #define daltlc ints[23] ! 158: #define detail ints[24] ! 159: #define dflag ints[25] ! 160: #define dkill ints[26] ! 161: #define door ints[27] ! 162: #define dprssn ints[28] ! 163: #define dragon ints[29] ! 164: #define dtotal ints[30] ! 165: #define dwarf ints[31] ! 166: #define eggs ints[32] ! 167: #define emrald ints[33] ! 168: #define entrnc ints[34] ! 169: #define find ints[35] ! 170: #define fissur ints[36] ! 171: #define foo ints[37] ! 172: #define foobar ints[38] ! 173: #define food ints[39] ! 174: #define from ints[40] ! 175: #define grate ints[41] ! 176: #define hint ints[42] ! 177: #define hntmax ints[43] ! 178: #define i ints[44] ! 179: #define inlen ints[45] ! 180: #define invent ints[46] ! 181: #define iwest ints[47] ! 182: #define j ints[48] ! 183: #define k ints[49] ! 184: #define keys ints[50] ! 185: #define kk ints[51] ! 186: #define knfloc ints[52] ! 187: #define knife ints[53] ! 188: #define kq ints[54] ! 189: #define k2 ints[55] ! 190: #define l ints[56] ! 191: #define lamp ints[57] ! 192: #define limit ints[58] ! 193: #define linuse ints[59] ! 194: #define hungup ints[60] ! 195: #define loc ints[61] ! 196: #define lock ints[62] ! 197: #define look ints[63] ! 198: #define m ints[64] ! 199: #define magzin ints[65] ! 200: #define maxdie ints[66] ! 201: #define maxtrs ints[67] ! 202: #define messag ints[68] ! 203: #define mirror ints[69] ! 204: #define mxscor ints[70] ! 205: #define nugget ints[71] ! 206: #define nullx ints[72] ! 207: #define numdie ints[73] ! 208: #define obj ints[74] ! 209: #define oil ints[75] ! 210: #define oldlc2 ints[76] ! 211: #define oldloc ints[77] ! 212: #define oyster ints[78] ! 213: #define pearl ints[79] ! 214: #define pillow ints[80] ! 215: #define plant ints[81] ! 216: #define plant2 ints[82] ! 217: #define posn ints[83] ! 218: #define pyram ints[84] ! 219: #define rod ints[85] ! 220: #define rod2 ints[86] ! 221: #define rug ints[87] ! 222: #define say ints[88] ! 223: #define score ints[89] ! 224: #define sect ints[90] ! 225: #define snake ints[91] ! 226: #define spices ints[92] ! 227: #define spk ints[93] ! 228: #define steps ints[94] ! 229: #define stick ints[95] ! 230: #define tablet ints[96] ! 231: #define tabndx ints[97] ! 232: #define tally ints[98] ! 233: #define tally2 ints[99] ! 234: #define temp ints[100] ! 235: #define throw ints[101] ! 236: #define attack ints[102] ! 237: #define tridnt ints[103] ! 238: #define troll ints[104] ! 239: #define troll2 ints[105] ! 240: #define trvs ints[106] ! 241: #define turns ints[107] ! 242: #define vase ints[108] ! 243: #define vend ints[109] ! 244: #define verb ints[110] ! 245: #define water ints[111] ! 246: #define word ints[112] ! 247: #define wordend ints[113] ! 248: #define wordsize ints[114] ! 249: #define wordstrt ints[115] ! 250: #define logon ints[116] ! 251: #define srel ints[117] ! 252: #define slev ints[118] ! 253: #define tleft ints[119] ! 254: #define tright ints[120] ! 255: int ints[121]; ! 256: ! 257: char suspend; /* End of variables to write during suspension */ ! 258: ! 259: /* ! 260: wzdark says whether the loc he's leaving was dark ! 261: lmwarn says whether he's been warned about lamp going dim ! 262: closng says whether its closing time yet ! 263: panic says whether he's found out he's trapped in the cave ! 264: closed says whether we're all the way closed ! 265: gaveup says whether he exited via "quit" ! 266: scorng indicates to the score routine whether we're doing ! 267: a "score" command ! 268: yea is random yes/no reply ! 269: hungup says whether he hung up the phone ! 270: */ ! 271: ! 272: sethup() ! 273: { ! 274: hungup = 1; ! 275: signal (SIGHUP, SIG_IGN); ! 276: ! 277: #ifndef INITBUG ! 278: signal (SIGINT, SIG_IGN); ! 279: signal (SIGQUIT, SIG_IGN); ! 280: #endif INITBUG ! 281: ! 282: } ! 283: ! 284: main() ! 285: { ! 286: char suspfile[100]; ! 287: static char outbuf[BUFSIZ]; ! 288: struct passwd *getpwuid(); ! 289: ! 290: setbuf(stdout, outbuf); ! 291: setbuf(stderr, NULL); ! 292: printf ("@(#)Adventure 1.20\n" + 4); ! 293: ! 294: cp1 = suspfile; ! 295: GETPWUID(); ! 296: cp2 = "/adv.susp"; ! 297: while (*cp1++ = *cp2++); ! 298: ! 299: #ifndef INITBUG ! 300: if (signal (SIGINT, SIG_IGN) != SIG_IGN) ! 301: signal (SIGINT, sethup); ! 302: if (signal (SIGQUIT, sethup) != SIG_IGN) ! 303: signal (SIGQUIT, sethup); ! 304: #endif INITBUG ! 305: ! 306: if (signal (SIGHUP, SIG_IGN) != SIG_IGN) ! 307: signal (SIGHUP, sethup); ! 308: ! 309: #ifdef LOG ! 310: logon = 1; ! 311: #else ! 312: logon = 0; ! 313: #endif ! 314: ! 315: if ((caves = fopen (CAVE, "r")) == NULL) ! 316: fatal ("Couldn't open cave file\n"); ! 317: ! 318: /* Description of the database format: ! 319: The data file contains several sections. Each begins ! 320: with a line containing a number identifying the section, ! 321: and ends with a line containing "-1". ! 322: Section 1: long form descriptions. Each line contains a ! 323: location number, a tab, and a line of text. The set ! 324: of (necessarily adjacent) lines whose numbers are x ! 325: form the long description of location x. ! 326: Section 2: Short form descriptions. Same format as long ! 327: form. Not all places have short descriptions. ! 328: Section 3: Travel table. Each line contains a location ! 329: number (x), a second location number (y), and a list ! 330: of motion numbers (see section 4). Each motion ! 331: represents a verb which will go to y if currently at ! 332: x. y, in turn, is interpreted as follows: Let ! 333: m=y/1000, n=y mod 1000. ! 334: If n<=300 it is the location to go to. ! 335: If 300<n<=500 n-300 is used in a computed ! 336: goto to a section of special ! 337: code. ! 338: If n>500 message n-500 from section 6 ! 339: is printed, and he stays ! 340: wherever he is. ! 341: Meanwhile, m specifies the conditions on the motion. ! 342: If m=0 it's unconditional. ! 343: If 0<m<100 it is done with m% ! 344: probability. ! 345: If m=100 unconditional, but forbidden ! 346: to dwarves. ! 347: If 100<m<=200 he must be carrying object ! 348: m-100. ! 349: If 200<m<=300 must be carrying or in same ! 350: room as m-200. ! 351: If 300<m<=400 prop(m mod 100) must NOT be ! 352: 0. ! 353: If 400<m<=500 prop(m mod 100) must NOT be ! 354: 1. ! 355: If 500<m<=600 prop(m mod 100) must NOT be ! 356: 2, etc. ! 357: If the condition (if any) is not met, then the next ! 358: DIFFERENT "destination" value is used (unless it ! 359: fails to meet ITS conditions, in which case the ! 360: next is found, etc.). Typically, the next dest will ! 361: be for one of the same verbs, so that its only use is ! 362: as the alternate destination for those verbs. For ! 363: instance: ! 364: 15 110022 29 31 34 35 23 43 ! 365: 15 14 29 ! 366: This says that, from loc 15, any of the verbs 29, 31, ! 367: etc., will take him to 22 if he's carrying object 10, ! 368: and otherwise will go to 14. ! 369: 11 303008 49 ! 370: 11 9 50 ! 371: This says that, from 11, 49 takes him to 8 unless ! 372: prop(3)=0, in which case he goes to 9. Verb 50 takes ! 373: him to 9 regardless of prop(3). ! 374: Section 4: vocabulary. Each line contains a number (n), ! 375: a tab, and a five-letter word. Call m=n/1000. If ! 376: m=0, then the word is a motion verb for use in ! 377: travelling (see section 3). Else, if m=1, the word ! 378: is an object. Else, if m=2, the word is an action ! 379: verb (such as "carry" or "attack"). Else, if m=3, ! 380: the word is a special case verb (such as "dig") and n ! 381: mod 1000 is an index into section 6. Objects from 50 ! 382: to (currently, anyway) 79 are considered treasures ! 383: (for pirate, closeout). ! 384: Section 5: object descriptions. Each line contains a ! 385: number (n), a tab, and a message. If n is from 1 to ! 386: 100, the message is the "inventory" message for ! 387: object n. Otherwise, n should be 000, 100, 200, ! 388: etc., and the message should be the description of ! 389: the preceding object when its prop value is n/100. ! 390: The n/100 is used only to distinguish multiple ! 391: messages from multi-line messages; the prop info ! 392: actually requires all messages for an object to be ! 393: present and consecutive. Properties which produce no ! 394: message should be given the message ">$<". ! 395: Section 6: arbitrary messages. Same format as sections ! 396: 1, 2, and 5, except the numbers bear no relation to ! 397: anything (except for special verbs in section 4). ! 398: Section 7: object locations. Each line contains an ! 399: object number and its initial location (zero (or ! 400: omitted) if none). If the object is immovable, the ! 401: location is followed by a "-1". If it has two ! 402: locations (e.g. the grate) the first location is ! 403: followed with the second, and the object is assumed ! 404: to be immovable. ! 405: Section 8: action defaults. Each line contains an ! 406: "action-verb" number and the index (in section 6) of ! 407: the default message for the verb. ! 408: Section 9: liquid assets, etc. Each line contains a ! 409: number (n) and up to 20 location numbers. Bit n ! 410: (where 0 is the units bit) is set in cond(loc) for ! 411: each loc given. The cond bits currently assigned ! 412: are: ! 413: 0 light ! 414: 1 if bit 2 is on: on for oil, off for ! 415: water ! 416: 2 liquid asset, see bit 1 ! 417: 3 pirate doesn't go here unless ! 418: following player ! 419: Other bits are used to indicate areas of interest to ! 420: "hint" routines: ! 421: 4 trying to get into cave ! 422: 5 trying to catch bird ! 423: 6 trying to deal with snake ! 424: 7 lost in maze ! 425: 8 pondering dark room ! 426: 9 at Witt's end ! 427: cond(loc) is set to 2, overriding all other bits, if ! 428: loc has forced motion. ! 429: Section 10: class messages. Each line contains a number ! 430: (n), a tab, and a message describing a classification ! 431: of player. The scoring section selects the ! 432: appropriate message, where each message is considered ! 433: to apply to players whose scores are higher than the ! 434: previous n but not higher than this n. Note that ! 435: these scores probably change with every modification ! 436: (and particularly expansion) of the program. ! 437: Section 11: hints. Each line contains a hint number ! 438: (corresponding to a cond bit, see section 9), the ! 439: number of turns he must be at the right loc(s) before ! 440: triggering the hint, the points deducted for taking ! 441: the hint, the message number (section 6) of the ! 442: question, and the message number of the hint. These ! 443: values are stashed in the "hints" array. hntmax is ! 444: set to the max hint number (<= hntsiz). Numbers 1-3 ! 445: are unusable since cond bits are otherwise assigned, ! 446: so 2 is used to remember if he's read the clue in the ! 447: repository, and 3 is used to remember whether he ! 448: asked for instructions (gets more turns, but loses ! 449: points). ! 450: Section 12: magic messages. Identical to section 6 ! 451: except put in a separate section for easier ! 452: reference. Magic messages are used by the startup, ! 453: maintenance mode, and related routines. ! 454: Section 0: end of database. ! 455: */ ! 456: ! 457: /* Read the database */ ! 458: ! 459: printf("Initializing... "); ! 460: fflush(stdout); ! 461: ! 462: /* ! 463: Clear out the various text-pointer arrays. All text is ! 464: stored in array lines; each line is preceded by a word ! 465: pointing to the next pointer (i.e. the word following ! 466: the end of the line). The pointer is negative if this is ! 467: first line of a message. The text-pointer arrays contain ! 468: indices of pointer-words in lines. stext(n) is short ! 469: description of location n. ltext(n) is long description. ! 470: ptext(n) points to message for prop(n)=0. Successive ! 471: prop messages are found by chasing pointers. rtext ! 472: contains section 6's stuff. ctext(n) points to a ! 473: player-class message. mtext is for section 12. we also ! 474: clear cond. see description of section 9 for details. ! 475: */ ! 476: for (i=1; i<=300; i++) { ! 477: if (i <= 100) ptext[i] = 0; ! 478: if (i <= rtxsiz) rtext[i] = 0; ! 479: if (i <= clsmax) ctext[i] = 0; ! 480: if (i <= locsiz) { ! 481: stext[i]=0; ! 482: ltext[i]=0; ! 483: cond[i]=0; ! 484: } ! 485: } ! 486: /* key=0; */ ! 487: linuse=1; ! 488: trvs=1; ! 489: clsses=1; ! 490: ! 491: /* Start new data section. sect is the section number. */ ! 492: l1002: ! 493: fscanf (caves, "%d", §); ! 494: oldloc= -1; ! 495: ! 496: #ifdef INITBUG ! 497: fprintf(stderr, "\nSect=%d\n", sect); ! 498: #endif INITBUG ! 499: ! 500: switch (sect) { ! 501: case 0: ! 502: goto l1100; /* (0) */ ! 503: case 1: ! 504: case 2: ! 505: case 5: ! 506: case 6: ! 507: case 10: ! 508: goto l1004; /* 1, 2, 5, 6, 10 */ ! 509: case 3: ! 510: goto l1030; /* (3) */ ! 511: case 4: ! 512: goto l1040; /* (4) */ ! 513: case 7: ! 514: goto l1050; /* (7) */ ! 515: case 8: ! 516: goto l1060; /* (8) */ ! 517: case 9: ! 518: goto l1070; /* (9) */ ! 519: case 11: ! 520: goto l1080; /* (11) */ ! 521: } ! 522: ! 523: bug(9); ! 524: ! 525: /* Sections 1, 2, 5, 6, 10. Read messages and set up pointers. */ ! 526: l1004: ! 527: fscanf (caves, "%d", &loc); ! 528: #ifdef INITBUG ! 529: fprintf(stderr, "Sect=%d; Loc=%d\n", sect, loc); ! 530: #endif INITBUG ! 531: while ((chr = getc (caves)) == ' ' || chr == '\t') ! 532: ; ! 533: ungetc (chr, caves); ! 534: lines[linuse] = ftell (caves); ! 535: fgets (linebuf, sizeof linebuf, caves); ! 536: if (loc == -1) goto l1002; ! 537: if (loc != oldloc) { ! 538: lines[linuse] = -lines[linuse]; ! 539: if (sect == 10) { ! 540: ctext[clsses] = linuse; ! 541: cval[clsses] = loc; ! 542: clsses++; ! 543: } ! 544: else if (sect == 6) { ! 545: if (loc > rtxsiz) bug(6); ! 546: rtext[loc] = linuse; ! 547: } ! 548: else if (sect == 5) { ! 549: if (loc > 0 && loc <= 100) ptext[loc] = linuse; ! 550: } ! 551: else if (sect == 1) { ! 552: ltext[loc] = linuse; ! 553: } ! 554: else ! 555: stext[loc] = linuse; ! 556: } ! 557: linuse++; ! 558: oldloc = loc; ! 559: goto l1004; ! 560: /* ! 561: The stuff for section 3 is encoded here. Each ! 562: "from-location" gets a contiguous section of the "travel" ! 563: array. Each entry in travel is newloc*1000 + keyword ! 564: (from section 4, motion verbs), and is negated if this is ! 565: the last entry for this location. key[n] is the index in ! 566: travel of the first option at location n. ! 567: */ ! 568: l1030: ! 569: fscanf (caves, "%d\t%ld", &loc, &newloc); ! 570: #ifdef INITBUG ! 571: fprintf(stderr, "Sect=%d; Loc=%d; newloc=%d\n", sect, loc, newloc); ! 572: #endif INITBUG ! 573: i = 0; ! 574: while ((chr = getc (caves)) != '\n') { ! 575: ungetc (chr, caves); ! 576: fscanf (caves, "%d", &tk[i++]); ! 577: } ! 578: if (loc == -1) goto l1002; ! 579: if (key[loc]) ! 580: travel[trvs-1] = -travel[trvs-1]; ! 581: else ! 582: key[loc] = trvs; ! 583: for (l=0; l<i; l++) { ! 584: travel[trvs] = newloc * 1000L + tk[l]; ! 585: trvs++; ! 586: if (trvs >= trvsiz) bug(3); ! 587: } ! 588: travel[trvs-1]= -travel[trvs-1]; ! 589: goto l1030; ! 590: /* ! 591: Here we read in the vocabulary. ktab[n] is the word ! 592: number, atab[n] is the corresponding word. The -1 at the ! 593: end of section 4 is left in ktab as an end-marker. ! 594: */ ! 595: l1040: ! 596: for (tabndx = 1; tabndx <= tabsiz; tabndx++) { ! 597: char str[6]; ! 598: fscanf (caves, "%d\t%s", &ktab[tabndx], str); ! 599: #ifdef INITBUG ! 600: fprintf(stderr, "Sect=%d; k=%d; str=%s\n", sect, ktab[tabndx], str); ! 601: #endif INITBUG ! 602: while ((chr = getc(caves)) != '\n') ! 603: ; ! 604: cpy (&atab[tabndx][0], str); ! 605: if (ktab[tabndx] == -1) goto l1002; ! 606: } ! 607: bug(4); ! 608: /* ! 609: Read in the initial locations for each object. Also the ! 610: immovability info. plac contains initial locations of ! 611: objects. fixd is -1 for immovable objects (including the ! 612: snake), or = second loc for two-placed objects. ! 613: */ ! 614: l1050: ! 615: while (fscanf (caves, "%d\t%d\t%d", &obj, &j, &k), obj != -1) { ! 616: #ifdef INITBUG ! 617: fprintf(stderr, "Sect=%d; obj=%d; plac=%d; fixd=%d\n", sect, obj, j, k); ! 618: #endif INITBUG ! 619: plac[obj]=j; ! 620: fixd[obj]=k; ! 621: } ! 622: goto l1002; ! 623: ! 624: /* Read default message numbers for action verbs, store in actspk. */ ! 625: l1060: ! 626: while (fscanf (caves, "%d\t%d", &verb, &j), verb != -1) { ! 627: #ifdef INITBUG ! 628: fprintf(stderr, "Sect=%d; verb=%d; j=%d\n", sect, verb, j); ! 629: #endif INITBUG ! 630: actspk[verb]=j; ! 631: } ! 632: goto l1002; ! 633: ! 634: /* Read info about available liquids and other conditions, ! 635: store in cond. */ ! 636: l1070: ! 637: while (fscanf (caves, "%d", &k), k != -1) { ! 638: #ifdef INITBUG ! 639: fprintf(stderr, "Sect=%d; cond=%d\n", sect, k); ! 640: #endif INITBUG ! 641: i = 0; ! 642: while ((chr = getc(caves)) != '\n') { ! 643: ungetc(chr, caves); ! 644: fscanf (caves, "%d", &i); ! 645: if (bitset (i, k)) { ! 646: int z; ! 647: for (z=0; z<10; z++) ! 648: printf ("cond[%d]=%d\n", z, cond[z]); ! 649: fatal ("Duplicate bit\n"); ! 650: } ! 651: cond[i] |= (1 << k); ! 652: } ! 653: } ! 654: goto l1002; ! 655: ! 656: /* Read data for hints. */ ! 657: l1080: ! 658: hntmax=0; ! 659: ! 660: while (fscanf (caves, "%d\t%d\t%d\t%d\t%d", ! 661: &k, &tk[1], &tk[2], &tk[3], &tk[4]), k != -1) { ! 662: #ifdef INITBUG ! 663: fprintf(stderr, "Sect=%d; k=%d; tk=[%d,%d,%d,%d]\n", ! 664: sect, k, tk[1], tk[2], tk[3], tk[4]); ! 665: #endif INITBUG ! 666: if (k != 0) { ! 667: if (k < 0 || k > hntsiz) bug(7); ! 668: for (i=1; i<=4; i++) ! 669: hints[k][i]=tk[i]; ! 670: if (k > hntmax) ! 671: hntmax = k; ! 672: } ! 673: } ! 674: goto l1002; ! 675: ! 676: /* ! 677: Finish constructing internal data format ! 678: Having read in the database, certain things are now ! 679: constructed. Props are set to zero. We finish setting ! 680: up cond by checking for forced-motion travel entries. ! 681: The plac and fixd arrays are used to set up atloc[n] as ! 682: the first object at location n, and rlink[obj] as the next ! 683: object at the same location as obj. (obj>100 indicates ! 684: that fixed[obj-100]=loc; rlink[obj] is still the correct ! 685: link to use.) abb is zeroed; it controls whether the ! 686: abbreviated description is printed. Counts mod 5 unless ! 687: "look" is used. ! 688: */ ! 689: l1100: ! 690: ! 691: printf("Linking... "); ! 692: fflush(stdout); ! 693: ! 694: for (i=1; i<=100; i++) { ! 695: place[i]=0; ! 696: prop[i]=0; ! 697: rlink[i]=0; ! 698: rlink[i+100]=0; ! 699: } ! 700: for (i=1; i<=locsiz; i++) { ! 701: abb[i]=0; ! 702: if (ltext[i] != 0 && key[i] != 0) { ! 703: k=key[i]; ! 704: if (longabs(travel[k]) % 1000 == 1) ! 705: cond[i]=2; ! 706: } ! 707: atloc[i]=0; ! 708: } ! 709: /* ! 710: Set up the atloc and rlink arrays as described above. ! 711: We'll use the drop subroutine, which prefaces new objects ! 712: on the lists. Since we want things in the other order, ! 713: we'll run the loop backwards. If the object is in two ! 714: locs, we drop it twice. This also sets up "place" and ! 715: "fixed" as copies of "plac" and "fixd". Also, since ! 716: two-placed objects are typically best described last, ! 717: we'll drop them first. ! 718: */ ! 719: for (i=1; i<=100; i++) { ! 720: k=101-i; ! 721: if (fixd[k] > 0) { ! 722: drop (k+100,fixd[k]); ! 723: drop (k,plac[k]); ! 724: } ! 725: } ! 726: for (i=1; i<=100; i++) { ! 727: k=101-i; ! 728: fixed[k]=fixd[k]; ! 729: if (plac[k] != 0 && fixd[k] <= 0) drop(k,plac[k]); ! 730: } ! 731: /* ! 732: Treasures, as noted earlier, are objects 50 through ! 733: maxtrs (currently 79). Their props are initially -1, and ! 734: are set to 0 the first time they are described. Tally ! 735: keeps track of how many are not yet found, so we know ! 736: when to close the cave. Tally2 counts how many can never ! 737: be found (e.g. if lost bird or bridge). ! 738: */ ! 739: maxtrs=79; ! 740: tally=0; ! 741: tally2=0; ! 742: for (i=50; i<=maxtrs; i++) { ! 743: if (ptext[i] != 0) prop[i]= -1; ! 744: tally -= prop[i]; ! 745: } ! 746: /* ! 747: Clear the hint stuff. hintlc[i] is how long he's been at ! 748: loc with cond bit i. hinted(i) is true iff hint i has ! 749: been used. ! 750: */ ! 751: for (i = 1; i<=hntmax; i++) ! 752: hinted[i] = hintlc[i] = 0; ! 753: /* Define some handy mnemonics. these correspond to object numbers. */ ! 754: keys=vocab("keys",1); ! 755: lamp=vocab("lamp",1); ! 756: grate=vocab("grate",1); ! 757: cage=vocab("cage",1); ! 758: rod=vocab("rod",1); ! 759: rod2=rod+1; ! 760: steps=vocab("steps",1); ! 761: bird=vocab("bird",1); ! 762: door=vocab("door",1); ! 763: pillow=vocab("pillo",1); ! 764: snake=vocab("snake",1); ! 765: fissur=vocab("fissu",1); ! 766: tablet=vocab("table",1); ! 767: clam=vocab("clam",1); ! 768: oyster=vocab("oyste",1); ! 769: magzin=vocab("magaz",1); ! 770: dwarf=vocab("dwarf",1); ! 771: knife=vocab("knife",1); ! 772: food=vocab("food",1); ! 773: bottle=vocab("bottl",1); ! 774: water=vocab("water",1); ! 775: oil=vocab("oil",1); ! 776: plant=vocab("plant",1); ! 777: plant2=plant+1; ! 778: axe=vocab("axe",1); ! 779: mirror=vocab("mirro",1); ! 780: dragon=vocab("drago",1); ! 781: chasm=vocab("chasm",1); ! 782: troll=vocab("troll",1); ! 783: troll2=troll+1; ! 784: bear=vocab("bear",1); ! 785: messag=vocab("messa",1); ! 786: vend=vocab("vendi",1); ! 787: batter=vocab("batte",1); ! 788: /* Objects from 50 through whatever are treasures. here are a few. */ ! 789: nugget=vocab("gold",1); ! 790: coins=vocab("coins",1); ! 791: chest=vocab("chest",1); ! 792: eggs=vocab("eggs",1); ! 793: tridnt=vocab("tride",1); ! 794: vase=vocab("vase",1); ! 795: emrald=vocab("emera",1); ! 796: pyram=vocab("pyram",1); ! 797: pearl=vocab("pearl",1); ! 798: rug=vocab("rug",1); ! 799: chain=vocab("chain",1); ! 800: /* These are motion-verb numbers. */ ! 801: back=vocab("back",0); ! 802: look=vocab("look",0); ! 803: cave=vocab("cave",0); ! 804: nullx=vocab("null",0); ! 805: entrnc=vocab("entra",0); ! 806: dprssn=vocab("depre",0); ! 807: /* And some action verbs. */ ! 808: say=vocab("say",2); ! 809: lock=vocab("lock",2); ! 810: throw=vocab("throw",2); ! 811: find=vocab("find",2); ! 812: invent=vocab("inven",2); ! 813: /* ! 814: Initialize the dwarves. dloc is loc of dwarves, ! 815: hard-wired in. odloc is prior loc of each dwarf, ! 816: initially garbage. daltlc is alternate initial loc for ! 817: dwarf, in case one of them starts out on top of the ! 818: adventurer. (no 2 of the 5 initial locs are adjacent.) ! 819: dseen is true if dwarf has seen him. dflag controls the ! 820: level of activation of all this: ! 821: 0 no dwarf stuff yet (wait until reaches hall ! 822: of mists) ! 823: 1 reached hall of mists, but hasn't met first dwarf ! 824: 2 met first dwarf, others start moving, no ! 825: knives thrown yet ! 826: 3 a knife has been thrown (first set always ! 827: misses) ! 828: 3+ dwarves are mad (increases their accuracy) ! 829: Sixth dwarf is special (the pirate). He always starts at ! 830: his chest's eventual location inside the maze. This loc ! 831: is saved in chloc for ref. The dead end in the other ! 832: maze has its loc stored in chloc2. ! 833: */ ! 834: chloc=114; ! 835: chloc2=140; ! 836: for (i=1; i<=6; i++) ! 837: dseen[i] = 0; ! 838: dflag=0; ! 839: dloc[1]=19; ! 840: dloc[2]=27; ! 841: dloc[3]=33; ! 842: dloc[4]=44; ! 843: dloc[5]=64; ! 844: dloc[6]=chloc; ! 845: daltlc=18; ! 846: /* ! 847: Other random flags and counters, as follows: ! 848: turns tallies how many commands he's given ! 849: (ignores yes/no) ! 850: limit lifetime of lamp (not set here) ! 851: iwest how many times he's said "west" instead of ! 852: "w" ! 853: knfloc 0 if no knife here, loc if knife here, -1 ! 854: after caveat ! 855: detail how often we've said "not allowed to give ! 856: more detail" ! 857: abbnum how often we should print non-abbreviated ! 858: descriptions ! 859: maxdie number of reincarnation messages available ! 860: (up to 5) ! 861: numdie number of times killed so far ! 862: holdng number of objects being carried ! 863: dkill number of dwarves killed (unused in scoring, ! 864: needed for msg) ! 865: foobar current progress in saying "fee fie foe ! 866: foo". ! 867: bonus used to determine amount of bonus if he ! 868: reaches closing ! 869: clock1 number of turns from finding last treasure ! 870: till closing ! 871: clock2 number of turns from first warning till ! 872: blinding flash ! 873: logicals were explained earlier ! 874: */ ! 875: turns=0; ! 876: lmwarn=0; ! 877: iwest=0; ! 878: knfloc=0; ! 879: detail=0; ! 880: abbnum=5; ! 881: for (i=0; i<=4; i++) ! 882: if (rtext[2*i+81] != 0) maxdie=i+1; ! 883: numdie=0; ! 884: /*holdng=0; */ ! 885: dkill=0; ! 886: foobar=0; ! 887: bonus=0; ! 888: clock1=30; ! 889: clock2=50; ! 890: closng=0; ! 891: panic=0; ! 892: closed=0; ! 893: gaveup=0; ! 894: scorng=0; ! 895: /* Report on amount of arrays actually used, ! 896: to permit reductions. */ ! 897: for (kk = locsiz; kk > 0; kk--) { ! 898: if (ltext[kk] != 0) ! 899: break; ! 900: } ! 901: obj=0; ! 902: for (k = 1; k <= 100; k++) { ! 903: if (ptext[k] != 0) obj++; ! 904: } ! 905: for (k = 1; k <= tabndx; k++) { ! 906: if (ktab[k]/1000 == 2) verb=ktab[k]-2000; ! 907: } ! 908: for (j = rtxsiz; j > 0; j--) { ! 909: if (rtext[j] != 0) ! 910: break; ! 911: } ! 912: k=100; ! 913: #ifdef INITBUG ! 914: printf ("%d of %d messages; ", linuse, linsiz); ! 915: printf ("%d of %d travel options;\n", trvs, trvsiz); ! 916: printf ("%d of %d vocabulary words; ", tabndx, tabsiz); ! 917: printf ("%d of %d locations;\n", kk, locsiz); ! 918: printf ("%d of %d objects; ", obj, k); ! 919: printf ("%d of %d action verbs;\n", verb, vrbsiz); ! 920: printf ("%d of %d rtext messages; ", j, rtxsiz); ! 921: printf ("%d of %d class messages;\n", clsses, clssiz); ! 922: printf ("%d of %d hints.\n", hntmax, hntsiz); ! 923: #endif INITBUG ! 924: /* Finally, since we're clearly setting things up for the first time */ ! 925: printf ("Done!\n"); ! 926: tvec = time((long *) 0); ! 927: srand ((int) (tvec % 32768L)); ! 928: if ((suspfd = fopen (suspfile, SUSPREAD)) != NULL) { ! 929: /* check if we suspended in this release */ ! 930: srel = getw (suspfd); ! 931: slev = getw (suspfd); ! 932: if (srel != 1 || slev != 20) { ! 933: printf("I deleted a suspend file from version %d.%d\n", ! 934: srel, slev); ! 935: unlink (suspfile); ! 936: hinted[3] = yes (65, 1, 0); ! 937: loc = newloc = 1; ! 938: limit = hinted[3]? 1000: 330; ! 939: } ! 940: else ! 941: { ! 942: /* When did we suspend? */ ! 943: xtime = getl (suspfd); ! 944: #ifndef NOTIME ! 945: tvec = time((long *) 0); ! 946: if (tvec - xtime < 1800) { ! 947: printf ("You cannot restart a suspended game"); ! 948: printf ("for at least half an hour.\n"); ! 949: exit (1); ! 950: } ! 951: #endif ! 952: ! 953: /* Delete the suspend file */ ! 954: if (unlink (suspfile) == -1) ! 955: fatal ("can't unlink suspend file"); ! 956: ! 957: fread (&suspbeg, sizeof suspbeg, &suspend - &suspbeg, suspfd); ! 958: fclose (suspfd); ! 959: printf ("Restarting a suspended game...\n"); ! 960: newloc = loc; ! 961: } ! 962: } ! 963: else ! 964: { ! 965: hinted[3]=yes(65,1,0); ! 966: loc=newloc=1; ! 967: limit = hinted[3]? 1000: 330; ! 968: } ! 969: /* Can't leave cave once it's closing (except by main office). */ ! 970: l2: ! 971: if (newloc < 9 && newloc != 0 && closng) { ! 972: rspeak(130); ! 973: newloc=loc; ! 974: if (!panic) clock2=15; ! 975: panic=1; ! 976: } ! 977: /* ! 978: See if a dwarf has seen him and has come from where he ! 979: wants to go. If so, the dwarf's blocking his way. If ! 980: coming from place forbidden to pirate (dwarves rooted in ! 981: place) let him get out (and attacked). ! 982: */ ! 983: if (newloc != loc && !forced(loc) && !bitset(loc,3)) { ! 984: for (i = 1; i <= 5; i++) { ! 985: if (!(odloc[i] != newloc || !dseen[i])) { ! 986: newloc=loc; ! 987: rspeak(2); ! 988: break; ! 989: } ! 990: } ! 991: } ! 992: loc=newloc; ! 993: /* ! 994: Dwarf stuff. See earlier comments for description of ! 995: variables. Remember sixth dwarf is pirate and is thus ! 996: very different except for motion rules. ! 997: First off, don't let the dwarves follow him into a pit or ! 998: a wall. Activate the whole mess the first time he gets ! 999: as far as the hall of mists (loc 15). If newloc is ! 1000: forbidden to pirate (in particular, if it's beyond the ! 1001: troll bridge), bypass dwarf stuff. That way pirate can't ! 1002: steal return toll, and dwarves can't meet the bear. Also ! 1003: means dwarves won't follow him into dead end in maze, but ! 1004: c'est la vie. They'll wait for him outside the dead end. ! 1005: */ ! 1006: if (loc == 0 || forced(loc) || bitset((int)newloc,3)) goto l2000; ! 1007: if (dflag == 0) { ! 1008: if (loc >= 15) dflag=1; ! 1009: goto l2000; ! 1010: } ! 1011: /* ! 1012: When we encounter the first dwarf, we kill 0, 1, or 2 of ! 1013: the 5 dwarves. If any of the survivors is at loc, ! 1014: replace him with the alternate. ! 1015: */ ! 1016: if (dflag == 1) { ! 1017: if (loc < 15 || pct(95)) goto l2000; ! 1018: dflag=2; ! 1019: for (i = 1; i <= 2; i++) { ! 1020: j=1+ran(5); ! 1021: if (pct(50)) dloc[j]=0; ! 1022: } ! 1023: for (i = 1; i <= 5; i++) { ! 1024: if (dloc[i] == loc) dloc[i]=daltlc; ! 1025: odloc[i]=dloc[i]; ! 1026: } ! 1027: rspeak(3); ! 1028: drop(axe,loc); ! 1029: goto l2000; ! 1030: } ! 1031: /* ! 1032: Things are in full swing. Move each dwarf at random, ! 1033: except if he's seen us he sticks with us. Dwarves never ! 1034: go to locs <15. If wandering at random, they don't back ! 1035: up unless there's no alternative. If they don't have to ! 1036: move, they attack. And, of course, dead dwarves don't do ! 1037: much of anything. ! 1038: */ ! 1039: dtotal=0; ! 1040: attack=0; ! 1041: stick=0; ! 1042: for (i = 1; i <= 6; i++) { ! 1043: if (dloc[i] == 0) goto l6030; ! 1044: j=1; ! 1045: kk=dloc[i]; ! 1046: kk=key[kk]; ! 1047: if (kk != 0) { ! 1048: do ! 1049: { ! 1050: newloc=longabs(travel[kk])/1000 % 1000; ! 1051: if (newloc <= 300 && newloc >=15 && newloc != odloc[i] ! 1052: && !(j > 1 && newloc == tk[j-1]) && j < 20 ! 1053: && newloc != dloc[i] && !forced((int)newloc) ! 1054: && !(i == 6 && bitset((int)newloc,3)) ! 1055: && longabs(travel[kk] / 1000000) != 100) { ! 1056: tk[j]=newloc; ! 1057: j++; ! 1058: } ! 1059: kk++; ! 1060: } ! 1061: while (travel[kk-1] >= 0); ! 1062: } ! 1063: tk[j]=odloc[i]; ! 1064: if (j >= 2) j--; ! 1065: j=1+ran(j); ! 1066: odloc[i]=dloc[i]; ! 1067: dloc[i]=tk[j]; ! 1068: dseen[i]=(dseen[i] && loc >= 15) ! 1069: || (dloc[i] == loc || odloc[i] == loc); ! 1070: if (!dseen[i]) goto l6030; ! 1071: dloc[i]=loc; ! 1072: if (i != 6) goto l6027; ! 1073: /* ! 1074: The pirate's spotted him. He leaves him alone once we've ! 1075: found chest. k counts if a treasure is here. If not, ! 1076: and tally=tally2 plus one for an unseen chest, let the ! 1077: pirate be spotted. ! 1078: */ ! 1079: if (loc == chloc || prop[chest] >= 0) goto l6030; ! 1080: k=0; ! 1081: for (j = 50; j <= maxtrs; j++) { ! 1082: /* Pirate won't take pyramid from plover room or dark room (too easy!). */ ! 1083: if (j != pyram || !(loc == plac[pyram] ! 1084: || loc == plac[emrald])) { ! 1085: if (toting(j)) goto l6022; ! 1086: } ! 1087: if (here(j)) k=1; ! 1088: } ! 1089: if (tally == tally2+1 && k == 0 && place[chest] == 0 ! 1090: && here(lamp) && prop[lamp] == 1) goto l6025; ! 1091: if (odloc[6] != dloc[6] && pct(20)) rspeak(127); ! 1092: goto l6030; ! 1093: l6022: ! 1094: rspeak(128); ! 1095: /* Don't steal chest back from troll! */ ! 1096: if (place[messag] == 0) move(chest,chloc); ! 1097: move(messag,chloc2); ! 1098: for (j = 50; j <= maxtrs; j++) { ! 1099: if (j == pyram && (loc == plac[pyram] ! 1100: || loc == plac[emrald])) goto l6023; ! 1101: if (at(j) && fixed[j] == 0) carry(j,loc); ! 1102: if (toting(j)) drop(j,chloc); ! 1103: l6023: ! 1104: ; ! 1105: } ! 1106: l6024: ! 1107: dloc[6]=chloc; ! 1108: odloc[6]=chloc; ! 1109: dseen[6]=0; ! 1110: goto l6030; ! 1111: l6025: ! 1112: rspeak(186); ! 1113: move(chest,chloc); ! 1114: move(messag,chloc2); ! 1115: goto l6024; ! 1116: /* This threatening little dwarf is in the room with him! */ ! 1117: l6027: ! 1118: dtotal++; ! 1119: if (odloc[i] != dloc[i]) goto l6030; ! 1120: attack++; ! 1121: if (knfloc >= 0) knfloc=loc; ! 1122: if (ran(1000) < 95*(dflag-2))stick++; ! 1123: l6030: ! 1124: ; ! 1125: } ! 1126: /* Now we know what's happening. let's tell the poor sucker about it. */ ! 1127: if (dtotal == 0) goto l2000; ! 1128: if (dtotal != 1) { ! 1129: printf ("There are %d threatening little dwarves", dtotal); ! 1130: printf (" in the room with you.\n"); ! 1131: } else ! 1132: rspeak(4); ! 1133: if (attack == 0) goto l2000; ! 1134: if (dflag == 2) dflag=3; ! 1135: /* ! 1136: Dwarves get VERY mad! ! 1137: */ ! 1138: if (attack == 1) { ! 1139: rspeak(5); ! 1140: k=52; ! 1141: } ! 1142: else { ! 1143: printf ("%d of them throw knives at you!\n", attack); ! 1144: k=6; ! 1145: } ! 1146: if (stick <= 1) { ! 1147: rspeak(k+stick); ! 1148: if (stick == 0) goto l2000; ! 1149: } ! 1150: else ! 1151: printf ("%d of them get you!\n", stick); ! 1152: oldlc2=loc; ! 1153: goto l99; ! 1154: /* Describe the current location and (maybe) get next command. */ ! 1155: /* Print text for current loc. */ ! 1156: l2000: ! 1157: if (loc == 0) goto l99; ! 1158: kk=stext[loc]; ! 1159: if (abb[loc] % abbnum == 0 || kk == 0) kk=ltext[loc]; ! 1160: if (forced(loc) || ! dark()) goto l2001; ! 1161: if (wzdark && pct(35)) goto l90; ! 1162: kk=rtext[16]; ! 1163: l2001: ! 1164: if (toting(bear)) rspeak(141); ! 1165: speak(kk); ! 1166: k=1; ! 1167: if (forced(loc)) goto l8; ! 1168: if (loc == 33 && pct(25) && ! closng) rspeak(8); ! 1169: /* ! 1170: Print out descriptions of objects at this location. If ! 1171: not closing and property value is negative, tally off ! 1172: another treasure. Rug is special case; once seen, its ! 1173: prop is 1 (dragon on it) till dragon is killed. ! 1174: Similarly for chain; prop is initially 1 (locked to ! 1175: bear). These hacks are because prop=0 is needed to get ! 1176: full score. ! 1177: */ ! 1178: if (dark()) goto l2012; ! 1179: abb[loc]++; ! 1180: i=atloc[loc]; ! 1181: for(;;) { ! 1182: if (i == 0) goto l2012; ! 1183: obj=i; ! 1184: if (obj > 100) obj -= 100; ! 1185: if (obj == steps && toting(nugget)) goto l2008; ! 1186: if (prop[obj] < 0) { ! 1187: if (closed) goto l2008; ! 1188: prop[obj]=0; ! 1189: if (obj == rug || obj == chain) prop[obj]=1; ! 1190: tally--; ! 1191: /* If remaining treasures too elusive, zap his lamp. */ ! 1192: if (tally == tally2 && tally != 0) ! 1193: limit = limit > 35? 35: limit; ! 1194: } ! 1195: kk=prop[obj]; ! 1196: if (obj == steps && loc == fixed[steps]) kk=1; ! 1197: pspeak(obj,kk); ! 1198: l2008: ! 1199: i=rlink[i]; ! 1200: } ! 1201: l2009: ! 1202: k=54; ! 1203: l2010: ! 1204: spk=k; ! 1205: l2011: ! 1206: rspeak(spk); ! 1207: l2012: ! 1208: verb=0; ! 1209: obj=0; ! 1210: /* ! 1211: Check if this loc is eligible for any hints. If been ! 1212: here long enough, branch to help section (on later page). ! 1213: Hints all come back here eventually to finish the loop. ! 1214: Ignore "hints" < 4 (special stuff, see database notes). ! 1215: */ ! 1216: l2600: ! 1217: for (hint = 4; hint <= hntmax; hint++) { ! 1218: if (! (hinted[hint])) { ! 1219: if (!bitset(loc,hint)) hintlc[hint]= -1; ! 1220: hintlc[hint]++; ! 1221: if (hintlc[hint] >= hints[hint][1]) goto l40000; ! 1222: } ! 1223: } ! 1224: /* ! 1225: Kick the random number generator just to add variety to ! 1226: the chase. Also, if closing time, check for any objects ! 1227: being toted with prop < 0 and set the prop to -1-prop. ! 1228: This way objects won't be described until they've been ! 1229: picked up and put down separate from their respective ! 1230: piles. Don't tick clock1 unless well into cave (and not ! 1231: at Y2). ! 1232: */ ! 1233: l2602: ! 1234: if (!closed) goto l2605; ! 1235: if (prop[oyster] < 0 && toting(oyster) ! 1236: ) pspeak(oyster,1); ! 1237: for (i = 1; i <= 100; i++) { ! 1238: if (toting(i) && prop[i] < 0) prop[i]= -1-prop[i]; ! 1239: } ! 1240: l2605: ! 1241: wzdark=dark(); ! 1242: if (knfloc > 0 && knfloc != loc) knfloc=0; ! 1243: i=ran(1); ! 1244: getin(wd1,wd1x,wd2,wd2x); ! 1245: /* ! 1246: Every input, check "foobar" flag. If zero, nothing's ! 1247: going on. If pos, make neg. If neg, he skipped a word, ! 1248: so make it zero. ! 1249: */ ! 1250: l2608: ! 1251: foobar = foobar < 0? 0: -foobar; ! 1252: turns++; ! 1253: if (verb == say && !blankp(wd2)) verb=0; ! 1254: if (verb == say) goto l4090; ! 1255: if (tally == 0 && loc >= 15 && loc != 33) clock1--; ! 1256: if (clock1 == 0) goto l10000; ! 1257: if (clock1 < 0) clock2--; ! 1258: if (clock2 == 0) goto l11000; ! 1259: if (prop[lamp] == 1) limit--; ! 1260: if (limit <= 30 && here(batter) && prop[batter] == 0 ! 1261: && here(lamp)) goto l12000; ! 1262: if (limit == 0) goto l12400; ! 1263: if (limit < 0 && loc <= 8) goto l12600; ! 1264: if (limit <= 30) goto l12200; ! 1265: l19999: ! 1266: k=43; ! 1267: if (liqloc(loc) == water) k=70; ! 1268: if (eqp (wd1, "enter") && (eqp (wd2, "strea") || eqp (wd2, "water"))) ! 1269: goto l2010; ! 1270: if (eqp (wd1, "enter") && !blankp(wd2)) goto l2800; ! 1271: if (!eqp (wd1, "water") && !eqp (wd1, "oil") ! 1272: || (!eqp (wd2, "plant") && !eqp (wd2, "door "))) goto l2610; ! 1273: if (at(vocab(wd2,1))) cpy (wd2, "pour "); ! 1274: l2610: ! 1275: if (!eqp(wd1, "west ")) goto l2630; ! 1276: iwest++; ! 1277: if (iwest == 10) rspeak(17); ! 1278: l2630: ! 1279: i=vocab(wd1,-1); ! 1280: if (i == -1) goto l3000; ! 1281: k=i % 1000; ! 1282: kq=i/1000+1; ! 1283: switch (kq - 1) { ! 1284: case 0: ! 1285: goto l8; ! 1286: case 1: ! 1287: goto l5000; ! 1288: case 2: ! 1289: goto l4000; ! 1290: case 3: ! 1291: goto l2010; ! 1292: } ! 1293: bug(22); ! 1294: /* Get second word for analysis. */ ! 1295: l2800: ! 1296: cpy (wd1, wd2); ! 1297: cpy (wd1x, wd2x); ! 1298: cpy (wd2, " "); ! 1299: goto l2610; ! 1300: /* Gee, I don't understand. */ ! 1301: l3000: ! 1302: spk=60; ! 1303: if (pct(20)) spk=61; ! 1304: if (pct(20)) spk=13; ! 1305: rspeak(spk); ! 1306: goto l2600; ! 1307: /* ! 1308: Analyse a verb. remember what it was, go back for object ! 1309: if second word unless verb is "say", which snarfs ! 1310: arbitrary second word. ! 1311: */ ! 1312: l4000: ! 1313: verb=k; ! 1314: spk=actspk[verb]; ! 1315: if (!blankp(wd2) && verb != say) goto l2800; ! 1316: if (verb == say) ! 1317: if (blankp (wd2)) goto l4080; ! 1318: else goto l4090; ! 1319: if (obj != 0) goto l4090; ! 1320: /* Analyse an intransitive verb (ie, no object given yet). */ ! 1321: l4080: ! 1322: switch (verb) { ! 1323: case 1: ! 1324: goto l8010; /* take */ ! 1325: case 2: ! 1326: goto l8000; /* drop */ ! 1327: case 3: ! 1328: goto l8000; /* say */ ! 1329: case 4: ! 1330: goto l8040; /* open */ ! 1331: case 5: ! 1332: goto l2009; /* noth */ ! 1333: case 6: ! 1334: goto l8040; /* lock */ ! 1335: case 7: ! 1336: goto l9070; /* on */ ! 1337: case 8: ! 1338: goto l9080; /* off */ ! 1339: case 9: ! 1340: goto l8000; /* wave */ ! 1341: case 10: ! 1342: goto l8000; /* calm */ ! 1343: case 11: ! 1344: goto l2011; /* walk */ ! 1345: case 12: ! 1346: goto l9120; /* kill */ ! 1347: case 13: ! 1348: goto l9130; /* pour */ ! 1349: case 14: ! 1350: goto l8140; /* eat */ ! 1351: case 15: ! 1352: goto l9150; /* drnk */ ! 1353: case 16: ! 1354: goto l8000; /* rub */ ! 1355: case 17: ! 1356: goto l8000; /* toss */ ! 1357: case 18: ! 1358: goto l8180; /* quit */ ! 1359: case 19: ! 1360: goto l8000; /* find */ ! 1361: case 20: ! 1362: goto l8200; /* invn */ ! 1363: case 21: ! 1364: goto l8000; /* feed */ ! 1365: case 22: ! 1366: goto l9220; /* fill */ ! 1367: case 23: ! 1368: goto l9230; /* blst */ ! 1369: case 24: ! 1370: goto l8240; /* scor */ ! 1371: case 25: ! 1372: goto l8250; /* foo */ ! 1373: case 26: ! 1374: goto l8260; /* brf */ ! 1375: case 27: ! 1376: goto l8270; /* read */ ! 1377: case 28: ! 1378: goto l8000; /* brek */ ! 1379: case 29: ! 1380: goto l8000; /* wake */ ! 1381: case 30: ! 1382: goto l8300; /* susp */ ! 1383: case 31: ! 1384: goto l8310; /* hour */ ! 1385: case 32: ! 1386: goto setlog; /* log */ ! 1387: } ! 1388: bug(23); ! 1389: /* Analyse a transitive verb. */ ! 1390: l4090: ! 1391: switch (verb) { ! 1392: case 1: ! 1393: goto l9010; /* take */ ! 1394: case 2: ! 1395: goto l9020; /* drop */ ! 1396: case 3: ! 1397: goto l9030; /* say */ ! 1398: case 4: ! 1399: goto l9040; /* open */ ! 1400: case 5: ! 1401: goto l2009; /* noth */ ! 1402: case 6: ! 1403: goto l9040; /* lock */ ! 1404: case 7: ! 1405: goto l9070; /* on */ ! 1406: case 8: ! 1407: goto l9080; /* off */ ! 1408: case 9: ! 1409: goto l9090; /* wave */ ! 1410: case 10: ! 1411: goto l2011; /* calm */ ! 1412: case 11: ! 1413: goto l2011; /* walk */ ! 1414: case 12: ! 1415: goto l9120; /* kill */ ! 1416: case 13: ! 1417: goto l9130; /* pour */ ! 1418: case 14: ! 1419: goto l9140; /* eat */ ! 1420: case 15: ! 1421: goto l9150; /* drnk */ ! 1422: case 16: ! 1423: goto l9160; /* rub */ ! 1424: case 17: ! 1425: goto l9170; /* toss */ ! 1426: case 18: ! 1427: goto l2011; /* quit */ ! 1428: case 19: ! 1429: goto l9190; /* find */ ! 1430: case 20: ! 1431: goto l9190; /* invn */ ! 1432: case 21: ! 1433: goto l9210; /* feed */ ! 1434: case 22: ! 1435: goto l9220; /* fill */ ! 1436: case 23: ! 1437: goto l9230; /* blst */ ! 1438: case 24: ! 1439: goto l2011; /* scor */ ! 1440: case 25: ! 1441: goto l2011; /* foo */ ! 1442: case 26: ! 1443: goto l2011; /* brf */ ! 1444: case 27: ! 1445: goto l9270; /* read */ ! 1446: case 28: ! 1447: goto l9280; /* brek */ ! 1448: case 29: ! 1449: goto l9290; /* wake */ ! 1450: case 30: ! 1451: goto l2011; /* susp */ ! 1452: case 31: ! 1453: goto l2011; /* hour */ ! 1454: case 32: ! 1455: goto l2011; /* log */ ! 1456: } ! 1457: bug(24); ! 1458: /* ! 1459: Analyze an object word. See if the thing is here, ! 1460: whether we've got a verb yet, and so on. Object must be ! 1461: here unless verb is "find" or "invent(ory)" (and no new ! 1462: verb yet to be analyzed). Water and oil are also funny, ! 1463: since they are never actually dropped at any location, ! 1464: but might be here inside the bottle or as a feature of ! 1465: the location. ! 1466: */ ! 1467: l5000: ! 1468: obj=k; ! 1469: if (fixed[k] != loc && ! here(k)) goto l5100; ! 1470: l5010: ! 1471: if (!blankp(wd2)) goto l2800; ! 1472: if (verb != 0) goto l4090; ! 1473: a5toa1(wd1,wd1x,tkword); ! 1474: printf ("What do you want to do with the %s?\n", tkword); ! 1475: goto l2600; ! 1476: l5100: ! 1477: if (k != grate) goto l5110; ! 1478: if (loc == 1 || loc == 4 || loc == 7) k=dprssn; ! 1479: if (loc > 9 && loc < 15) k=entrnc; ! 1480: if (k != grate) goto l8; ! 1481: l5110: ! 1482: if (k != dwarf) goto l5120; ! 1483: for (i = 1; i <= 5; i++) { ! 1484: if (dloc[i] == loc && dflag >= 2) goto l5010; ! 1485: } ! 1486: l5120: ! 1487: if ((liq() == k && here(bottle)) ! 1488: || k == liqloc(loc)) goto l5010; ! 1489: if (obj != plant || ! at(plant2) || prop[plant2] == 0 ! 1490: ) goto l5130; ! 1491: obj=plant2; ! 1492: goto l5010; ! 1493: l5130: ! 1494: if (obj == knife && knfloc == loc) { ! 1495: knfloc= -1; ! 1496: spk=116; ! 1497: goto l2011; ! 1498: } ! 1499: if (obj != rod || !here(rod2)) goto l5190; ! 1500: obj=rod2; ! 1501: goto l5010; ! 1502: l5190: ! 1503: if ((verb == find || verb == invent) && blankp (wd2) ! 1504: ) goto l5010; ! 1505: a5toa1(wd1,wd1x,tkword); ! 1506: printf ("I see no %s here!\n", tkword); ! 1507: goto l2012; ! 1508: /* ! 1509: Figure out the new location ! 1510: Given the current location in "loc", and a motion verb ! 1511: number in "k", put the new location in "newloc". The ! 1512: current loc is saved in "oldloc" in case he wants to ! 1513: retreat. The current oldloc is saved in oldlc2, in case ! 1514: he dies. (if he does, newloc will be limbo, and oldloc ! 1515: will be what killed him, so we need oldlc2, which is the ! 1516: last place he was safe.) ! 1517: */ ! 1518: l8: ! 1519: kk=key[loc]; ! 1520: newloc=loc; ! 1521: if (kk == 0) bug(26); ! 1522: if (k == nullx) goto l2; ! 1523: if (k == back) goto l20; ! 1524: if (k == look) goto l30; ! 1525: if (k == cave) goto l40; ! 1526: oldlc2=oldloc; ! 1527: oldloc=loc; ! 1528: l9: ! 1529: ll=longabs(travel[kk]); ! 1530: if (ll % 1000 == 1 || ll % 1000 == k) goto l10; ! 1531: if (travel[kk] < 0) goto l50; ! 1532: kk++; ! 1533: goto l9; ! 1534: l10: ! 1535: ll/=1000; ! 1536: l11: ! 1537: newloc=ll/1000; ! 1538: k=newloc % 100; ! 1539: if (newloc <= 300) goto l13; ! 1540: if (prop[k] != newloc/100-3) goto l16; ! 1541: l12: ! 1542: if (travel[kk] < 0) bug(25); ! 1543: kk++; ! 1544: newloc=longabs(travel[kk])/1000; ! 1545: if (newloc == ll) goto l12; ! 1546: ll=newloc; ! 1547: goto l11; ! 1548: l13: ! 1549: if (newloc <= 100) goto l14; ! 1550: if (toting(k) || (newloc > 200 && at(k))) goto l16; ! 1551: goto l12; ! 1552: l14: ! 1553: if (newloc != 0 && !pct((int)newloc)) goto l12; ! 1554: l16: ! 1555: newloc=ll % 1000; ! 1556: if (newloc <= 300) goto l2; ! 1557: if (newloc <= 500) goto l30000; ! 1558: rspeak((int)newloc-500); ! 1559: newloc=loc; ! 1560: goto l2; ! 1561: /* ! 1562: Special motions come here. Labelling convention: ! 1563: statement numbers nnnxx (xx=00-99) are used for special ! 1564: case number nnn (nnn=301-500). ! 1565: */ ! 1566: l30000: ! 1567: newloc=newloc-300; ! 1568: switch ((int) newloc-1) { ! 1569: case 0: ! 1570: goto l30100; ! 1571: case 1: ! 1572: goto l30200; ! 1573: case 2: ! 1574: goto l30300; ! 1575: } ! 1576: bug(20); ! 1577: /* ! 1578: Travel 301. Plover-alcove passage. can carry only ! 1579: emerald. Note: travel table must include "useless" ! 1580: entries going through passage, which can never be used ! 1581: for actual motion, but can be spotted by "go back". ! 1582: */ ! 1583: l30100: ! 1584: newloc=99+100-loc; ! 1585: if (holdng == 0 || (holdng == 1 && toting(emrald))) goto l2; ! 1586: newloc=loc; ! 1587: rspeak(117); ! 1588: goto l2; ! 1589: /* ! 1590: Travel 302. Plover transport. Drop the emerald (only ! 1591: use special travel if toting it), so he's forced to use ! 1592: the plover-passage to get it out. Having dropped it, go ! 1593: back and pretend he wasn't carrying it after all. ! 1594: */ ! 1595: l30200: ! 1596: drop(emrald,loc); ! 1597: goto l12; ! 1598: /* ! 1599: Travel 303. Troll bridge. Must be done only as special ! 1600: motion so that dwarves won't wander across and encounter ! 1601: the bear. (They won't follow the player there because ! 1602: that region is forbidden to the pirate.) If ! 1603: prop(troll)=1, he's crossed since paying, so step out and ! 1604: block him. (Standard travel entries check for ! 1605: prop(troll)=0.) Special stuff for bear. ! 1606: */ ! 1607: l30300: ! 1608: if (prop[troll] != 1) goto l30310; ! 1609: pspeak(troll,1); ! 1610: prop[troll]=0; ! 1611: move(troll2,0); ! 1612: move(troll2+100,0); ! 1613: move(troll,plac[troll]); ! 1614: move(troll+100,fixd[troll]); ! 1615: juggle(chasm); ! 1616: newloc=loc; ! 1617: goto l2; ! 1618: l30310: ! 1619: newloc=plac[troll]+fixd[troll]-loc; ! 1620: if (prop[troll] == 0) prop[troll]=1; ! 1621: if (!toting(bear)) goto l2; ! 1622: rspeak(162); ! 1623: prop[chasm]=1; ! 1624: prop[troll]=2; ! 1625: drop(bear,(int)newloc); ! 1626: fixed[bear]= -1; ! 1627: prop[bear]=3; ! 1628: if (prop[spices] < 0)tally2++; ! 1629: oldlc2=newloc; ! 1630: goto l99; ! 1631: /* End of specials. */ ! 1632: /* ! 1633: Handle "go back". Look for verb which goes from loc to ! 1634: oldloc, or to oldlc2 if oldloc has forced-motion. k2 ! 1635: saves entry -> forced loc -> previous loc. ! 1636: */ ! 1637: l20: ! 1638: k=oldloc; ! 1639: if (forced(k)) k=oldlc2; ! 1640: oldlc2=oldloc; ! 1641: oldloc=loc; ! 1642: k2=0; ! 1643: if (k != loc) goto l21; ! 1644: rspeak(91); ! 1645: goto l2; ! 1646: l21: ! 1647: ll=(longabs(travel[kk])/1000) % 1000; ! 1648: if (ll == k) goto l25; ! 1649: if (ll > 300) goto l22; ! 1650: j=key[ll]; ! 1651: if (forced((int)ll) && (longabs(travel[j])/1000) % 1000 == k ! 1652: ) k2=kk; ! 1653: l22: ! 1654: if (travel[kk] < 0) goto l23; ! 1655: kk++; ! 1656: goto l21; ! 1657: l23: ! 1658: kk=k2; ! 1659: if (kk != 0) goto l25; ! 1660: rspeak(140); ! 1661: goto l2; ! 1662: l25: ! 1663: k=longabs(travel[kk]) % 1000; ! 1664: kk=key[loc]; ! 1665: goto l9; ! 1666: /* ! 1667: Look. Can't give more detail. Pretend it wasn't dark ! 1668: (though it may "now" be dark) so he won't fall into a pit ! 1669: while staring into the gloom. ! 1670: */ ! 1671: l30: ! 1672: if (detail < 3) rspeak(15); ! 1673: detail++; ! 1674: wzdark=0; ! 1675: abb[loc]=0; ! 1676: goto l2; ! 1677: /* Cave. Different messages depending on whether above ground. */ ! 1678: l40: ! 1679: if (loc < 8) rspeak(57); ! 1680: if (loc >= 8) rspeak(58); ! 1681: goto l2; ! 1682: /* Non-applicable motion. Various messages depending on word given. */ ! 1683: l50: ! 1684: spk=12; ! 1685: if (k >= 43 && k <= 50) spk=9; ! 1686: if (k == 29 || k == 30) spk=9; ! 1687: if (k == 7 || k == 36 || k == 37) spk=10; ! 1688: if (k == 11 || k == 19) spk=11; ! 1689: if (verb == find || verb == invent) spk=59; ! 1690: if (k == 62 || k == 65) spk=42; ! 1691: if (k == 17) spk=80; ! 1692: rspeak(spk); ! 1693: goto l2; ! 1694: /* ! 1695: "You're dead, Jim." ! 1696: If the current loc is zero, it means the clown got ! 1697: himself killed. We'll allow this maxdie times. maxdie ! 1698: is automatically set based on the number of snide ! 1699: messages available. Each death results in a message (81, ! 1700: 83, etc.) which offers reincarnation; if accepted, this ! 1701: results in message 82, 84, etc. The last time, if he ! 1702: wants another chance, he gets a snide remark as we exit. ! 1703: When reincarnated, all objects being carried get dropped ! 1704: at oldlc2 (presumably the last place prior to being ! 1705: killed) without change of props. The loop runs backwards ! 1706: to assure that the bird is dropped before the cage. ! 1707: (This kluge could be changed once we're sure all ! 1708: references to bird and cage are done by keywords.) The ! 1709: lamp is a special case (it wouldn't do to leave it in the ! 1710: cave). It is turned off and left outside the building ! 1711: (only if he was carrying it, of course). He himself is ! 1712: left inside the building (and heaven help him if he tries ! 1713: to xyzzy back into the cave without the lamp!). oldloc ! 1714: is zapped so he can't just "retreat". ! 1715: The easiest way to get killed is to fall into a pit in ! 1716: pitch darkness. ! 1717: */ ! 1718: l90: ! 1719: rspeak(23); ! 1720: oldlc2=loc; ! 1721: /* Okay, he's dead. Let's get on with it. */ ! 1722: l99: ! 1723: if (closng) goto l95; ! 1724: yea=yes(81+numdie*2,82+numdie*2,54); ! 1725: numdie++; ! 1726: if (numdie == maxdie || !yea) goto l20000; ! 1727: place[water]=0; ! 1728: place[oil]=0; ! 1729: if (toting(lamp)) prop[lamp]=0; ! 1730: for (j = 1; j <= 100; j++) { ! 1731: i=101-j; ! 1732: if (!toting(i)) goto l98; ! 1733: k=oldlc2; ! 1734: if (i == lamp) k=1; ! 1735: drop(i,k); ! 1736: l98: ! 1737: ; ! 1738: } ! 1739: loc=3; ! 1740: oldloc=loc; ! 1741: goto l2000; ! 1742: /* He died during closing time. No resurrection. tally up ! 1743: a death and exit. */ ! 1744: l95: ! 1745: rspeak(131); ! 1746: numdie++; ! 1747: goto l20000; ! 1748: /* ! 1749: Routines for performing the various action verbs ! 1750: Statement numbers in this section are 8000 for ! 1751: intransitive verbs, 9000 for transitive, plus ten times ! 1752: the verb number. Many intransitive verbs use the ! 1753: transitive code, and some verbs use code for other verbs, ! 1754: as noted below. ! 1755: Random intransitive verbs come here. Clear obj just in ! 1756: case (see "attack"). ! 1757: */ ! 1758: l8000: ! 1759: a5toa1(wd1,wd1x,tkword); ! 1760: printf ("%s what?\n", tkword); ! 1761: obj=0; ! 1762: goto l2600; ! 1763: /* Carry, no object given yet. OK if only one object present. */ ! 1764: l8010: ! 1765: if (atloc[loc] == 0 || rlink[atloc[loc]] != 0) goto l8000; ! 1766: for (i = 1; i <= 5; i++) { ! 1767: if (dloc[i] == loc && dflag >= 2) goto l8000; ! 1768: } ! 1769: obj=atloc[loc]; ! 1770: /* ! 1771: Carry an object. Special cases for bird and cage (if ! 1772: bird in cage, can't take one without the other. Liquids ! 1773: also special, since they depend on status of bottle. ! 1774: Also various side effects, etc. ! 1775: */ ! 1776: l9010: ! 1777: if (toting(obj)) goto l2011; ! 1778: spk=25; ! 1779: if (obj == plant && prop[plant] <= 0) spk=115; ! 1780: if (obj == bear && prop[bear] == 1) spk=169; ! 1781: if (obj == chain && prop[bear] != 0) spk=170; ! 1782: if (fixed[obj] != 0) goto l2011; ! 1783: if (obj != water && obj != oil) goto l9017; ! 1784: if (here(bottle) && liq() == obj) goto l9018; ! 1785: obj=bottle; ! 1786: if (toting(bottle) && prop[bottle] == 1) goto l9220; ! 1787: if (prop[bottle] != 1) spk=105; ! 1788: if (!toting(bottle)) spk=104; ! 1789: goto l2011; ! 1790: l9018: ! 1791: obj=bottle; ! 1792: l9017: ! 1793: if (holdng < 7) goto l9016; ! 1794: rspeak(92); ! 1795: goto l2012; ! 1796: l9016: ! 1797: if (obj != bird) goto l9014; ! 1798: if (prop[bird] != 0) goto l9014; ! 1799: if (!toting(rod)) goto l9013; ! 1800: rspeak(26); ! 1801: goto l2012; ! 1802: l9013: ! 1803: if (toting(cage)) goto l9015; ! 1804: rspeak(27); ! 1805: goto l2012; ! 1806: l9015: ! 1807: prop[bird]=1; ! 1808: l9014: ! 1809: if ((obj == bird || obj == cage) && prop[bird] != 0 ! 1810: ) carry(bird+cage-obj,loc); ! 1811: carry(obj,loc); ! 1812: k=liq(); ! 1813: if (obj == bottle && k != 0) place[k]= -1; ! 1814: goto l2009; ! 1815: /* ! 1816: Discard object. "Throw" also comes here for most ! 1817: objects. Special cases for bird (might attack snake or ! 1818: dragon) and cage (might contain bird) and vase. Drop ! 1819: coins at vending machine for extra batteries. ! 1820: */ ! 1821: l9020: ! 1822: if (toting(rod2) && obj == rod && ! toting(rod)) obj=rod2; ! 1823: if (!toting(obj)) goto l2011; ! 1824: if (obj != bird || ! here(snake)) goto l9024; ! 1825: rspeak(30); ! 1826: if (closed) goto l19000; ! 1827: dstroy(snake); ! 1828: /* Set prop for use by travel options */ ! 1829: prop[snake]=1; ! 1830: l9021: ! 1831: k=liq(); ! 1832: if (k == obj) obj=bottle; ! 1833: if (obj == bottle && k != 0) place[k]=0; ! 1834: if (obj == cage && prop[bird] != 0) drop(bird,loc); ! 1835: if (obj == bird) prop[bird]=0; ! 1836: drop(obj,loc); ! 1837: goto l2012; ! 1838: l9024: ! 1839: if (obj != coins || ! here(vend)) goto l9025; ! 1840: dstroy(coins); ! 1841: drop(batter,loc); ! 1842: pspeak(batter,0); ! 1843: goto l2012; ! 1844: l9025: ! 1845: if (obj != bird || ! at(dragon) || prop[dragon] != 0 ! 1846: ) goto l9026; ! 1847: rspeak(154); ! 1848: dstroy(bird); ! 1849: prop[bird]=0; ! 1850: if (place[snake] == plac[snake])tally2++; ! 1851: goto l2012; ! 1852: l9026: ! 1853: if (obj != bear || !at(troll)) goto l9027; ! 1854: rspeak(163); ! 1855: move(troll,0); ! 1856: move(troll+100,0); ! 1857: move(troll2,plac[troll]); ! 1858: move(troll2+100,fixd[troll]); ! 1859: juggle(chasm); ! 1860: prop[troll]=2; ! 1861: goto l9021; ! 1862: l9027: ! 1863: if (obj == vase && loc != plac[pillow]) goto l9028; ! 1864: rspeak(54); ! 1865: goto l9021; ! 1866: l9028: ! 1867: prop[vase]=2; ! 1868: if (at(pillow)) prop[vase]=0; ! 1869: pspeak(vase,prop[vase]+1); ! 1870: if (prop[vase] != 0) fixed[vase]= -1; ! 1871: goto l9021; ! 1872: /* Say. Echo wd2 (or wd1 if no wd2 (say what?, etc.).) ! 1873: Magic words override. */ ! 1874: l9030: ! 1875: a5toa1(wd2,wd2x,tkword); ! 1876: if (blankp(wd2)) a5toa1(wd1,wd1x,tkword); ! 1877: else cpy(wd1,wd2); ! 1878: i=vocab(wd1,-1); ! 1879: if (i == 62 || i == 65 || i == 71 || i == 2025) goto l9035; ! 1880: printf ("Okay, \"%s\"\n", tkword); ! 1881: goto l2012; ! 1882: l9035: ! 1883: cpy(wd2, " "); ! 1884: obj=0; ! 1885: goto l2630; ! 1886: /* Lock, unlock, no object given. Assume various things if present. */ ! 1887: l8040: ! 1888: spk=28; ! 1889: if (here(clam)) obj=clam; ! 1890: if (here(oyster)) obj=oyster; ! 1891: if (at(door)) obj=door; ! 1892: if (at(grate)) obj=grate; ! 1893: if (obj != 0 && here(chain)) goto l8000; ! 1894: if (here(chain)) obj=chain; ! 1895: if (obj == 0) goto l2011; ! 1896: /* Lock, unlock object. Special stuff for opening ! 1897: clam/oyster and for chain. */ ! 1898: l9040: ! 1899: if (obj == clam || obj == oyster) goto l9046; ! 1900: if (obj == door) spk=111; ! 1901: if (obj == door && prop[door] == 1) spk=54; ! 1902: if (obj == cage) spk=32; ! 1903: if (obj == keys) spk=55; ! 1904: if (obj == grate || obj == chain) spk=31; ! 1905: if (spk != 31 || ! here(keys)) goto l2011; ! 1906: if (obj == chain) goto l9048; ! 1907: if (!closng) goto l9043; ! 1908: k=130; ! 1909: if (!panic) clock2=15; ! 1910: panic=1; ! 1911: goto l2010; ! 1912: l9043: ! 1913: k=34+prop[grate]; ! 1914: prop[grate]=1; ! 1915: if (verb == lock) prop[grate]=0; ! 1916: k=k+2*prop[grate]; ! 1917: goto l2010; ! 1918: /* Clam/oyster. */ ! 1919: l9046: ! 1920: k=0; ! 1921: if (obj == oyster) k=1; ! 1922: spk=124+k; ! 1923: if (toting(obj)) spk=120+k; ! 1924: if (!toting(tridnt)) spk=122+k; ! 1925: if (verb == lock) spk=61; ! 1926: if (spk != 124) goto l2011; ! 1927: dstroy(clam); ! 1928: drop(oyster,loc); ! 1929: drop(pearl,105); ! 1930: goto l2011; ! 1931: /* Chain. */ ! 1932: l9048: ! 1933: if (verb == lock) goto l9049; ! 1934: spk=171; ! 1935: if (prop[bear] == 0) spk=41; ! 1936: if (prop[chain] == 0) spk=37; ! 1937: if (spk != 171) goto l2011; ! 1938: prop[chain]=0; ! 1939: fixed[chain]=0; ! 1940: if (prop[bear] != 3) prop[bear]=2; ! 1941: fixed[bear]=2-prop[bear]; ! 1942: goto l2011; ! 1943: l9049: ! 1944: spk=172; ! 1945: if (prop[chain] != 0) spk=34; ! 1946: if (loc != plac[chain]) spk=173; ! 1947: if (spk != 172) goto l2011; ! 1948: prop[chain]=2; ! 1949: if (toting(chain)) drop(chain,loc); ! 1950: fixed[chain]= -1; ! 1951: goto l2011; ! 1952: /* Light lamp */ ! 1953: l9070: ! 1954: if(!here(lamp)) goto l2011; ! 1955: spk=184; ! 1956: if(limit < 0) goto l2011; ! 1957: prop[lamp]=1; ! 1958: rspeak(39); ! 1959: if(wzdark) goto l2000; ! 1960: goto l2012; ! 1961: /* Lamp off */ ! 1962: l9080: ! 1963: if(!here(lamp)) goto l2011; ! 1964: prop[lamp]=0; ! 1965: rspeak(40); ! 1966: if(dark()) rspeak(16); ! 1967: goto l2012; ! 1968: /* Wave. No effect unless waving rod at fissure. */ ! 1969: l9090: ! 1970: if ((!toting(obj)) && (obj != rod || ! toting(rod2)) ! 1971: ) spk=29; ! 1972: if (obj != rod || ! at(fissur) || ! toting(obj) ! 1973: || closng) goto l2011; ! 1974: prop[fissur]=1-prop[fissur]; ! 1975: pspeak(fissur,2-prop[fissur]); ! 1976: goto l2012; ! 1977: /* ! 1978: Attack. Assume target if unambiguous. "throw" also ! 1979: links here. Attackable objects fall into two categories: ! 1980: enemies (snake, dwarf, etc.) and others (bird, clam). ! 1981: Ambiguous if two enemies, or if no enemies but two ! 1982: others. ! 1983: */ ! 1984: l9120: ! 1985: for (i = 1; i <= 5; i++) { ! 1986: if(dloc[i] == loc && dflag >= 2) goto l9122; ! 1987: } ! 1988: i=0; ! 1989: l9122: ! 1990: if(obj != 0) goto l9124; ! 1991: if(i != 0) obj=dwarf; ! 1992: if(here(snake)) obj=obj*100+snake; ! 1993: if(at(dragon) && prop[dragon] == 0) obj=obj*100+dragon; ! 1994: if(at(troll)) obj=obj*100+troll; ! 1995: if(here(bear) && prop[bear] == 0) obj=obj*100+bear; ! 1996: if(obj > 100) goto l8000; ! 1997: if(obj != 0) goto l9124; ! 1998: /* Can't attack bird by throwing axe. */ ! 1999: if(here(bird) && verb != throw) obj=bird; ! 2000: /* Clam and oyster both treated as clam for intransitive ! 2001: case; no harm done. */ ! 2002: if(here(clam) || here(oyster)) obj=100*obj+clam; ! 2003: if(obj > 100) goto l8000; ! 2004: l9124: ! 2005: if(obj != bird) goto l9125; ! 2006: spk=137; ! 2007: if(closed) goto l2011; ! 2008: dstroy(bird); ! 2009: prop[bird]=0; ! 2010: if(place[snake] == plac[snake])tally2++; ! 2011: spk=45; ! 2012: l9125: ! 2013: if(obj == 0) spk=44; ! 2014: if(obj == clam || obj == oyster) spk=150; ! 2015: if(obj == snake) spk=46; ! 2016: if(obj == dwarf) spk=49; ! 2017: if(obj == dwarf && closed) goto l19000; ! 2018: if(obj == dragon) spk=167; ! 2019: if(obj == troll) spk=157; ! 2020: if(obj == bear) spk=165+(prop[bear]+1)/2; ! 2021: if(obj != dragon || prop[dragon] != 0) goto l2011; ! 2022: /* ! 2023: Fun stuff for dragon. If he insists on attacking it, ! 2024: win! Set prop to dead, move dragon to central loc (still ! 2025: fixed), move rug there (not fixed), and move him there, ! 2026: too. Then do a null motion to get new description. ! 2027: */ ! 2028: rspeak(49); ! 2029: verb=0; ! 2030: obj=0; ! 2031: getin(wd1,wd1x,wd2,wd2x); ! 2032: if (!eqp (wd1, "y") && !eqp (wd1, "yes")) goto l2608; ! 2033: pspeak(dragon,1); ! 2034: prop[dragon]=2; ! 2035: prop[rug]=0; ! 2036: k=(plac[dragon]+fixd[dragon])/2; ! 2037: move(dragon+100,-1); ! 2038: move(rug+100,0); ! 2039: move(dragon,k); ! 2040: move(rug,k); ! 2041: for (obj=1; obj<=100; obj++) { ! 2042: if (place[obj] == plac[dragon] || place[obj] == fixd[dragon] ! 2043: ) move(obj,k); ! 2044: } ! 2045: loc=k; ! 2046: k=nullx; ! 2047: goto l8; ! 2048: /* ! 2049: Pour. If no object, or object is bottle, assume contents ! 2050: of bottle. Special tests for pouring water or oil on ! 2051: plant or rusty door. ! 2052: */ ! 2053: l9130: ! 2054: if(obj == bottle || obj == 0) obj=liq(); ! 2055: if(obj == 0) goto l8000; ! 2056: if(!toting(obj)) goto l2011; ! 2057: spk=78; ! 2058: if(obj != oil && obj != water) goto l2011; ! 2059: prop[bottle]=1; ! 2060: place[obj]=0; ! 2061: spk=77; ! 2062: if(!(at(plant) || at(door))) goto l2011; ! 2063: if(at(door)) goto l9132; ! 2064: spk=112; ! 2065: if(obj != water) goto l2011; ! 2066: pspeak(plant,prop[plant]+1); ! 2067: prop[plant]=(prop[plant]+2) % 6; ! 2068: prop[plant2]=prop[plant]/2; ! 2069: k=nullx; ! 2070: goto l8; ! 2071: l9132: ! 2072: prop[door]=0; ! 2073: if(obj == oil) prop[door]=1; ! 2074: spk=113+prop[door]; ! 2075: goto l2011; ! 2076: /* ! 2077: Eat. Intransitive: assume food if present, else ask ! 2078: what. Transitive: food ok, some things lose appetite, ! 2079: rest are ridiculous. ! 2080: */ ! 2081: l8140: ! 2082: if(!here(food)) goto l8000; ! 2083: l8142: ! 2084: dstroy(food); ! 2085: spk=72; ! 2086: goto l2011; ! 2087: l9140: ! 2088: if(obj == food) goto l8142; ! 2089: if (obj == bird || obj == snake || obj == clam || obj == oyster ! 2090: || obj == dwarf || obj == dragon || obj == troll ! 2091: || obj == bear) spk=71; ! 2092: goto l2011; ! 2093: /* ! 2094: Drink. If no object, assume water and look for it here. ! 2095: if water is in the bottle, drink that, else must be at a ! 2096: water loc, so drink stream. ! 2097: */ ! 2098: l9150: ! 2099: if (obj == 0 && liqloc(loc) != water && (liq() != water ! 2100: || ! here(bottle))) goto l8000; ! 2101: if(obj != 0 && obj != water) spk=110; ! 2102: if (spk == 110 || liq() != water || ! here(bottle) ! 2103: ) goto l2011; ! 2104: prop[bottle]=1; ! 2105: place[water]=0; ! 2106: spk=74; ! 2107: goto l2011; ! 2108: /* Rub. Yields various snide remarks. */ ! 2109: l9160: ! 2110: if(obj != lamp) spk=76; ! 2111: goto l2011; ! 2112: /* ! 2113: Throw. Same as discard unless axe. Then same as attack ! 2114: except ignore bird, and if dwarf is present then one ! 2115: might be killed. (only way to do so!) Axe also special ! 2116: for dragon, bear, and troll. Treasures special for ! 2117: troll. ! 2118: */ ! 2119: l9170: ! 2120: if(toting(rod2) && obj == rod && ! toting(rod)) obj=rod2; ! 2121: if(!toting(obj)) goto l2011; ! 2122: if(obj >= 50 && obj <= maxtrs && at(troll)) goto l9178; ! 2123: if(obj == food && here(bear)) goto l9177; ! 2124: if(obj != axe) goto l9020; ! 2125: for (i = 1; i <= 5; i++) { ! 2126: /* Needn't check dflag if axe is here. */ ! 2127: if(dloc[i] == loc) goto l9172; ! 2128: } ! 2129: spk=152; ! 2130: if(at(dragon) && prop[dragon] == 0) goto l9175; ! 2131: spk=158; ! 2132: if(at(troll)) goto l9175; ! 2133: if(here(bear) && prop[bear] == 0) goto l9176; ! 2134: obj=0; ! 2135: goto l9120; ! 2136: l9172: ! 2137: spk=48; ! 2138: if(ran(3) == 0) goto l9175; ! 2139: dseen[i]=0; ! 2140: dloc[i]=0; ! 2141: spk=47; ! 2142: dkill++; ! 2143: if(dkill == 1) spk=149; ! 2144: l9175: ! 2145: rspeak(spk); ! 2146: drop(axe,loc); ! 2147: k=nullx; ! 2148: goto l8; ! 2149: /* This'll teach him to throw the axe at the bear! */ ! 2150: l9176: ! 2151: spk=164; ! 2152: drop(axe,loc); ! 2153: fixed[axe]= -1; ! 2154: prop[axe]=1; ! 2155: juggle(bear); ! 2156: goto l2011; ! 2157: /* But throwing food is another story. */ ! 2158: l9177: ! 2159: obj=bear; ! 2160: goto l9210; ! 2161: l9178: ! 2162: spk=159; ! 2163: /* Snarf a treasure for the troll. */ ! 2164: drop(obj,0); ! 2165: move(troll,0); ! 2166: move(troll+100,0); ! 2167: drop(troll2,plac[troll]); ! 2168: drop(troll2+100,fixd[troll]); ! 2169: juggle(chasm); ! 2170: goto l2011; ! 2171: /* Quit. Intransitive only. Verify intent and exit if ! 2172: that's what he wants. */ ! 2173: l8180: ! 2174: gaveup=yes(22,54,54); ! 2175: if(gaveup) goto l20000; ! 2176: goto l2012; ! 2177: /* Find. Might be carrying it, or it might be here. Else give caveat. */ ! 2178: l9190: ! 2179: if (at(obj) || (liq() == obj && at(bottle)) ! 2180: || k == liqloc(loc)) spk=94; ! 2181: for (i = 1; i <= 5; i++) { ! 2182: if(dloc[i] == loc && dflag >= 2 && obj == dwarf) spk=94; ! 2183: } ! 2184: if(closed) spk=138; ! 2185: if(toting(obj)) spk=24; ! 2186: goto l2011; ! 2187: /* Inventory. If object, treat same as find. Else report ! 2188: on current burden. */ ! 2189: l8200: ! 2190: spk=98; ! 2191: for (i = 1; i <= 100; i++) { ! 2192: if(i == bear || ! toting(i)) goto l8201; ! 2193: if(spk == 98) rspeak(99); ! 2194: blklin=0; ! 2195: pspeak(i,-1); ! 2196: blklin=1; ! 2197: spk=0; ! 2198: l8201: ! 2199: ; ! 2200: } ! 2201: if(toting(bear)) spk=141; ! 2202: goto l2011; ! 2203: /* ! 2204: Feed. If bird, no seed. snake, dragon, troll: quip. If ! 2205: dwarf, make him mad. Bear, special. ! 2206: */ ! 2207: l9210: ! 2208: if(obj != bird) goto l9212; ! 2209: spk=100; ! 2210: goto l2011; ! 2211: l9212: ! 2212: if(obj != snake && obj != dragon && obj != troll) goto l9213; ! 2213: spk=102; ! 2214: if(obj == dragon && prop[dragon] != 0) spk=110; ! 2215: if(obj == troll) spk=182; ! 2216: if(obj != snake || closed || ! here(bird)) goto l2011; ! 2217: spk=101; ! 2218: dstroy(bird); ! 2219: prop[bird]=0; ! 2220: tally2++; ! 2221: goto l2011; ! 2222: l9213: ! 2223: if(obj != dwarf) goto l9214; ! 2224: if(!here(food)) goto l2011; ! 2225: spk=103; ! 2226: dflag++; ! 2227: goto l2011; ! 2228: l9214: ! 2229: if(obj != bear) goto l9215; ! 2230: if(prop[bear] == 0) spk=102; ! 2231: if(prop[bear] == 3) spk=110; ! 2232: if(!here(food)) goto l2011; ! 2233: dstroy(food); ! 2234: prop[bear]=1; ! 2235: fixed[axe]=0; ! 2236: prop[axe]=0; ! 2237: spk=168; ! 2238: goto l2011; ! 2239: l9215: ! 2240: spk=14; ! 2241: goto l2011; ! 2242: /* Fill. Bottle must be empty, and some liquid available. ! 2243: (vase is nasty.) */ ! 2244: l9220: ! 2245: if(obj == vase) goto l9222; ! 2246: if(obj != 0 && obj != bottle) goto l2011; ! 2247: if(obj == 0 && ! here(bottle)) goto l8000; ! 2248: spk=107; ! 2249: if(liqloc(loc) == 0) spk=106; ! 2250: if(liq() != 0) spk=105; ! 2251: if(spk != 107) goto l2011; ! 2252: prop[bottle]=(cond[loc] % 4)/2; ! 2253: prop[bottle]=prop[bottle]*2; ! 2254: k=liq(); ! 2255: if(toting(bottle)) place[k]= -1; ! 2256: if(k == oil) spk=108; ! 2257: goto l2011; ! 2258: l9222: ! 2259: spk=29; ! 2260: if(liqloc(loc) == 0) spk=144; ! 2261: if(liqloc(loc) == 0 || !toting(vase)) goto l2011; ! 2262: rspeak(145); ! 2263: prop[vase]=2; ! 2264: fixed[vase]= -1; ! 2265: goto l9024; ! 2266: /* Blast. No effect unless you've got dynamite, which is a ! 2267: neat trick! */ ! 2268: l9230: ! 2269: if(prop[rod2] < 0 || ! closed) goto l2011; ! 2270: bonus=133; ! 2271: if(loc == 115) bonus=134; ! 2272: if(here(rod2)) bonus=135; ! 2273: rspeak(bonus); ! 2274: goto l20000; ! 2275: /* Score. Go to scoring section, which will return to 8241 ! 2276: if scorng is true. */ ! 2277: l8240: ! 2278: scorng=1; ! 2279: goto l20000; ! 2280: l8241: ! 2281: scorng=0; ! 2282: printf ("If you were to quit now, you would score "); ! 2283: printf ("%d out of a possible %d in %d turns.\n", ! 2284: score, mxscor, turns+1); ! 2285: goto l2012; ! 2286: /* ! 2287: Fee fie foe foo (and fum). Advance to next state if given ! 2288: in proper order. Look up wd1 in section 3 of vocab to ! 2289: determine which word we've got. Last word zips the eggs ! 2290: back to the giant room (unless already there). ! 2291: */ ! 2292: l8250: ! 2293: k=vocab(wd1,3); ! 2294: spk=42; ! 2295: if(foobar == 1-k) goto l8252; ! 2296: if(foobar != 0) spk=151; ! 2297: goto l2011; ! 2298: l8252: ! 2299: foobar=k; ! 2300: if(k != 4) goto l2009; ! 2301: foobar=0; ! 2302: if (place[eggs] == plac[eggs] ! 2303: || (toting(eggs) && loc == plac[eggs])) goto l2011; ! 2304: /* Bring back troll if we steal the eggs back from him ! 2305: before crossing. */ ! 2306: if (place[eggs] == 0 && place[troll] == 0 && prop[troll] == 0 ! 2307: ) prop[troll]=1; ! 2308: k=2; ! 2309: if(here(eggs)) k=1; ! 2310: if(loc == plac[eggs]) k=0; ! 2311: move(eggs,plac[eggs]); ! 2312: pspeak(eggs,k); ! 2313: goto l2012; ! 2314: /* Brief. Intransitive only. Suppress long descriptions ! 2315: after first time. */ ! 2316: l8260: ! 2317: spk=156; ! 2318: abbnum=10000; ! 2319: detail=3; ! 2320: goto l2011; ! 2321: /* Read. Magazines in dwarvish, message we've seen, and . ! 2322: . . oyster? */ ! 2323: l8270: ! 2324: if(here(magzin)) obj=magzin; ! 2325: if(here(tablet)) obj=obj*100+tablet; ! 2326: if(here(messag)) obj=obj*100+messag; ! 2327: if(closed && toting(oyster)) obj=oyster; ! 2328: if(obj > 100 || obj == 0 || dark()) goto l8000; ! 2329: l9270: ! 2330: if(dark()) goto l5190; ! 2331: if(obj == magzin) spk=190; ! 2332: if(obj == tablet) spk=196; ! 2333: if(obj == messag) spk=191; ! 2334: if(obj == oyster && hinted[2] && toting(oyster)) spk=194; ! 2335: if (obj != oyster || hinted[2] || !toting(oyster) ! 2336: || !closed) goto l2011; ! 2337: hinted[2]=yes(192,193,54); ! 2338: goto l2012; ! 2339: /* Break. Only works for mirror in repository and, of ! 2340: course, the vase. */ ! 2341: l9280: ! 2342: if(obj == mirror) spk=148; ! 2343: if(obj == vase && prop[vase] == 0) goto l9282; ! 2344: if(obj != mirror || !closed) goto l2011; ! 2345: rspeak(197); ! 2346: goto l19000; ! 2347: l9282: ! 2348: spk=198; ! 2349: if(toting(vase)) drop(vase,loc); ! 2350: prop[vase]=2; ! 2351: fixed[vase]= -1; ! 2352: goto l2011; ! 2353: /* Wake. Only use is to disturb the dwarves. */ ! 2354: l9290: ! 2355: if(obj != dwarf || !closed) goto l2011; ! 2356: rspeak(199); ! 2357: goto l19000; ! 2358: /* ! 2359: Suspend. Exit leaving things restartable. ! 2360: */ ! 2361: l8300: ! 2362: if ((suspfd = fopen (suspfile, SUSPWRITE)) == NULL) { ! 2363: printf ("Something's wrong...I can't suspend.\n"); ! 2364: if (hungup) { ! 2365: hungup = 0; ! 2366: goto l20000; ! 2367: } ! 2368: goto l2012; ! 2369: } ! 2370: hungup = 0; ! 2371: printf ("OK...I'm suspending this game in %s\n", suspfile); ! 2372: ! 2373: /* Block interrupts to ensure completion of suspension */ ! 2374: signal (SIGINT, SIG_IGN); ! 2375: signal (SIGQUIT, SIG_IGN); ! 2376: signal (SIGHUP, SIG_IGN); ! 2377: ! 2378: /* Write the release and level into the suspend file */ ! 2379: putw (1, suspfd); ! 2380: putw (20, suspfd); ! 2381: ! 2382: /* Write the time to prevent premature resumption */ ! 2383: tvec = time(0); ! 2384: putl (tvec, suspfd); ! 2385: ! 2386: /* Write the suspend data into the file */ ! 2387: fwrite (&suspbeg, sizeof suspbeg, &suspend - &suspbeg, suspfd); ! 2388: ! 2389: /* Make sure everything went ok */ ! 2390: if (ferror (suspfd)) ! 2391: fatal ("I/O error during suspension"); ! 2392: ! 2393: fclose (suspfd); ! 2394: #ifdef NOTIME ! 2395: printf ("Play will resume automatically next time.\n"); ! 2396: #else ! 2397: printf ("You may resume play half an hour from now.\n"); ! 2398: #endif ! 2399: exit(0); ! 2400: /* Hours. Report current non-prime-time hours. */ ! 2401: l8310: ! 2402: printf (HOURS); ! 2403: goto l2012; ! 2404: /* Log. Toggle loggin either on or off */ ! 2405: setlog: ! 2406: logon = ! logon; ! 2407: if (logon) ! 2408: printf ("Log on.\n"); ! 2409: else ! 2410: printf ("Log off.\n"); ! 2411: goto l2012; ! 2412: /* ! 2413: hints ! 2414: Come here if he's been long enough at required loc(s) for ! 2415: some unused hint. Hint number is in variable "hint". ! 2416: branch to quick test for additional conditions, then come ! 2417: back to do neat stuff. goto 40010 if conditions are met ! 2418: and we want to offer the hint. goto 40020 to clear ! 2419: hintlc back to zero, 40030 to take no action yet. ! 2420: */ ! 2421: l40000: ! 2422: switch (hint-4) { ! 2423: case 0: ! 2424: goto l40400; /* cave */ ! 2425: case 1: ! 2426: goto l40500; /* bird */ ! 2427: case 2: ! 2428: goto l40600; /* snake */ ! 2429: case 3: ! 2430: goto l40700; /* maze */ ! 2431: case 4: ! 2432: goto l40800; /* dark */ ! 2433: case 5: ! 2434: goto l40900; /* witt */ ! 2435: } ! 2436: bug(27); ! 2437: l40010: ! 2438: hintlc[hint]=0; ! 2439: if(!yes(hints[hint][3],0,54)) goto l2602; ! 2440: printf ("I am prepared to give you a hint,"); ! 2441: printf (" but it will cost you %d points.\n", hints[hint][2]); ! 2442: hinted[hint]=yes(175,hints[hint][4],54); ! 2443: if (hinted[hint] && limit > 30 ! 2444: ) limit=limit+30*hints[hint][2]; ! 2445: l40020: ! 2446: hintlc[hint]=0; ! 2447: l40030: ! 2448: goto l2602; ! 2449: /* Now for the quick tests. See database description for ! 2450: one-line notes. */ ! 2451: l40400: ! 2452: if(prop[grate] == 0 && ! here(keys)) goto l40010; ! 2453: goto l40020; ! 2454: l40500: ! 2455: if(here(bird) && toting(rod) && obj == bird) goto l40010; ! 2456: goto l40030; ! 2457: l40600: ! 2458: if(here(snake) && ! here(bird)) goto l40010; ! 2459: goto l40020; ! 2460: l40700: ! 2461: if (atloc[loc] == 0 && atloc[oldloc] == 0 ! 2462: && atloc[oldlc2] == 0 && holdng > 1) goto l40010; ! 2463: goto l40020; ! 2464: l40800: ! 2465: if(prop[emrald] != -1 && prop[pyram] == -1) goto l40010; ! 2466: goto l40020; ! 2467: l40900: ! 2468: goto l40010; ! 2469: /* ! 2470: Cave closing and scoring ! 2471: These sections handle the closing of the cave. The cave ! 2472: closes "clock1" turns after the last treasure has been ! 2473: located (including the pirate's chest, which may of ! 2474: course never show up). Note that the treasures need not ! 2475: have been taken yet, just located. Hence clock1 must be ! 2476: large enough to get out of the cave (it only ticks while ! 2477: inside the cave). When it hits zero, we branch to 10000 ! 2478: to start closing the cave, and then sit back and wait for ! 2479: him to try to get out. If he doesn't within clock2 ! 2480: turns, we close the cave; if he does try, we assume he ! 2481: panics, and give him a few additional turns to get ! 2482: frantic before we close. When clock2 hits zero, we ! 2483: branch to 11000 to transport him into the final puzzle. ! 2484: Note that the puzzle depends upon all sorts of random ! 2485: things. For instance, there must be no water or oil, ! 2486: since there are beanstalks which we don't want to be able ! 2487: to water, since the code can't handle it. Also, we can ! 2488: have no keys, since there is a grate (having moved the ! 2489: fixed object!) there separating him from all the ! 2490: treasures. Most of these problems arise from the use of ! 2491: negative prop numbers to suppress the object descriptions ! 2492: until he's actually moved the objects. ! 2493: When the first warning comes, we lock the grate, destroy ! 2494: the bridge, kill all the dwarves (and the pirate), remove ! 2495: the troll and bear (unless dead), and set "closng" to ! 2496: true. Leave the dragon; too much trouble to move it. ! 2497: From now until clock2 runs out, he cannot unlock the ! 2498: grate, move to any location outside the cave (loc<9), or ! 2499: create the bridge. Nor can he be resurrected if he dies. ! 2500: Note that the snake is already gone, since he got to the ! 2501: treasure accessible only via the hall of the mt. king. ! 2502: also, he's been in giant room (to get eggs), so we can ! 2503: refer to it. Also also, he's gotten the pearl, so we ! 2504: know the bivalve is an oyster. AND, the dwarves must ! 2505: have been activated, since we've found chest. ! 2506: */ ! 2507: l10000: ! 2508: prop[grate]=0; ! 2509: prop[fissur]=0; ! 2510: for (i = 1; i <= 6; i++) { ! 2511: dseen[i]=0; ! 2512: } ! 2513: move(troll,0); ! 2514: move(troll+100,0); ! 2515: move(troll2,plac[troll]); ! 2516: move(troll2+100,fixd[troll]); ! 2517: juggle(chasm); ! 2518: if(prop[bear] != 3) dstroy(bear); ! 2519: prop[chain]=0; ! 2520: fixed[chain]=0; ! 2521: prop[axe]=0; ! 2522: fixed[axe]=0; ! 2523: rspeak(129); ! 2524: clock1= -1; ! 2525: closng=1; ! 2526: goto l19999; ! 2527: /* ! 2528: Once he's panicked, and clock2 has run out, we come here ! 2529: to set up the storage room. The room has two locs, ! 2530: hardwired as 115 (ne) and 116 (sw). At the ne end, we ! 2531: place empty bottles, a nursery of plants, a bed of ! 2532: oysters, a pile of lamps, rods with stars, sleeping ! 2533: dwarves, and him. At the sw end we place grate over ! 2534: treasures, snake pit, covey of caged birds, more rods, ! 2535: and pillows. A mirror stretches across one wall. Many ! 2536: of the objects come from known locations and/or states ! 2537: (e.g. the snake is known to have been destroyed and ! 2538: needn't be carried away from its old "place"), making the ! 2539: various objects be handled differently. We also drop all ! 2540: other objects he might be carrying (lest he have some ! 2541: which could cause trouble, such as the keys). We ! 2542: describe the flash of light and trundle back. ! 2543: */ ! 2544: l11000: ! 2545: prop[bottle]=put(bottle,115,1); ! 2546: prop[plant]=put(plant,115,0); ! 2547: prop[oyster]=put(oyster,115,0); ! 2548: prop[lamp]=put(lamp,115,0); ! 2549: prop[rod]=put(rod,115,0); ! 2550: prop[dwarf]=put(dwarf,115,0); ! 2551: loc=115; ! 2552: oldloc=115; ! 2553: newloc=115; ! 2554: /* Leave the grate with normal (non-negative property). */ ! 2555: foo=put(grate,116,0); ! 2556: prop[snake]=put(snake,116,1); ! 2557: prop[bird]=put(bird,116,1); ! 2558: prop[cage]=put(cage,116,0); ! 2559: prop[rod2]=put(rod2,116,0); ! 2560: prop[pillow]=put(pillow,116,0); ! 2561: prop[mirror]=put(mirror,115,0); ! 2562: fixed[mirror]=116; ! 2563: for (i = 1; i <= 100; i++) { ! 2564: if(toting(i)) dstroy(i); ! 2565: } ! 2566: rspeak(132); ! 2567: closed=1; ! 2568: goto l2; ! 2569: /* ! 2570: Another way we can force an end to things is by having ! 2571: the lamp give out. When it gets close, we come here to ! 2572: warn him. We go to 12000 if the lamp and fresh batteries ! 2573: are here, in which case we replace the batteries and ! 2574: continue. 12200 is for other cases of lamp dying. 12400 ! 2575: is when it goes out, and 12600 is if he's wandered ! 2576: outside and the lamp is used up, in which case we force ! 2577: him to give up. ! 2578: */ ! 2579: l12000: ! 2580: rspeak(188); ! 2581: prop[batter]=1; ! 2582: if(toting(batter)) drop(batter,loc); ! 2583: limit=limit+2500; ! 2584: lmwarn=0; ! 2585: goto l19999; ! 2586: l12200: ! 2587: if (lmwarn || !here(lamp)) goto l19999; ! 2588: lmwarn=1; ! 2589: spk=187; ! 2590: if (place[batter] == 0) spk=183; ! 2591: if (prop[batter] == 1) spk=189; ! 2592: rspeak(spk); ! 2593: goto l19999; ! 2594: l12400: ! 2595: limit= -1; ! 2596: prop[lamp]=0; ! 2597: if (here(lamp)) rspeak(184); ! 2598: goto l19999; ! 2599: l12600: ! 2600: rspeak(185); ! 2601: gaveup=1; ! 2602: goto l20000; ! 2603: /* Oh dear, he's disturbed the dwarves. */ ! 2604: l19000: ! 2605: rspeak(136); ! 2606: /* ! 2607: Exit code. ! 2608: the present scoring algorithm is as follows: ! 2609: objective: points: present total possible: ! 2610: getting well into cave 25 25 ! 2611: each treasure < chest 12 60 ! 2612: treasure chest itself 14 14 ! 2613: each treasure > chest 16 144 ! 2614: surviving (max-num)*10 30 ! 2615: not quitting 4 4 ! 2616: reaching "closng" 25 25 ! 2617: "closed": quit/killed 10 ! 2618: klutzed 25 ! 2619: wrong way 30 ! 2620: success 45 45 ! 2621: came to witt's end 1 1 ! 2622: round out the total 2 2 ! 2623: total: 350 ! 2624: (points can also be deducted for using hints.) ! 2625: */ ! 2626: l20000: ! 2627: score=0; ! 2628: mxscor=0; ! 2629: /* ! 2630: First tally up the treasures. Must be in building and ! 2631: not broken. Give the poor guy 2 points just for finding ! 2632: each treasure. ! 2633: */ ! 2634: for (i = 50; i <= maxtrs; i++) { ! 2635: if (ptext[i] != 0) { ! 2636: k=12; ! 2637: if (i == chest) k=14; ! 2638: if (i > chest) k=16; ! 2639: if (prop[i] >= 0) score=score+2; ! 2640: if (place[i] == 3 && prop[i] == 0) score=score+k-2; ! 2641: mxscor=mxscor+k; ! 2642: } ! 2643: } ! 2644: /* ! 2645: Now look at how he finished and how far he got. maxdie ! 2646: and numdie tell us how well he survived. gaveup says ! 2647: whether he exited via quit. dflag will tell us if he ! 2648: ever got suitably deep into the cave. closng still ! 2649: indicates whether he reached the endgame. And if he got ! 2650: as far as "cave closed" (indicated by "closed"), then ! 2651: bonus is zero for mundane exits or 133, 134, 135 if he ! 2652: blew it (so to speak). ! 2653: */ ! 2654: score=score+(maxdie-numdie)*10; ! 2655: mxscor=mxscor+maxdie*10; ! 2656: if (!(scorng || gaveup)) score=score+4; ! 2657: mxscor=mxscor+4; ! 2658: if (dflag != 0) score=score+25; ! 2659: mxscor=mxscor+25; ! 2660: if (closng) score=score+25; ! 2661: mxscor=mxscor+25; ! 2662: if (!closed) goto l20020; ! 2663: if (bonus == 0) score=score+10; ! 2664: if (bonus == 135) score=score+25; ! 2665: if (bonus == 134) score=score+30; ! 2666: if (bonus == 133) score=score+45; ! 2667: l20020: ! 2668: mxscor=mxscor+45; ! 2669: /* Did he come to Witt's End as he should? */ ! 2670: if (place[magzin] == 108)score++; ! 2671: mxscor++; ! 2672: /* Round it off. */ ! 2673: score=score+2; ! 2674: mxscor=mxscor+2; ! 2675: /* Deduct points for hints. hints < 4 are special; see ! 2676: database description. */ ! 2677: for (i = 1; i <= hntmax; i++) { ! 2678: if (hinted[i]) score=score-hints[i][2]; ! 2679: } ! 2680: /* Return to score command if that's where we came from. */ ! 2681: if (scorng) goto l8241; ! 2682: /* That should be good enough. Let's tell him all about it. */ ! 2683: printf ("You scored %d out of a possible %d using %d turn%s.\n", ! 2684: score, mxscor, turns, turns==1? "": "s"); ! 2685: for (i = 1; i <= clsses; i++) { ! 2686: if (cval[i] >= score) goto l20210; ! 2687: } ! 2688: printf("You just went off my scale!!!\n"); ! 2689: goto l25000; ! 2690: l20210: ! 2691: speak(ctext[i]); ! 2692: if (i == clsses-1) goto l20220; ! 2693: k=cval[i]+1-score; ! 2694: printf ("To achieve the next higher rating, you need %d more point%s.\n", ! 2695: k, k==1? "": "s"); ! 2696: goto l25000; ! 2697: l20220: ! 2698: printf ("To achieve the next higher rating would be a neat trick!\n"); ! 2699: printf ("Congratulations!!\n"); ! 2700: l25000: ! 2701: if (logon) { ! 2702: /* Log this termination for the interest of other users */ ! 2703: FILE *logfile; ! 2704: char *ctime(); ! 2705: if ((logfile = fopen ("/usr/games/advlog", "a")) != NULL) { ! 2706: tvec = time((long *) 0); ! 2707: cp1 = ctime (&tvec); ! 2708: /* Assumed format "Mon Jan 99 99:99:99 1999\n\0" */ ! 2709: cp1[10] = '\0'; ! 2710: fprintf (logfile, "%s; %s: %d in %d\n", ! 2711: cp1 + 4, pwbuf -> pw_name, ! 2712: score, turns); ! 2713: } ! 2714: } ! 2715: } ! 2716: ! 2717: /* ! 2718: * subroutines/functions ! 2719: * toting(obj) = true if the obj is being carried ! 2720: * here(obj) = true if the obj is at "loc" (or is being carried) ! 2721: * at(obj) = true if on either side of two-placed object ! 2722: * liq(dummy) = object number of liquid in bottle ! 2723: * liqloc(loc) = object number of liquid (if any) at loc ! 2724: * bitset(l,n) = true if cond(l) has bit n set (bit 0 is units bit) ! 2725: * forced(loc) = true if loc moves without asking for input (cond=2) ! 2726: * dark(dummy) = true if location "loc" is dark ! 2727: * pct(n) = true n% of the time (n integer from 0 to 100) ! 2728: */ ! 2729: ! 2730: toting(ob) ! 2731: { ! 2732: return place[ob] == -1; ! 2733: } ! 2734: ! 2735: here(ob) ! 2736: { ! 2737: return place[ob] == loc || toting (ob); ! 2738: } ! 2739: ! 2740: at(ob) ! 2741: { ! 2742: return place[ob] == loc || fixed[ob] == loc; ! 2743: } ! 2744: ! 2745: liq2(pbotl) ! 2746: { ! 2747: int liq2temp; ! 2748: liq2temp = pbotl/2; ! 2749: return (1-pbotl)*water + liq2temp * (water+oil); ! 2750: } ! 2751: ! 2752: liq() ! 2753: { ! 2754: int t; ! 2755: t = prop[bottle]; ! 2756: return liq2(t>-1-t? t: -1-t); ! 2757: } ! 2758: ! 2759: liqloc(where) ! 2760: { ! 2761: int t1, t2; ! 2762: t1 = cond[where] / 2; ! 2763: t1 = t1 * 2; ! 2764: t2 = cond[where] / 4; ! 2765: return liq2 (((t1 % 8)-5)*(t2%2)+1); ! 2766: } ! 2767: ! 2768: bitset (mm, n) ! 2769: { ! 2770: return (cond[mm] >> n) & 1; ! 2771: } ! 2772: ! 2773: forced(where) ! 2774: { ! 2775: return cond[where] == 2; ! 2776: } ! 2777: ! 2778: dark() ! 2779: { ! 2780: return ((cond[loc] & 1) == 0) && (prop[lamp] == 0 || !here(lamp)); ! 2781: } ! 2782: ! 2783: pct (n) ! 2784: { ! 2785: return ran(100) < n; ! 2786: } ! 2787: ! 2788: /* ! 2789: * Place any object anywhere by picking it up and dropping ! 2790: * it. May already be toting, in which case the carry is ! 2791: * a no-op. Mustn't pick up objects which are not at any ! 2792: * loc, since carry wants to remove objects from atloc chains. ! 2793: */ ! 2794: move (object, where) { ! 2795: int source; ! 2796: if (object <= 100) ! 2797: source = place[object]; ! 2798: else ! 2799: source = fixed[object-100]; ! 2800: if (source > 0 && source <= 300) ! 2801: carry (object, source); ! 2802: drop (object, where); ! 2803: } ! 2804: ! 2805: dstroy (object) ! 2806: { ! 2807: move (object, 0); ! 2808: } ! 2809: ! 2810: juggle (object) ! 2811: { ! 2812: register int ii, jj; ! 2813: ii = place[object]; ! 2814: jj = fixed [object]; ! 2815: move (object, ii); ! 2816: move (object+100, jj); ! 2817: } ! 2818: ! 2819: put (object, where, pval) ! 2820: { ! 2821: move (object, where); ! 2822: return -1-pval; ! 2823: } ! 2824: ! 2825: /* ! 2826: * Start toting an object, removing it from the list of things at ! 2827: * its former location. Increment holding unless it was already ! 2828: * being toted. If object>100 (moving "fixed" second loc) ! 2829: * don't change place or holdng. ! 2830: */ ! 2831: carry (object, where) ! 2832: { ! 2833: int tmp; ! 2834: if (object <= 100) { ! 2835: if (place[object] == -1) return; ! 2836: place[object] = -1; ! 2837: holdng++; ! 2838: } ! 2839: if (atloc[where] == object) { ! 2840: atloc[where] = rlink[object]; ! 2841: return; ! 2842: } ! 2843: tmp = atloc[where]; ! 2844: while (rlink[tmp] != object) ! 2845: tmp = rlink[tmp]; ! 2846: rlink[tmp] = rlink[object]; ! 2847: } ! 2848: ! 2849: /* ! 2850: * Place an object at a given loc, prefixing ot onto the atloc list. ! 2851: * Decrement holdng if the object was being toted. ! 2852: */ ! 2853: drop (object, where) ! 2854: { ! 2855: if (object > 100) ! 2856: fixed[object-100] = where; ! 2857: else ! 2858: { ! 2859: if (place[object] == -1) holdng--; ! 2860: place[object] = where; ! 2861: } ! 2862: if (where <= 0) return; ! 2863: rlink[object] = atloc[where]; ! 2864: atloc[where] = object; ! 2865: } ! 2866: ! 2867: fatal(s) ! 2868: char *s; ! 2869: { ! 2870: printf ("\nFatal error: %s\n", s); ! 2871: exit(1); ! 2872: } ! 2873: ! 2874: bug(n) ! 2875: { ! 2876: printf ("Bug number %d\n", n); ! 2877: printf ("Program quits\n"); ! 2878: exit(1); ! 2879: } ! 2880: ! 2881: /* Returns a random number between 0 and num-1 inclusive */ ! 2882: ran(num) ! 2883: { ! 2884: return (((long) num * rand()) / 32768L); ! 2885: } ! 2886: ! 2887: /* ! 2888: * return 1 if the five-character argument ! 2889: * is entirely blank, 0 otherwise ! 2890: */ ! 2891: blankp(a5) ! 2892: char *a5; ! 2893: { ! 2894: return eqp (a5, " "); ! 2895: } ! 2896: ! 2897: /* ! 2898: * return 1 if a5 and b5 are equal, 0 otherwise. ! 2899: * The lengths of a5 and b5 are limited to 5, ! 2900: * but if either contains a null character, it is assumed ! 2901: * to be padded out to length 5 with blanks. ! 2902: */ ! 2903: eqp(a5, b5) ! 2904: char *a5, *b5; ! 2905: { ! 2906: register int z; ! 2907: register char *aa, *bb; ! 2908: aa = a5; ! 2909: bb = b5; ! 2910: z = 5; ! 2911: do { ! 2912: if ((*aa == '\0'? ' ': *aa++) != ! 2913: (*bb == '\0'? ' ': *bb++)) ! 2914: return 0; ! 2915: } while (--z); ! 2916: return 1; ! 2917: } ! 2918: ! 2919: /* ! 2920: * copy the character string from "source" to "sink". Length is limited ! 2921: * to 5 characters, and "sink" is blank padded if "source" is shorter. ! 2922: */ ! 2923: cpy (sink, source) ! 2924: register char *source, *sink; ! 2925: { ! 2926: register n; ! 2927: n = 5; ! 2928: do { ! 2929: if (*source == '\0') ! 2930: *sink++ = ' '; ! 2931: else ! 2932: *sink++ = *source++; ! 2933: } while (--n); ! 2934: } ! 2935: ! 2936: /* ! 2937: * Look up id in the vocabulary (atab) and return its "definition" ! 2938: * (ktab), or -1 if not found. If init is positive, this is an ! 2939: * initialization call setting up a keyword variable, and not finding ! 2940: * it constitutes a bug. It also means that only ktab values which taken ! 2941: * over 1000 equal init may be considered. Thus "steps", which is a ! 2942: * motion verb as well as an object, may be located as an object. It also ! 2943: * means the ktab value is taken mod 1000. ! 2944: */ ! 2945: vocab (id, init) ! 2946: char *id; ! 2947: { ! 2948: for (i=1; i<=tabsiz; i++) { ! 2949: if (ktab[i] == -1) goto l2; ! 2950: if ((init < 0 || init == ktab[i]/1000) && eqp(atab[i], id)) ! 2951: goto l3; ! 2952: } ! 2953: bug(21); ! 2954: l2: ! 2955: if (init < 0) return -1; ! 2956: bug(5); ! 2957: l3: ! 2958: return init<0? ktab[i]: ktab[i] % 1000; ! 2959: } ! 2960: ! 2961: /* ! 2962: * This program catenates the characters of x and y, which are assumed to ! 2963: * be 5-character fields, into z. The process stops at the first blank, ! 2964: * and a null character is appended to the result. ! 2965: */ ! 2966: a5toa1 (x, y, z) ! 2967: char *x, *y, *z; ! 2968: { ! 2969: register int n; ! 2970: n = 5; ! 2971: do { ! 2972: if (*x == ' ') { ! 2973: *z++ = '\0'; ! 2974: return; ! 2975: } ! 2976: *z++ = *x++; ! 2977: } while (--n); ! 2978: n = 5; ! 2979: do { ! 2980: if (*y == ' ') { ! 2981: *z++ = '\0'; ! 2982: return; ! 2983: } ! 2984: *z++ = *y++; ! 2985: } while (--n); ! 2986: *z++ = '\0'; ! 2987: } ! 2988: ! 2989: /* ! 2990: * Get a command from the terminal. The first word goes into pl and pr, ! 2991: * and the second word goes into ql and qr. In each case the word is ! 2992: * padded with blanks to 10 characters; the first 5 will be in the "l" ! 2993: * variable and the second 5 will be in the "r" variable. ! 2994: * If hungup is nonzero, indicating he hung up the phone, fudge ! 2995: * pl, pr, ql, and qr to make it look as if he typed "suspend". ! 2996: */ ! 2997: getin (pl, pr, ql, qr) ! 2998: char *pl, *pr, *ql, *qr; ! 2999: { ! 3000: register int p; ! 3001: cpy (pl, ""); ! 3002: cpy (pr, ""); ! 3003: cpy (ql, ""); ! 3004: cpy (qr, ""); ! 3005: fflush(stdout); ! 3006: /* Eat blank lines */ ! 3007: if (!hungup) { ! 3008: while ((p = getchar()) == '\n'); ! 3009: while (p == '!') { ! 3010: char pl[512]; ! 3011: if (fgets (pl, sizeof(pl), stdin) == 0) ! 3012: p = EOF; ! 3013: if (strcmp (pwbuf->pw_name, "games") == 0) ! 3014: printf ("No Shell escape from \"games\"\n"); ! 3015: else { ! 3016: system (pl); ! 3017: printf ("!\n"); ! 3018: fflush (stdout); ! 3019: } ! 3020: if (p != EOF) ! 3021: p = getchar(); ! 3022: } ! 3023: if (p == EOF) { ! 3024: cpy (pl, "suspe"); ! 3025: cpy (pr, "nd"); ! 3026: hungup = 1; ! 3027: return; ! 3028: } ! 3029: ungetc (p, stdin); ! 3030: } ! 3031: if (snarf (pl, pr) && snarf (ql, qr)) ! 3032: while (getchar() != '\n'); ! 3033: } ! 3034: ! 3035: /* ! 3036: * This is a subroutine of getin ! 3037: */ ! 3038: snarf (left, right) ! 3039: char *left, *right; ! 3040: { ! 3041: register int n; ! 3042: char s[10]; ! 3043: register int p; ! 3044: /* Blank the array */ ! 3045: for (n=0; n<10; n++) ! 3046: s[n] = ' '; ! 3047: /* If hung up phone, pretend he said 'suspend' followed by nl */ ! 3048: if (hungup) ! 3049: goto susp; ! 3050: /* Skip leading blanks; if nl encountered, return immediately */ ! 3051: while ((p=getchar()) == ' '); ! 3052: if (p == '\n') return 0; ! 3053: if (p == EOF) goto susp; ! 3054: /* Now eat characters until blank or newline */ ! 3055: n = 0; ! 3056: do { ! 3057: if (n < 10) ! 3058: s[n++] = p; ! 3059: p = getchar(); ! 3060: if (p == EOF) goto susp; ! 3061: } while (p != ' ' && p != '\n'); ! 3062: /* Break up the string into two five-character components */ ! 3063: cpy (left, s); ! 3064: cpy (right, s+5); ! 3065: /* Indicate to caller whether we hit a blank or newline */ ! 3066: return p == ' '; ! 3067: /* Abnormal exit for EOF */ ! 3068: susp: ! 3069: cpy (left, "suspe"); ! 3070: cpy (right, "nd"); ! 3071: hungup = 1; ! 3072: return 0; ! 3073: } ! 3074: ! 3075: /* ! 3076: * Print the n-th "random" message (section 6) ! 3077: */ ! 3078: rspeak(n) ! 3079: { ! 3080: if (n != 0) ! 3081: speak (rtext[n]); ! 3082: } ! 3083: ! 3084: /* ! 3085: * Print the message which starts at lines[n] ! 3086: */ ! 3087: speak(n) ! 3088: { ! 3089: long rec; ! 3090: do { ! 3091: rec = lines[n]; ! 3092: if (rec < 0) ! 3093: rec = -rec; ! 3094: fseek (caves, rec, 0); ! 3095: fgets (linebuf, sizeof linebuf, caves); ! 3096: if (linebuf[0] != '>') ! 3097: fputs (linebuf, stdout); ! 3098: } while (++n < linuse && lines[n] >= 0); ! 3099: } ! 3100: ! 3101: /* ! 3102: * Find the skip+1st message from msg and print it. Msg should be ! 3103: * the index of the inventory message for object ! 3104: */ ! 3105: pspeak (msg, skip) ! 3106: { ! 3107: int n, q; ! 3108: q = ptext[msg]; ! 3109: if (skip >= 0) ! 3110: for (n=0; n<=skip; n++) { ! 3111: while (lines[++q] >= 0); ! 3112: } ! 3113: speak(q); ! 3114: } ! 3115: ! 3116: /* ! 3117: * Print message x, wait for yes/no. If yes, print message y and leave ! 3118: * "yea" true; else print message z and leave "yea" false. ! 3119: * If hungup is nonzero, he hung up the phone, so simulate an ! 3120: * answer of "no". ! 3121: */ ! 3122: yes (x, y, z) { ! 3123: char reply[300]; ! 3124: rspeak(x); ! 3125: fflush(stdout); ! 3126: if (scanf ("%s", reply) == EOF) ! 3127: hungup = 1; ! 3128: while (hungup == 0 && reply[0] != 'y' && reply[0] != 'n') { ! 3129: printf ("Please answer the question.\n"); ! 3130: fflush(stdout); ! 3131: if (scanf ("%s", reply) == EOF) ! 3132: hungup = 1; ! 3133: } ! 3134: if (yea = (reply[0] == 'y' && hungup == 0)) { ! 3135: if (y != 0) ! 3136: rspeak(y); ! 3137: } else if (z != 0) ! 3138: rspeak (z); ! 3139: return yea; ! 3140: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.