|
|
1.1 root 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, sizeof(int), 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("There's 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 long first;
327:
328: if(first==0) {
329: time(&first);
330: srand((int)first);
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.