]> git.cameronkatri.com Git - bsdgames-darwin.git/blobdiff - wump/wump.c
Fix merge conflicts
[bsdgames-darwin.git] / wump / wump.c
index 93fc6c5fcd707beee4bbf98967982dd533540b62..fdb9ae4b940fb6b027fc3094596fef3f895b3c07 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: wump.c,v 1.11 1999/09/10 10:47:56 kleink Exp $ */
+/*     $NetBSD: wump.c,v 1.31 2021/05/02 12:50:47 rillig Exp $ */
 
 /*
  * Copyright (c) 1989, 1993
  * 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.
  *
 
 #include <sys/cdefs.h>
 #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.11 1999/09/10 10:47:56 kleink Exp $");
+__RCSID("$NetBSD: wump.c,v 1.31 2021/05/02 12:50:47 rillig Exp $");
 #endif
 #endif /* not lint */
 
@@ -90,7 +86,7 @@ __RCSID("$NetBSD: wump.c,v 1.11 1999/09/10 10:47:56 kleink 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];
@@ -99,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)) __attribute__((__noreturn__));
-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)
@@ -179,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;
@@ -187,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;
@@ -232,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(
@@ -283,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
@@ -312,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;
 
@@ -404,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;
 
        /*
@@ -450,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;
@@ -506,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();
@@ -517,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 r;
+
+       r = a % b;
+       if (r == 0)
+               return (b);
+       return (gcd(b, r));
+}
+
+static void
+cave_init(void)
 {
-       int i, j, k, link;
+       int i, j, k, lnk;
        int delta;
 
        /*
@@ -539,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;
                                }
                        }
@@ -577,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
@@ -591,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;
 
@@ -604,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;
 
@@ -624,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)
@@ -638,15 +652,18 @@ initialize_things_in_cave()
                (void)printf("<wumpus in room %d>\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];
 
@@ -670,9 +687,9 @@ getans(prompt)
        /* NOTREACHED */
 }
 
-int
-bats_nearby()
-{ 
+static int
+bats_nearby(void)
+{
        int i;
 
        /* check for bats in the immediate vicinity */
@@ -682,9 +699,9 @@ bats_nearby()
        return(0);
 }
 
-int
-pit_nearby()
-{ 
+static int
+pit_nearby(void)
+{
        int i;
 
        /* check for pits in the immediate vicinity */
@@ -694,8 +711,8 @@ pit_nearby()
        return(0);
 }
 
-int
-wump_nearby()
+static int
+wump_nearby(void)
 {
        int i, j;
 
@@ -711,21 +728,20 @@ 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(*(const int *)a < *(const int *)b ? -1 : 1);
 }
 
-void
-instructions()
+static void
+instructions(void)
 {
        const char *pager;
        pid_t pid;
@@ -758,7 +774,7 @@ puff of greasy black smoke! (poof)\n");
                        err(1, "open %s", _PATH_WUMPINFO);
                if (dup2(fd, STDIN_FILENO) == -1)
                        err(1, "dup2");
-               (void)execl("/bin/sh", "sh", "-c", pager, NULL);
+               (void)execl("/bin/sh", "sh", "-c", pager, (char *) NULL);
                err(1, "exec sh -c %s", pager);
        case -1:
                err(1, "fork");
@@ -768,8 +784,8 @@ puff of greasy black smoke! (poof)\n");
        }
 }
 
-void
-usage()
+static void
+usage(void)
 {
        (void)fprintf(stderr,
 "usage: wump [-h] [-a arrows] [-b bats] [-p pits] [-r rooms] [-t tunnels]\n");
@@ -778,8 +794,8 @@ usage()
 
 /* messages */
 
-void
-wump_kill()
+static void
+wump_kill(void)
 {
        (void)printf(
 "*ROAR* *chomp* *snurfle* *chomp*!\n\
@@ -790,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\
@@ -802,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\
@@ -823,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\
@@ -833,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\
@@ -845,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\