1 /* $OpenBSD: main.c,v 1.26 2021/01/27 01:59:39 deraadt Exp $ */
2 /* $NetBSD: main.c,v 1.5 1996/05/21 21:53:09 mrg Exp $ */
3
4 /*-
5 * Copyright (c) 1991, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * The game adventure was originally written in Fortran by Will Crowther
9 * and Don Woods. It was later translated to C and enhanced by Jim
10 * Gillogly. This code is derived from software contributed to Berkeley
11 * by Jim Gillogly at The Rand Corporation.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37
38 /* Re-coding of advent in C: main program */
39
40 #include <err.h>
41 #include <stdio.h>
42 #include <time.h>
43 #include <unistd.h>
44
45 #include "extern.h"
46 #include "hdr.h"
47
48 int datfd; /* message file descriptor */
49 volatile sig_atomic_t delhit;
50 int yea;
51
52 int loc, newloc, oldloc, oldlc2, wzdark, gaveup, kq, k, k2;
53 int verb, obj, spk;
54 time_t savet;
55 int mxscor, latncy;
56
57 char wd1[MAXSTR]; /* the complete words */
58 char wd2[MAXSTR];
59
60 struct hashtab voc[HTSIZE];
61
62 struct text rtext[RTXSIZ]; /* random text messages */
63
64 struct text mtext[MAGSIZ]; /* magic messages */
65
66 int clsses;
67 struct text ctext[CLSMAX]; /* classes of adventurer */
68 int cval[CLSMAX];
69
70 struct text ptext[101]; /* object descriptions */
71
72 struct text ltext[LOCSIZ]; /* long loc description */
73 struct text stext[LOCSIZ]; /* short loc descriptions */
74
75 struct travlist *travel[LOCSIZ],*tkk; /* travel is closer to keys(...)*/
76
77 int atloc[LOCSIZ];
78
79 int plac[101]; /* initial object placement */
80 int fixd[101], fixed[101]; /* location fixed? */
81
82 int actspk[35]; /* rtext msg for verb <n> */
83
84 int cond[LOCSIZ]; /* various condition bits */
85
86 int hntmax;
87 int hints[20][5]; /* info on hints */
88 int hinted[20], hintlc[20];
89
90 int place[101], prop[101], linkx[201];
91 int abb[LOCSIZ];
92
93 int maxtrs, tally, tally2; /* treasure values */
94
95 int keys, lamp, grate, cage, rod, rod2, steps, /* mnemonics */
96 bird, door, pillow, snake, fissur, tablet, clam, oyster,
97 magzin, dwarf, knife, food, bottle, water, oil, plant, plant2,
98 axe, mirror, dragon, chasm, troll, troll2, bear, messag,
99 vend, batter, nugget, coins, chest, eggs, tridnt, vase,
100 emrald, pyram, pearl, rug, chain, spices, back, look, cave,
101 null, entrnc, dprssn, enter, stream, pour, say, lock, throw,
102 find, invent;
103
104 int chloc, chloc2, dseen[7], dloc[7], /* dwarf stuff */
105 odloc[7], dflag, daltlc;
106
107 int tk[21], stick, dtotal, attack;
108 int turns, lmwarn, iwest, knfloc, detail, /* various flags & counters */
109 abbnum, maxdie, numdie, holdng, dkill, foobar, bonus, clock1,
110 clock2, saved, closng, panic, closed, scorng;
111
112 int demo, limit;
113
114 int
main(int argc,char * argv[])115 main(int argc, char *argv[])
116 {
117 int i;
118 int rval, ll;
119 struct text *kk;
120
121 if (pledge("stdio rpath wpath cpath", NULL) == -1)
122 err(1, "pledge");
123
124 init(); /* Initialize everything */
125 signal(SIGINT, trapdel);
126
127 if (argc > 1) { /* Restore file specified */
128 /* Restart is label 8305 (Fortran) */
129 i = restore(argv[1]); /* See what we've got */
130 switch (i) {
131 case 0: /* The restore worked fine */
132 yea = Start();
133 k = null;
134 unlink(argv[1]);/* Don't re-use the save */
135 goto l8; /* Get where we're going */
136 case 1: /* Couldn't open it */
137 errx(1, "can't open file"); /* So give up */
138 case 2: /* Oops -- file was altered */
139 rspeak(202); /* You dissolve */
140 return 2; /* File could be non-adventure */
141 } /* So don't unlink it. */
142 }
143
144 startup(); /* prepare for a user */
145
146 for (;;) { /* main command loop (label 2) */
147 if (newloc < 9 && newloc != 0 && closng) {
148 rspeak(130); /* if closing leave only by */
149 newloc = loc; /* main office */
150 if (!panic)
151 clock2 = 15;
152 panic = TRUE;
153 }
154
155 rval = fdwarf(); /* dwarf stuff */
156 if (rval == 99)
157 die(99);
158
159 l2000: if (loc == 0)
160 die(99); /* label 2000 */
161 kk = &stext[loc];
162 if ((abb[loc] % abbnum) ==0 || kk->seekadr == 0)
163 kk = <ext[loc];
164 if (!forced(loc) && dark()) {
165 if (wzdark && pct(35)) {
166 die(90);
167 goto l2000;
168 }
169 kk = &rtext[16];
170 }
171 if (toting(bear))
172 rspeak(141); /* 2001 */
173 speak(kk);
174 k = 1;
175 if (forced(loc))
176 goto l8;
177 if (loc == 33 && pct(25) && !closng)
178 rspeak(8);
179 if (!dark()) {
180 abb[loc]++;
181 for (i = atloc[loc]; i != 0; i = linkx[i]) { /*2004*/
182 obj = i;
183 if (obj > 100)
184 obj -= 100;
185 if (obj == steps && toting(nugget))
186 continue;
187 if (prop[obj] < 0) {
188 if (closed)
189 continue;
190 prop[obj] = 0;
191 if (obj == rug || obj == chain)
192 prop[obj] = 1;
193 tally--;
194 if (tally == tally2 && tally != 0)
195 if (limit > 35)
196 limit = 35;
197 }
198 ll = prop[obj]; /* 2006 */
199 if (obj == steps && loc == fixed[steps])
200 ll = 1;
201 pspeak(obj, ll);
202 } /* 2008 */
203 goto l2012;
204 l2009: k = 54; /* 2009 */
205 l2010: spk = k;
206 l2011: rspeak(spk);
207 }
208 l2012: verb = 0; /* 2012 */
209 obj = 0;
210 l2600: checkhints(); /* to 2600-2602 */
211 if (closed) {
212 if (prop[oyster] < 0 && toting(oyster))
213 pspeak(oyster, 1);
214 for (i = 1; i < 100; i++)
215 if (toting(i) && prop[i] < 0) /* 2604 */
216 prop[i] = -1 - prop[i];
217 }
218 wzdark = dark(); /* 2605 */
219 if (knfloc > 0 && knfloc != loc)
220 knfloc = 1;
221 getin(wd1, sizeof(wd1), wd2, sizeof(wd2));
222 if (delhit) { /* user typed a DEL */
223 delhit = 0; /* reset counter */
224 /* pretend he's quitting */
225 strlcpy(wd1, "quit", sizeof(wd1));
226 wd2[0] = 0;
227 }
228 l2608: if ((foobar = -foobar) > 0)
229 foobar = 0; /* 2608 */
230 /* should check here for "magic mode" */
231 turns++;
232 if (demo && turns >= SHORT)
233 done(1); /* to 13000 */
234
235 if (verb == say && wd2[0] != 0)
236 verb = 0;
237 if (verb == say)
238 goto l4090;
239 if (tally == 0 && loc >= 15 && loc != 33)
240 clock1--;
241 if (clock1 == 0) {
242 closing(); /* to 10000 */
243 goto l19999;
244 }
245 if (clock1 < 0)
246 clock2--;
247 if (clock2 == 0) {
248 caveclose(); /* to 11000 */
249 continue; /* back to 2 */
250 }
251 if (prop[lamp] == 1)
252 limit--;
253 if (limit <= 30 && here(batter) && prop[batter] == 0
254 && here(lamp)) {
255 rspeak(188); /* 12000 */
256 prop[batter] = 1;
257 if (toting(batter))
258 drop(batter, loc);
259 limit += 2500;
260 lmwarn = FALSE;
261 goto l19999;
262 }
263 if (limit == 0) {
264 limit = -1; /* 12400 */
265 prop[lamp] = 0;
266 rspeak(184);
267 goto l19999;
268 }
269 if (limit < 0 && loc <= 8) {
270 rspeak(185); /* 12600 */
271 gaveup = TRUE;
272 done(2); /* to 20000 */
273 }
274 if (limit <= 30) {
275 if (lmwarn || !here(lamp))
276 goto l19999; /*12200*/
277 lmwarn = TRUE;
278 spk = 187;
279 if (place[batter] == 0)
280 spk = 183;
281 if (prop[batter] == 1)
282 spk = 189;
283 rspeak(spk);
284 }
285 l19999: k = 43;
286 if (liqloc(loc) == water)
287 k = 70;
288 if (weq(wd1, "enter") &&
289 (weq(wd2, "strea") || weq(wd2, "water")))
290 goto l2010;
291 if (weq(wd1, "enter") && *wd2 != 0)
292 goto l2800;
293 if ((!weq(wd1, "water") && !weq(wd1, "oil"))
294 || (!weq(wd2, "plant") && !weq(wd2, "door")))
295 goto l2610;
296 if (at(vocab(wd2, 1, 0)))
297 strlcpy(wd2, "pour", sizeof(wd2));
298
299 l2610: if (weq(wd1, "west"))
300 if (++iwest == 10)
301 rspeak(17);
302 l2630: i = vocab(wd1, -1, 0);
303 if (i== -1) {
304 spk = 60; /* 3000 */
305 if (pct(20))
306 spk = 61;
307 if (pct(20))
308 spk = 13;
309 rspeak(spk);
310 goto l2600;
311 }
312 k = i % 1000;
313 kq = i / 1000 + 1;
314 switch (kq) {
315 case 1: goto l8;
316 case 2: goto l5000;
317 case 3: goto l4000;
318 case 4: goto l2010;
319 default:
320 bug(22);
321 }
322
323 l8:
324 switch (march()) {
325 case 2: continue; /* i.e. goto l2 */
326 case 99:
327 die(99);
328 goto l2000;
329 default: bug(110);
330 }
331
332 l2800: strlcpy(wd1, wd2, sizeof(wd1));
333 wd2[0] = 0;
334 goto l2610;
335
336 l4000: verb = k;
337 spk = actspk[verb];
338 if (wd2[0] != 0 && verb != say)
339 goto l2800;
340 if (verb == say)
341 obj = wd2[0];
342 if (obj != 0)
343 goto l4090;
344
345 switch (verb) {
346 case 1: /* take = 8010 */
347 if (atloc[loc] == 0 || linkx[atloc[loc]] != 0)
348 goto l8000;
349 for (i = 1; i <= 5; i++)
350 if (dloc[i] == loc && dflag >= 2)
351 goto l8000;
352 obj = atloc[loc];
353 goto l9010;
354 case 2: case 3: case 9: /* 8000 : drop, say, wave */
355 case 10: case 16: case 17: /* calm, rub, toss */
356 case 19: case 21: case 28: /* find, feed, break */
357 case 29: /* wake */
358 l8000: printf("%s what?\n", wd1);
359 obj = 0;
360 goto l2600;
361 case 4: case 6: /* 8040 open, lock */
362 spk = 28;
363 if (here(clam))
364 obj = clam;
365 if (here(oyster))
366 obj = oyster;
367 if (at(door))
368 obj = door;
369 if (at(grate))
370 obj = grate;
371 if (obj != 0 && here(chain))
372 goto l8000;
373 if (here(chain))
374 obj = chain;
375 if (obj == 0)
376 goto l2011;
377 goto l9040;
378 case 5: goto l2009; /* nothing */
379 case 7: goto l9070; /* on */
380 case 8: goto l9080; /* off */
381 case 11: goto l8000; /* walk */
382 case 12: goto l9120; /* kill */
383 case 13: goto l9130; /* pour */
384 case 14: /* eat: 8140 */
385 if (!here(food))
386 goto l8000;
387 l8142: dstroy(food);
388 spk = 72;
389 goto l2011;
390 case 15: goto l9150; /* drink */
391 case 18: /* quit: 8180 */
392 gaveup = yes(22, 54, 54);
393 if (gaveup)
394 done(2); /* 8185 */
395 goto l2012;
396 case 20: /* invent = 8200 */
397 spk = 98;
398 for (i = 1; i <= 100; i++) {
399 if (i != bear && toting(i)) {
400 if (spk == 98)
401 rspeak(99);
402 blklin = FALSE;
403 pspeak(i, -1);
404 blklin = TRUE;
405 spk = 0;
406 }
407 }
408 if (toting(bear))
409 spk = 141;
410 goto l2011;
411 case 22: goto l9220; /* fill */
412 case 23: goto l9230; /* blast */
413 case 24: /* score: 8240 */
414 scorng = TRUE;
415 printf("If you were to quit now, you would score");
416 printf(" %d out of a possible ", score());
417 printf("%d.", mxscor);
418 scorng = FALSE;
419 gaveup = yes(143, 54, 54);
420 if (gaveup)
421 done(2);
422 goto l2012;
423 case 25: /* foo: 8250 */
424 k = vocab(wd1, 3, 0);
425 spk = 42;
426 if (foobar == 1 - k)
427 goto l8252;
428 if (foobar != 0)
429 spk = 151;
430 goto l2011;
431 l8252: foobar = k;
432 if (k != 4)
433 goto l2009;
434 foobar = 0;
435 if (place[eggs] == plac[eggs]
436 || (toting(eggs) && loc == plac[eggs])) goto l2011;
437 if (place[eggs] == 0 && place[troll] == 0 && prop[troll] == 0)
438 prop[troll] = 1;
439 k = 2;
440 if (here(eggs))
441 k = 1;
442 if (loc == plac[eggs])
443 k = 0;
444 move(eggs, plac[eggs]);
445 pspeak(eggs, k);
446 goto l2012;
447 case 26: /* brief = 8260 */
448 spk = 156;
449 abbnum = 10000;
450 detail = 3;
451 goto l2011;
452 case 27: /* read = 8270 */
453 if (here(magzin))
454 obj = magzin;
455 if (here(tablet))
456 obj = obj * 100 + tablet;
457 if (here(messag))
458 obj = obj * 100 + messag;
459 if (closed && toting(oyster))
460 obj = oyster;
461 if (obj > 100 || obj == 0 || dark())
462 goto l8000;
463 goto l9270;
464 case 30: /* suspend = 8300 */
465 spk = 201;
466 if (demo)
467 goto l2011;
468 printf("I can suspend your adventure for you so");
469 printf(" you can resume later, but\n");
470 printf("you will have to wait at least");
471 printf(" %d minutes before continuing.", latncy);
472 if (!yes(200, 54, 54))
473 goto l2012;
474 time(&savet);
475 ciao(); /* Do we quit? */
476 continue; /* Maybe not */
477 case 31: /* hours = 8310 */
478 printf("Colossal cave is closed 9am-5pm Mon ");
479 printf("through Fri except holidays.\n");
480 goto l2012;
481 default:
482 bug(23);
483 }
484
485 l4090:
486 switch (verb) {
487 case 1: /* take = 9010 */
488 l9010: switch (trtake()) {
489 case 2011: goto l2011;
490 case 9220: goto l9220;
491 case 2009: goto l2009;
492 case 2012: goto l2012;
493 default: bug(102);
494 }
495 l9020: case 2: /* drop = 9020 */
496 switch (trdrop()) {
497 case 2011: goto l2011;
498 case 19000: done(3);
499 case 2012: goto l2012;
500 default: bug(105);
501 }
502 case 3:
503 switch (trsay()) {
504 case 2012: goto l2012;
505 case 2630: goto l2630;
506 default: bug(107);
507 }
508 l9040: case 4: case 6: /* open, close */
509 switch (tropen()) {
510 case 2011: goto l2011;
511 case 2010: goto l2010;
512 default: bug(106);
513 }
514 case 5: goto l2009; /* nothing */
515 case 7: /* on 9070 */
516 l9070: if (!here(lamp))
517 goto l2011;
518 spk = 184;
519 if (limit < 0)
520 goto l2011;
521 prop[lamp] = 1;
522 rspeak(39);
523 if (wzdark)
524 goto l2000;
525 goto l2012;
526
527 case 8: /* off */
528 l9080: if (!here(lamp))
529 goto l2011;
530 prop[lamp] = 0;
531 rspeak(40);
532 if (dark())
533 rspeak(16);
534 goto l2012;
535
536 case 9: /* wave */
537 if ((!toting(obj)) && (obj != rod || !toting(rod2)))
538 spk = 29;
539 if (obj != rod || !at(fissur)||!toting(obj) || closng)
540 goto l2011;
541 prop[fissur] = 1-prop[fissur];
542 pspeak(fissur, 2-prop[fissur]);
543 goto l2012;
544 case 10: case 11: case 18: /* calm, walk, quit */
545 case 24: case 25: case 26: /* score, foo, brief */
546 case 30: case 31: /* suspend, hours */
547 goto l2011;
548 l9120: case 12: /* kill */
549 switch (trkill()) {
550 case 8000: goto l8000;
551 case 8: goto l8;
552 case 2011: goto l2011;
553 case 2608: goto l2608;
554 case 19000: done(3);
555 default: bug(112);
556 }
557 l9130: case 13: /* pour */
558 if (obj == bottle || obj == 0)
559 obj = liq();
560 if (obj == 0)
561 goto l8000;
562 if (!toting(obj))
563 goto l2011;
564 spk = 78;
565 if (obj != oil && obj != water)
566 goto l2011;
567 prop[bottle] = 1;
568 place[obj] = 0;
569 spk = 77;
570 if (!(at(plant) || at(door)))
571 goto l2011;
572 if (at(door)) {
573 prop[door] = 0; /* 9132 */
574 if (obj == oil)
575 prop[door] = 1;
576 spk = 113 + prop[door];
577 goto l2011;
578 }
579 spk = 112;
580 if (obj != water)
581 goto l2011;
582 pspeak(plant, prop[plant] + 1);
583 prop[plant] = (prop[plant] + 2) % 6;
584 prop[plant2] = prop[plant] / 2;
585 k = null;
586 goto l8;
587 case 14: /* 9140 - eat */
588 if (obj == food)
589 goto l8142;
590 if (obj == bird || obj == snake || obj == clam || obj == oyster
591 || obj == dwarf || obj == dragon || obj == troll
592 || obj == bear) spk = 71;
593 goto l2011;
594 l9150: case 15: /* 9150 - drink */
595 if (obj == 0 && liqloc(loc) != water && (liq() != water
596 || !here(bottle)))
597 goto l8000;
598 if (obj != 0 && obj != water)
599 spk = 110;
600 if (spk == 110 || liq() != water || !here(bottle))
601 goto l2011;
602 prop[bottle] = 1;
603 place[water] = 0;
604 spk = 74;
605 goto l2011;
606 case 16: /* 9160: rub */
607 if (obj != lamp)
608 spk = 76;
609 goto l2011;
610 case 17: /* 9170: throw */
611 switch (trtoss()) {
612 case 2011: goto l2011;
613 case 9020: goto l9020;
614 case 9120: goto l9120;
615 case 8: goto l8;
616 case 9210: goto l9210;
617 default: bug(113);
618 }
619 case 19: case 20: /* 9190: find, invent */
620 if (at(obj) || (liq() == obj && at(bottle))
621 || k == liqloc(loc))
622 spk = 94;
623 for (i = 1; i <= 5; i++)
624 if (dloc[i] == loc && dflag >= 2 && obj == dwarf)
625 spk = 94;
626 if (closed)
627 spk = 138;
628 if (toting(obj))
629 spk = 24;
630 goto l2011;
631 l9210: case 21: /* feed */
632 switch (trfeed()) {
633 case 2011: goto l2011;
634 default: bug(114);
635 }
636 l9220: case 22: /* fill */
637 switch (trfill()) {
638 case 2011: goto l2011;
639 case 8000: goto l8000;
640 case 9020: goto l9020;
641 default: bug(115);
642 }
643 l9230: case 23: /* blast */
644 if (prop[rod2] < 0 || !closed)
645 goto l2011;
646 bonus = 133;
647 if (loc == 115)
648 bonus = 134;
649 if (here(rod2))
650 bonus = 135;
651 rspeak(bonus);
652 done(2);
653 l9270: case 27: /* read */
654 if (dark())
655 goto l5190;
656 if (obj == magzin)
657 spk = 190;
658 if (obj == tablet)
659 spk = 196;
660 if (obj == messag)
661 spk = 191;
662 if (obj == oyster && hinted[2] && toting(oyster))
663 spk = 194;
664 if (obj != oyster || hinted[2] || !toting(oyster)
665 || !closed) goto l2011;
666 hinted[2] = yes(192, 193, 54);
667 goto l2012;
668 case 28: /* break */
669 if (obj == mirror)
670 spk = 148;
671 if (obj == vase && prop[vase] == 0) {
672 spk = 198;
673 if (toting(vase))
674 drop(vase, loc);
675 prop[vase] = 2;
676 fixed[vase] = -1;
677 goto l2011;
678 }
679 if (obj != mirror||!closed)
680 goto l2011;
681 rspeak(197);
682 done(3);
683 case 29: /* wake */
684 if (obj != dwarf||!closed)
685 goto l2011;
686 rspeak(199);
687 done(3);
688
689 default: bug(24);
690 }
691
692 l5000:
693 obj = k;
694 if (fixed[k] != loc && !here(k))
695 goto l5100;
696 l5010: if (wd2[0] != 0)
697 goto l2800;
698 if (verb != 0)
699 goto l4090;
700 printf("What do you want to do with the %s?\n", wd1);
701 goto l2600;
702 l5100: if (k != grate)
703 goto l5110;
704 if (loc == 1 || loc == 4 || loc == 7)
705 k = dprssn;
706 if (loc > 9 && loc < 15)
707 k = entrnc;
708 if (k != grate)
709 goto l8;
710 l5110: if (k != dwarf)
711 goto l5120;
712 for (i = 1; i <= 5; i++)
713 if (dloc[i] == loc && dflag >= 2)
714 goto l5010;
715 l5120: if ((liq() == k && here(bottle)) || k == liqloc(loc))
716 goto l5010;
717 if (obj != plant || !at(plant2) || prop[plant2] == 0)
718 goto l5130;
719 obj = plant2;
720 goto l5010;
721 l5130: if (obj != knife || knfloc != loc)
722 goto l5140;
723 knfloc = -1;
724 spk = 116;
725 goto l2011;
726 l5140: if (obj != rod || !here(rod2))
727 goto l5190;
728 obj = rod2;
729 goto l5010;
730 l5190: if ((verb == find || verb == invent) && wd2[0] == 0)
731 goto l5010;
732 printf("I see no %s here\n", wd1);
733 goto l2012;
734 }
735 }
736