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