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