1
2
3
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
14
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
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
155
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
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
389 drain()
390 {
391 fflush(stdout);
392
393
394
395
396
397
398
399 }
400
401 rani(n)
402 int n;
403 {
404 return(rand()%n);
405 }