1 /*
  2  * wump.c: version 1.2 of 10/20/82
  3  * Unix Game Source File
  4  */
  5 # ifdef SCCS
  6 static char *sccsid = "@(#)wump.c       1.2 (NSC) 10/20/82";
  7 # endif
  8 
  9 #
 10 #include <stdio.h>
 11 
 12 /*
 13  *        wumpus
 14  *        stolen from PCC Vol 2 No 1
 15  */
 16 
 17 #define   NBAT      3
 18 #define   NROOM     20
 19 #define   NTUNN     3
 20 #define   NPIT      3
 21 
 22 struct room
 23 {
 24           int       tunn[NTUNN];
 25           int       flag;
 26 } room[NROOM];
 27 
 28 char      *intro[] =
 29 {
 30           "\n",
 31           "Welcome to 'Hunt the Wumpus.'\n",
 32           "\n",
 33           "The Wumpus lives in a cave of %d rooms.\n",
 34           "Each room has %d tunnels leading to other rooms.\n",
 35           "\n",
 36           "Hazards:\n",
 37           "\n",
 38           "Bottomless Pits - Some rooms have Bottomless Pits in them.\n",
 39           "         If you go there, you fall into the pit and lose!\n",
 40           "Super Bats - Some other rooms have super bats.\n",
 41           "         If you go there, a bat will grab you and take you to\n",
 42           "         somewhere else in the cave where you could\n",
 43           "         fall into a pit or run into the . . .\n",
 44           "\n",
 45           "Wumpus:\n",
 46           "\n",
 47           "The Wumpus is not bothered by the hazards since\n",
 48           "he has sucker feet and is too big for a bat to lift.\n",
 49           "\n",
 50           "Usually he is asleep.\n",
 51           "Two things wake him up:\n",
 52           "         your entering his room\n",
 53           "         your shooting an arrow anywhere in the cave.\n",
 54           "If the wumpus wakes, he either decides to move one room or\n",
 55           "stay where he was.  But if he ends up where you are,\n",
 56           "he eats you up and you lose!\n",
 57           "\n",
 58           "You:\n",
 59           "\n",
 60           "Each turn you may either move or shoot a crooked arrow.\n",
 61           "\n",
 62           "Moving - You can move to one of the adjoining rooms;\n",
 63           "         that is, to one that has a tunnel connecting it with\n",
 64           "         the room you are in.\n",
 65           "\n",
 66           "Shooting - You have 5 arrows.  You lose when you run out.\n",
 67           "         Each arrow can go from 1 to 5 rooms.\n",
 68           "         You aim by telling the computer\n",
 69           "         The arrow's path is a list of room numbers\n",
 70           "         telling the arrow which room to go to next.\n",
 71           "         The list is terminated with a 0.\n",
 72           "         The first room in the path must be connected to the\n",
 73           "         room you are in.  Each succeeding room must be\n",
 74           "         connected to the previous room.\n",
 75           "         If there is no tunnel between two of the rooms\n",
 76           "         in the arrow's path, the arrow chooses one of the\n",
 77           "         three tunnels from the room it's in and goes its\n",
 78           "         own way.\n",
 79           "\n",
 80           "         If the arrow hits the wumpus, you win!\n",
 81           "         If the arrow hits you, you lose!\n",
 82           "\n",
 83           "Warnings:\n",
 84           "\n",
 85           "When you are one or two rooms away from the wumpus,\n",
 86           "the computer says:\n",
 87           "                   'I smell a Wumpus'\n",
 88           "When you are one room away from some other hazard, it says:\n",
 89           "                   Bat    - 'Bats nearby'\n",
 90           "                   Pit    - 'I feel a draft'\n",
 91           "\n",
 92           0,
 93 };
 94 
 95 #define   BAT       01
 96 #define   PIT       02
 97 #define   WUMP      04
 98 
 99 int       arrow;
