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: }