xref: /original-bsd/games/wump/wump.c (revision aba77441)
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 }
395