386BSD 0.1 development
authorWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Tue, 9 Apr 1991 01:11:21 +0000 (17:11 -0800)
committerWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Tue, 9 Apr 1991 01:11:21 +0000 (17:11 -0800)
Work on file usr/othersrc/games/worms/worms.6
Work on file usr/othersrc/games/worms/worms.c
Work on file usr/othersrc/games/wump/pathnames.h
Work on file usr/othersrc/games/wump/wump.6
Work on file usr/othersrc/games/wump/wump.c

Co-Authored-By: Lynne Greer Jolitz <ljolitz@cardio.ucsf.edu>
Synthesized-from: 386BSD-0.1

usr/othersrc/games/worms/worms.6 [new file with mode: 0644]
usr/othersrc/games/worms/worms.c [new file with mode: 0644]
usr/othersrc/games/wump/pathnames.h [new file with mode: 0644]
usr/othersrc/games/wump/wump.6 [new file with mode: 0644]
usr/othersrc/games/wump/wump.c [new file with mode: 0644]

diff --git a/usr/othersrc/games/worms/worms.6 b/usr/othersrc/games/worms/worms.6
new file mode 100644 (file)
index 0000000..45d258e
--- /dev/null
@@ -0,0 +1,71 @@
+.\" Copyright (c) 1989 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 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
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)worms.6     6.4 (Berkeley) 6/23/90
+.\"
+.UC 7
+.TH WORMS 6 "June 23, 1990"
+.UC 4
+.SH NAME
+worms  \-  animate worms on a display terminal
+.SH SYNOPSIS
+.B worms
+[
+.B \-ft
+] [
+.B \-length
+# ] [
+.B \-number
+# ]
+.SH DESCRIPTION
+.ad b
+Brian Horn (cithep!bdh) showed me a
+.I TOPS-20
+program on the DEC-2136 machine called
+.IR WORM ,
+and suggested that I write a similar program that would run under
+.IR Unix .
+I did, and no apologies.
+.PP
+The options are as follows:
+.TP
+.I -f
+makes a ``field'' for the worm(s) to eat.
+.TP
+.I -t
+causes each worm to leave a trail behind it.
+.PP
+You can figure out the rest by yourself.
+.SH AUTHOR
+Eric P. Scott
+.SH BUGS
+The lower-right-hand character position will not be updated properly
+on a terminal that wraps at the right margin.
diff --git a/usr/othersrc/games/worms/worms.c b/usr/othersrc/games/worms/worms.c
new file mode 100644 (file)
index 0000000..0e78036
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 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
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1980 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)worms.c    5.9 (Berkeley) 2/28/91";
+#endif /* not lint */
+
+/*
+ *
+ *      @@@        @@@    @@@@@@@@@@     @@@@@@@@@@@    @@@@@@@@@@@@
+ *      @@@        @@@   @@@@@@@@@@@@    @@@@@@@@@@@@   @@@@@@@@@@@@@
+ *      @@@        @@@  @@@@      @@@@   @@@@           @@@@ @@@  @@@@
+ *      @@@   @@   @@@  @@@        @@@   @@@            @@@  @@@   @@@
+ *      @@@  @@@@  @@@  @@@        @@@   @@@            @@@  @@@   @@@
+ *      @@@@ @@@@ @@@@  @@@        @@@   @@@            @@@  @@@   @@@
+ *       @@@@@@@@@@@@   @@@@      @@@@   @@@            @@@  @@@   @@@
+ *        @@@@  @@@@     @@@@@@@@@@@@    @@@            @@@  @@@   @@@
+ *         @@    @@       @@@@@@@@@@     @@@            @@@  @@@   @@@
+ *
+ *                              Eric P. Scott
+ *                       Caltech High Energy Physics
+ *                              October, 1980
+ *
+ */
+#include <sys/types.h>
+#include <stdio.h>
+#ifdef USG
+#include <termio.h>
+#else
+#include <sgtty.h>
+#endif
+#include <signal.h>
+
+static struct options {
+       int nopts;
+       int opts[3];
+}
+       normal[8] = {
+       { 3, { 7, 0, 1 } },
+       { 3, { 0, 1, 2 } },
+       { 3, { 1, 2, 3 } },
+       { 3, { 2, 3, 4 } },
+       { 3, { 3, 4, 5 } },
+       { 3, { 4, 5, 6 } },
+       { 3, { 5, 6, 7 } },
+       { 3, { 6, 7, 0 } }
+},     upper[8] = {
+       { 1, { 1, 0, 0 } },
+       { 2, { 1, 2, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 2, { 4, 5, 0 } },
+       { 1, { 5, 0, 0 } },
+       { 2, { 1, 5, 0 } }
+},
+       left[8] = {
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 2, { 2, 3, 0 } },
+       { 1, { 3, 0, 0 } },
+       { 2, { 3, 7, 0 } },
+       { 1, { 7, 0, 0 } },
+       { 2, { 7, 0, 0 } }
+},
+       right[8] = {
+       { 1, { 7, 0, 0 } },
+       { 2, { 3, 7, 0 } },
+       { 1, { 3, 0, 0 } },
+       { 2, { 3, 4, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 2, { 6, 7, 0 } }
+},
+       lower[8] = {
+       { 0, { 0, 0, 0 } },
+       { 2, { 0, 1, 0 } },
+       { 1, { 1, 0, 0 } },
+       { 2, { 1, 5, 0 } },
+       { 1, { 5, 0, 0 } },
+       { 2, { 5, 6, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } }
+},
+       upleft[8] = {
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 1, { 3, 0, 0 } },
+       { 2, { 1, 3, 0 } },
+       { 1, { 1, 0, 0 } }
+},
+       upright[8] = {
+       { 2, { 3, 5, 0 } },
+       { 1, { 3, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 1, { 5, 0, 0 } }
+},
+       lowleft[8] = {
+       { 3, { 7, 0, 1 } },
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 1, { 1, 0, 0 } },
+       { 2, { 1, 7, 0 } },
+       { 1, { 7, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } }
+},
+       lowright[8] = {
+       { 0, { 0, 0, 0 } },
+       { 1, { 7, 0, 0 } },
+       { 2, { 5, 7, 0 } },
+       { 1, { 5, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } },
+       { 0, { 0, 0, 0 } }
+};
+
+#define        cursor(c, r)    tputs(tgoto(CM, c, r), 1, fputchar)
+
+char *tcp;
+int fputchar();
+
+static char    flavor[] = {
+       'O', '*', '#', '$', '%', '0', '@', '~'
+};
+static short   xinc[] = {
+       1,  1,  1,  0, -1, -1, -1,  0
+}, yinc[] = {
+       -1,  0,  1,  1,  1,  0, -1, -1
+};
+static struct  worm {
+       int orientation, head;
+       short *xpos, *ypos;
+} *worm;
+
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       extern int optind;
+       extern short ospeed;
+       extern char *optarg, *UP;
+       register int x, y, h, n;
+       register struct worm *w;
+       register struct options *op;
+       register short *ip;
+       register char *term;
+       int CO, IN, LI, last, bottom, ch, length, number, trail, Wrap;
+       void onsig();
+       short **ref;
+       char *AL, *BC, *CM, *EI, *HO, *IC, *IM, *IP, *SR;
+       char *field, tcb[100], *mp, *malloc(), *getenv(), *tgetstr(), *tgoto();
+       long random();
+#ifdef USG
+       struct termio sg;
+#else
+       struct sgttyb sg;
+#endif
+
+       length = 16;
+       number = 3;
+       trail = ' ';
+       field = NULL;
+       while ((ch = getopt(argc, argv, "fl:n:t")) != EOF)
+               switch(ch) {
+               case 'f':
+                       field = "WORM";
+                       break;
+               case 'l':
+                       if ((length = atoi(optarg)) < 2 || length > 1024) {
+                               (void)fprintf(stderr,
+                                   "worms: invalid length (%d - %d).\n",
+                                    2, 1024);
+                               exit(1);
+                       }
+                       break;
+               case 'n':
+                       if ((number = atoi(optarg)) < 1) {
+                               (void)fprintf(stderr,
+                                   "worms: invalid number of worms.\n");
+                               exit(1);
+                       }
+                       break;
+               case 't':
+                       trail = '.';
+                       break;
+               case '?':
+               default:
+                       (void)fprintf(stderr,
+                           "usage: worms [-ft] [-length #] [-number #]\n");
+                       exit(1);
+               }
+
+       if (!(term = getenv("TERM"))) {
+               (void)fprintf(stderr, "worms: no TERM environment variable.\n");
+               exit(1);
+       }
+       if (!(worm = (struct worm *)malloc((u_int)number *
+           sizeof(struct worm))) || !(mp = malloc((u_int)1024)))
+               nomem();
+       if (tgetent(mp, term) <= 0) {
+               (void)fprintf(stderr, "worms: %s: unknown terminal type.\n",
+                   term);
+               exit(1);
+       }
+       tcp = tcb;
+       if (!(CM = tgetstr("cm", &tcp))) {
+               (void)fprintf(stderr,
+                   "worms: terminal incapable of cursor motion.\n");
+               exit(1);
+       }
+       AL = tgetstr("al", &tcp);
+       BC = tgetflag("bs") ? "\b" : tgetstr("bc", &tcp);
+       if ((CO = tgetnum("co")) <= 0)
+               CO = 80;
+       last = CO - 1;
+       EI = tgetstr("ei", &tcp);
+       HO = tgetstr("ho", &tcp);
+       IC = tgetstr("ic", &tcp);
+       IM = tgetstr("im", &tcp);
+       IN = tgetflag("in");
+       IP = tgetstr("ip", &tcp);
+       if ((LI = tgetnum("li")) <= 0)
+               LI = 24;
+       bottom = LI - 1;
+       SR = tgetstr("sr", &tcp);
+       UP = tgetstr("up", &tcp);
+#ifdef USG
+       ioctl(1, TCGETA, &sg);
+       ospeed = sg.c_cflag&CBAUD;
+#else
+       gtty(1, &sg);
+       ospeed = sg.sg_ospeed;
+#endif
+       Wrap = tgetflag("am");
+       if (!(ip = (short *)malloc((u_int)(LI * CO * sizeof(short)))))
+               nomem();
+       if (!(ref = (short **)malloc((u_int)(LI * sizeof(short *)))))
+               nomem();
+       for (n = 0; n < LI; ++n) {
+               ref[n] = ip;
+               ip += CO;
+       }
+       for (ip = ref[0], n = LI * CO; --n >= 0;)
+               *ip++ = 0;
+       if (Wrap)
+               ref[bottom][last] = 1;
+       for (n = number, w = &worm[0]; --n >= 0; w++) {
+               w->orientation = w->head = 0;
+               if (!(ip = (short *)malloc((u_int)(length * sizeof(short)))))
+                       nomem();
+               w->xpos = ip;
+               for (x = length; --x >= 0;)
+                       *ip++ = -1;
+               if (!(ip = (short *)malloc((u_int)(length * sizeof(short)))))
+                       nomem();
+               w->ypos = ip;
+               for (y = length; --y >= 0;)
+                       *ip++ = -1;
+       }
+
+       (void)signal(SIGHUP, onsig);
+       (void)signal(SIGINT, onsig);
+       (void)signal(SIGQUIT, onsig);
+       (void)signal(SIGSTOP, onsig);
+       (void)signal(SIGTSTP, onsig);
+       (void)signal(SIGTERM, onsig);
+
+       tputs(tgetstr("ti", &tcp), 1, fputchar);
+       tputs(tgetstr("cl", &tcp), 1, fputchar);
+       if (field) {
+               register char *p = field;
+
+               for (y = bottom; --y >= 0;) {
+                       for (x = CO; --x >= 0;) {
+                               fputchar(*p++);
+                               if (!*p)
+                                       p = field;
+                       }
+                       if (!Wrap)
+                               fputchar('\n');
+                       (void)fflush(stdout);
+               }
+               if (Wrap) {
+                       if (IM && !IN) {
+                               for (x = last; --x > 0;) {
+                                       fputchar(*p++);
+                                       if (!*p)
+                                               p = field;
+                               }
+                               y = *p++;
+                               if (!*p)
+                                       p = field;
+                               fputchar(*p);
+                               if (BC)
+                                       tputs(BC, 1, fputchar);
+                               else
+                                       cursor(last - 1, bottom);
+                               tputs(IM, 1, fputchar);
+                               if (IC)
+                                       tputs(IC, 1, fputchar);
+                               fputchar(y);
+                               if (IP)
+                                       tputs(IP, 1, fputchar);
+                               tputs(EI, 1, fputchar);
+                       }
+                       else if (SR || AL) {
+                               if (HO)
+                                       tputs(HO, 1, fputchar);
+                               else
+                                       cursor(0, 0);
+                               if (SR)
+                                       tputs(SR, 1, fputchar);
+                               else
+                                       tputs(AL, LI, fputchar);
+                               for (x = CO; --x >= 0;) {
+                                       fputchar(*p++);
+                                       if (!*p)
+                                               p = field;
+                               }
+                       }
+                       else for (x = last; --x >= 0;) {
+                               fputchar(*p++);
+                               if (!*p)
+                                       p = field;
+                       }
+               }
+               else for (x = CO; --x >= 0;) {
+                       fputchar(*p++);
+                       if (!*p)
+                               p = field;
+               }
+       }
+       for (;;) {
+               (void)fflush(stdout);
+               for (n = 0, w = &worm[0]; n < number; n++, w++) {
+                       if ((x = w->xpos[h = w->head]) < 0) {
+                               cursor(x = w->xpos[h] = 0,
+                                    y = w->ypos[h] = bottom);
+                               fputchar(flavor[n % sizeof(flavor)]);
+                               ref[y][x]++;
+                       }
+                       else
+                               y = w->ypos[h];
+                       if (++h == length)
+                               h = 0;
+                       if (w->xpos[w->head = h] >= 0) {
+                               register int x1, y1;
+
+                               x1 = w->xpos[h];
+                               y1 = w->ypos[h];
+                               if (--ref[y1][x1] == 0) {
+                                       cursor(x1, y1);
+                                       if (trail)
+                                               fputchar(trail);
+                               }
+                       }
+                       op = &(!x ? (!y ? upleft : (y == bottom ? lowleft : left)) : (x == last ? (!y ? upright : (y == bottom ? lowright : right)) : (!y ? upper : (y == bottom ? lower : normal))))[w->orientation];
+                       switch (op->nopts) {
+                       case 0:
+                               (void)fflush(stdout);
+                               abort();
+                               return;
+                       case 1:
+                               w->orientation = op->opts[0];
+                               break;
+                       default:
+                               w->orientation =
+                                   op->opts[(int)random() % op->nopts];
+                       }
+                       cursor(x += xinc[w->orientation],
+                           y += yinc[w->orientation]);
+                       if (!Wrap || x != last || y != bottom)
+                               fputchar(flavor[n % sizeof(flavor)]);
+                       ref[w->ypos[h] = y][w->xpos[h] = x]++;
+               }
+       }
+}
+
+void
+onsig()
+{
+       tputs(tgetstr("cl", &tcp), 1, fputchar);
+       tputs(tgetstr("te", &tcp), 1, fputchar);
+       exit(0);
+}
+
+fputchar(c)
+       char c;
+{
+       putchar(c);
+}
+
+nomem()
+{
+       (void)fprintf(stderr, "worms: not enough memory.\n");
+       exit(1);
+}
diff --git a/usr/othersrc/games/wump/pathnames.h b/usr/othersrc/games/wump/pathnames.h
new file mode 100644 (file)
index 0000000..62e4203
--- /dev/null
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 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
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)pathnames.h 5.1 (Berkeley) 6/1/90
+ */
+
+#define        _PATH_PAGER     "/usr/bin/more"
+#define        _PATH_WUMPINFO  "/usr/share/games/wump.info"
diff --git a/usr/othersrc/games/wump/wump.6 b/usr/othersrc/games/wump/wump.6
new file mode 100644 (file)
index 0000000..b230aab
--- /dev/null
@@ -0,0 +1,110 @@
+.\" Copyright (c) 1989 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Dave Taylor, of Intuitive Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 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
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)wump.6      6.3 (Berkeley) 6/23/90
+.\"
+.TH WUMP 6 "June 23, 1990"
+.UC 7
+.SH NAME
+wump \- hunt the wumpus in an underground cave
+.SH SYNOPSIS
+.ft B
+wump [-h] [-a arrows] [-b bats] [-p pits] [-r rooms] [-t tunnels]
+.ft R
+.SH DESCRIPTION
+The game
+.I wump 
+is based on a fantasy game first presented in the pages of
+.I "People's Computer Company"
+in 1973.
+In Hunt the Wumpus you are placed in a cave built of many different rooms,
+all interconnected by tunnels.
+Your quest is to find and shoot the evil Wumpus that resides elsewhere in
+the cave without running into any pits or using up your limited supply of
+arrows.
+.PP
+The options are as follows:
+.TP
+.I -a
+Specifies the number of magic arrows the adventurer gets.
+The default is five.
+.TP
+.I -b
+Specifies the number of rooms in the cave which contain bats.
+The default is three.
+.TP
+.I -h
+Play the hard version -- more pits, more bats, and a generally more
+dangerous cave.
+.TP
+.I -n
+Specifies the number of rooms in the cave which contain bottomless pits.
+The default is three.
+.TP
+.I -r
+Specifies the number of rooms in the cave.
+The default cave size is twenty-five rooms.
+.TP
+.I -t
+Specifies the number of tunnels connecting each room in the cave to
+another room.
+Beware, too many tunnels in a small cave can easily cause it to collapse!
+The default cave room has three tunnels to other rooms.
+.PP
+While wandering through the cave you'll notice that, while there are tunnels
+everywhere, there are some mysterious quirks to the cave topology, including
+some tunnels that go from one room to another, but not necessarily back!
+Also, most pesky of all are the rooms that are home to large numbers of bats,
+which, upon being disturbed, will en masse grab you and move you to another
+portion of the cave (including those housing bottomless pits, sure
+death for unwary explorers).
+.PP
+Fortunately, you're not going into the cave without any weapons or tools,
+and in fact your biggest aids are your senses; you can often smell the
+rather odiferous Wumpus up to
+.I two
+rooms away, and you can always feel the drafts created by the occasional
+bottomless pit and hear the rustle of the bats in caves they might be
+sleeping within.
+.PP
+To kill the wumpus, you'll need to shoot it with one of your magic arrows.
+Fortunately, you don't have to be in the same room as the creature, and can
+instead shoot the arrow from as far as three or four rooms away!
+.PP
+When you shoot an arrow, you do so by typing in a list of rooms that you'd
+like it to travel to.
+If at any point in its travels it cannot find a tunnel to the room you
+specify from the room it's in, it will instead randomly fly down one of the
+tunnels, possibly, if you're real unlucky, even flying back into the room
+you're in and hitting you!
diff --git a/usr/othersrc/games/wump/wump.c b/usr/othersrc/games/wump/wump.c
new file mode 100644 (file)
index 0000000..7d40b69
--- /dev/null
@@ -0,0 +1,778 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * Copyright (c) 1989 Dave Taylor, Intuitive Systems.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Dave Taylor, of Intuitive Systems.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 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
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)wump.c     4.3 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+/*
+ * A very new version of the age old favorite Hunt-The-Wumpus game that has
+ * been a part of the BSD distribution of Unix for longer than us old folk
+ * would care to remember.
+ */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.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_LINKS_IN_ROOM       25              /* a complex cave */
+
+#define        MAX_ROOMS_IN_CAVE       250
+#define        ROOMS_IN_CAVE           20
+#define        MIN_ROOMS_IN_CAVE       10
+
+#define        LINKS_IN_ROOM           3
+#define        NUMBER_OF_ARROWS        5
+#define        PIT_COUNT               3
+#define        BAT_COUNT               3
+
+#define        EASY                    1               /* levels of play */
+#define        HARD                    2
+
+/* some macro definitions for cleaner output */
+
+#define        plural(n)       (n == 1 ? "" : "s")
+
+/* simple cave data structure; +1 so we can index from '1' not '0' */
+struct room_record {
+       int tunnel[MAX_LINKS_IN_ROOM];
+       int has_a_pit, has_a_bat;
+} cave[MAX_ROOMS_IN_CAVE+1];
+
+/*
+ * 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 */
+
+#ifdef DEBUG
+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;
+{
+       extern char *optarg;
+       int c;
+
+#ifdef DEBUG
+       while ((c = getopt(argc, argv, "a:b:hp:r:t:d")) != EOF)
+#else
+       while ((c = getopt(argc, argv, "a:b:hp:r:t:")) != EOF)
+#endif
+               switch (c) {
+               case 'a':
+                       arrow_num = atoi(optarg);
+                       break;
+               case 'b':
+                       bat_num = atoi(optarg);
+                       break;
+#ifdef DEBUG
+               case 'd':
+                       debug = 1;
+                       break;
+#endif
+               case 'h':
+                       level = HARD;
+                       break;
+               case 'p':
+                       pit_num = atoi(optarg);
+                       break;
+               case 'r':
+                       room_num = atoi(optarg);
+                       if (room_num < MIN_ROOMS_IN_CAVE) {
+                               (void)fprintf(stderr,
+       "No self-respecting wumpus would live in such a small cave!\n");
+                               exit(1);
+                       }
+                       if (room_num > MAX_ROOMS_IN_CAVE) {
+                               (void)fprintf(stderr,
+       "Even wumpii can't furnish caves that large!\n");
+                               exit(1);
+                       }
+                       break;
+               case 't':
+                       link_num = atoi(optarg);
+                       if (link_num < 2) {
+                               (void)fprintf(stderr,
+       "Wumpii like extra doors in their caves!\n");
+                               exit(1);
+                       }
+                       break;
+               case '?':
+               default:
+                       usage();
+       }
+
+       if (link_num > MAX_LINKS_IN_ROOM ||
+           link_num > room_num - (room_num / 4)) {
+               (void)fprintf(stderr,
+"Too many tunnels!  The cave collapsed!\n(Fortunately, the wumpus escaped!)\n");
+               exit(1);
+       }
+
+       if (level == HARD) {
+               bat_num += ((random() % (room_num / 2)) + 1);
+               pit_num += ((random() % (room_num / 2)) + 1);
+       }
+
+       if (bat_num > room_num / 2) {
+               (void)fprintf(stderr,
+"The wumpus refused to enter the cave, claiming it was too crowded!\n");
+               exit(1);
+       }
+
+       if (pit_num > room_num / 2) {
+               (void)fprintf(stderr,
+"The wumpus refused to enter the cave, claiming it was too dangerous!\n");
+               exit(1);
+       }
+
+       instructions();
+       cave_init();
+
+       /* and we're OFF!  da dum, da dum, da dum, da dum... */
+       (void)printf(
+"\nYou're in a cave with %d rooms and %d tunnels leading from each room.\n\
+There are %d bat%s and %d pit%s scattered throughout the cave, and your\n\
+quiver holds %d custom super anti-evil Wumpus arrows.  Good luck.\n",
+           room_num, link_num, bat_num, plural(bat_num), pit_num,
+           plural(pit_num), arrow_num);
+
+       for (;;) {
+               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))
+                               break;
+               } while (!take_action());
+
+               if (!getans("\nCare to play another game? (y-n) "))
+                       exit(0);
+               if (getans("In the same cave? (y-n) "))
+                       clear_things_in_cave();
+               else
+                       cave_init();
+       }
+       /* NOTREACHED */
+}
+
+display_room_stats()
+{
+       register 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
+        * all pretty mindless, really.
+        */
+       (void)printf(
+"\nYou are in room %d of the cave, and have %d arrow%s left.\n",
+           player_loc, arrows_left, plural(arrows_left));
+
+       if (bats_nearby())
+               (void)printf("*rustle* *rustle* (must be bats nearby)\n");
+       if (pit_nearby())
+               (void)printf("*whoosh* (I feel a draft from some pits).\n");
+       if (wump_nearby())
+               (void)printf("*sniff* (I can smell the evil Wumpus nearby!)\n");
+
+       (void)printf("There are tunnels to rooms %d, ",
+          cave[player_loc].tunnel[0]);
+
+       for (i = 1; i < link_num - 1; i++)
+               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]);
+}
+
+take_action()
+{
+       /*
+        * Do the action specified by the player, either 'm'ove, 's'hoot
+        * or something exceptionally bizarre and strange!  Returns 1
+        * iff the player died during this turn, otherwise returns 0.
+        */
+       switch (*answer) {
+               case 'M':
+               case 'm':                       /* move */
+                       return(move_to(answer + 1));
+               case 'S':
+               case 's':                       /* shoot */
+                       return(shoot(answer + 1));
+               case 'Q':
+               case 'q':
+               case 'x':
+                       exit(0);
+               case '\n':
+                       return(0);
+               }
+       if (random() % 15 == 1)
+               (void)printf("Que pasa?\n");
+       else
+               (void)printf("I don't understand!\n");
+       return(0);
+}
+
+move_to(room_number)
+       char *room_number;
+{
+       int i, just_moved_by_bats, next_room, tunnel_available;
+
+       /*
+        * This is responsible for moving the player into another room in the
+        * cave as per their directions.  If room_number is a null string,
+        * then we'll prompt the user for the next room to go into.   Once
+        * we've moved into the room, we'll check for things like bats, pits,
+        * and so on.  This routine returns 1 if something occurs that kills
+        * the player and 0 otherwise...
+        */
+       tunnel_available = just_moved_by_bats = 0;
+       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 < 0 && next_room != -1)
+(void)printf("Sorry, but we're constrained to a semi-Euclidean cave!\n");
+               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? ");
+               (void)fflush(stdout);
+               if (!fgets(answer, sizeof(answer), stdin))
+                       return(1);
+               next_room = atoi(answer);
+       }
+
+       /* now let's see if we can move to that room or not */
+       tunnel_available = 0;
+       for (i = 0; i < link_num; i++)
+               if (cave[player_loc].tunnel[i] == next_room)
+                       tunnel_available = 1;
+
+       if (!tunnel_available) {
+               (void)printf("*Oof!*  (You hit the wall)\n");
+               if (random() % 6 == 1) {
+(void)printf("Your colorful comments awaken the wumpus!\n");
+                       move_wump();
+                       if (wumpus_loc == player_loc) {
+                               wump_kill();
+                               return(1);
+                       }
+               }
+               return(0);
+       }
+
+       /* 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);
+
+       player_loc = next_room;
+       for (;;) {
+               if (next_room == wumpus_loc) {          /* uh oh... */
+                       wump_kill();
+                       return(1);
+               }
+               if (cave[next_room].has_a_pit)
+                       if (random() % 12 < 2) {
+                               pit_survive();
+                               return(0);
+                       } else {
+                               pit_kill();
+                               return(1);
+                       }
+
+               if (cave[next_room].has_a_bat) {
+                       (void)printf(
+"*flap*  *flap*  *flap*  (humongous bats pick you up and move you%s!)\n",
+                           just_moved_by_bats ? " again": "");
+                       next_room = player_loc = (random() % room_num) + 1;
+                       just_moved_by_bats = 1;
+               }
+
+               else
+                       break;
+       }
+       return(0);
+}
+
+shoot(room_list)
+       char *room_list;
+{
+       int chance, next, roomcnt;
+       int j, arrow_location, link, ok;
+       char *p, *strtok();
+
+       /*
+        * Implement shooting arrows.  Arrows are shot by the player indicating
+        * a space-separated list of rooms that the arrow should pass through;
+        * 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
+        * 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);
+                       } else
+                               break;
+               if (roomcnt > 5) {
+                       (void)printf(
+"The arrow wavers in its flight and and can go no further!\n");
+                       break;
+               }
+               next = atoi(p);
+               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;
+               } else {
+                       link = (random() % link_num);
+                       if (link == player_loc)
+                               (void)printf(
+"*thunk*  The arrow can't find a way from %d to %d and flys 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
+                               (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]);
+                       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);
+       }
+
+       if (arrow_location == player_loc) {
+               shoot_self();
+               return(1);
+       }
+
+       if (!--arrows_left) {
+               no_arrows();
+               return(1);
+       }
+
+       {
+               /* each time you shoot, it's more likely the wumpus moves */
+               static int lastchance = 2;
+
+               if (random() % level == EASY ? 12 : 9 < (lastchance += 2)) {
+                       move_wump();
+                       if (wumpus_loc == player_loc)
+                               wump_kill();
+                       lastchance = random() % 3;
+
+               }
+       }
+       return(0);
+}
+
+cave_init()
+{
+       register int i, j, k, link;
+       int delta, int_compare();
+       time_t time();
+
+       /*
+        * This does most of the interesting work in this program actually!
+        * In this routine we'll initialize the Wumpus cave to have all rooms
+        * linking to all others by stepping through our data structure once,
+        * recording all forward links and backwards links too.  The parallel
+        * "linkcount" data structure ensures that no room ends up with more
+        * than three links, regardless of the quality of the random number
+        * generator that we're using.
+        */
+       srandom((int)time((time_t *)0));
+
+       /* initialize the cave first off. */
+       for (i = 1; i <= room_num; ++i)
+               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));
+
+       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 */
+       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;
+                       /* skip duplicates */
+                       for (k = 0; k < j; k++)
+                               if (cave[i].tunnel[k] == link)
+                                       goto try_again;
+                       cave[i].tunnel[j] = link;
+                       if (random() % 2 == 1)
+                               continue;
+                       for (k = 0; k < link_num; ++k) {
+                               /* 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;
+                               }
+                       }
+               }
+       /*
+        * now that we're done, sort the tunnels in each of the rooms to
+        * make it easier on the intrepid adventurer.
+        */
+       for (i = 1; i <= room_num; ++i)
+               qsort(cave[i].tunnel, (u_int)link_num,
+                   sizeof(cave[i].tunnel[0]), int_compare);
+
+#ifdef DEBUG
+       if (debug)
+               for (i = 1; i <= room_num; ++i) {
+                       (void)printf("<room %d  has tunnels to ", i);
+                       for (j = 0; j < link_num; ++j)
+                               (void)printf("%d ", cave[i].tunnel[j]);
+                       (void)printf(">\n");
+               }
+#endif
+}
+
+clear_things_in_cave()
+{
+       register int i;
+
+       /*
+        * remove bats and pits from the current cave in preparation for us
+        * adding new ones via the initialize_things_in_cave() routines.
+        */
+       for (i = 1; i <= room_num; ++i)
+               cave[i].has_a_bat = cave[i].has_a_pit = 0;
+}
+
+initialize_things_in_cave()
+{
+       register int i, loc;
+
+       /* place some bats, pits, the wumpus, and the player. */
+       for (i = 0; i < bat_num; ++i) {
+               do {
+                       loc = (random() % room_num) + 1;
+               } while (cave[loc].has_a_bat);
+               cave[loc].has_a_bat = 1;
+#ifdef DEBUG
+               if (debug)
+                       (void)printf("<bat in room %d>\n", loc);
+#endif
+       }
+
+       for (i = 0; i < pit_num; ++i) {
+               do {
+                       loc = (random() % room_num) + 1;
+               } while (cave[loc].has_a_pit && cave[loc].has_a_bat);
+               cave[loc].has_a_pit = 1;
+#ifdef DEBUG
+               if (debug)
+                       (void)printf("<pit in room %d>\n", loc);
+#endif
+       }
+
+       wumpus_loc = (random() % room_num) + 1;
+#ifdef DEBUG
+       if (debug)
+               (void)printf("<wumpus in room %d>\n", 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));
+}
+
+getans(prompt)
+       char *prompt;
+{
+       char buf[20];
+
+       /*
+        * simple routine to ask the yes/no question specified until the user
+        * answers yes or no, then return 1 if they said 'yes' and 0 if they
+        * answered 'no'.
+        */
+       for (;;) {
+               (void)printf("%s", prompt);
+               (void)fflush(stdout);
+               if (!fgets(buf, sizeof(buf), stdin))
+                       return(0);
+               if (*buf == 'N' || *buf == 'n')
+                       return(0);
+               if (*buf == 'Y' || *buf == 'y')
+                       return(1);
+               (void)printf(
+"I don't understand your answer; please enter 'y' or 'n'!\n");
+       }
+       /* NOTREACHED */
+}
+
+bats_nearby()
+{ 
+       register int i;
+
+       /* check for bats in the immediate vicinity */
+       for (i = 0; i < link_num; ++i)
+               if (cave[cave[player_loc].tunnel[i]].has_a_bat)
+                       return(1);
+       return(0);
+}
+
+pit_nearby()
+{ 
+       register int i;
+
+       /* check for pits in the immediate vicinity */
+       for (i = 0; i < link_num; ++i)
+               if (cave[cave[player_loc].tunnel[i]].has_a_pit)
+                       return(1);
+       return(0);
+}
+
+wump_nearby()
+{
+       register int i, j;
+
+       /* check for a wumpus within TWO caves of where we are */
+       for (i = 0; i < link_num; ++i) {
+               if (cave[player_loc].tunnel[i] == wumpus_loc)
+                       return(1);
+               for (j = 0; j < link_num; ++j)
+                       if (cave[cave[player_loc].tunnel[i]].tunnel[j] ==
+                           wumpus_loc)
+                               return(1);
+       }
+       return(0);
+}
+
+move_wump()
+{
+       wumpus_loc = cave[wumpus_loc].tunnel[random() % link_num];
+}
+
+int_compare(a, b)
+       int *a, *b;
+{
+       return(*a < *b ? -1 : 1);
+}
+
+instructions()
+{
+       char buf[120], *p, *getenv();
+
+       /*
+        * read the instructions file, if needed, and show the user how to
+        * play this game!
+        */
+       if (!getans("Instructions? (y-n) "))
+               return;
+
+       if (access(_PATH_WUMPINFO, R_OK)) {
+               (void)printf(
+"Sorry, but the instruction file seems to have disappeared in a\n\
+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);
+}
+
+usage()
+{
+       (void)fprintf(stderr,
+"usage: wump [-h] [-a arrows] [-b bats] [-p pits] [-r rooms] [-t tunnels]\n");
+       exit(1);
+}
+
+/* messages */
+
+wump_kill()
+{
+       (void)printf(
+"*ROAR* *chomp* *snurfle* *chomp*!\n\
+Much to the delight of the Wumpus, you walked 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");
+}
+
+kill_wump()
+{
+       (void)printf(
+"*thwock!* *groan* *crash*\n\n\
+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\
+mightiest adventurer at a single whiff!!\n");
+}
+
+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\
+you, and with a mighty *ROAR* eats you alive!\n");
+}
+
+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\
+(*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);
+}
+
+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\
+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");
+}
+
+pit_survive()
+{
+       (void)printf(
+"Without conscious thought you grab for the side of the cave and manage\n\
+to grasp onto a rocky outcrop.  Beneath your feet stretches the limitless\n\
+depths of a bottomless pit!  Rock crumbles beneath your feet!\n");
+}