X-Git-Url: https://git.cameronkatri.com/bsdgames-darwin.git/blobdiff_plain/77e3814f0c0e3dea4d0032e25666f77e6f83bfff..HEAD:/wump/wump.c diff --git a/wump/wump.c b/wump/wump.c index 7d40b69b..fdb9ae4b 100644 --- a/wump/wump.c +++ b/wump/wump.c @@ -1,6 +1,8 @@ +/* $NetBSD: wump.c,v 1.31 2021/05/02 12:50:47 rillig Exp $ */ + /* - * Copyright (c) 1989 The Regents of the University of California. - * Copyright (c) 1989 Dave Taylor, Intuitive Systems. + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. * All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -14,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. * @@ -35,14 +33,18 @@ * SUCH DAMAGE. */ +#include #ifndef lint -char copyright[] = -"@(#) Copyright (c) 1989 The Regents of the University of California.\n\ - All rights reserved.\n"; +__COPYRIGHT("@(#) Copyright (c) 1989, 1993\ + The Regents of the University of California. All rights reserved."); #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)wump.c 4.3 (Berkeley) 6/1/90"; +#if 0 +static char sccsid[] = "@(#)wump.c 8.1 (Berkeley) 5/31/93"; +#else +__RCSID("$NetBSD: wump.c,v 1.31 2021/05/02 12:50:47 rillig Exp $"); +#endif #endif /* not lint */ /* @@ -51,9 +53,15 @@ static char sccsid[] = "@(#)wump.c 4.3 (Berkeley) 6/1/90"; * would care to remember. */ +#include #include #include +#include #include +#include +#include +#include +#include #include "pathnames.h" /* some defines to spec out what our wumpus cave should look like */ @@ -78,7 +86,7 @@ static char sccsid[] = "@(#)wump.c 4.3 (Berkeley) 6/1/90"; #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]; @@ -87,34 +95,60 @@ 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 */ - -main(argc, argv) - int argc; - char **argv; +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(int argc, char **argv) { - extern char *optarg; - int c; + int c, e=0; + + /* Revoke setgid privileges */ + setgid(getgid()); #ifdef DEBUG - while ((c = getopt(argc, argv, "a:b:hp:r:t:d")) != EOF) + while ((c = getopt(argc, argv, "a:b:hp:r:t:d")) != -1) #else - while ((c = getopt(argc, argv, "a:b:hp:r:t:")) != EOF) + while ((c = getopt(argc, argv, "a:b:hp:r:t:")) != -1) #endif switch (c) { case 'a': @@ -143,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; @@ -151,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; @@ -196,33 +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); } -display_room_stats() +static void +display_room_stats(void) { - register int i; + 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( @@ -245,7 +282,8 @@ display_room_stats() (void)printf("and %d.\n", cave[player_loc].tunnel[link_num - 1]); } -take_action() +static int +take_action(void) { /* * Do the action specified by the player, either 'm'ove, 's'hoot @@ -273,8 +311,8 @@ take_action() return(0); } -move_to(room_number) - char *room_number; +static int +move_to(const char *room_number) { int i, just_moved_by_bats, next_room, tunnel_available; @@ -340,7 +378,7 @@ move_to(room_number) wump_kill(); return(1); } - if (cave[next_room].has_a_pit) + if (cave[next_room].has_a_pit) { if (random() % 12 < 2) { pit_survive(); return(0); @@ -348,6 +386,7 @@ move_to(room_number) pit_kill(); return(1); } + } if (cave[next_room].has_a_bat) { (void)printf( @@ -363,12 +402,12 @@ move_to(room_number) return(0); } -shoot(room_list) - char *room_list; +static int +shoot(char *room_list) { int chance, next, roomcnt; - int j, arrow_location, link, ok; - char *p, *strtok(); + int j, arrow_location, lnk, ok; + char *p; /* * Implement shooting arrows. Arrows are shot by the player indicating @@ -382,13 +421,14 @@ shoot(room_list) */ arrow_location = player_loc; for (roomcnt = 1;; ++roomcnt, room_list = NULL) { - if (!(p = strtok(room_list, " \t\n"))) + if (!(p = strtok(room_list, " \t\n"))) { if (roomcnt == 1) { (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"); @@ -407,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; @@ -463,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(); @@ -474,11 +514,22 @@ The arrow is weakly shot and can go no further!\n"); return(0); } -cave_init() +static int +gcd(int a, int b) +{ + int r; + + r = a % b; + if (r == 0) + return (b); + return (gcd(b, r)); +} + +static void +cave_init(void) { - register int i, j, k, link; - int delta, int_compare(); - time_t time(); + int i, j, k, lnk; + int delta; /* * This does most of the interesting work in this program actually! @@ -496,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; } } @@ -534,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 @@ -548,9 +605,10 @@ try_again: link = (random() % room_num) + 1; #endif } -clear_things_in_cave() +static void +clear_things_in_cave(void) { - register int i; + int i; /* * remove bats and pits from the current cave in preparation for us @@ -560,9 +618,10 @@ clear_things_in_cave() cave[i].has_a_bat = cave[i].has_a_pit = 0; } -initialize_things_in_cave() +static void +initialize_things_in_cave(void) { - register int i, loc; + int i, loc; /* place some bats, pits, the wumpus, and the player. */ for (i = 0; i < bat_num; ++i) { @@ -579,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) @@ -593,14 +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)); } -getans(prompt) - char *prompt; +static int +getans(const char *prompt) { char buf[20]; @@ -624,9 +687,10 @@ getans(prompt) /* NOTREACHED */ } -bats_nearby() -{ - register int i; +static int +bats_nearby(void) +{ + int i; /* check for bats in the immediate vicinity */ for (i = 0; i < link_num; ++i) @@ -635,9 +699,10 @@ bats_nearby() return(0); } -pit_nearby() -{ - register int i; +static int +pit_nearby(void) +{ + int i; /* check for pits in the immediate vicinity */ for (i = 0; i < link_num; ++i) @@ -646,9 +711,10 @@ pit_nearby() return(0); } -wump_nearby() +static int +wump_nearby(void) { - register int i, j; + int i, j; /* check for a wumpus within TWO caves of where we are */ for (i = 0; i < link_num; ++i) { @@ -662,20 +728,25 @@ wump_nearby() return(0); } -move_wump() +static void +move_wump(void) { wumpus_loc = cave[wumpus_loc].tunnel[random() % link_num]; } -int_compare(a, b) - int *a, *b; +static int +int_compare(const void *a, const void *b) { - return(*a < *b ? -1 : 1); + return(*(const int *)a < *(const int *)b ? -1 : 1); } -instructions() +static void +instructions(void) { - char buf[120], *p, *getenv(); + const char *pager; + pid_t pid; + int status; + int fd; /* * read the instructions file, if needed, and show the user how to @@ -691,15 +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; + } } -usage() +static void +usage(void) { (void)fprintf(stderr, "usage: wump [-h] [-a arrows] [-b bats] [-p pits] [-r rooms] [-t tunnels]\n"); @@ -708,7 +794,8 @@ usage() /* messages */ -wump_kill() +static void +wump_kill(void) { (void)printf( "*ROAR* *chomp* *snurfle* *chomp*!\n\ @@ -719,7 +806,8 @@ so long since the evil Wumpus cleaned his teeth that you immediately\n\ passed out from the stench!\n"); } -kill_wump() +static void +kill_wump(void) { (void)printf( "*thwock!* *groan* *crash*\n\n\ @@ -730,16 +818,18 @@ dead Wumpus is also quite well known, a stench plenty enough to slay the\n\ mightiest adventurer at a single whiff!!\n"); } -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"); } -shoot_self() +static void +shoot_self(void) { (void)printf( "\n*Thwack!* A sudden piercing feeling informs you that the ricochet\n\ @@ -749,8 +839,8 @@ and immediately rushes to your side, not to help, alas, but to EAT YOU!\n\ (*CHOMP*)\n"); } -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\ @@ -758,7 +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); } -pit_kill() +static void +pit_kill(void) { (void)printf( "*AAAUUUUGGGGGHHHHHhhhhhhhhhh...*\n\ @@ -769,7 +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"); } -pit_survive() +static void +pit_survive(void) { (void)printf( "Without conscious thought you grab for the side of the cave and manage\n\