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