file locking with flock(), plus error return from Sync().
[unix-history] / usr / src / games / wump / wump.c
CommitLineData
52230e1a
KM
1
2static 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
18struct room
19{
20 int tunn[NTUNN];
21 int flag;
22} room[NROOM];
23
24char *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
95int arrow;
96int loc;
97int wloc;
98int tchar;
99
100main()
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
116init:
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
154setup:
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
190loop:
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
222again:
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
273mwump:
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
282done:
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
294tunnel(i)
295{
296 register struct room *p;
297 register n, j;
298 int c;
299
300 c = 20;
301
302loop:
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
316rline()
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
331rnum(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
343rin()
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
364near(ap, ahaz)
365struct 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
378icomp(p1, p2)
379int *p1, *p2;
380{
381
382 return(*p1 - *p2);
383}
384#include <sgtty.h>
385drain()
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}