]> git.cameronkatri.com Git - bsdgames-darwin.git/blobdiff - wump/wump.c
Fix some minor buglets in wump:
[bsdgames-darwin.git] / wump / wump.c
index bcffa5eb43c9043e99e0d8194bdacd9fdf6e5786..1cff6dbc4699c0983e0c5df465ca108556fdad98 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: wump.c,v 1.6 1998/08/30 09:19:41 veego Exp $   */
+/*     $NetBSD: wump.c,v 1.20 2006/01/19 21:20:35 garbled 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.
  *
@@ -47,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\
 #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.20 2006/01/19 21:20:35 garbled 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 <err.h>
 #include <sys/types.h>
 #include <sys/file.h>
+#include <sys/wait.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 #include <unistd.h>
 #include "pathnames.h"
 
@@ -113,36 +112,40 @@ 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));
+int    bats_nearby(void);
+void   cave_init(void);
+void   clear_things_in_cave(void);
+void   display_room_stats(void);
+int    gcd(int, int);
+int    getans(const char *);
+void   initialize_things_in_cave(void);
+void   instructions(void);
+int    int_compare(const void *, const void *);
+void   jump(int);
+void   kill_wump(void);
+int    main(int, char **);
+int    move_to(const char *);
+void   move_wump(void);
+void   no_arrows(void);
+void   pit_kill(void);
+int    pit_nearby(void);
+void   pit_survive(void);
+int    shoot(char *);
+void   shoot_self(void);
+int    take_action(void);
+void   usage(void) __attribute__((__noreturn__));
+void   wump_kill(void);
+int    wump_nearby(void);
 
 int
 main(argc, argv)
        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)
@@ -229,21 +232,22 @@ 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 */
@@ -503,7 +507,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,6 +518,18 @@ The arrow is weakly shot and can go no further!\n");
        return(0);
 }
 
+int
+gcd(a, b)
+       int a, b;
+{
+       int r;
+
+       r = a % b;
+       if (r == 0)
+               return (b);
+       return (gcd(b, r));
+}
+
 void
 cave_init()
 {
@@ -536,8 +552,14 @@ 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 */
@@ -621,7 +643,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,10 +657,14 @@ 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
@@ -718,13 +744,16 @@ int
 int_compare(a, b)
        const void *a, *b;
 {
-       return(*(int *)a < *(int *)b ? -1 : 1);
+       return(*(const int *)a < *(const int *)b ? -1 : 1);
 }
 
 void
 instructions()
 {
-       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,12 +769,26 @@ 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