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