X-Git-Url: https://git.cameronkatri.com/bsdgames-darwin.git/blobdiff_plain/5a555a984855e94b0fc3c9154da6b65208ba2c70..32a54d49158271df4ffa0cf4422f612647973022:/wump/wump.c diff --git a/wump/wump.c b/wump/wump.c index bcffa5eb..0175bb05 100644 --- a/wump/wump.c +++ b/wump/wump.c @@ -1,4 +1,4 @@ -/* $NetBSD: wump.c,v 1.6 1998/08/30 09:19:41 veego Exp $ */ +/* $NetBSD: wump.c,v 1.30 2012/06/19 05:46:09 dholland Exp $ */ /* * Copyright (c) 1989, 1993 @@ -16,11 +16,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -39,15 +35,15 @@ #include #ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\ - The Regents of the University of California. All rights reserved.\n"); +__COPYRIGHT("@(#) Copyright (c) 1989, 1993\ + The Regents of the University of California. All rights reserved."); #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)wump.c 8.1 (Berkeley) 5/31/93"; #else -__RCSID("$NetBSD: wump.c,v 1.6 1998/08/30 09:19:41 veego Exp $"); +__RCSID("$NetBSD: wump.c,v 1.30 2012/06/19 05:46:09 dholland Exp $"); #endif #endif /* not lint */ @@ -57,11 +53,14 @@ __RCSID("$NetBSD: wump.c,v 1.6 1998/08/30 09:19:41 veego Exp $"); * would care to remember. */ +#include #include #include +#include #include #include #include +#include #include #include "pathnames.h" @@ -87,7 +86,7 @@ __RCSID("$NetBSD: wump.c,v 1.6 1998/08/30 09:19:41 veego Exp $"); #define plural(n) (n == 1 ? "" : "s") /* simple cave data structure; +1 so we can index from '1' not '0' */ -struct room_record { +static struct room_record { int tunnel[MAX_LINKS_IN_ROOM]; int has_a_pit, has_a_bat; } cave[MAX_ROOMS_IN_CAVE+1]; @@ -96,53 +95,55 @@ struct room_record { * global variables so we can keep track of where the player is, how * many arrows they still have, where el wumpo is, and so on... */ -int player_loc = -1; /* player location */ -int wumpus_loc = -1; /* The Bad Guy location */ -int level = EASY; /* level of play */ -int arrows_left; /* arrows unshot */ +static int player_loc = -1; /* player location */ +static int wumpus_loc = -1; /* The Bad Guy location */ +static int level = EASY; /* level of play */ +static int arrows_left; /* arrows unshot */ #ifdef DEBUG -int debug = 0; +static int debug = 0; #endif -int pit_num = PIT_COUNT; /* # pits in cave */ -int bat_num = BAT_COUNT; /* # bats */ -int room_num = ROOMS_IN_CAVE; /* # rooms in cave */ -int link_num = LINKS_IN_ROOM; /* links per room */ -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)); -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)); -int wump_nearby __P((void)); +static int pit_num = PIT_COUNT; /* # pits in cave */ +static int bat_num = BAT_COUNT; /* # bats */ +static int room_num = ROOMS_IN_CAVE; /* # rooms in cave */ +static int link_num = LINKS_IN_ROOM; /* links per room */ +static int arrow_num = NUMBER_OF_ARROWS;/* arrow inventory */ + +static char answer[20]; /* user input */ + +int main(int, char **); +static int bats_nearby(void); +static void cave_init(void); +static void clear_things_in_cave(void); +static void display_room_stats(void); +static int gcd(int, int); +static int getans(const char *); +static void initialize_things_in_cave(void); +static void instructions(void); +static int int_compare(const void *, const void *); +static void jump(int); +static void kill_wump(void); +static int move_to(const char *); +static void move_wump(void); +static void no_arrows(void); +static void pit_kill(void); +static int pit_nearby(void); +static void pit_survive(void); +static int shoot(char *); +static void shoot_self(void); +static int take_action(void); +static void usage(void) __dead; +static void wump_kill(void); +static int wump_nearby(void); int -main(argc, argv) - int argc; - char **argv; +main(int argc, char **argv) { - int c; + int c, e=0; + + /* Revoke setgid privileges */ + setgid(getgid()); #ifdef DEBUG while ((c = getopt(argc, argv, "a:b:hp:r:t:d")) != -1) @@ -176,7 +177,7 @@ main(argc, argv) } if (room_num > MAX_ROOMS_IN_CAVE) { (void)fprintf(stderr, - "Even wumpii can't furnish caves that large!\n"); + "Even wumpi can't furnish caves that large!\n"); exit(1); } break; @@ -184,7 +185,7 @@ main(argc, argv) link_num = atoi(optarg); if (link_num < 2) { (void)fprintf(stderr, - "Wumpii like extra doors in their caves!\n"); + "Wumpi like extra doors in their caves!\n"); exit(1); } break; @@ -229,35 +230,36 @@ quiver holds %d custom super anti-evil Wumpus arrows. Good luck.\n", plural(pit_num), arrow_num); for (;;) { + clear_things_in_cave(); initialize_things_in_cave(); arrows_left = arrow_num; do { display_room_stats(); (void)printf("Move or shoot? (m-s) "); (void)fflush(stdout); - if (!fgets(answer, sizeof(answer), stdin)) + if (!fgets(answer, sizeof(answer), stdin)) { + e=2; break; - } while (!take_action()); + } + } while (!(e = take_action())); - if (!getans("\nCare to play another game? (y-n) ")) + if (e == 2 || !getans("\nCare to play another game? (y-n) ")) exit(0); - if (getans("In the same cave? (y-n) ")) - clear_things_in_cave(); - else + if (getans("In the same cave? (y-n) ") == 0) cave_init(); } /* NOTREACHED */ return (0); } -void -display_room_stats() +static void +display_room_stats(void) { int i; /* * Routine will explain what's going on with the current room, as well - * as describe whether there are pits, bats, & wumpii nearby. It's + * as describe whether there are pits, bats, & wumpi nearby. It's * all pretty mindless, really. */ (void)printf( @@ -280,8 +282,8 @@ display_room_stats() (void)printf("and %d.\n", cave[player_loc].tunnel[link_num - 1]); } -int -take_action() +static int +take_action(void) { /* * Do the action specified by the player, either 'm'ove, 's'hoot @@ -309,9 +311,8 @@ take_action() return(0); } -int -move_to(room_number) - const char *room_number; +static int +move_to(const char *room_number) { int i, just_moved_by_bats, next_room, tunnel_available; @@ -401,12 +402,11 @@ move_to(room_number) return(0); } -int -shoot(room_list) - char *room_list; +static int +shoot(char *room_list) { int chance, next, roomcnt; - int j, arrow_location, link, ok; + int j, arrow_location, lnk, ok; char *p; /* @@ -447,24 +447,24 @@ shoot(room_list) } else arrow_location = next; } else { - link = (random() % link_num); - if (link == player_loc) + lnk = (random() % link_num); + if (lnk == 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) + else if (cave[arrow_location].tunnel[lnk] > room_num) (void)printf( -"*thunk* The arrow flys randomly into a magic tunnel, thence into\n\ +"*thunk* The arrow flies randomly into a magic tunnel, thence into\n\ room %d!\n", - cave[arrow_location].tunnel[link]); + cave[arrow_location].tunnel[lnk]); else (void)printf( -"*thunk* The arrow can't find a way from %d to %d and flys randomly\n\ +"*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]; + cave[arrow_location].tunnel[lnk]); + arrow_location = cave[arrow_location].tunnel[lnk]; break; } chance = random() % 10; @@ -503,7 +503,7 @@ The arrow is weakly shot and can go no further!\n"); /* each time you shoot, it's more likely the wumpus moves */ static int lastchance = 2; - if (random() % level == EASY ? 12 : 9 < (lastchance += 2)) { + if (random() % (level == EASY ? 12 : 9) < (lastchance += 2)) { move_wump(); if (wumpus_loc == player_loc) wump_kill(); @@ -514,10 +514,21 @@ The arrow is weakly shot and can go no further!\n"); return(0); } -void -cave_init() +static int +gcd(int a, int b) { - int i, j, k, link; + int r; + + r = a % b; + if (r == 0) + return (b); + return (gcd(b, r)); +} + +static void +cave_init(void) +{ + int i, j, k, lnk; int delta; /* @@ -536,35 +547,41 @@ cave_init() for (j = 0; j < link_num ; ++j) cave[i].tunnel[j] = -1; - /* choose a random 'hop' delta for our guaranteed link */ - while (!(delta = random() % room_num)); + /* + * Choose a random 'hop' delta for our guaranteed link. + * To keep the cave connected, we need the greatest common divisor + * of (delta + 1) and room_num to be 1. + */ + do { + delta = (random() % (room_num - 1)) + 1; + } while (gcd(room_num, delta + 1) != 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 */ + lnk = ((i + delta) % room_num) + 1; /* connection */ + cave[i].tunnel[0] = lnk; /* forw link */ + cave[lnk].tunnel[1] = i; /* back link */ } /* now fill in the rest of the cave with random connections */ for (i = 1; i <= room_num; i++) for (j = 2; j < link_num ; j++) { if (cave[i].tunnel[j] != -1) continue; -try_again: link = (random() % room_num) + 1; +try_again: lnk = (random() % room_num) + 1; /* skip duplicates */ for (k = 0; k < j; k++) - if (cave[i].tunnel[k] == link) + if (cave[i].tunnel[k] == lnk) goto try_again; - cave[i].tunnel[j] = link; + cave[i].tunnel[j] = lnk; if (random() % 2 == 1) continue; for (k = 0; k < link_num; ++k) { /* if duplicate, skip it */ - if (cave[link].tunnel[k] == i) + if (cave[lnk].tunnel[k] == i) k = link_num; /* if open link, use it, force exit */ - if (cave[link].tunnel[k] == -1) { - cave[link].tunnel[k] = i; + if (cave[lnk].tunnel[k] == -1) { + cave[lnk].tunnel[k] = i; k = link_num; } } @@ -574,7 +591,7 @@ try_again: link = (random() % room_num) + 1; * make it easier on the intrepid adventurer. */ for (i = 1; i <= room_num; ++i) - qsort(cave[i].tunnel, (u_int)link_num, + qsort(cave[i].tunnel, link_num, sizeof(cave[i].tunnel[0]), int_compare); #ifdef DEBUG @@ -588,8 +605,8 @@ try_again: link = (random() % room_num) + 1; #endif } -void -clear_things_in_cave() +static void +clear_things_in_cave(void) { int i; @@ -601,8 +618,8 @@ clear_things_in_cave() cave[i].has_a_bat = cave[i].has_a_pit = 0; } -void -initialize_things_in_cave() +static void +initialize_things_in_cave(void) { int i, loc; @@ -621,7 +638,7 @@ 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); cave[loc].has_a_pit = 1; #ifdef DEBUG if (debug) @@ -635,15 +652,18 @@ initialize_things_in_cave() (void)printf("\n", loc); #endif + i = 0; do { player_loc = (random() % room_num) + 1; - } while (player_loc == wumpus_loc || (level == HARD ? - (link_num / room_num < 0.4 ? wump_nearby() : 0) : 0)); + i++; + } while (player_loc == wumpus_loc || cave[player_loc].has_a_pit || + cave[player_loc].has_a_bat || (level == HARD ? + (link_num / room_num < 0.4 ? wump_nearby() : 0) : 0) || + (i > 100 && player_loc != wumpus_loc)); } -int -getans(prompt) - const char *prompt; +static int +getans(const char *prompt) { char buf[20]; @@ -667,8 +687,8 @@ getans(prompt) /* NOTREACHED */ } -int -bats_nearby() +static int +bats_nearby(void) { int i; @@ -679,8 +699,8 @@ bats_nearby() return(0); } -int -pit_nearby() +static int +pit_nearby(void) { int i; @@ -691,8 +711,8 @@ pit_nearby() return(0); } -int -wump_nearby() +static int +wump_nearby(void) { int i, j; @@ -708,23 +728,25 @@ wump_nearby() return(0); } -void -move_wump() +static void +move_wump(void) { wumpus_loc = cave[wumpus_loc].tunnel[random() % link_num]; } -int -int_compare(a, b) - const void *a, *b; +static int +int_compare(const void *a, const void *b) { - return(*(int *)a < *(int *)b ? -1 : 1); + return(*(const int *)a < *(const int *)b ? -1 : 1); } -void -instructions() +static void +instructions(void) { - char buf[120], *p; + const char *pager; + pid_t pid; + int status; + int fd; /* * read the instructions file, if needed, and show the user how to @@ -740,16 +762,30 @@ puff of greasy black smoke! (poof)\n"); return; } - if (!(p = getenv("PAGER")) || - strlen(p) > sizeof(buf) + strlen(_PATH_WUMPINFO) + 5) - p = _PATH_PAGER; - - (void)sprintf(buf, "%s %s", p, _PATH_WUMPINFO); - (void)system(buf); + if (!isatty(STDOUT_FILENO)) + pager = "cat"; + else { + if (!(pager = getenv("PAGER")) || (*pager == 0)) + pager = _PATH_PAGER; + } + switch (pid = fork()) { + case 0: /* child */ + if ((fd = open(_PATH_WUMPINFO, O_RDONLY)) == -1) + err(1, "open %s", _PATH_WUMPINFO); + if (dup2(fd, STDIN_FILENO) == -1) + err(1, "dup2"); + (void)execl("/bin/sh", "sh", "-c", pager, (char *) NULL); + err(1, "exec sh -c %s", pager); + case -1: + err(1, "fork"); + default: + (void)waitpid(pid, &status, 0); + break; + } } -void -usage() +static void +usage(void) { (void)fprintf(stderr, "usage: wump [-h] [-a arrows] [-b bats] [-p pits] [-r rooms] [-t tunnels]\n"); @@ -758,8 +794,8 @@ usage() /* messages */ -void -wump_kill() +static void +wump_kill(void) { (void)printf( "*ROAR* *chomp* *snurfle* *chomp*!\n\ @@ -770,8 +806,8 @@ so long since the evil Wumpus cleaned his teeth that you immediately\n\ passed out from the stench!\n"); } -void -kill_wump() +static void +kill_wump(void) { (void)printf( "*thwock!* *groan* *crash*\n\n\ @@ -782,18 +818,18 @@ dead Wumpus is also quite well known, a stench plenty enough to slay the\n\ mightiest adventurer at a single whiff!!\n"); } -void -no_arrows() +static void +no_arrows(void) { (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() +static void +shoot_self(void) { (void)printf( "\n*Thwack!* A sudden piercing feeling informs you that the ricochet\n\ @@ -803,9 +839,8 @@ and immediately rushes to your side, not to help, alas, but to EAT YOU!\n\ (*CHOMP*)\n"); } -void -jump(where) - int where; +static void +jump(int where) { (void)printf( "\nWith a jaunty step you enter the magic tunnel. As you do, you\n\ @@ -813,8 +848,8 @@ 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() +static void +pit_kill(void) { (void)printf( "*AAAUUUUGGGGGHHHHHhhhhhhhhhh...*\n\ @@ -825,8 +860,8 @@ 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_survive() +static void +pit_survive(void) { (void)printf( "Without conscious thought you grab for the side of the cave and manage\n\