diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1998-01-31 19:20:24 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1998-01-31 19:20:24 +0000 |
commit | 6209c9c85ab1ceb6ca82db6c20890cc2134ca7f5 (patch) | |
tree | e02a0759e282db76e4cb6457effe220690aa1cdf /games | |
parent | c1dd0a33e6f172c1e52c95ee2b965286d225cc28 (diff) |
tweaks and cleanup; pjanzen@foatdi.harvard.edu
Diffstat (limited to 'games')
-rw-r--r-- | games/wump/wump.c | 363 | ||||
-rw-r--r-- | games/wump/wump.info | 22 |
2 files changed, 263 insertions, 122 deletions
diff --git a/games/wump/wump.c b/games/wump/wump.c index fb9a9bc02d7..29177b3d1b3 100644 --- a/games/wump/wump.c +++ b/games/wump/wump.c @@ -60,12 +60,14 @@ static char rcsid[] = "$NetBSD: wump.c,v 1.4 1995/04/24 12:26:22 cgd Exp $"; #include <sys/types.h> #include <sys/file.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> +#include <unistd.h> #include "pathnames.h" /* some defines to spec out what our wumpus cave should look like */ -#define MAX_ARROW_SHOT_DISTANCE 6 /* +1 for '0' stopper */ +/* #define MAX_ARROW_SHOT_DISTANCE 6 */ /* +1 for '0' stopper */ #define MAX_LINKS_IN_ROOM 25 /* a complex cave */ #define MAX_ROOMS_IN_CAVE 250 @@ -111,6 +113,35 @@ int arrow_num = NUMBER_OF_ARROWS; /* arrow inventory */ char answer[20]; /* user input */ +int bats_nearby __P((void)); +void cave_init __P((void)); +void clear_things_in_cave __P((void)); +void display_room_stats __P((void)); +int getans __P((const char *)); +void initialize_things_in_cave __P((void)); +void instructions __P((void)); +int int_compare __P((const void *, const void *)); +/* void jump __P((int)); */ +void kill_wump __P((void)); +int main __P((int, char **)); +int move_to __P((const char *)); +void move_wump __P((void)); +void no_arrows __P((void)); +void pit_kill __P((void)); +void pit_kill_bat __P((void)); +int pit_nearby __P((void)); +void pit_survive __P((void)); +int shoot __P((char *)); +void shoot_self __P((void)); +int take_action __P((void)); +void usage __P((void)); +void wump_kill __P((void)); +void wump_bat_kill __P((void)); +void wump_walk_kill __P((void)); +int wump_nearby __P((void)); + + +int main(argc, argv) int argc; char **argv; @@ -179,17 +210,23 @@ main(argc, argv) } if (level == HARD) { - bat_num += ((random() % (room_num / 2)) + 1); - pit_num += ((random() % (room_num / 2)) + 1); + srandom((int)time((time_t *)0)); + if (room_num / 2 - bat_num) + bat_num += (random() % (room_num / 2 - bat_num)); + if (room_num / 2 - pit_num) + pit_num += (random() % (room_num / 2 - pit_num)); } - if (bat_num > room_num / 2) { + /* Leave at least two rooms free--one for the player to start in, and + * potentially one for the wumpus. + */ + if (bat_num > room_num / 2 - 1) { (void)fprintf(stderr, "The wumpus refused to enter the cave, claiming it was too crowded!\n"); exit(1); } - if (pit_num > room_num / 2) { + if (pit_num > room_num / 2 - 1) { (void)fprintf(stderr, "The wumpus refused to enter the cave, claiming it was too dangerous!\n"); exit(1); @@ -213,20 +250,22 @@ quiver holds %d custom super anti-evil Wumpus arrows. Good luck.\n", display_room_stats(); (void)printf("Move or shoot? (m-s) "); (void)fflush(stdout); + (void)fpurge(stdin); if (!fgets(answer, sizeof(answer), stdin)) break; } while (!take_action()); + (void)fpurge(stdin); if (!getans("\nCare to play another game? (y-n) ")) exit(0); - if (getans("In the same cave? (y-n) ")) - clear_things_in_cave(); - else + clear_things_in_cave(); + if (!getans("In the same cave? (y-n) ")) cave_init(); } /* NOTREACHED */ } +void display_room_stats() { register int i; @@ -251,11 +290,12 @@ display_room_stats() cave[player_loc].tunnel[0]); for (i = 1; i < link_num - 1; i++) - if (cave[player_loc].tunnel[i] <= room_num) +/* if (cave[player_loc].tunnel[i] <= room_num) */ (void)printf("%d, ", cave[player_loc].tunnel[i]); (void)printf("and %d.\n", cave[player_loc].tunnel[link_num - 1]); } +int take_action() { /* @@ -284,8 +324,9 @@ take_action() return(0); } +int move_to(room_number) - char *room_number; + const char *room_number; { int i, just_moved_by_bats, next_room, tunnel_available; @@ -301,21 +342,21 @@ move_to(room_number) next_room = atoi(room_number); /* crap for magic tunnels */ - if (next_room == room_num + 1 && - cave[player_loc].tunnel[link_num-1] != next_room) - ++next_room; - - while (next_room < 1 || next_room > room_num + 1) { +/* if (next_room == room_num + 1 && + * cave[player_loc].tunnel[link_num-1] != next_room) + * ++next_room; + */ + while (next_room < 1 || next_room > room_num /* + 1 */) { if (next_room < 0 && next_room != -1) (void)printf("Sorry, but we're constrained to a semi-Euclidean cave!\n"); - if (next_room > room_num + 1) + if (next_room > room_num /* + 1 */) (void)printf("What? The cave surely isn't quite that big!\n"); - if (next_room == room_num + 1 && - cave[player_loc].tunnel[link_num-1] != next_room) { - (void)printf("What? The cave isn't that big!\n"); - ++next_room; - } - (void)printf("To which room do you wish to move? "); +/* if (next_room == room_num + 1 && + * cave[player_loc].tunnel[link_num-1] != next_room) { + * (void)printf("What? The cave isn't that big!\n"); + * ++next_room; + * } + */ (void)printf("To which room do you wish to move? "); (void)fflush(stdout); if (!fgets(answer, sizeof(answer), stdin)) return(1); @@ -334,7 +375,7 @@ move_to(room_number) (void)printf("Your colorful comments awaken the wumpus!\n"); move_wump(); if (wumpus_loc == player_loc) { - wump_kill(); + wump_walk_kill(); return(1); } } @@ -342,13 +383,16 @@ move_to(room_number) } /* now let's move into that room and check it out for dangers */ - if (next_room == room_num + 1) - jump(next_room = (random() % room_num) + 1); - +/* if (next_room == room_num + 1) + * jump(next_room = (random() % room_num) + 1); + */ player_loc = next_room; for (;;) { if (next_room == wumpus_loc) { /* uh oh... */ - wump_kill(); + if (just_moved_by_bats) + wump_bat_kill(); + else + wump_kill(); return(1); } if (cave[next_room].has_a_pit) @@ -356,7 +400,10 @@ move_to(room_number) pit_survive(); return(0); } else { - pit_kill(); + if (just_moved_by_bats) + pit_kill_bat(); + else + pit_kill(); return(1); } @@ -374,12 +421,13 @@ move_to(room_number) return(0); } +int shoot(room_list) char *room_list; { int chance, next, roomcnt; int j, arrow_location, link, ok; - char *p, *strtok(); + char *p; /* * Implement shooting arrows. Arrows are shot by the player indicating @@ -387,82 +435,92 @@ shoot(room_list) * if any of the rooms they specify are not accessible via tunnel from * the room the arrow is in, it will instead fly randomly into another * room. If the player hits the wumpus, this routine will indicate - * such. If it misses, this routine will *move* the wumpus one room. - * If it's the last arrow, the player then dies... Returns 1 if the + * such. If it misses, this routine may *move* the wumpus one room. + * If it's the last arrow, then the player dies... Returns 1 if the * player has won or died, 0 if nothing has happened. */ arrow_location = player_loc; for (roomcnt = 1;; ++roomcnt, room_list = NULL) { if (!(p = strtok(room_list, " \t\n"))) if (roomcnt == 1) { - (void)printf( - "The arrow falls to the ground at your feet!\n"); - return(0); + (void)printf("Enter a list of rooms to shoot into:\n"); + (void)fflush(stdout); + if (!(p = strtok(fgets(answer, sizeof(answer), stdin), + " \t\n"))) { + (void)printf( + "The arrow falls to the ground at your feet.\n"); + return(0); + } } else break; if (roomcnt > 5) { (void)printf( -"The arrow wavers in its flight and and can go no further!\n"); +"The arrow wavers in its flight and and can go no further than room %d!\n", + arrow_location); break; } + next = atoi(p); + if (next == 0) + break; /* Old wumpus used room 0 as the terminator */ + + chance = random() % 10; + if (roomcnt == 4 && chance < 2) { + (void)printf( +"Your finger slips on the bowstring! *twaaaaaang*\n\ +The arrow is weakly shot and can go no further than room %d!\n",arrow_location); + break; + } else if (roomcnt == 5 && chance < 6) { + (void)printf( +"The arrow wavers in its flight and and can go no further than room %d!\n", + arrow_location); + break; + } + for (j = 0, ok = 0; j < link_num; j++) if (cave[arrow_location].tunnel[j] == next) ok = 1; if (ok) { - if (next > room_num) { - (void)printf( -"A faint gleam tells you the arrow has gone through a magic tunnel!\n"); - arrow_location = (random() % room_num) + 1; - } else - arrow_location = next; +/* if (next > room_num) { + * (void)printf( + * "A faint gleam tells you the arrow has gone through a magic tunnel!\n"); + * arrow_location = (random() % room_num) + 1; + * } else + */ arrow_location = next; } else { link = (random() % link_num); - if (link == player_loc) + if (cave[arrow_location].tunnel[link] == player_loc) (void)printf( -"*thunk* The arrow can't find a way from %d to %d and flys back into\n\ +"*thunk* The arrow can't find a way from %d to %d and flies back into\n\ your room!\n", arrow_location, next); - else if (cave[arrow_location].tunnel[link] > room_num) - (void)printf( -"*thunk* The arrow flys randomly into a magic tunnel, thence into\n\ -room %d!\n", - cave[arrow_location].tunnel[link]); - else +/* else if (cave[arrow_location].tunnel[link] > room_num) + * (void)printf( + *"*thunk* The arrow flies randomly into a magic tunnel, thence into\n\ + *room %d!\n", + * cave[arrow_location].tunnel[link]); + */ else (void)printf( -"*thunk* The arrow can't find a way from %d to %d and flys randomly\n\ -into room %d!\n", - arrow_location, next, - cave[arrow_location].tunnel[link]); +"*thunk* The arrow can't find a way from %d to %d and flies randomly\n\ +into room %d!\n", arrow_location, next, cave[arrow_location].tunnel[link]); + arrow_location = cave[arrow_location].tunnel[link]; - break; - } - chance = random() % 10; - if (roomcnt == 3 && chance < 2) { - (void)printf( -"Your bowstring breaks! *twaaaaaang*\n\ -The arrow is weakly shot and can go no further!\n"); - break; - } else if (roomcnt == 4 && chance < 6) { - (void)printf( -"The arrow wavers in its flight and and can go no further!\n"); - break; } - } - /* - * now we've gotten into the new room let us see if El Wumpo is - * in the same room ... if so we've a HIT and the player WON! - */ - if (arrow_location == wumpus_loc) { - kill_wump(); - return(1); - } + /* + * now we've gotten into the new room let us see if El Wumpo is + * in the same room ... if so we've a HIT and the player WON! + */ + if (arrow_location == wumpus_loc) { + kill_wump(); + return(1); + } - if (arrow_location == player_loc) { - shoot_self(); - return(1); + if (arrow_location == player_loc) { + shoot_self(); + return(1); + } } if (!--arrows_left) { @@ -476,15 +534,19 @@ The arrow is weakly shot and can go no further!\n"); if (random() % level == EASY ? 12 : 9 < (lastchance += 2)) { move_wump(); - if (wumpus_loc == player_loc) - wump_kill(); - lastchance = random() % 3; + if (wumpus_loc == player_loc) { + wump_walk_kill(); + lastchance = random() % 3; /* Reset for next game */ + return(1); + } } } + (void)printf("The arrow hit nothing.\n"); return(0); } +void cave_init() { register int i, j, k, link; @@ -500,6 +562,14 @@ cave_init() * than three links, regardless of the quality of the random number * generator that we're using. */ + + /* Note that throughout the source there are commented-out vestigial + * remains of the 'magic tunnel', which was a tunnel to room + * room_num +1. It was necessary if all paths were two-way and + * there was an odd number of rooms, each with an odd number of + * exits. It's being kept in case cave_init ever gets reworked into + * something more traditional. + */ srandom((int)time((time_t *)0)); /* initialize the cave first off. */ @@ -508,14 +578,16 @@ cave_init() cave[i].tunnel[j] = -1; /* choose a random 'hop' delta for our guaranteed link */ - while (!(delta = random() % room_num)); + while (!(delta = random() % (room_num - 1))); for (i = 1; i <= room_num; ++i) { link = ((i + delta) % room_num) + 1; /* connection */ cave[i].tunnel[0] = link; /* forw link */ cave[link].tunnel[1] = i; /* back link */ } - /* now fill in the rest of the cave with random connections */ + /* now fill in the rest of the cave with random connections. + * This is a departure from historical versions of wumpus. + */ for (i = 1; i <= room_num; i++) for (j = 2; j < link_num ; j++) { if (cave[i].tunnel[j] != -1) @@ -525,6 +597,9 @@ try_again: link = (random() % room_num) + 1; for (k = 0; k < j; k++) if (cave[i].tunnel[k] == link) goto try_again; + /* don't let a room connect to itself */ + if (link == i) + goto try_again; cave[i].tunnel[j] = link; if (random() % 2 == 1) continue; @@ -532,11 +607,12 @@ try_again: link = (random() % room_num) + 1; /* if duplicate, skip it */ if (cave[link].tunnel[k] == i) k = link_num; - - /* if open link, use it, force exit */ - if (cave[link].tunnel[k] == -1) { - cave[link].tunnel[k] = i; - k = link_num; + else { + /* if open link, use it, force exit */ + if (cave[link].tunnel[k] == -1) { + cave[link].tunnel[k] = i; + k = link_num; + } } } } @@ -559,6 +635,7 @@ try_again: link = (random() % room_num) + 1; #endif } +void clear_things_in_cave() { register int i; @@ -571,6 +648,7 @@ clear_things_in_cave() cave[i].has_a_bat = cave[i].has_a_pit = 0; } +void initialize_things_in_cave() { register int i, loc; @@ -590,7 +668,9 @@ initialize_things_in_cave() for (i = 0; i < pit_num; ++i) { do { loc = (random() % room_num) + 1; - } while (cave[loc].has_a_pit && cave[loc].has_a_bat); + } while (cave[loc].has_a_pit || cave[loc].has_a_bat); + /* Above used to be &&; || makes sense but so does just + * checking cave[loc].has_a_pit */ cave[loc].has_a_pit = 1; #ifdef DEBUG if (debug) @@ -601,17 +681,23 @@ initialize_things_in_cave() wumpus_loc = (random() % room_num) + 1; #ifdef DEBUG if (debug) - (void)printf("<wumpus in room %d>\n", loc); + (void)printf("<wumpus in room %d>\n", wumpus_loc); #endif do { player_loc = (random() % room_num) + 1; - } while (player_loc == wumpus_loc || (level == HARD ? - (link_num / room_num < 0.4 ? wump_nearby() : 0) : 0)); + } while (player_loc == wumpus_loc || cave[player_loc].has_a_pit || + cave[player_loc].has_a_bat); + /* Replaced (level == HARD ? + * (link_num / room_num < 0.4 ? wump_nearby() : 0) : 0) + * with bat/pit checks in initial room. If this is kept there is + * a slight chance that no room satisfies all four conditions. + */ } +int getans(prompt) - char *prompt; + const char *prompt; { char buf[20]; @@ -635,6 +721,7 @@ getans(prompt) /* NOTREACHED */ } +int bats_nearby() { register int i; @@ -646,6 +733,7 @@ bats_nearby() return(0); } +int pit_nearby() { register int i; @@ -657,6 +745,7 @@ pit_nearby() return(0); } +int wump_nearby() { register int i, j; @@ -673,17 +762,24 @@ wump_nearby() return(0); } +void move_wump() { wumpus_loc = cave[wumpus_loc].tunnel[random() % link_num]; +#ifdef DEBUG + if (debug) + (void)printf("Wumpus moved to room %d\n",wumpus_loc); +#endif } +int int_compare(a, b) - int *a, *b; + const void *a, *b; { - return(*a < *b ? -1 : 1); + return(*(int *)a < *(int *)b ? -1 : 1); } +void instructions() { char buf[120], *p, *getenv(); @@ -710,6 +806,7 @@ puff of greasy black smoke! (poof)\n"); (void)system(buf); } +void usage() { (void)fprintf(stderr, @@ -718,18 +815,43 @@ usage() } /* messages */ - +void wump_kill() { (void)printf( "*ROAR* *chomp* *snurfle* *chomp*!\n\ -Much to the delight of the Wumpus, you walked right into his mouth,\n\ +Much to the delight of the Wumpus, you walk right into his mouth,\n\ making you one of the easiest dinners he's ever had! For you, however,\n\ it's a rather unpleasant death. The only good thing is that it's been\n\ so long since the evil Wumpus cleaned his teeth that you immediately\n\ -passed out from the stench!\n"); +pass out from the stench!\n"); } +void +wump_walk_kill() +{ + (void)printf( +"Oh dear. All the commotion has managed to awaken the evil Wumpus, who\n\ +has chosen to walk into this very room! Your eyes open wide as they behold\n\ +the great sucker-footed bulk that is the Wumpus; the mouth of the Wumpus\n\ +also opens wide as the the evil beast beholds dinner.\n\ +*ROAR* *chomp* *snurfle* *chomp*!\n"); +} + +void +wump_bat_kill() +{ + (void)printf( +"Flap, flap. The bats fly you right into the room with the evil Wumpus!\n\ +The Wumpus, seeing a fine dinner flying overhead, takes a swipe at you,\n\ +and the bats, not wanting to serve as hors d'oeuvres, drop their\n\ +soon-to-be-dead weight and take off in the way that only bats flying out\n\ +of a very bad place can. As you fall towards the large, sharp, and very\n\ +foul-smelling teeth of the Wumpus, you think, \"Man, this is going to hurt.\"\n\ +It does.\n"); +} + +void kill_wump() { (void)printf( @@ -737,49 +859,66 @@ kill_wump() A horrible roar fills the cave, and you realize, with a smile, that you\n\ have slain the evil Wumpus and won the game! You don't want to tarry for\n\ long, however, because not only is the Wumpus famous, but the stench of\n\ -dead Wumpus is also quite well known, a stench plenty enough to slay the\n\ +dead Wumpus is also quite well known--a stench powerful enough to slay the\n\ mightiest adventurer at a single whiff!!\n"); } +void no_arrows() { (void)printf( "\nYou turn and look at your quiver, and realize with a sinking feeling\n\ that you've just shot your last arrow (figuratively, too). Sensing this\n\ -with its psychic powers, the evil Wumpus rampagees through the cave, finds\n\ +with its psychic powers, the evil Wumpus rampages through the cave, finds\n\ you, and with a mighty *ROAR* eats you alive!\n"); } +void shoot_self() { (void)printf( -"\n*Thwack!* A sudden piercing feeling informs you that the ricochet\n\ -of your wild arrow has resulted in it wedging in your side, causing\n\ -extreme agony. The evil Wumpus, with its psychic powers, realizes this\n\ -and immediately rushes to your side, not to help, alas, but to EAT YOU!\n\ +"\n*Thwack!* A sudden piercing feeling informs you that your wild arrow\n\ +has ricocheted back and wedged in your side, causing extreme agony. The\n\ +evil Wumpus, with its psychic powers, realizes this and immediately rushes\n\ +to your side, not to help, alas, but to EAT YOU!\n\ (*CHOMP*)\n"); } -jump(where) - int where; -{ - (void)printf( -"\nWith a jaunty step you enter the magic tunnel. As you do, you\n\ -notice that the walls are shimmering and glowing. Suddenly you feel\n\ -a very curious, warm sensation and find yourself in room %d!!\n", where); -} +/* + * void + * jump(where) + * int where; + * { + * (void)printf( + * "\nWith a jaunty step you enter the magic tunnel. As you do, you\n\ + * notice that the walls are shimmering and glowing. Suddenly you feel\n\ + * a very curious, warm sensation and find yourself in room %d!!\n", where); + * } + */ +void pit_kill() { (void)printf( "*AAAUUUUGGGGGHHHHHhhhhhhhhhh...*\n\ The whistling sound and updraft as you walked into this room of the\n\ -cave apparently wasn't enough to clue you in to the presence of the\n\ +cave apparently weren't enough to clue you in to the presence of the\n\ bottomless pit. You have a lot of time to reflect on this error as\n\ you fall many miles to the core of the earth. Look on the bright side;\n\ you can at least find out if Jules Verne was right...\n"); } +void +pit_kill_bat() +{ + (void)printf( +"*AAAUUUUGGGGGHHHHHhhhhhhhhhh...*\n\ +It appears the bats have decided to drop you into a bottomless pit. At\n\ +least, that's what the whistling sound and updraft would suggest. Look on\n\ +the bright side; you can at least find out if Jules Verne was right...\n"); +} + +void pit_survive() { (void)printf( diff --git a/games/wump/wump.info b/games/wump/wump.info index 329e8219c0c..679264d6762 100644 --- a/games/wump/wump.info +++ b/games/wump/wump.info @@ -1,10 +1,11 @@ Welcome to the game of Hunt the Wumpus. -The Wumpus typically lives in a cave of twenty rooms, with each room having -three tunnels connecting it to other rooms in the cavern. Caves may vary, -however, depending on options specified when starting the game. +The Wumpus typically lives in a cave of twenty rooms, where each room +is connected by three tunnels to the other rooms in the cavern. Caves +may vary, however, depending on options specified when starting the game. +The cave may contain one-way passages. -The game has the following hazards for intrepid adventurers to wind their +The game has the following hazards for intrepid adventurers to wend their way through: Pits -- If you fall into one of the bottomless pits, you find yourself @@ -21,8 +22,8 @@ way through: recommended. The Wumpus, by the way, is not bothered by the hazards since he has sucker -feet and is too big for a bat to lift. If you try to shoot him and miss, -there's also a chance that he'll up and move himself into another cave, +feet and is too big for the bats to lift. If you try to shoot him and miss, +there's also a chance that he'll up and move himself into another room, though by nature the Wumpus is a sedentary creature. Each turn you may either move or shoot a crooked arrow. Moving is done @@ -32,10 +33,11 @@ that you'd like to shoot one of your magic arrows with an "s" for shoot, then list a set of connected room numbers through which the deadly shaft should fly! -If your path for the arrow is incorrect, however, it will flail about in -the room it can't understand and randomly pick a tunnel to continue -through. You might just end up shooting yourself in the foot if you're -not careful! On the other hand, if you shoot the Wumpus you've WON! +If a tunnel does not exist between two consecutive rooms in the arrow's +path, the arrow will flail about and randomly pick an existing tunnel +to continue through. You might just end up shooting yourself in the +foot if you're not careful! On the other hand, if you shoot the Wumpus +you've WON! Good luck. |