100 int       loc;
101 int       wloc;
102 int       tchar;
103 
104 main()
105 {
106           register i, j;
107           register struct room *p;
108           int k, icomp();
109 
110           printf("Instructions? (y-n) ");
111           if(rline() == 'y')
112                     for(i=0; intro[i]; i++)
113                               printf(intro[i], i&1? NROOM: NTUNN);
114 
115 
116 /*
117  * initialize the room connections
118  */
119 
120 init:
121           p = &room[0];
122           for(i=0; i<NROOM; i++) {
123                     for(j=0; j<NTUNN; j++)
124                               p->tunn[j] = -1;
125                     p++;
126           }
127           k = 0;
128           for(i=1; i<NROOM; ) {
129                     j = rnum(NROOM);
130                     p = &room[j];
131                     if(j == k || p->tunn[0] >= 0 || p->tunn[1] >= 0)
132                               continue;
133                     p->tunn[1] = k;
134                     room[k].tunn[0] = j;
135                     k = j;
136                     i++;
137           }
138           p = &room[0];
139           for(i=0; i<NROOM; i++) {
140                     for(j=0; j<NTUNN; j++) {
141                               if(p->tunn[j] < 0)
142                                         p->tunn[j] = tunnel(i);
143                               if(p->tunn[j] == i)
144                                         goto init;
145                               for(k=0; k<j; k++)
146                                         if(p->tunn[j] == p->tunn[k])
147                                                   goto init;
148                     }
149                     qsort(&p->tunn[0], NTUNN, sizeof(p->tunn[0]), icomp);
150                     p++;
151           }
152 
153 /*
154  * put in player, wumpus,
155  * pits and bats
156  */
157 
158 setup:
159           arrow = 5;
160           p = &room[0];
161           for(i=0; i<NROOM; i++) {
162                     p->flag = 0;
163                     p++;
164           }
165           for(i=0; i<NPIT; ) {
166                     p = &room[rnum(NROOM)];
167                     if((p->flag&PIT) == 0) {
168                               p->flag |= PIT;
169                               i++;
170                     }
171           }
172           for(i=0; i<NBAT; ) {
173                     p = &room[rnum(NROOM)];
174                     if((p->flag&(PIT|BAT)) == 0) {
175                               p->flag |= BAT;
176                               i++;
177                     }
178           }
179           i = rnum(NROOM);
180           wloc = i;
181           room[i].flag |= WUMP;
182           for(;;) {
183                     i = rnum(NROOM);
184                     if((room[i].flag&(PIT|BAT|WUMP)) == 0) {
185                               loc = i;
186                               break;
187                     }
188           }
189 
190 /*
191  *        main loop of the game
192  */
193 
194 loop:
195           printf("You are in room %d\n", loc+1);
196           p = &room[loc];
197           if(p->flag&PIT) {
198                     printf("You fell into a pit\n");
199                     goto done;
200           }
201           if(p->flag&WUMP) {
202                     printf("You were eaten by the wumpus\n");
203                     goto done;
204           }
205           if(p->flag&BAT) {
206                     printf("Theres a bat in your room\n");
207                     loc = rnum(NROOM);
208                     goto loop;
209           }
210           for(i=0; i<NTUNN; i++)
211           if(near(&room[p->tunn[i]], WUMP))
212                     goto nearwump;
213           if (near(p, WUMP)) {
214           nearwump:
215                     printf("I smell a wumpus\n");
216           }
217           if (near(p, BAT))
218                     printf("Bats nearby\n");
219           if (near(p, PIT))
220                     printf("I feel a draft\n");
221           printf("There are tunnels to");
222           for(i=0; i<NTUNN; i++)
223                     printf(" %d", p->tunn[i]+1);
224           printf("\n");
225 
226 again:
227           printf("Move or shoot (m-s) ");
228           switch(rline()) {
229           case 'm':
230                     if(tchar == '\n')
231                               printf("which room? ");
232                     i = rin()-1;
233                     for(j=0; j<NTUNN; j++)
234                               if(i == p->tunn[j])
235                                         goto groom;
236                     printf("You hit the wall\n");
237                     goto again;
238           groom:
239                     loc = i;
240                     if(i == wloc)
241                               goto mwump;
242                     goto loop;
243 
244           case 's':
245                     if(tchar == '\n')
246                               printf("Give list of rooms terminated by 0\n");
247                     for(i=0; i<5; i++) {
248                               j = rin()-1;
249                               if(j == -1)
250                                         break;
251                     ranarw:
252                               for(k=0; k<NTUNN; k++)
253                                         if(j == p->tunn[k])
254                                                   goto garow;
255                               j = rnum(NROOM);
256                               goto ranarw;
257                     garow:
258                               p = &room[j];
259                               if(j == loc) {
260                                         printf("You shot yourself\n");
261                                         goto done;
262                               }
263                               if(p->flag&WUMP) {
264                                         printf("You slew the wumpus\n");
265                                         goto done;
266                               }
267                     }
268                     if(--arrow == 0) {
269                               printf("That was your last shot\n");
270                               goto done;
271                     }
272                     goto mwump;
273           }
274 
275           goto again;
276 
277 mwump:
278           p = &room[wloc];
279           p->flag &= ~WUMP;
280           i = rnum(NTUNN+1);
281           if(i != NTUNN)
282                     wloc = p->tunn[i];
283           room[wloc].flag |= WUMP;
284           goto loop;
285 
286 done:
287           drain();
288           printf("Another game? (y-n) ");
289           if(rline() != 'n') {
290                     drain();
291                     printf("Same room setup? (y-n) ");
292                     if(rline() != 'n')
293                               goto setup;
294                     goto init;
295           }
296 }
297 
298 tunnel(i)
299 {
300           register struct room *p;
301           register n, j;
302           int c;
303 
304           c = 20;
305 
306 loop:
307           n = rnum(NROOM);
308           if(n == i)
309                     if(--c > 0)
310                               goto loop;
311           p = &room[n];
312           for(j=0; j<NTUNN; j++)
313           if(p->tunn[j] == -1) {
314                     p->tunn[j] = i;
315                     return(n);
316           }
317           goto loop;
318 }
319 
320 rline()
321 {
322           register char c, r;
323 
324           while((c=getchar()) == ' ');
325           r = c;
326           while(c != '\n' && c != ' ') {
327                     if(c == EOF)
328                               exit(0);
329                     c = getchar();
330           }
331           tchar = c;
332           return(r);
333 }
334 
335 rnum(n)
336 {
337           static short first[2];
338 
339           if(first[1] == 0) {
340                     time(first);
341                     if(first[1]==0) first[1] = 1;
342                     srand((first[1]*first[0])^first[1]);
343           }
344           return(rani(n));
345 }
346 
347 rin()
348 {
349           register n, c;
350 
351           n = 0;
352           c = getchar();
353           while(c != '\n' && c != ' ') {
354                     if(c<'0' || c>'9') {
355                               while(c != '\n') {
356                                         if(c == EOF)
357                                                   exit(0);
358                                         c = getchar();
359                               }
360                               return(0);
361                     }
362                     n = n*10 + c-'0';
363                     c = getchar();
364           }
365           return(n);
366 }
367 
368 near(ap, ahaz)
369 struct room *ap;
370 {
371           register struct room *p;
372           register haz, i;
373 
374           p = ap;
375           haz = ahaz;
376           for(i=0; i<NTUNN; i++)
377           if(room[p->tunn[i]].flag & haz)
378                     return (1);
379           return(0);
380 }
381 
382 icomp(p1, p2)
383 int *p1, *p2;
384 {
385 
386           return(*p1 - *p2);
387 }
388 /*#include <sgtty.h>*/
389 drain()
390 {
391           fflush(stdout);
392           /*register FILE *port = stdin;
393           register int iodes = fileno(port);
394           struct sgttyb arg;
395 
396           port->_cnt = 0;
397           port->_ptr = port->_base;
398           if(gtty(iodes,&arg) != -1) stty(iodes,&arg);*/
399 }
400 
401 rani(n)
402 int n;
403 {
404     return(rand()%n);
405 }