1 /* $NetBSD: hack.read.c,v 1.4 1997/10/19 16:58:52 christos Exp $ */ 2 3 /* 4 * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. 5 */ 6 7 #include <sys/cdefs.h> 8 #ifndef lint 9 __RCSID("$NetBSD: hack.read.c,v 1.4 1997/10/19 16:58:52 christos Exp $"); 10 #endif /* not lint */ 11 12 #include <stdlib.h> 13 #include "hack.h" 14 #include "extern.h" 15 16 int 17 doread() 18 { 19 struct obj *scroll; 20 boolean confused = (Confusion != 0); 21 boolean known = FALSE; 22 23 scroll = getobj("?", "read"); 24 if (!scroll) 25 return (0); 26 if (!scroll->dknown && Blind) { 27 pline("Being blind, you cannot read the formula on the scroll."); 28 return (0); 29 } 30 if (Blind) 31 pline("As you pronounce the formula on it, the scroll disappears."); 32 else 33 pline("As you read the scroll, it disappears."); 34 if (confused) 35 pline("Being confused, you mispronounce the magic words ... "); 36 37 switch (scroll->otyp) { 38 #ifdef MAIL 39 case SCR_MAIL: 40 readmail( /* scroll */ ); 41 break; 42 #endif /* MAIL */ 43 case SCR_ENCHANT_ARMOR: 44 { 45 struct obj *otmp = some_armor(); 46 if (!otmp) { 47 strange_feeling(scroll, "Your skin glows then fades."); 48 return (1); 49 } 50 if (confused) { 51 pline("Your %s glows silver for a moment.", 52 objects[otmp->otyp].oc_name); 53 otmp->rustfree = 1; 54 break; 55 } 56 if (otmp->spe > 3 && rn2(otmp->spe)) { 57 pline("Your %s glows violently green for a while, then evaporates.", 58 objects[otmp->otyp].oc_name); 59 useup(otmp); 60 break; 61 } 62 pline("Your %s glows green for a moment.", 63 objects[otmp->otyp].oc_name); 64 otmp->cursed = 0; 65 otmp->spe++; 66 break; 67 } 68 case SCR_DESTROY_ARMOR: 69 if (confused) { 70 struct obj *otmp = some_armor(); 71 if (!otmp) { 72 strange_feeling(scroll, "Your bones itch."); 73 return (1); 74 } 75 pline("Your %s glows purple for a moment.", 76 objects[otmp->otyp].oc_name); 77 otmp->rustfree = 0; 78 break; 79 } 80 if (uarm) { 81 pline("Your armor turns to dust and falls to the floor!"); 82 useup(uarm); 83 } else if (uarmh) { 84 pline("Your helmet turns to dust and is blown away!"); 85 useup(uarmh); 86 } else if (uarmg) { 87 pline("Your gloves vanish!"); 88 useup(uarmg); 89 selftouch("You"); 90 } else { 91 strange_feeling(scroll, "Your skin itches."); 92 return (1); 93 } 94 break; 95 case SCR_CONFUSE_MONSTER: 96 if (confused) { 97 pline("Your hands begin to glow purple."); 98 Confusion += rnd(100); 99 } else { 100 pline("Your hands begin to glow blue."); 101 u.umconf = 1; 102 } 103 break; 104 case SCR_SCARE_MONSTER: 105 { 106 int ct = 0; 107 struct monst *mtmp; 108 109 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) 110 if (cansee(mtmp->mx, mtmp->my)) { 111 if (confused) 112 mtmp->mflee = mtmp->mfroz = 113 mtmp->msleep = 0; 114 else 115 mtmp->mflee = 1; 116 ct++; 117 } 118 if (!ct) { 119 if (confused) 120 pline("You hear sad wailing in the distance."); 121 else 122 pline("You hear maniacal laughter in the distance."); 123 } 124 break; 125 } 126 case SCR_BLANK_PAPER: 127 if (confused) 128 pline("You see strange patterns on this scroll."); 129 else 130 pline("This scroll seems to be blank."); 131 break; 132 case SCR_REMOVE_CURSE: 133 { 134 struct obj *obj; 135 if (confused) 136 pline("You feel like you need some help."); 137 else 138 pline("You feel like someone is helping you."); 139 for (obj = invent; obj; obj = obj->nobj) 140 if (obj->owornmask) 141 obj->cursed = confused; 142 if (Punished && !confused) { 143 Punished = 0; 144 freeobj(uchain); 145 unpobj(uchain); 146 free((char *) uchain); 147 uball->spe = 0; 148 uball->owornmask &= ~W_BALL; 149 uchain = uball = (struct obj *) 0; 150 } 151 break; 152 } 153 case SCR_CREATE_MONSTER: 154 { 155 int cnt = 1; 156 157 if (!rn2(73)) 158 cnt += rnd(4); 159 if (confused) 160 cnt += 12; 161 while (cnt--) 162 (void) makemon(confused ? PM_ACID_BLOB : 163 (struct permonst *) 0, u.ux, u.uy); 164 break; 165 } 166 case SCR_ENCHANT_WEAPON: 167 if (uwep && confused) { 168 pline("Your %s glows silver for a moment.", 169 objects[uwep->otyp].oc_name); 170 uwep->rustfree = 1; 171 } else if (!chwepon(scroll, 1)) /* tests for !uwep */ 172 return (1); 173 break; 174 case SCR_DAMAGE_WEAPON: 175 if (uwep && confused) { 176 pline("Your %s glows purple for a moment.", 177 objects[uwep->otyp].oc_name); 178 uwep->rustfree = 0; 179 } else if (!chwepon(scroll, -1)) /* tests for !uwep */ 180 return (1); 181 break; 182 case SCR_TAMING: 183 { 184 int i, j; 185 int bd = confused ? 5 : 1; 186 struct monst *mtmp; 187 188 for (i = -bd; i <= bd; i++) 189 for (j = -bd; j <= bd; j++) 190 if ((mtmp = m_at(u.ux + i, u.uy + j)) != NULL) 191 (void) tamedog(mtmp, (struct obj *) 0); 192 break; 193 } 194 case SCR_GENOCIDE: 195 { 196 extern char genocided[], fut_geno[]; 197 char buf[BUFSZ]; 198 struct monst *mtmp, *mtmp2; 199 200 pline("You have found a scroll of genocide!"); 201 known = TRUE; 202 if (confused) 203 *buf = u.usym; 204 else 205 do { 206 pline("What monster do you want to genocide (Type the letter)? "); 207 getlin(buf); 208 } while (strlen(buf) != 1 || !monstersym(*buf)); 209 if (!strchr(fut_geno, *buf)) 210 charcat(fut_geno, *buf); 211 if (!strchr(genocided, *buf)) 212 charcat(genocided, *buf); 213 else { 214 pline("Such monsters do not exist in this world."); 215 break; 216 } 217 for (mtmp = fmon; mtmp; mtmp = mtmp2) { 218 mtmp2 = mtmp->nmon; 219 if (mtmp->data->mlet == *buf) 220 mondead(mtmp); 221 } 222 pline("Wiped out all %c's.", *buf); 223 if (*buf == u.usym) { 224 killer = "scroll of genocide"; 225 u.uhp = -1; 226 } 227 break; 228 } 229 case SCR_LIGHT: 230 if (!Blind) 231 known = TRUE; 232 litroom(!confused); 233 break; 234 case SCR_TELEPORTATION: 235 if (confused) 236 level_tele(); 237 else { 238 #ifdef QUEST 239 int oux = u.ux, ouy = u.uy; 240 tele(); 241 if (dist(oux, ouy) > 100) 242 known = TRUE; 243 #else /* QUEST */ 244 int uroom = inroom(u.ux, u.uy); 245 tele(); 246 if (uroom != inroom(u.ux, u.uy)) 247 known = TRUE; 248 #endif /* QUEST */ 249 } 250 break; 251 case SCR_GOLD_DETECTION: 252 /* 253 * Unfortunately this code has become slightly less elegant, 254 * now that gold and traps no longer are of the same type. 255 */ 256 if (confused) { 257 struct trap *ttmp; 258 259 if (!ftrap) { 260 strange_feeling(scroll, "Your toes stop itching."); 261 return (1); 262 } else { 263 for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) 264 if (ttmp->tx != u.ux || ttmp->ty != u.uy) 265 goto outtrapmap; 266 /* 267 * only under me - no separate display 268 * required 269 */ 270 pline("Your toes itch!"); 271 break; 272 outtrapmap: 273 cls(); 274 for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) 275 at(ttmp->tx, ttmp->ty, '$'); 276 prme(); 277 pline("You feel very greedy!"); 278 } 279 } else { 280 struct gold *gtmp; 281 282 if (!fgold) { 283 strange_feeling(scroll, "You feel materially poor."); 284 return (1); 285 } else { 286 known = TRUE; 287 for (gtmp = fgold; gtmp; gtmp = gtmp->ngold) 288 if (gtmp->gx != u.ux || gtmp->gy != u.uy) 289 goto outgoldmap; 290 /* 291 * only under me - no separate display 292 * required 293 */ 294 pline("You notice some gold between your feet."); 295 break; 296 outgoldmap: 297 cls(); 298 for (gtmp = fgold; gtmp; gtmp = gtmp->ngold) 299 at(gtmp->gx, gtmp->gy, '$'); 300 prme(); 301 pline("You feel very greedy, and sense gold!"); 302 } 303 } 304 /* common sequel */ 305 more(); 306 docrt(); 307 break; 308 case SCR_FOOD_DETECTION: 309 { 310 int ct = 0, ctu = 0; 311 struct obj *obj; 312 char foodsym = confused ? POTION_SYM : FOOD_SYM; 313 314 for (obj = fobj; obj; obj = obj->nobj) 315 if (obj->olet == FOOD_SYM) { 316 if (obj->ox == u.ux && obj->oy == u.uy) 317 ctu++; 318 else 319 ct++; 320 } 321 if (!ct && !ctu) { 322 strange_feeling(scroll, "Your nose twitches."); 323 return (1); 324 } else if (!ct) { 325 known = TRUE; 326 pline("You smell %s close nearby.", 327 confused ? "something" : "food"); 328 329 } else { 330 known = TRUE; 331 cls(); 332 for (obj = fobj; obj; obj = obj->nobj) 333 if (obj->olet == foodsym) 334 at(obj->ox, obj->oy, FOOD_SYM); 335 prme(); 336 pline("Your nose tingles and you smell %s!", 337 confused ? "something" : "food"); 338 more(); 339 docrt(); 340 } 341 break; 342 } 343 case SCR_IDENTIFY: 344 /* known = TRUE; */ 345 if (confused) 346 pline("You identify this as an identify scroll."); 347 else 348 pline("This is an identify scroll."); 349 useup(scroll); 350 objects[SCR_IDENTIFY].oc_name_known = 1; 351 if (!confused) 352 while ( 353 !ggetobj("identify", identify, rn2(5) ? 1 : rn2(5)) 354 && invent 355 ); 356 return (1); 357 case SCR_MAGIC_MAPPING: 358 { 359 struct rm *lev; 360 int num, zx, zy; 361 362 known = TRUE; 363 pline("On this scroll %s a map!", 364 confused ? "was" : "is"); 365 for (zy = 0; zy < ROWNO; zy++) 366 for (zx = 0; zx < COLNO; zx++) { 367 if (confused && rn2(7)) 368 continue; 369 lev = &(levl[zx][zy]); 370 if ((num = lev->typ) == 0) 371 continue; 372 if (num == SCORR) { 373 lev->typ = CORR; 374 lev->scrsym = CORR_SYM; 375 } else if (num == SDOOR) { 376 lev->typ = DOOR; 377 lev->scrsym = '+'; 378 /* do sth in doors ? */ 379 } else if (lev->seen) 380 continue; 381 #ifndef QUEST 382 if (num != ROOM) 383 #endif /* QUEST */ 384 { 385 lev->seen = lev->new = 1; 386 if (lev->scrsym == ' ' || !lev->scrsym) 387 newsym(zx, zy); 388 else 389 on_scr(zx, zy); 390 } 391 } 392 break; 393 } 394 case SCR_AMNESIA: 395 { 396 int zx, zy; 397 398 known = TRUE; 399 for (zx = 0; zx < COLNO; zx++) 400 for (zy = 0; zy < ROWNO; zy++) 401 if (!confused || rn2(7)) 402 if (!cansee(zx, zy)) 403 levl[zx][zy].seen = 0; 404 docrt(); 405 pline("Thinking of Maud you forget everything else."); 406 break; 407 } 408 case SCR_FIRE: 409 { 410 int num = 0; 411 struct monst *mtmp; 412 413 known = TRUE; 414 if (confused) { 415 pline("The scroll catches fire and you burn your hands."); 416 losehp(1, "scroll of fire"); 417 } else { 418 pline("The scroll erupts in a tower of flame!"); 419 if (Fire_resistance) 420 pline("You are uninjured."); 421 else { 422 num = rnd(6); 423 u.uhpmax -= num; 424 losehp(num, "scroll of fire"); 425 } 426 } 427 num = (2 * num + 1) / 3; 428 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { 429 if (dist(mtmp->mx, mtmp->my) < 3) { 430 mtmp->mhp -= num; 431 if (strchr("FY", mtmp->data->mlet)) 432 mtmp->mhp -= 3 * num; /* this might well kill 433 * 'F's */ 434 if (mtmp->mhp < 1) { 435 killed(mtmp); 436 break; /* primitive */ 437 } 438 } 439 } 440 break; 441 } 442 case SCR_PUNISHMENT: 443 known = TRUE; 444 if (confused) { 445 pline("You feel guilty."); 446 break; 447 } 448 pline("You are being punished for your misbehaviour!"); 449 if (Punished) { 450 pline("Your iron ball gets heavier."); 451 uball->owt += 15; 452 break; 453 } 454 Punished = INTRINSIC; 455 setworn(mkobj_at(CHAIN_SYM, u.ux, u.uy), W_CHAIN); 456 setworn(mkobj_at(BALL_SYM, u.ux, u.uy), W_BALL); 457 uball->spe = 1; /* special ball (see save) */ 458 break; 459 default: 460 impossible("What weird language is this written in? (%u)", 461 scroll->otyp); 462 } 463 if (!objects[scroll->otyp].oc_name_known) { 464 if (known && !confused) { 465 objects[scroll->otyp].oc_name_known = 1; 466 more_experienced(0, 10); 467 } else if (!objects[scroll->otyp].oc_uname) 468 docall(scroll); 469 } 470 useup(scroll); 471 return (1); 472 } 473 474 int 475 identify(otmp) /* also called by newmail() */ 476 struct obj *otmp; 477 { 478 objects[otmp->otyp].oc_name_known = 1; 479 otmp->known = otmp->dknown = 1; 480 prinv(otmp); 481 return (1); 482 } 483 484 void 485 litroom(on) 486 boolean on; 487 { 488 #ifndef QUEST 489 int num, zx, zy; 490 #endif 491 492 /* first produce the text (provided he is not blind) */ 493 if (Blind) 494 goto do_it; 495 if (!on) { 496 if (u.uswallow || !xdnstair || levl[u.ux][u.uy].typ == CORR || 497 !levl[u.ux][u.uy].lit) { 498 pline("It seems even darker in here than before."); 499 return; 500 } else 501 pline("It suddenly becomes dark in here."); 502 } else { 503 if (u.uswallow) { 504 pline("%s's stomach is lit.", Monnam(u.ustuck)); 505 return; 506 } 507 if (!xdnstair) { 508 pline("Nothing Happens."); 509 return; 510 } 511 #ifdef QUEST 512 pline("The cave lights up around you, then fades."); 513 return; 514 #else /* QUEST */ 515 if (levl[u.ux][u.uy].typ == CORR) { 516 pline("The corridor lights up around you, then fades."); 517 return; 518 } else if (levl[u.ux][u.uy].lit) { 519 pline("The light here seems better now."); 520 return; 521 } else 522 pline("The room is lit."); 523 #endif /* QUEST */ 524 } 525 526 do_it: 527 #ifdef QUEST 528 return; 529 #else /* QUEST */ 530 if (levl[u.ux][u.uy].lit == on) 531 return; 532 if (levl[u.ux][u.uy].typ == DOOR) { 533 if (IS_ROOM(levl[u.ux][u.uy + 1].typ)) 534 zy = u.uy + 1; 535 else if (IS_ROOM(levl[u.ux][u.uy - 1].typ)) 536 zy = u.uy - 1; 537 else 538 zy = u.uy; 539 if (IS_ROOM(levl[u.ux + 1][u.uy].typ)) 540 zx = u.ux + 1; 541 else if (IS_ROOM(levl[u.ux - 1][u.uy].typ)) 542 zx = u.ux - 1; 543 else 544 zx = u.ux; 545 } else { 546 zx = u.ux; 547 zy = u.uy; 548 } 549 for (seelx = u.ux; (num = levl[seelx - 1][zy].typ) != CORR && num != 0; 550 seelx--); 551 for (seehx = u.ux; (num = levl[seehx + 1][zy].typ) != CORR && num != 0; 552 seehx++); 553 for (seely = u.uy; (num = levl[zx][seely - 1].typ) != CORR && num != 0; 554 seely--); 555 for (seehy = u.uy; (num = levl[zx][seehy + 1].typ) != CORR && num != 0; 556 seehy++); 557 for (zy = seely; zy <= seehy; zy++) 558 for (zx = seelx; zx <= seehx; zx++) { 559 levl[zx][zy].lit = on; 560 if (!Blind && dist(zx, zy) > 2) 561 if (on) 562 prl(zx, zy); 563 else 564 nosee(zx, zy); 565 } 566 if (!on) 567 seehx = 0; 568 #endif /* QUEST */ 569 } 570 571 /* Test whether we may genocide all monsters with symbol ch */ 572 int 573 monstersym(ch) /* arnold@ucsfcgl */ 574 char ch; 575 { 576 struct permonst *mp; 577 extern struct permonst pm_eel; 578 579 /* 580 * can't genocide certain monsters 581 */ 582 if (strchr("12 &:", ch)) 583 return FALSE; 584 585 if (ch == pm_eel.mlet) 586 return TRUE; 587 for (mp = mons; mp < &mons[CMNUM + 2]; mp++) 588 if (mp->mlet == ch) 589 return TRUE; 590 return FALSE; 591 } 592