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