1 /* $NetBSD: main.c,v 1.8 1997/10/11 01:53:31 lukem 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.8 1997/10/11 01:53:31 lukem 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(NULL); /* 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(0); 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 = <ext[loc]; 116 if (!forced(loc) && dark(0)) { 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(0)) { 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(0); /* 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(0)) 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(argv[0]); /* 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(0)) 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(0); 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(0) != water 612 || !here(bottle))) 613 goto l8000; 614 if (obj != 0 && obj != water) 615 spk = 110; 616 if (spk == 110 || liq(0) != 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(0) == 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(0)) 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(0) == 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 } 773