wumpus.c (7372B)
1 // Copyright Creative Computing, Morristown, New Jersey 2 // C conversion by Payton Byrd from BASIC in "More BASIC 3 // Computer Games" by Creative Computing. 4 // 5 // Adapted for CC65 by gb 6 7 #include <ctype.h> 8 #include <stdlib.h> 9 #include <stdio.h> 10 #include <string.h> 11 #include <stdbool.h> 12 #include <time.h> 13 #include <conio.h> 14 15 unsigned char arrows = 5u; 16 17 unsigned char items[6]; 18 19 // Rooms and their connections 20 const unsigned char rooms[20][3] = 21 { 22 { 2, 5, 8 }, // 1 23 { 1, 3, 10 }, // 2 24 { 2, 4, 12 }, // 3 25 { 3, 5, 14 }, // 4 26 { 1, 4, 6 }, // 5 27 { 5, 7, 15 }, // 6 28 { 6, 8, 17 }, // 7 29 { 1, 7, 9 }, // 8 30 { 8, 10, 18 }, // 9 31 { 2, 9, 11 }, // 10 32 { 10, 12, 19 }, // 11 33 { 3, 11, 13 }, // 12 34 { 12, 14, 20 }, // 13 35 { 4, 13, 15 }, // 14 36 { 6, 14, 16 }, // 15 37 { 15, 17, 20 }, // 16 38 { 7, 16, 18 }, // 17 39 { 9, 17, 19 }, // 18 40 { 11, 18, 20 }, // 19 41 { 13, 16, 19 } // 20 42 }; 43 44 // Generates a random number between 1 and 20 45 unsigned char fna() 46 { 47 return (unsigned char)(rand() % 20u + 1u); 48 } 49 50 // Generates a random number between 1 and 3 51 unsigned char fnb() 52 { 53 return (unsigned char)(rand() % 3u + 1u); 54 } 55 56 // Generates a random number between 1 and 4 57 unsigned char fnc() 58 { 59 return (unsigned char)(rand() % 4u + 1u); 60 } 61 62 // Ensures all items are in different rooms. 63 bool validateItems(void) 64 { 65 unsigned char i, j; 66 67 for(i = 0; i < 6; ++i) 68 { 69 for(j = 0; j < 6; ++j) 70 { 71 if(i != j) 72 { 73 if(items[i] == items[j]) 74 { 75 // OOPS, two items in 76 // same room, no good! 77 return false; 78 } 79 } 80 } 81 } 82 83 return true; 84 } 85 86 // Place each item in a separate room. 87 void randomizeItems(unsigned int seed) 88 { 89 // Seeding of RNG changed by gb 90 srand(seed); 91 92 do 93 { 94 items[0] = fna(); // You 95 items[1] = fna(); // Wumpus 96 items[2] = fna(); // Bat 97 items[3] = fna(); // Bat 98 items[4] = fna(); // Pit 99 items[5] = fna(); // Pit 100 } 101 while(!validateItems()); 102 } 103 104 // Displays information about the current room. 105 void printLocation() 106 { 107 unsigned char k; 108 109 cputs("\r\n"); 110 111 for(k = 0; k < 3; ++k) 112 { 113 if(rooms[items[0]-1][k] == items[1]) 114 { 115 cputs("I smell a wumpus!\r\n"); 116 } 117 118 if(rooms[items[0]-1][k] == items[2] 119 || rooms[items[0]-1][k] == items[3]) 120 { 121 cputs("Bats nearby!\r\n"); 122 } 123 124 if(rooms[items[0]-1][k] == items[4] 125 || rooms[items[0]-1][k] == items[5]) 126 { 127 cputs("I feel a draft!\r\n"); 128 } 129 } 130 131 cprintf("You are in room %u\r\n", items[0]); 132 cprintf("Tunnels lead to %u, %u, %u\r\n", 133 rooms[items[0]-1][0], 134 rooms[items[0]-1][1], 135 rooms[items[0]-1][2]); 136 } 137 138 // User selects whether to shoot or move. 139 unsigned char chooseOption() 140 { 141 unsigned char input = '\0'; 142 143 while(input != 'm' && input != 's' && input != 'q') 144 { 145 cprintf("\r\nShoot or move [M or S]: "); 146 input = cgetc(); 147 tolower(input); 148 } 149 150 return input; 151 } 152 153 // User selects the number of rooms 154 // to shoot the arrow through. 155 unsigned char chooseNumberOfRooms() 156 { 157 unsigned char input = 0; 158 unsigned char result[1] = ""; 159 160 while(input < '1' || input > '5') 161 { 162 cprintf("\r\nNo. of rooms (1-5):"); 163 input = cgetc(); 164 } 165 166 sprintf(result, "%c", input); 167 168 return (unsigned char)atoi(result); 169 } 170 171 // User selects a room adjacent to the current 172 // room. 173 unsigned char chooseRoom(unsigned char currentRoom) 174 { 175 char input[3]; 176 char selectedRoom; 177 int result = -1; 178 179 do 180 { 181 cprintf("\r\nChoose room [%u, %u, %u]: ", 182 rooms[currentRoom - 1][0], 183 rooms[currentRoom - 1][1], 184 rooms[currentRoom - 1][2]); 185 186 cscanf("%s", input); 187 188 selectedRoom = (unsigned char)atoi(input); 189 190 if(selectedRoom == rooms[currentRoom - 1][0] 191 || selectedRoom == rooms[currentRoom - 1][1] 192 || selectedRoom == rooms[currentRoom - 1][2]) 193 { 194 result = selectedRoom; 195 } 196 } 197 while(result == -1); 198 199 cputs("\r\n"); 200 201 return (unsigned char)result; 202 } 203 204 // User fires an arrow 205 char shootArrow() 206 { 207 unsigned char counter, room; 208 unsigned char numberOfRooms; 209 210 // Get the number of rooms for the arrow 211 // to travel. 212 numberOfRooms = chooseNumberOfRooms(); 213 214 // Start in our room. 215 room = items[0]; 216 217 // Loop the number of rooms selected. 218 for(counter = 0; counter < numberOfRooms; ++counter) 219 { 220 // Move arrow to chosen room. 221 room = chooseRoom(room); 222 } 223 224 // Did we hit him? 225 if(room == items[1]) 226 { 227 cputs("\r\nAHA! You got the Wumpus!\r\n"); 228 return 1; 229 } 230 231 // Did we hit ourself? 232 if(room == items[0]) 233 { 234 cputs("\r\nOUCH! The arrow got you!\r\n"); 235 return -1; 236 } 237 238 // Decrement arrow count 239 --arrows; 240 cputs("\r\nMissed.\r\n"); 241 242 if(arrows == 0) 243 { 244 // Uh oh. 245 cputs("\r\nYou are out of arrows!\r\n"); 246 return -1; 247 } 248 249 return 0; 250 } 251 252 // Moves the wumpus. 253 char moveWumpus() 254 { 255 // Randomly chooses another room. 256 items[1] = rooms[items[1]][fnc()]; 257 258 // Are we sharing a room with the wumpus now? 259 if(items[1] == items[0]) 260 { 261 cputs("\r\n\r\nTSK TSK TSK - Wumpus got you!"); 262 return 1; 263 } 264 265 return 0; 266 } 267 268 // Move the player 269 char movePlayer() 270 { 271 unsigned char newRoom = 0; 272 char wumpusResult; 273 274 // Choose the room to move to. 275 newRoom = chooseRoom(items[0]); 276 277 // Did we actually move? 278 if(items[0] == newRoom) 279 { 280 cputs("Can't stay still!"); 281 return 0; 282 } 283 284 // Set the items array to our new 285 // room. 286 items[0] = newRoom; 287 288 // Did we find the wumpus? 289 if(items[1] == newRoom) 290 { 291 // Yup, make him move. 292 cputs("\r\n\r\n... OOPS! Bumped a Wumpus!\r\n"); 293 294 wumpusResult = moveWumpus(); 295 296 return wumpusResult; 297 } 298 // Did we find a bat? 299 else if(items[2] == newRoom || items[3] == newRoom) 300 { 301 // Yup, it's off to Elsewhereville with the player 302 cputs("\r\n\r\nZAP--Super Bat Snatch!! Elsewhereville for you!\r\n"); 303 304 // Player's position is randomly selected from 305 // all 20 rooms. 306 items[0] = fna(); 307 } 308 // Did we find a pit? 309 else if(items[4] == newRoom || items[5] == newRoom) 310 { 311 // Dum, dum, de dum... 312 cputs("\r\n\r\nYYYIIIIEEEE . . . Fell in pit!\r\n"); 313 return 1; 314 } 315 316 return 0; 317 } 318 319 // Ye old main routine. 320 void main(void) 321 { 322 unsigned char option, shootResult; 323 unsigned int seed; 324 325 // Polite header. 326 #ifdef __CBM__ 327 putchar(147); 328 #endif 329 cputs("\r\nPress a key.\r\n"); 330 while(!kbhit()){ 331 ++seed; 332 } 333 cgetc(); 334 335 cputs(" WUMPUS!\r\n"); 336 cputs(" CREATIVE COMPUTING\r\n"); 337 cputs(" Morristown, NJ\r\n"); 338 cputs(" Converted to C by Payton Byrd\r\n"); 339 340 341 // Put everything in it's place. 342 randomizeItems(seed); 343 344 // Loop until someone gets hurt. 345 for(;;) 346 { 347 cputs("\r\n"); 348 349 // Display the location to the user. 350 printLocation(); 351 352 // Get their choice of move or shoot 353 option = tolower(chooseOption()); 354 if(option == 'q') 355 break; 356 357 if(option == 's') 358 { 359 // They chose to shoot. Get result. 360 shootResult = shootArrow(); 361 362 if(shootResult != 0) 363 { 364 // Something got shot 365 break; 366 } 367 } 368 else 369 { 370 // They chose to move. Get result. 371 if(movePlayer() == 1) 372 { 373 // Something bad happened to the player. 374 break; 375 } 376 } 377 } 378 // That's all, folks! 379 cputs("\r\nThanks for playing!\r\n"); 380 cgetc(); 381 }