1 /* $NetBSD: cypher.c,v 1.24 2021/05/02 12:50:43 rillig Exp $ */ 2 3 /* 4 * Copyright (c) 1983, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)cypher.c 8.2 (Berkeley) 4/28/95"; 36 #else 37 __RCSID("$NetBSD: cypher.c,v 1.24 2021/05/02 12:50:43 rillig Exp $"); 38 #endif 39 #endif /* not lint */ 40 41 #include "extern.h" 42 43 int 44 cypher(void) 45 { 46 int n; 47 int junk; 48 int lflag = -1; 49 char buffer[10]; 50 char *filename, *rfilename; 51 size_t filename_len; 52 53 while (wordnumber <= wordcount) { 54 if (wordtype[wordnumber] != VERB && 55 !(wordtype[wordnumber] == OBJECT && 56 wordvalue[wordnumber] == KNIFE)) { 57 printf("%s: How's that?\n", 58 (wordnumber == wordcount) ? words[0] : 59 words[wordnumber]); 60 return (-1); 61 } 62 63 switch (wordvalue[wordnumber]) { 64 65 case AUXVERB: 66 /* 67 * Take the following word as the verb (e.g. 68 * "make love", "climb up"). 69 */ 70 wordnumber++; 71 continue; 72 73 case UP: 74 if (location[position].access || wiz || tempwiz) { 75 if (!location[position].access) { 76 printf("Zap! A gust of wind lifts "); 77 puts("you up."); 78 } 79 if (!moveplayer(location[position].up, AHEAD)) 80 return (-1); 81 } else { 82 puts("There is no way up."); 83 return (-1); 84 } 85 lflag = 0; 86 break; 87 88 case DOWN: 89 if (!moveplayer(location[position].down, AHEAD)) 90 return (-1); 91 lflag = 0; 92 break; 93 94 case LEFT: 95 if (!moveplayer(left, LEFT)) 96 return (-1); 97 lflag = 0; 98 break; 99 100 case RIGHT: 101 if (!moveplayer(right, RIGHT)) 102 return (-1); 103 lflag = 0; 104 break; 105 106 case AHEAD: 107 if (!moveplayer(ahead, AHEAD)) 108 return (-1); 109 lflag = 0; 110 break; 111 112 case BACK: 113 if (!moveplayer(back, BACK)) 114 return (-1); 115 lflag = 0; 116 break; 117 118 case SHOOT: 119 if (wordnumber < wordcount && 120 wordvalue[wordnumber + 1] == EVERYTHING) { 121 int things; 122 things = 0; 123 for (n = 0; n < NUMOFOBJECTS; n++) 124 if (testbit(location[position].objects, 125 n) && objsht[n]) { 126 things++; 127 wordvalue[wordnumber + 1] = n; 128 wordnumber = shoot(); 129 } 130 if (!things) 131 puts("Nothing to shoot at!"); 132 wordnumber++; 133 wordnumber++; 134 } else 135 shoot(); 136 break; 137 138 case TAKE: 139 if (wordnumber < wordcount && 140 wordvalue[wordnumber + 1] == EVERYTHING) { 141 int things; 142 things = 0; 143 for (n = 0; n < NUMOFOBJECTS; n++) 144 if (testbit(location[position].objects, 145 n) && objsht[n]) { 146 things++; 147 wordvalue[wordnumber + 1] = n; 148 /* Some objects (type NOUNS) 149 * have special treatment in 150 * take(). For these we 151 * must set the type to NOUNS. 152 * However for SWORD and BODY 153 * all it does is find which 154 * of many objects is meant, 155 * so we need do nothing here. 156 * BATHGOD must become 157 * NORMGOD as well. NOUNS 158 * with no special case 159 * must be included here to 160 * get the right error. DOOR 161 * cannot occur as an object 162 * so need not be included. */ 163 switch(n) { 164 case BATHGOD: 165 wordvalue[wordnumber + 1] = NORMGOD; 166 /* FALLTHROUGH */ 167 case NORMGOD: 168 case AMULET: 169 case MEDALION: 170 case TALISMAN: 171 case MAN: 172 case TIMER: 173 case NATIVE: 174 wordtype[wordnumber + 1] = NOUNS; 175 break; 176 default: 177 wordtype[wordnumber + 1] = OBJECT; 178 } 179 wordnumber = take(location[position].objects); 180 } 181 wordnumber++; 182 wordnumber++; 183 if (!things) 184 puts("Nothing to take!"); 185 } else 186 take(location[position].objects); 187 break; 188 189 case DROP: 190 if (wordnumber < wordcount && 191 wordvalue[wordnumber + 1] == EVERYTHING) { 192 int things; 193 things = 0; 194 for (n = 0; n < NUMOFOBJECTS; n++) 195 if (testbit(inven, n)) { 196 things++; 197 wordvalue[wordnumber + 1] = n; 198 wordnumber = drop("Dropped"); 199 } 200 wordnumber++; 201 wordnumber++; 202 if (!things) 203 puts("Nothing to drop!"); 204 } else 205 drop("Dropped"); 206 break; 207 208 case KICK: 209 case THROW: 210 if (wordnumber < wordcount && 211 wordvalue[wordnumber + 1] == EVERYTHING) { 212 int things, wv; 213 things = 0; 214 wv = wordvalue[wordnumber]; 215 for (n = 0; n < NUMOFOBJECTS; n++) 216 if (testbit(inven, n) || 217 (testbit(location[position].objects, n) && objsht[n])) { 218 things++; 219 wordvalue[wordnumber + 1] = n; 220 wordnumber = throw(wordvalue[wordnumber] == KICK ? "Kicked" : "Thrown"); 221 } 222 wordnumber += 2; 223 if (!things) 224 printf("Nothing to %s!\n", 225 wv == KICK ? "kick" : "throw"); 226 } else 227 throw(wordvalue[wordnumber] == 228 KICK ? "Kicked" : "Thrown"); 229 break; 230 231 case TAKEOFF: 232 if (wordnumber < wordcount && 233 wordvalue[wordnumber + 1] == EVERYTHING) { 234 int things; 235 things = 0; 236 for (n = 0; n < NUMOFOBJECTS; n++) 237 if (testbit(wear, n)) { 238 things++; 239 wordvalue[wordnumber + 1] = n; 240 wordnumber = takeoff(); 241 } 242 wordnumber += 2; 243 if (!things) 244 puts("Nothing to take off!"); 245 } else 246 takeoff(); 247 break; 248 249 case DRAW: 250 if (wordnumber < wordcount && 251 wordvalue[wordnumber + 1] == EVERYTHING) { 252 int things; 253 things = 0; 254 for (n = 0; n < NUMOFOBJECTS; n++) 255 if (testbit(wear, n)) { 256 things++; 257 wordvalue[wordnumber + 1] = n; 258 wordnumber = draw(); 259 } 260 wordnumber += 2; 261 if (!things) 262 puts("Nothing to draw!"); 263 } else 264 draw(); 265 break; 266 267 case PUTON: 268 if (wordnumber < wordcount && 269 wordvalue[wordnumber + 1] == EVERYTHING) { 270 int things; 271 things = 0; 272 for (n = 0; n < NUMOFOBJECTS; n++) 273 if (testbit(location[position].objects, 274 n) && objsht[n]) { 275 things++; 276 wordvalue[wordnumber + 1] = n; 277 wordnumber = puton(); 278 } 279 wordnumber += 2; 280 if (!things) 281 puts("Nothing to put on!"); 282 } else 283 puton(); 284 break; 285 286 case WEARIT: 287 if (wordnumber < wordcount && 288 wordvalue[wordnumber + 1] == EVERYTHING) { 289 int things; 290 things = 0; 291 for (n = 0; n < NUMOFOBJECTS; n++) 292 if (testbit(inven, n)) { 293 things++; 294 wordvalue[wordnumber + 1] = n; 295 wordnumber = wearit(); 296 } 297 wordnumber += 2; 298 if (!things) 299 puts("Nothing to wear!"); 300 } else 301 wearit(); 302 break; 303 304 case EAT: 305 if (wordnumber < wordcount && 306 wordvalue[wordnumber + 1] == EVERYTHING) { 307 int things; 308 things = 0; 309 for (n = 0; n < NUMOFOBJECTS; n++) 310 if (testbit(inven, n)) { 311 things++; 312 wordvalue[wordnumber + 1] = n; 313 wordnumber = eat(); 314 } 315 wordnumber += 2; 316 if (!things) 317 puts("Nothing to eat!"); 318 } else 319 eat(); 320 break; 321 322 case PUT: 323 put(); 324 break; 325 326 case INVEN: 327 if (ucard(inven)) { 328 puts("You are holding:\n"); 329 for (n = 0; n < NUMOFOBJECTS; n++) 330 if (testbit(inven, n)) 331 printf("\t%s\n", objsht[n]); 332 if (WEIGHT == 0) { 333 printf("\n= %d kilogram%s", 334 carrying, 335 (carrying == 1 ? "." : "s.")); 336 printf(" (can't lift any weight%s)\n", 337 (carrying ? 338 " or move with what you have" : 339 "")); 340 } else 341 printf("\n= %d kilogram%s (%d%%)\n", 342 carrying, 343 (carrying == 1 ? "." : "s."), 344 carrying * 100 / WEIGHT); 345 if (CUMBER == 0) { 346 printf("Your arms can't pick "); 347 printf("anything up.\n"); 348 } else 349 printf("Your arms are %d%% full.\n", 350 encumber * 100 / CUMBER); 351 } else 352 puts("You aren't carrying anything."); 353 354 if (ucard(wear)) { 355 puts("\nYou are wearing:\n"); 356 for (n = 0; n < NUMOFOBJECTS; n++) 357 if (testbit(wear, n)) 358 printf("\t%s\n", objsht[n]); 359 } else 360 puts("\nYou are stark naked."); 361 if (card(injuries, NUMOFINJURIES)) { 362 puts("\nYou have suffered:\n"); 363 for (n = 0; n < NUMOFINJURIES; n++) 364 if (injuries[n]) 365 printf("\t%s\n", ouch[n]); 366 printf("\nYou can still carry up to "); 367 printf("%d kilogram%s\n", WEIGHT, 368 (WEIGHT == 1 ? "." : "s.")); 369 } else 370 puts("\nYou are in perfect health."); 371 wordnumber++; 372 break; 373 374 case USE: 375 lflag = use(); 376 break; 377 378 case OPEN: 379 if (wordnumber < wordcount && 380 wordvalue[wordnumber + 1] == EVERYTHING) { 381 int things; 382 things = 0; 383 for (n = 0; n < NUMOFOBJECTS; n++) 384 if (testbit(inven, n)) { 385 things++; 386 wordvalue[wordnumber + 1] = n; 387 dooropen(); 388 } 389 wordnumber += 2; 390 if (!things) 391 puts("Nothing to open!"); 392 } else 393 dooropen(); 394 break; 395 396 case LOOK: 397 if (!notes[CANTSEE] || testbit(inven, LAMPON) || 398 testbit(location[position].objects, LAMPON) 399 || matchlight) { 400 beenthere[position] = 2; 401 writedes(); 402 printobjs(); 403 if (matchlight) { 404 puts("\nYour match splutters out."); 405 matchlight = 0; 406 } 407 } else 408 puts("I can't see anything."); 409 return (-1); 410 break; 411 412 case SU: 413 if (wiz || tempwiz) { 414 printf("\nRoom (was %d) = ", position); 415 fgets(buffer, 10, stdin); 416 if (*buffer != '\n') 417 sscanf(buffer, "%d", &position); 418 printf("Time (was %d) = ", ourtime); 419 fgets(buffer, 10, stdin); 420 if (*buffer != '\n') 421 sscanf(buffer, "%d", &ourtime); 422 printf("Fuel (was %d) = ", fuel); 423 fgets(buffer, 10, stdin); 424 if (*buffer != '\n') 425 sscanf(buffer, "%d", &fuel); 426 printf("Torps (was %d) = ", torps); 427 fgets(buffer, 10, stdin); 428 if (*buffer != '\n') 429 sscanf(buffer, "%d", &torps); 430 printf("CUMBER (was %d) = ", CUMBER); 431 fgets(buffer, 10, stdin); 432 if (*buffer != '\n') 433 sscanf(buffer, "%d", &CUMBER); 434 printf("WEIGHT (was %d) = ", WEIGHT); 435 fgets(buffer, 10, stdin); 436 if (*buffer != '\n') 437 sscanf(buffer, "%d", &WEIGHT); 438 printf("Clock (was %d) = ", ourclock); 439 fgets(buffer, 10, stdin); 440 if (*buffer != '\n') 441 sscanf(buffer, "%d", &ourclock); 442 printf("Wizard (was %d, %d) = ", wiz, tempwiz); 443 fgets(buffer, 10, stdin); 444 if (*buffer != '\n') { 445 sscanf(buffer, "%d", &junk); 446 if (!junk) 447 tempwiz = wiz = 0; 448 } 449 printf("\nDONE.\n"); 450 return (0); 451 } else 452 puts("You aren't a wizard."); 453 break; 454 455 case SCORE: 456 printf("\tPLEASURE\tPOWER\t\tEGO\n"); 457 printf("\t%3d\t\t%3d\t\t%3d\n\n", pleasure, power, ego); 458 printf("This gives you the rating of "); 459 printf("%s in %d turns.\n", rate(), ourtime); 460 printf("You have visited %d out of %d rooms ", 461 card(beenthere, NUMOFROOMS), NUMOFROOMS); 462 printf("this run (%d%%).\n", 463 card(beenthere, NUMOFROOMS) * 100 / NUMOFROOMS); 464 break; 465 466 case KNIFE: 467 case KILL: 468 murder(); 469 break; 470 471 case UNDRESS: 472 case RAVAGE: 473 ravage(); 474 break; 475 476 case SAVE: 477 printf("\nSave file name (default %s): ", 478 DEFAULT_SAVE_FILE); 479 filename = fgetln(stdin, &filename_len); 480 if (filename_len == 0 481 || (filename_len == 1 && filename[0] == '\n')) 482 rfilename = save_file_name(DEFAULT_SAVE_FILE, 483 strlen(DEFAULT_SAVE_FILE)); 484 else { 485 if (filename[filename_len - 1] == '\n') 486 filename_len--; 487 rfilename = save_file_name(filename, 488 filename_len); 489 } 490 save(rfilename); 491 free(rfilename); 492 break; 493 494 case VERBOSE: 495 verbose = 1; 496 printf("[Maximum verbosity]\n"); 497 break; 498 499 case BRIEF: 500 verbose = 0; 501 printf("[Standard verbosity]\n"); 502 break; 503 504 case FOLLOW: 505 lflag = follow(); 506 break; 507 508 case GIVE: 509 give(); 510 break; 511 512 case KISS: 513 kiss(); 514 break; 515 516 case LOVE: 517 love(); 518 break; 519 520 case RIDE: 521 lflag = ride(); 522 break; 523 524 case DRIVE: 525 lflag = drive(); 526 break; 527 528 case LIGHT: 529 light(); 530 break; 531 532 case LAUNCH: 533 if (!launch()) 534 return (-1); 535 else 536 lflag = 0; 537 break; 538 539 case LANDIT: 540 if (!land()) 541 return (-1); 542 else 543 lflag = 0; 544 break; 545 546 case TIME: 547 chime(); 548 break; 549 550 case SLEEP: 551 zzz(); 552 break; 553 554 case DIG: 555 dig(); 556 break; 557 558 case JUMP: 559 lflag = jump(); 560 break; 561 562 case BURY: 563 bury(); 564 break; 565 566 case SWIM: 567 puts("Surf's up!"); 568 break; 569 570 case DRINK: 571 drink(); 572 break; 573 574 case QUIT: 575 die(); 576 577 default: 578 puts("How's that?"); 579 return (-1); 580 break; 581 582 } 583 if (wordnumber < wordcount && *words[wordnumber++] == ',') 584 continue; 585 else 586 return (lflag); 587 } 588 return (lflag); 589 } 590