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