|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1989 The Regents of the University of California. ! 3: * Copyright (c) 1989 Dave Taylor, Intuitive Systems. ! 4: * All rights reserved. ! 5: * ! 6: * This code is derived from software contributed to Berkeley by ! 7: * Dave Taylor, of Intuitive Systems. ! 8: * ! 9: * Redistribution and use in source and binary forms are permitted provided ! 10: * that: (1) source distributions retain this entire copyright notice and ! 11: * comment, and (2) distributions including binaries display the following ! 12: * acknowledgement: ``This product includes software developed by the ! 13: * University of California, Berkeley and its contributors'' in the ! 14: * documentation or other materials provided with the distribution and in ! 15: * all advertising materials mentioning features or use of this software. ! 16: * Neither the name of the University nor the names of its contributors may ! 17: * be used to endorse or promote products derived from this software without ! 18: * specific prior written permission. ! 19: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 20: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 21: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 22: LAR PURPOSE. ! 23: */ ! 24: ! 25: #ifndef lint ! 26: char copyright[] = ! 27: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ ! 28: All rights reserved.\n"; ! 29: #endif /* not lint */ ! 30: ! 31: #ifndef lint ! 32: static char sccsid[] = "@(#)wump.c 4.3 (Berkeley) 6/1/90"; ! 33: #endif /* not lint */ ! 34: ! 35: /* ! 36: * A very new version of the age old favorite Hunt-The-Wumpus game that has ! 37: * been a part of the BSD distribution of Unix for longer than us old folk ! 38: * would care to remember. ! 39: */ ! 40: ! 41: #include <sys/types.h> ! 42: #include <sys/file.h> ! 43: #include <stdio.h> ! 44: #include "pathnames.h" ! 45: ! 46: /* some defines to spec out what our wumpus cave should look like */ ! 47: ! 48: #define MAX_ARROW_SHOT_DISTANCE 6 /* +1 for '0' stopper */ ! 49: #define MAX_LINKS_IN_ROOM 25 /* a complex cave */ ! 50: ! 51: #define MAX_ROOMS_IN_CAVE 250 ! 52: #define ROOMS_IN_CAVE 20 ! 53: #define MIN_ROOMS_IN_CAVE 10 ! 54: ! 55: #define LINKS_IN_ROOM 3 ! 56: #define NUMBER_OF_ARROWS 5 ! 57: #define PIT_COUNT 3 ! 58: #define BAT_COUNT 3 ! 59: ! 60: #define EASY 1 /* levels of play */ ! 61: #define HARD 2 ! 62: ! 63: /* some macro definitions for cleaner output */ ! 64: ! 65: #define plural(n) (n == 1 ? "" : "s") ! 66: ! 67: /* simple cave data structure; +1 so we can index from '1' not '0' */ ! 68: struct room_record { ! 69: int tunnel[MAX_LINKS_IN_ROOM]; ! 70: int has_a_pit, has_a_bat; ! 71: } cave[MAX_ROOMS_IN_CAVE+1]; ! 72: ! 73: /* ! 74: * global variables so we can keep track of where the player is, how ! 75: * many arrows they still have, where el wumpo is, and so on... ! 76: */ ! 77: int player_loc = -1; /* player location */ ! 78: int wumpus_loc = -1; /* The Bad Guy location */ ! 79: int level = EASY; /* level of play */ ! 80: int arrows_left; /* arrows unshot */ ! 81: ! 82: #ifdef DEBUG ! 83: int debug = 0; ! 84: #endif ! 85: ! 86: int pit_num = PIT_COUNT; /* # pits in cave */ ! 87: int bat_num = BAT_COUNT; /* # bats */ ! 88: int room_num = ROOMS_IN_CAVE; /* # rooms in cave */ ! 89: int link_num = LINKS_IN_ROOM; /* links per room */ ! 90: int arrow_num = NUMBER_OF_ARROWS; /* arrow inventory */ ! 91: ! 92: char answer[20]; /* user input */ ! 93: ! 94: main(argc, argv) ! 95: int argc; ! 96: char **argv; ! 97: { ! 98: extern char *optarg; ! 99: int c; ! 100: ! 101: #ifdef DEBUG ! 102: while ((c = getopt(argc, argv, "a:b:hp:r:t:d")) != EOF) ! 103: #else ! 104: while ((c = getopt(argc, argv, "a:b:hp:r:t:")) != EOF) ! 105: #endif ! 106: switch (c) { ! 107: case 'a': ! 108: arrow_num = atoi(optarg); ! 109: break; ! 110: case 'b': ! 111: bat_num = atoi(optarg); ! 112: break; ! 113: #ifdef DEBUG ! 114: case 'd': ! 115: debug = 1; ! 116: break; ! 117: #endif ! 118: case 'h': ! 119: level = HARD; ! 120: break; ! 121: case 'p': ! 122: pit_num = atoi(optarg); ! 123: break; ! 124: case 'r': ! 125: room_num = atoi(optarg); ! 126: if (room_num < MIN_ROOMS_IN_CAVE) { ! 127: (void)fprintf(stderr, ! 128: "No self-respecting wumpus would live in such a small cave!\n"); ! 129: exit(1); ! 130: } ! 131: if (room_num > MAX_ROOMS_IN_CAVE) { ! 132: (void)fprintf(stderr, ! 133: "Even wumpii can't furnish caves that large!\n"); ! 134: exit(1); ! 135: } ! 136: break; ! 137: case 't': ! 138: link_num = atoi(optarg); ! 139: if (link_num < 2) { ! 140: (void)fprintf(stderr, ! 141: "Wumpii like extra doors in their caves!\n"); ! 142: exit(1); ! 143: } ! 144: break; ! 145: case '?': ! 146: default: ! 147: usage(); ! 148: } ! 149: ! 150: if (link_num > MAX_LINKS_IN_ROOM || ! 151: link_num > room_num - (room_num / 4)) { ! 152: (void)fprintf(stderr, ! 153: "Too many tunnels! The cave collapsed!\n(Fortunately, the wumpus escaped!)\n"); ! 154: exit(1); ! 155: } ! 156: ! 157: if (level == HARD) { ! 158: bat_num += ((random() % (room_num / 2)) + 1); ! 159: pit_num += ((random() % (room_num / 2)) + 1); ! 160: } ! 161: ! 162: if (bat_num > room_num / 2) { ! 163: (void)fprintf(stderr, ! 164: "The wumpus refused to enter the cave, claiming it was too crowded!\n"); ! 165: exit(1); ! 166: } ! 167: ! 168: if (pit_num > room_num / 2) { ! 169: (void)fprintf(stderr, ! 170: "The wumpus refused to enter the cave, claiming it was too dangerous!\n"); ! 171: exit(1); ! 172: } ! 173: ! 174: instructions(); ! 175: cave_init(); ! 176: ! 177: /* and we're OFF! da dum, da dum, da dum, da dum... */ ! 178: (void)printf( ! 179: "\nYou're in a cave with %d rooms and %d tunnels leading from each room.\n\ ! 180: There are %d bat%s and %d pit%s scattered throughout the cave, and your\n\ ! 181: quiver holds %d custom super anti-evil Wumpus arrows. Good luck.\n", ! 182: room_num, link_num, bat_num, plural(bat_num), pit_num, ! 183: plural(pit_num), arrow_num); ! 184: ! 185: for (;;) { ! 186: initialize_things_in_cave(); ! 187: arrows_left = arrow_num; ! 188: do { ! 189: display_room_stats(); ! 190: (void)printf("Move or shoot? (m-s) "); ! 191: (void)fflush(stdout); ! 192: if (!fgets(answer, sizeof(answer), stdin)) ! 193: break; ! 194: } while (!take_action()); ! 195: ! 196: if (!getans("\nCare to play another game? (y-n) ")) ! 197: exit(0); ! 198: if (getans("In the same cave? (y-n) ")) ! 199: clear_things_in_cave(); ! 200: else ! 201: cave_init(); ! 202: } ! 203: /* NOTREACHED */ ! 204: } ! 205: ! 206: display_room_stats() ! 207: { ! 208: register int i; ! 209: ! 210: /* ! 211: * Routine will explain what's going on with the current room, as well ! 212: * as describe whether there are pits, bats, & wumpii nearby. It's ! 213: * all pretty mindless, really. ! 214: */ ! 215: (void)printf( ! 216: "\nYou are in room %d of the cave, and have %d arrow%s left.\n", ! 217: player_loc, arrows_left, plural(arrows_left)); ! 218: ! 219: if (bats_nearby()) ! 220: (void)printf("*rustle* *rustle* (must be bats nearby)\n"); ! 221: if (pit_nearby()) ! 222: (void)printf("*whoosh* (I feel a draft from some pits).\n"); ! 223: if (wump_nearby()) ! 224: (void)printf("*sniff* (I can smell the evil Wumpus nearby!)\n"); ! 225: ! 226: (void)printf("There are tunnels to rooms %d, ", ! 227: cave[player_loc].tunnel[0]); ! 228: ! 229: for (i = 1; i < link_num - 1; i++) ! 230: if (cave[player_loc].tunnel[i] <= room_num) ! 231: (void)printf("%d, ", cave[player_loc].tunnel[i]); ! 232: (void)printf("and %d.\n", cave[player_loc].tunnel[link_num - 1]); ! 233: } ! 234: ! 235: take_action() ! 236: { ! 237: /* ! 238: * Do the action specified by the player, either 'm'ove, 's'hoot ! 239: * or something exceptionally bizarre and strange! Returns 1 ! 240: * iff the player died during this turn, otherwise returns 0. ! 241: */ ! 242: switch (*answer) { ! 243: case 'M': ! 244: case 'm': /* move */ ! 245: return(move_to(answer + 1)); ! 246: case 'S': ! 247: case 's': /* shoot */ ! 248: return(shoot(answer + 1)); ! 249: case 'Q': ! 250: case 'q': ! 251: case 'x': ! 252: exit(0); ! 253: case '\n': ! 254: return(0); ! 255: } ! 256: if (random() % 15 == 1) ! 257: (void)printf("Que pasa?\n"); ! 258: else ! 259: (void)printf("I don't understand!\n"); ! 260: return(0); ! 261: } ! 262: ! 263: move_to(room_number) ! 264: char *room_number; ! 265: { ! 266: int i, just_moved_by_bats, next_room, tunnel_available; ! 267: ! 268: /* ! 269: * This is responsible for moving the player into another room in the ! 270: * cave as per their directions. If room_number is a null string, ! 271: * then we'll prompt the user for the next room to go into. Once ! 272: * we've moved into the room, we'll check for things like bats, pits, ! 273: * and so on. This routine returns 1 if something occurs that kills ! 274: * the player and 0 otherwise... ! 275: */ ! 276: tunnel_available = just_moved_by_bats = 0; ! 277: next_room = atoi(room_number); ! 278: ! 279: /* crap for magic tunnels */ ! 280: if (next_room == room_num + 1 && ! 281: cave[player_loc].tunnel[link_num-1] != next_room) ! 282: ++next_room; ! 283: ! 284: while (next_room < 1 || next_room > room_num + 1) { ! 285: if (next_room < 0 && next_room != -1) ! 286: (void)printf("Sorry, but we're constrained to a semi-Euclidean cave!\n"); ! 287: if (next_room > room_num + 1) ! 288: (void)printf("What? The cave surely isn't quite that big!\n"); ! 289: if (next_room == room_num + 1 && ! 290: cave[player_loc].tunnel[link_num-1] != next_room) { ! 291: (void)printf("What? The cave isn't that big!\n"); ! 292: ++next_room; ! 293: } ! 294: (void)printf("To which room do you wish to move? "); ! 295: (void)fflush(stdout); ! 296: if (!fgets(answer, sizeof(answer), stdin)) ! 297: return(1); ! 298: next_room = atoi(answer); ! 299: } ! 300: ! 301: /* now let's see if we can move to that room or not */ ! 302: tunnel_available = 0; ! 303: for (i = 0; i < link_num; i++) ! 304: if (cave[player_loc].tunnel[i] == next_room) ! 305: tunnel_available = 1; ! 306: ! 307: if (!tunnel_available) { ! 308: (void)printf("*Oof!* (You hit the wall)\n"); ! 309: if (random() % 6 == 1) { ! 310: (void)printf("Your colorful comments awaken the wumpus!\n"); ! 311: move_wump(); ! 312: if (wumpus_loc == player_loc) { ! 313: wump_kill(); ! 314: return(1); ! 315: } ! 316: } ! 317: return(0); ! 318: } ! 319: ! 320: /* now let's move into that room and check it out for dangers */ ! 321: if (next_room == room_num + 1) ! 322: jump(next_room = (random() % room_num) + 1); ! 323: ! 324: player_loc = next_room; ! 325: for (;;) { ! 326: if (next_room == wumpus_loc) { /* uh oh... */ ! 327: wump_kill(); ! 328: return(1); ! 329: } ! 330: if (cave[next_room].has_a_pit) ! 331: if (random() % 12 < 2) { ! 332: pit_survive(); ! 333: return(0); ! 334: } else { ! 335: pit_kill(); ! 336: return(1); ! 337: } ! 338: ! 339: if (cave[next_room].has_a_bat) { ! 340: (void)printf( ! 341: "*flap* *flap* *flap* (humongous bats pick you up and move you%s!)\n", ! 342: just_moved_by_bats ? " again": ""); ! 343: next_room = player_loc = (random() % room_num) + 1; ! 344: just_moved_by_bats = 1; ! 345: } ! 346: ! 347: else ! 348: break; ! 349: } ! 350: return(0); ! 351: } ! 352: ! 353: shoot(room_list) ! 354: char *room_list; ! 355: { ! 356: int chance, next, roomcnt; ! 357: int j, arrow_location, link, ok; ! 358: char *p, *strtok(); ! 359: ! 360: /* ! 361: * Implement shooting arrows. Arrows are shot by the player indicating ! 362: * a space-separated list of rooms that the arrow should pass through; ! 363: * if any of the rooms they specify are not accessible via tunnel from ! 364: * the room the arrow is in, it will instead fly randomly into another ! 365: * room. If the player hits the wumpus, this routine will indicate ! 366: * such. If it misses, this routine will *move* the wumpus one room. ! 367: * If it's the last arrow, the player then dies... Returns 1 if the ! 368: * player has won or died, 0 if nothing has happened. ! 369: */ ! 370: arrow_location = player_loc; ! 371: for (roomcnt = 1;; ++roomcnt, room_list = NULL) { ! 372: if (!(p = strtok(room_list, " \t\n"))) ! 373: if (roomcnt == 1) { ! 374: (void)printf( ! 375: "The arrow falls to the ground at your feet!\n"); ! 376: return(0); ! 377: } else ! 378: break; ! 379: if (roomcnt > 5) { ! 380: (void)printf( ! 381: "The arrow wavers in its flight and and can go no further!\n"); ! 382: break; ! 383: } ! 384: next = atoi(p); ! 385: for (j = 0, ok = 0; j < link_num; j++) ! 386: if (cave[arrow_location].tunnel[j] == next) ! 387: ok = 1; ! 388: ! 389: if (ok) { ! 390: if (next > room_num) { ! 391: (void)printf( ! 392: "A faint gleam tells you the arrow has gone through a magic tunnel!\n"); ! 393: arrow_location = (random() % room_num) + 1; ! 394: } else ! 395: arrow_location = next; ! 396: } else { ! 397: link = (random() % link_num); ! 398: if (link == player_loc) ! 399: (void)printf( ! 400: "*thunk* The arrow can't find a way from %d to %d and flys back into\n\ ! 401: your room!\n", ! 402: arrow_location, next); ! 403: else if (cave[arrow_location].tunnel[link] > room_num) ! 404: (void)printf( ! 405: "*thunk* The arrow flys randomly into a magic tunnel, thence into\n\ ! 406: room %d!\n", ! 407: cave[arrow_location].tunnel[link]); ! 408: else ! 409: (void)printf( ! 410: "*thunk* The arrow can't find a way from %d to %d and flys randomly\n\ ! 411: into room %d!\n", ! 412: arrow_location, next, ! 413: cave[arrow_location].tunnel[link]); ! 414: arrow_location = cave[arrow_location].tunnel[link]; ! 415: break; ! 416: } ! 417: chance = random() % 10; ! 418: if (roomcnt == 3 && chance < 2) { ! 419: (void)printf( ! 420: "Your bowstring breaks! *twaaaaaang*\n\ ! 421: The arrow is weakly shot and can go no further!\n"); ! 422: break; ! 423: } else if (roomcnt == 4 && chance < 6) { ! 424: (void)printf( ! 425: "The arrow wavers in its flight and and can go no further!\n"); ! 426: break; ! 427: } ! 428: } ! 429: ! 430: /* ! 431: * now we've gotten into the new room let us see if El Wumpo is ! 432: * in the same room ... if so we've a HIT and the player WON! ! 433: */ ! 434: if (arrow_location == wumpus_loc) { ! 435: kill_wump(); ! 436: return(1); ! 437: } ! 438: ! 439: if (arrow_location == player_loc) { ! 440: shoot_self(); ! 441: return(1); ! 442: } ! 443: ! 444: if (!--arrows_left) { ! 445: no_arrows(); ! 446: return(1); ! 447: } ! 448: ! 449: { ! 450: /* each time you shoot, it's more likely the wumpus moves */ ! 451: static int lastchance = 2; ! 452: ! 453: if (random() % level == EASY ? 12 : 9 < (lastchance += 2)) { ! 454: move_wump(); ! 455: if (wumpus_loc == player_loc) ! 456: wump_kill(); ! 457: lastchance = random() % 3; ! 458: ! 459: } ! 460: } ! 461: return(0); ! 462: } ! 463: ! 464: cave_init() ! 465: { ! 466: register int i, j, k, link; ! 467: int delta, int_compare(); ! 468: time_t time(); ! 469: ! 470: /* ! 471: * This does most of the interesting work in this program actually! ! 472: * In this routine we'll initialize the Wumpus cave to have all rooms ! 473: * linking to all others by stepping through our data structure once, ! 474: * recording all forward links and backwards links too. The parallel ! 475: * "linkcount" data structure ensures that no room ends up with more ! 476: * than three links, regardless of the quality of the random number ! 477: * generator that we're using. ! 478: */ ! 479: srandom((int)time((time_t *)0)); ! 480: ! 481: /* initialize the cave first off. */ ! 482: for (i = 1; i <= room_num; ++i) ! 483: for (j = 0; j < link_num ; ++j) ! 484: cave[i].tunnel[j] = -1; ! 485: ! 486: /* choose a random 'hop' delta for our guaranteed link */ ! 487: while (!(delta = random() % room_num)); ! 488: ! 489: for (i = 1; i <= room_num; ++i) { ! 490: link = ((i + delta) % room_num) + 1; /* connection */ ! 491: cave[i].tunnel[0] = link; /* forw link */ ! 492: cave[link].tunnel[1] = i; /* back link */ ! 493: } ! 494: /* now fill in the rest of the cave with random connections */ ! 495: for (i = 1; i <= room_num; i++) ! 496: for (j = 2; j < link_num ; j++) { ! 497: if (cave[i].tunnel[j] != -1) ! 498: continue; ! 499: try_again: link = (random() % room_num) + 1; ! 500: /* skip duplicates */ ! 501: for (k = 0; k < j; k++) ! 502: if (cave[i].tunnel[k] == link) ! 503: goto try_again; ! 504: cave[i].tunnel[j] = link; ! 505: if (random() % 2 == 1) ! 506: continue; ! 507: for (k = 0; k < link_num; ++k) { ! 508: /* if duplicate, skip it */ ! 509: if (cave[link].tunnel[k] == i) ! 510: k = link_num; ! 511: ! 512: /* if open link, use it, force exit */ ! 513: if (cave[link].tunnel[k] == -1) { ! 514: cave[link].tunnel[k] = i; ! 515: k = link_num; ! 516: } ! 517: } ! 518: } ! 519: /* ! 520: * now that we're done, sort the tunnels in each of the rooms to ! 521: * make it easier on the intrepid adventurer. ! 522: */ ! 523: for (i = 1; i <= room_num; ++i) ! 524: qsort(cave[i].tunnel, (u_int)link_num, ! 525: sizeof(cave[i].tunnel[0]), int_compare); ! 526: ! 527: #ifdef DEBUG ! 528: if (debug) ! 529: for (i = 1; i <= room_num; ++i) { ! 530: (void)printf("<room %d has tunnels to ", i); ! 531: for (j = 0; j < link_num; ++j) ! 532: (void)printf("%d ", cave[i].tunnel[j]); ! 533: (void)printf(">\n"); ! 534: } ! 535: #endif ! 536: } ! 537: ! 538: clear_things_in_cave() ! 539: { ! 540: register int i; ! 541: ! 542: /* ! 543: * remove bats and pits from the current cave in preparation for us ! 544: * adding new ones via the initialize_things_in_cave() routines. ! 545: */ ! 546: for (i = 1; i <= room_num; ++i) ! 547: cave[i].has_a_bat = cave[i].has_a_pit = 0; ! 548: } ! 549: ! 550: initialize_things_in_cave() ! 551: { ! 552: register int i, loc; ! 553: ! 554: /* place some bats, pits, the wumpus, and the player. */ ! 555: for (i = 0; i < bat_num; ++i) { ! 556: do { ! 557: loc = (random() % room_num) + 1; ! 558: } while (cave[loc].has_a_bat); ! 559: cave[loc].has_a_bat = 1; ! 560: #ifdef DEBUG ! 561: if (debug) ! 562: (void)printf("<bat in room %d>\n", loc); ! 563: #endif ! 564: } ! 565: ! 566: for (i = 0; i < pit_num; ++i) { ! 567: do { ! 568: loc = (random() % room_num) + 1; ! 569: } while (cave[loc].has_a_pit && cave[loc].has_a_bat); ! 570: cave[loc].has_a_pit = 1; ! 571: #ifdef DEBUG ! 572: if (debug) ! 573: (void)printf("<pit in room %d>\n", loc); ! 574: #endif ! 575: } ! 576: ! 577: wumpus_loc = (random() % room_num) + 1; ! 578: #ifdef DEBUG ! 579: if (debug) ! 580: (void)printf("<wumpus in room %d>\n", loc); ! 581: #endif ! 582: ! 583: do { ! 584: player_loc = (random() % room_num) + 1; ! 585: } while (player_loc == wumpus_loc || (level == HARD ? ! 586: (link_num / room_num < 0.4 ? wump_nearby() : 0) : 0)); ! 587: } ! 588: ! 589: getans(prompt) ! 590: char *prompt; ! 591: { ! 592: char buf[20]; ! 593: ! 594: /* ! 595: * simple routine to ask the yes/no question specified until the user ! 596: * answers yes or no, then return 1 if they said 'yes' and 0 if they ! 597: * answered 'no'. ! 598: */ ! 599: for (;;) { ! 600: (void)printf("%s", prompt); ! 601: (void)fflush(stdout); ! 602: if (!fgets(buf, sizeof(buf), stdin)) ! 603: return(0); ! 604: if (*buf == 'N' || *buf == 'n') ! 605: return(0); ! 606: if (*buf == 'Y' || *buf == 'y') ! 607: return(1); ! 608: (void)printf( ! 609: "I don't understand your answer; please enter 'y' or 'n'!\n"); ! 610: } ! 611: /* NOTREACHED */ ! 612: } ! 613: ! 614: bats_nearby() ! 615: { ! 616: register int i; ! 617: ! 618: /* check for bats in the immediate vicinity */ ! 619: for (i = 0; i < link_num; ++i) ! 620: if (cave[cave[player_loc].tunnel[i]].has_a_bat) ! 621: return(1); ! 622: return(0); ! 623: } ! 624: ! 625: pit_nearby() ! 626: { ! 627: register int i; ! 628: ! 629: /* check for pits in the immediate vicinity */ ! 630: for (i = 0; i < link_num; ++i) ! 631: if (cave[cave[player_loc].tunnel[i]].has_a_pit) ! 632: return(1); ! 633: return(0); ! 634: } ! 635: ! 636: wump_nearby() ! 637: { ! 638: register int i, j; ! 639: ! 640: /* check for a wumpus within TWO caves of where we are */ ! 641: for (i = 0; i < link_num; ++i) { ! 642: if (cave[player_loc].tunnel[i] == wumpus_loc) ! 643: return(1); ! 644: for (j = 0; j < link_num; ++j) ! 645: if (cave[cave[player_loc].tunnel[i]].tunnel[j] == ! 646: wumpus_loc) ! 647: return(1); ! 648: } ! 649: return(0); ! 650: } ! 651: ! 652: move_wump() ! 653: { ! 654: wumpus_loc = cave[wumpus_loc].tunnel[random() % link_num]; ! 655: } ! 656: ! 657: int_compare(a, b) ! 658: int *a, *b; ! 659: { ! 660: return(*a < *b ? -1 : 1); ! 661: } ! 662: ! 663: instructions() ! 664: { ! 665: char buf[120], *p, *getenv(); ! 666: ! 667: /* ! 668: * read the instructions file, if needed, and show the user how to ! 669: * play this game! ! 670: */ ! 671: if (!getans("Instructions? (y-n) ")) ! 672: return; ! 673: ! 674: if (access(_PATH_WUMPINFO, R_OK)) { ! 675: (void)printf( ! 676: "Sorry, but the instruction file seems to have disappeared in a\n\ ! 677: puff of greasy black smoke! (poof)\n"); ! 678: return; ! 679: } ! 680: ! 681: if (!(p = getenv("PAGER")) || ! 682: strlen(p) > sizeof(buf) + strlen(_PATH_WUMPINFO) + 5) ! 683: p = _PATH_PAGER; ! 684: ! 685: (void)sprintf(buf, "%s %s", p, _PATH_WUMPINFO); ! 686: (void)system(buf); ! 687: } ! 688: ! 689: usage() ! 690: { ! 691: (void)fprintf(stderr, ! 692: "usage: wump [-h] [-a arrows] [-b bats] [-p pits] [-r rooms] [-t tunnels]\n"); ! 693: exit(1); ! 694: } ! 695: ! 696: /* messages */ ! 697: ! 698: wump_kill() ! 699: { ! 700: (void)printf( ! 701: "*ROAR* *chomp* *snurfle* *chomp*!\n\ ! 702: Much to the delight of the Wumpus, you walked right into his mouth,\n\ ! 703: making you one of the easiest dinners he's ever had! For you, however,\n\ ! 704: it's a rather unpleasant death. The only good thing is that it's been\n\ ! 705: so long since the evil Wumpus cleaned his teeth that you immediately\n\ ! 706: passed out from the stench!\n"); ! 707: } ! 708: ! 709: kill_wump() ! 710: { ! 711: (void)printf( ! 712: "*thwock!* *groan* *crash*\n\n\ ! 713: A horrible roar fills the cave, and you realize, with a smile, that you\n\ ! 714: have slain the evil Wumpus and won the game! You don't want to tarry for\n\ ! 715: long, however, because not only is the Wumpus famous, but the stench of\n\ ! 716: dead Wumpus is also quite well known, a stench plenty enough to slay the\n\ ! 717: mightiest adventurer at a single whiff!!\n"); ! 718: } ! 719: ! 720: no_arrows() ! 721: { ! 722: (void)printf( ! 723: "\nYou turn and look at your quiver, and realize with a sinking feeling\n\ ! 724: that you've just shot your last arrow (figuratively, too). Sensing this\n\ ! 725: with its psychic powers, the evil Wumpus rampagees through the cave, finds\n\ ! 726: you, and with a mighty *ROAR* eats you alive!\n"); ! 727: } ! 728: ! 729: shoot_self() ! 730: { ! 731: (void)printf( ! 732: "\n*Thwack!* A sudden piercing feeling informs you that the ricochet\n\ ! 733: of your wild arrow has resulted in it wedging in your side, causing\n\ ! 734: extreme agony. The evil Wumpus, with its psychic powers, realizes this\n\ ! 735: and immediately rushes to your side, not to help, alas, but to EAT YOU!\n\ ! 736: (*CHOMP*)\n"); ! 737: } ! 738: ! 739: jump(where) ! 740: int where; ! 741: { ! 742: (void)printf( ! 743: "\nWith a jaunty step you enter the magic tunnel. As you do, you\n\ ! 744: notice that the walls are shimmering and glowing. Suddenly you feel\n\ ! 745: a very curious, warm sensation and find yourself in room %d!!\n", where); ! 746: } ! 747: ! 748: pit_kill() ! 749: { ! 750: (void)printf( ! 751: "*AAAUUUUGGGGGHHHHHhhhhhhhhhh...*\n\ ! 752: The whistling sound and updraft as you walked into this room of the\n\ ! 753: cave apparently wasn't enough to clue you in to the presence of the\n\ ! 754: bottomless pit. You have a lot of time to reflect on this error as\n\ ! 755: you fall many miles to the core of the earth. Look on the bright side;\n\ ! 756: you can at least find out if Jules Verne was right...\n"); ! 757: } ! 758: ! 759: pit_survive() ! 760: { ! 761: (void)printf( ! 762: "Without conscious thought you grab for the side of the cave and manage\n\ ! 763: to grasp onto a rocky outcrop. Beneath your feet stretches the limitless\n\ ! 764: depths of a bottomless pit! Rock crumbles beneath your feet!\n"); ! 765: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.