1/* SCCS Id: @(#)polyself.c 3.4 2003/01/08 */ 2/* Copyright (C) 1987, 1988, 1989 by Ken Arromdee */ 3/* NetHack may be freely redistributed. See license for details. */ 4 5/* 6 * Polymorph self routine. 7 * 8 * Note: the light source handling code assumes that both youmonst.m_id 9 * and youmonst.mx will always remain 0 when it handles the case of the 10 * player polymorphed into a light-emitting monster. 11 */ 12 13#include "hack.h" 14 15#ifdef OVLB 16STATIC_DCL void FDECL(polyman, (const char *,const char *)); 17STATIC_DCL void NDECL(break_armor); 18STATIC_DCL void FDECL(drop_weapon,(int)); 19STATIC_DCL void NDECL(uunstick); 20STATIC_DCL int FDECL(armor_to_dragon,(int)); 21STATIC_DCL void NDECL(newman); 22 23/* update the youmonst.data structure pointer */ 24void 25set_uasmon() 26{ 27 set_mon_data(&youmonst, &mons[u.umonnum], 0); 28} 29 30/* make a (new) human out of the player */ 31STATIC_OVL void 32polyman(fmt, arg) 33const char *fmt, *arg; 34{ 35 boolean sticky = sticks(youmonst.data) && u.ustuck && !u.uswallow, 36 was_mimicking = (youmonst.m_ap_type == M_AP_OBJECT); 37 boolean could_pass_walls = Passes_walls; 38 boolean was_blind = !!Blind; 39 40 if (Upolyd) { 41 u.acurr = u.macurr; /* restore old attribs */ 42 u.amax = u.mamax; 43 u.umonnum = u.umonster; 44 flags.female = u.mfemale; 45 } 46 set_uasmon(); 47 48 u.mh = u.mhmax = 0; 49 u.mtimedone = 0; 50 skinback(FALSE); 51 u.uundetected = 0; 52 53 if (sticky) uunstick(); 54 find_ac(); 55 if (was_mimicking) { 56 if (multi < 0) unmul(""); 57 youmonst.m_ap_type = M_AP_NOTHING; 58 } 59 60 newsym(u.ux,u.uy); 61 62 You(fmt, arg); 63 /* check whether player foolishly genocided self while poly'd */ 64 if ((mvitals[urole.malenum].mvflags & G_GENOD) || 65 (urole.femalenum != NON_PM && 66 (mvitals[urole.femalenum].mvflags & G_GENOD)) || 67 (mvitals[urace.malenum].mvflags & G_GENOD) || 68 (urace.femalenum != NON_PM && 69 (mvitals[urace.femalenum].mvflags & G_GENOD))) { 70 /* intervening activity might have clobbered genocide info */ 71 killer = delayed_killer; 72 if (!killer || !strstri(killer, "genocid")) { 73 killer_format = KILLED_BY; 74 killer = "self-genocide"; 75 } 76 done(GENOCIDED); 77 } 78 79 if (u.twoweap && !could_twoweap(youmonst.data)) 80 untwoweapon(); 81 82 if (u.utraptype == TT_PIT) { 83 if (could_pass_walls) { /* player forms cannot pass walls */ 84 u.utrap = rn1(6,2); 85 } 86 } 87 if (was_blind && !Blind) { /* reverting from eyeless */ 88 Blinded = 1L; 89 make_blinded(0L, TRUE); /* remove blindness */ 90 } 91 92 if(!Levitation && !u.ustuck && 93 (is_pool(u.ux,u.uy) || is_lava(u.ux,u.uy))) 94 spoteffects(TRUE); 95 96 see_monsters(); 97} 98 99void 100change_sex() 101{ 102 /* setting u.umonster for caveman/cavewoman or priest/priestess 103 swap unintentionally makes `Upolyd' appear to be true */ 104 boolean already_polyd = (boolean) Upolyd; 105 106 /* Some monsters are always of one sex and their sex can't be changed */ 107 /* succubi/incubi can change, but are handled below */ 108 /* !already_polyd check necessary because is_male() and is_female() 109 are true if the player is a priest/priestess */ 110 if (!already_polyd || (!is_male(youmonst.data) && !is_female(youmonst.data) && !is_neuter(youmonst.data))) 111 flags.female = !flags.female; 112 if (already_polyd) /* poly'd: also change saved sex */ 113 u.mfemale = !u.mfemale; 114 max_rank_sz(); /* [this appears to be superfluous] */ 115 if ((already_polyd ? u.mfemale : flags.female) && urole.name.f) 116 Strcpy(pl_character, urole.name.f); 117 else 118 Strcpy(pl_character, urole.name.m); 119 u.umonster = ((already_polyd ? u.mfemale : flags.female) && urole.femalenum != NON_PM) ? 120 urole.femalenum : urole.malenum; 121 if (!already_polyd) { 122 u.umonnum = u.umonster; 123 } else if (u.umonnum == PM_SUCCUBUS || u.umonnum == PM_INCUBUS) { 124 flags.female = !flags.female; 125 /* change monster type to match new sex */ 126 u.umonnum = (u.umonnum == PM_SUCCUBUS) ? PM_INCUBUS : PM_SUCCUBUS; 127 set_uasmon(); 128 } 129} 130 131STATIC_OVL void 132newman() 133{ 134 int tmp, oldlvl; 135 136 tmp = u.uhpmax; 137 oldlvl = u.ulevel; 138 u.ulevel = u.ulevel + rn1(5, -2); 139 if (u.ulevel > 127 || u.ulevel < 1) { /* level went below 0? */ 140 u.ulevel = oldlvl; /* restore old level in case they lifesave */ 141 goto dead; 142 } 143 if (u.ulevel > MAXULEV) u.ulevel = MAXULEV; 144 /* If your level goes down, your peak level goes down by 145 the same amount so that you can't simply use blessed 146 full healing to undo the decrease. But if your level 147 goes up, your peak level does *not* undergo the same 148 adjustment; you might end up losing out on the chance 149 to regain some levels previously lost to other causes. */ 150 if (u.ulevel < oldlvl) u.ulevelmax -= (oldlvl - u.ulevel); 151 if (u.ulevelmax < u.ulevel) u.ulevelmax = u.ulevel; 152 153 if (!rn2(10)) change_sex(); 154 155 adjabil(oldlvl, (int)u.ulevel); 156 reset_rndmonst(NON_PM); /* new monster generation criteria */ 157 158 /* random experience points for the new experience level */ 159 u.uexp = rndexp(FALSE); 160 161 /* u.uhpmax * u.ulevel / oldlvl: proportionate hit points to new level 162 * -10 and +10: don't apply proportionate HP to 10 of a starting 163 * character's hit points (since a starting character's hit points 164 * are not on the same scale with hit points obtained through level 165 * gain) 166 * 9 - rn2(19): random change of -9 to +9 hit points 167 */ 168#ifndef LINT 169 u.uhpmax = ((u.uhpmax - 10) * (long)u.ulevel / oldlvl + 10) + 170 (9 - rn2(19)); 171#endif 172 173#ifdef LINT 174 u.uhp = u.uhp + tmp; 175#else 176 u.uhp = u.uhp * (long)u.uhpmax/tmp; 177#endif 178 179 tmp = u.uenmax; 180#ifndef LINT 181 u.uenmax = u.uenmax * (long)u.ulevel / oldlvl + 9 - rn2(19); 182#endif 183 if (u.uenmax < 0) u.uenmax = 0; 184#ifndef LINT 185 u.uen = (tmp ? u.uen * (long)u.uenmax / tmp : u.uenmax); 186#endif 187 188 redist_attr(); 189 u.uhunger = rn1(500,500); 190 if (Sick) make_sick(0L, (char *) 0, FALSE, SICK_ALL); 191 Stoned = 0; 192 delayed_killer = 0; 193 if (u.uhp <= 0 || u.uhpmax <= 0) { 194 if (Polymorph_control) { 195 if (u.uhp <= 0) u.uhp = 1; 196 if (u.uhpmax <= 0) u.uhpmax = 1; 197 } else { 198dead: /* we come directly here if their experience level went to 0 or less */ 199 Your("new form doesn't seem healthy enough to survive."); 200 killer_format = KILLED_BY_AN; 201 killer="unsuccessful polymorph"; 202 done(DIED); 203 newuhs(FALSE); 204 return; /* lifesaved */ 205 } 206 } 207 newuhs(FALSE); 208 polyman("feel like a new %s!", 209 (flags.female && urace.individual.f) ? urace.individual.f : 210 (urace.individual.m) ? urace.individual.m : urace.noun); 211 if (Slimed) { 212 Your("body transforms, but there is still slime on you."); 213 Slimed = 10L; 214 } 215 flags.botl = 1; 216 see_monsters(); 217 (void) encumber_msg(); 218} 219 220void 221polyself(forcecontrol) 222boolean forcecontrol; 223{ 224 char buf[BUFSZ]; 225 int old_light, new_light; 226 int mntmp = NON_PM; 227 int tries=0; 228 boolean draconian = (uarm && 229 uarm->otyp >= GRAY_DRAGON_SCALE_MAIL && 230 uarm->otyp <= YELLOW_DRAGON_SCALES); 231 boolean iswere = (u.ulycn >= LOW_PM || is_were(youmonst.data)); 232 boolean isvamp = (youmonst.data->mlet == S_VAMPIRE || u.umonnum == PM_VAMPIRE_BAT); 233 boolean was_floating = (Levitation || Flying); 234 235 if(!Polymorph_control && !forcecontrol && !draconian && !iswere && !isvamp) { 236 if (rn2(20) > ACURR(A_CON)) { 237 You(shudder_for_moment); 238 losehp(rnd(30), "system shock", KILLED_BY_AN); 239 exercise(A_CON, FALSE); 240 return; 241 } 242 } 243 old_light = Upolyd ? emits_light(youmonst.data) : 0; 244 245 if (Polymorph_control || forcecontrol) { 246 do { 247 getlin("Become what kind of monster? [type the name]", 248 buf); 249 mntmp = name_to_mon(buf); 250 if (mntmp < LOW_PM) 251 pline("I've never heard of such monsters."); 252 /* Note: humans are illegal as monsters, but an 253 * illegal monster forces newman(), which is what we 254 * want if they specified a human.... */ 255 else if (!polyok(&mons[mntmp]) && !your_race(&mons[mntmp])) 256 You("cannot polymorph into that."); 257 else break; 258 } while(++tries < 5); 259 if (tries==5) pline(thats_enough_tries); 260 /* allow skin merging, even when polymorph is controlled */ 261 if (draconian && 262 (mntmp == armor_to_dragon(uarm->otyp) || tries == 5)) 263 goto do_merge; 264 } else if (draconian || iswere || isvamp) { 265 /* special changes that don't require polyok() */ 266 if (draconian) { 267 do_merge: 268 mntmp = armor_to_dragon(uarm->otyp); 269 if (!(mvitals[mntmp].mvflags & G_GENOD)) { 270 /* allow G_EXTINCT */ 271 You("merge with your scaly armor."); 272 uskin = uarm; 273 uarm = (struct obj *)0; 274 /* save/restore hack */ 275 uskin->owornmask |= I_SPECIAL; 276 } 277 } else if (iswere) { 278 if (is_were(youmonst.data)) 279 mntmp = PM_HUMAN; /* Illegal; force newman() */ 280 else 281 mntmp = u.ulycn; 282 } else { 283 if (youmonst.data->mlet == S_VAMPIRE) 284 mntmp = PM_VAMPIRE_BAT; 285 else 286 mntmp = PM_VAMPIRE; 287 } 288 /* if polymon fails, "you feel" message has been given 289 so don't follow up with another polymon or newman */ 290 if (mntmp == PM_HUMAN) newman(); /* werecritter */ 291 else (void) polymon(mntmp); 292 goto made_change; /* maybe not, but this is right anyway */ 293 } 294 295 if (mntmp < LOW_PM) { 296 tries = 0; 297 do { 298 /* randomly pick an "ordinary" monster */ 299 mntmp = rn1(SPECIAL_PM - LOW_PM, LOW_PM); 300 } while((!polyok(&mons[mntmp]) || is_placeholder(&mons[mntmp])) 301 && tries++ < 200); 302 } 303 304 /* The below polyok() fails either if everything is genocided, or if 305 * we deliberately chose something illegal to force newman(). 306 */ 307 if (!polyok(&mons[mntmp]) || !rn2(5) || your_race(&mons[mntmp])) 308 newman(); 309 else if(!polymon(mntmp)) return; 310 311 if (!uarmg) selftouch("No longer petrify-resistant, you"); 312 313 made_change: 314 new_light = Upolyd ? emits_light(youmonst.data) : 0; 315 if (old_light != new_light) { 316 if (old_light) 317 del_light_source(LS_MONSTER, (genericptr_t)&youmonst); 318 if (new_light == 1) ++new_light; /* otherwise it's undetectable */ 319 if (new_light) 320 new_light_source(u.ux, u.uy, new_light, 321 LS_MONSTER, (genericptr_t)&youmonst); 322 } 323 if (is_pool(u.ux,u.uy) && was_floating && !(Levitation || Flying) && 324 !breathless(youmonst.data) && !amphibious(youmonst.data) && 325 !Swimming) drown(); 326} 327 328/* (try to) make a mntmp monster out of the player */ 329int 330polymon(mntmp) /* returns 1 if polymorph successful */ 331int mntmp; 332{ 333 boolean sticky = sticks(youmonst.data) && u.ustuck && !u.uswallow, 334 was_blind = !!Blind, dochange = FALSE; 335 boolean could_pass_walls = Passes_walls; 336 int mlvl; 337 338 if (mvitals[mntmp].mvflags & G_GENOD) { /* allow G_EXTINCT */ 339 You_feel("rather %s-ish.",mons[mntmp].mname); 340 exercise(A_WIS, TRUE); 341 return(0); 342 } 343 344 /* KMH, conduct */ 345 u.uconduct.polyselfs++; 346 347 if (!Upolyd) { 348 /* Human to monster; save human stats */ 349 u.macurr = u.acurr; 350 u.mamax = u.amax; 351 u.mfemale = flags.female; 352 } else { 353 /* Monster to monster; restore human stats, to be 354 * immediately changed to provide stats for the new monster 355 */ 356 u.acurr = u.macurr; 357 u.amax = u.mamax; 358 flags.female = u.mfemale; 359 } 360 361 if (youmonst.m_ap_type) { 362 /* stop mimicking immediately */ 363 if (multi < 0) unmul(""); 364 } else if (mons[mntmp].mlet != S_MIMIC) { 365 /* as in polyman() */ 366 youmonst.m_ap_type = M_AP_NOTHING; 367 } 368 if (is_male(&mons[mntmp])) { 369 if(flags.female) dochange = TRUE; 370 } else if (is_female(&mons[mntmp])) { 371 if(!flags.female) dochange = TRUE; 372 } else if (!is_neuter(&mons[mntmp]) && mntmp != u.ulycn) { 373 if(!rn2(10)) dochange = TRUE; 374 } 375 if (dochange) { 376 flags.female = !flags.female; 377 You("%s %s%s!", 378 (u.umonnum != mntmp) ? "turn into a" : "feel like a new", 379 (is_male(&mons[mntmp]) || is_female(&mons[mntmp])) ? "" : 380 flags.female ? "female " : "male ", 381 mons[mntmp].mname); 382 } else { 383 if (u.umonnum != mntmp) 384 You("turn into %s!", an(mons[mntmp].mname)); 385 else 386 You_feel("like a new %s!", mons[mntmp].mname); 387 } 388 if (Stoned && poly_when_stoned(&mons[mntmp])) { 389 /* poly_when_stoned already checked stone golem genocide */ 390 You("turn to stone!"); 391 mntmp = PM_STONE_GOLEM; 392 Stoned = 0; 393 delayed_killer = 0; 394 } 395 396 u.mtimedone = rn1(500, 500); 397 u.umonnum = mntmp; 398 set_uasmon(); 399 400 /* New stats for monster, to last only as long as polymorphed. 401 * Currently only strength gets changed. 402 */ 403 if(strongmonst(&mons[mntmp])) ABASE(A_STR) = AMAX(A_STR) = STR18(100); 404 405 if (Stone_resistance && Stoned) { /* parnes@eniac.seas.upenn.edu */ 406 Stoned = 0; 407 delayed_killer = 0; 408 You("no longer seem to be petrifying."); 409 } 410 if (Sick_resistance && Sick) { 411 make_sick(0L, (char *) 0, FALSE, SICK_ALL); 412 You("no longer feel sick."); 413 } 414 if (Slimed) { 415 if (flaming(youmonst.data)) { 416 pline_The("slime burns away!"); 417 Slimed = 0L; 418 flags.botl = 1; 419 } else if (mntmp == PM_GREEN_SLIME) { 420 /* do it silently */ 421 Slimed = 0L; 422 flags.botl = 1; 423 } 424 } 425 if (nohands(youmonst.data)) Glib = 0; 426 427 /* 428 mlvl = adj_lev(&mons[mntmp]); 429 * We can't do the above, since there's no such thing as an 430 * "experience level of you as a monster" for a polymorphed character. 431 */ 432 mlvl = (int)mons[mntmp].mlevel; 433 if (youmonst.data->mlet == S_DRAGON && mntmp >= PM_GRAY_DRAGON) { 434 u.mhmax = In_endgame(&u.uz) ? (8*mlvl) : (4*mlvl + d(mlvl,4)); 435 } else if (is_golem(youmonst.data)) { 436 u.mhmax = golemhp(mntmp); 437 } else { 438 if (!mlvl) u.mhmax = rnd(4); 439 else u.mhmax = d(mlvl, 8); 440 if (is_home_elemental(&mons[mntmp])) u.mhmax *= 3; 441 } 442 u.mh = u.mhmax; 443 444 if (u.ulevel < mlvl) { 445 /* Low level characters can't become high level monsters for long */ 446#ifdef DUMB 447 /* DRS/NS 2.2.6 messes up -- Peter Kendell */ 448 int mtd = u.mtimedone, ulv = u.ulevel; 449 450 u.mtimedone = mtd * ulv / mlvl; 451#else 452 u.mtimedone = u.mtimedone * u.ulevel / mlvl; 453#endif 454 } 455 456 if (uskin && mntmp != armor_to_dragon(uskin->otyp)) 457 skinback(FALSE); 458 break_armor(); 459 drop_weapon(1); 460 if (hides_under(youmonst.data)) 461 u.uundetected = OBJ_AT(u.ux, u.uy); 462 else if (youmonst.data->mlet == S_EEL) 463 u.uundetected = is_pool(u.ux, u.uy); 464 else 465 u.uundetected = 0; 466 467 if (u.utraptype == TT_PIT) { 468 if (could_pass_walls && !Passes_walls) { 469 u.utrap = rn1(6,2); 470 } else if (!could_pass_walls && Passes_walls) { 471 u.utrap = 0; 472 } 473 } 474 if (was_blind && !Blind) { /* previous form was eyeless */ 475 Blinded = 1L; 476 make_blinded(0L, TRUE); /* remove blindness */ 477 } 478 newsym(u.ux,u.uy); /* Change symbol */ 479 480 if (!sticky && !u.uswallow && u.ustuck && sticks(youmonst.data)) u.ustuck = 0; 481 else if (sticky && !sticks(youmonst.data)) uunstick(); 482#ifdef STEED 483 if (u.usteed) { 484 if (touch_petrifies(u.usteed->data) && 485 !Stone_resistance && rnl(3)) { 486 char buf[BUFSZ]; 487 488 pline("No longer petrifying-resistant, you touch %s.", 489 mon_nam(u.usteed)); 490 Sprintf(buf, "riding %s", an(u.usteed->data->mname)); 491 instapetrify(buf); 492 } 493 if (!can_ride(u.usteed)) dismount_steed(DISMOUNT_POLY); 494 } 495#endif 496 497 if (flags.verbose) { 498 static const char use_thec[] = "Use the command #%s to %s."; 499 static const char monsterc[] = "monster"; 500 if (can_breathe(youmonst.data)) 501 pline(use_thec,monsterc,"use your breath weapon"); 502 if (attacktype(youmonst.data, AT_SPIT)) 503 pline(use_thec,monsterc,"spit venom"); 504 if (youmonst.data->mlet == S_NYMPH) 505 pline(use_thec,monsterc,"remove an iron ball"); 506 if (attacktype(youmonst.data, AT_GAZE)) 507 pline(use_thec,monsterc,"gaze at monsters"); 508 if (is_hider(youmonst.data)) 509 pline(use_thec,monsterc,"hide"); 510 if (is_were(youmonst.data)) 511 pline(use_thec,monsterc,"summon help"); 512 if (webmaker(youmonst.data)) 513 pline(use_thec,monsterc,"spin a web"); 514 if (u.umonnum == PM_GREMLIN) 515 pline(use_thec,monsterc,"multiply in a fountain"); 516 if (is_unicorn(youmonst.data)) 517 pline(use_thec,monsterc,"use your horn"); 518 if (is_mind_flayer(youmonst.data)) 519 pline(use_thec,monsterc,"emit a mental blast"); 520 if (youmonst.data->msound == MS_SHRIEK) /* worthless, actually */ 521 pline(use_thec,monsterc,"shriek"); 522 if (lays_eggs(youmonst.data) && flags.female) 523 pline(use_thec,"sit","lay an egg"); 524 } 525 /* you now know what an egg of your type looks like */ 526 if (lays_eggs(youmonst.data)) { 527 learn_egg_type(u.umonnum); 528 /* make queen bees recognize killer bee eggs */ 529 learn_egg_type(egg_type_from_parent(u.umonnum, TRUE)); 530 } 531 find_ac(); 532 if((!Levitation && !u.ustuck && !Flying && 533 (is_pool(u.ux,u.uy) || is_lava(u.ux,u.uy))) || 534 (Underwater && !Swimming)) 535 spoteffects(TRUE); 536 if (Passes_walls && u.utrap && u.utraptype == TT_INFLOOR) { 537 u.utrap = 0; 538 pline_The("rock seems to no longer trap you."); 539 } else if (likes_lava(youmonst.data) && u.utrap && u.utraptype == TT_LAVA) { 540 u.utrap = 0; 541 pline_The("lava now feels soothing."); 542 } 543 if (amorphous(youmonst.data) || is_whirly(youmonst.data) || unsolid(youmonst.data)) { 544 if (Punished) { 545 You("slip out of the iron chain."); 546 unpunish(); 547 } 548 } 549 if (u.utrap && (u.utraptype == TT_WEB || u.utraptype == TT_BEARTRAP) && 550 (amorphous(youmonst.data) || is_whirly(youmonst.data) || unsolid(youmonst.data) || 551 (youmonst.data->msize <= MZ_SMALL && u.utraptype == TT_BEARTRAP))) { 552 You("are no longer stuck in the %s.", 553 u.utraptype == TT_WEB ? "web" : "bear trap"); 554 /* probably should burn webs too if PM_FIRE_ELEMENTAL */ 555 u.utrap = 0; 556 } 557 if (webmaker(youmonst.data) && u.utrap && u.utraptype == TT_WEB) { 558 You("orient yourself on the web."); 559 u.utrap = 0; 560 } 561 flags.botl = 1; 562 vision_full_recalc = 1; 563 see_monsters(); 564 exercise(A_CON, FALSE); 565 exercise(A_WIS, TRUE); 566 (void) encumber_msg(); 567 return(1); 568} 569 570STATIC_OVL void 571break_armor() 572{ 573 register struct obj *otmp; 574 575 if (breakarm(youmonst.data)) { 576 if ((otmp = uarm) != 0) { 577 if (donning(otmp)) cancel_don(); 578 You("break out of your armor!"); 579 exercise(A_STR, FALSE); 580 (void) Armor_gone(); 581 useup(otmp); 582 } 583 if ((otmp = uarmc) != 0) { 584 if(otmp->oartifact) { 585 Your("%s falls off!", cloak_simple_name(otmp)); 586 (void) Cloak_off(); 587 dropx(otmp); 588 } else { 589 Your("%s tears apart!", cloak_simple_name(otmp)); 590 (void) Cloak_off(); 591 useup(otmp); 592 } 593 } 594#ifdef TOURIST 595 if (uarmu) { 596 Your("shirt rips to shreds!"); 597 useup(uarmu); 598 } 599#endif 600 } else if (sliparm(youmonst.data)) { 601 if (((otmp = uarm) != 0) && (racial_exception(&youmonst, otmp) < 1)) { 602 if (donning(otmp)) cancel_don(); 603 Your("armor falls around you!"); 604 (void) Armor_gone(); 605 dropx(otmp); 606 } 607 if ((otmp = uarmc) != 0) { 608 if (is_whirly(youmonst.data)) 609 Your("%s falls, unsupported!", cloak_simple_name(otmp)); 610 else You("shrink out of your %s!", cloak_simple_name(otmp)); 611 (void) Cloak_off(); 612 dropx(otmp); 613 } 614#ifdef TOURIST 615 if ((otmp = uarmu) != 0) { 616 if (is_whirly(youmonst.data)) 617 You("seep right through your shirt!"); 618 else You("become much too small for your shirt!"); 619 setworn((struct obj *)0, otmp->owornmask & W_ARMU); 620 dropx(otmp); 621 } 622#endif 623 } 624 if (has_horns(youmonst.data)) { 625 if ((otmp = uarmh) != 0) { 626 if (is_flimsy(otmp) && !donning(otmp)) { 627 char hornbuf[BUFSZ], yourbuf[BUFSZ]; 628 629 /* Future possiblities: This could damage/destroy helmet */ 630 Sprintf(hornbuf, "horn%s", plur(num_horns(youmonst.data))); 631 Your("%s %s through %s %s.", hornbuf, vtense(hornbuf, "pierce"), 632 shk_your(yourbuf, otmp), xname(otmp)); 633 } else { 634 if (donning(otmp)) cancel_don(); 635 Your("helmet falls to the %s!", surface(u.ux, u.uy)); 636 (void) Helmet_off(); 637 dropx(otmp); 638 } 639 } 640 } 641 if (nohands(youmonst.data) || verysmall(youmonst.data)) { 642 if ((otmp = uarmg) != 0) { 643 if (donning(otmp)) cancel_don(); 644 /* Drop weapon along with gloves */ 645 You("drop your gloves%s!", uwep ? " and weapon" : ""); 646 drop_weapon(0); 647 (void) Gloves_off(); 648 dropx(otmp); 649 } 650 if ((otmp = uarms) != 0) { 651 You("can no longer hold your shield!"); 652 (void) Shield_off(); 653 dropx(otmp); 654 } 655 if ((otmp = uarmh) != 0) { 656 if (donning(otmp)) cancel_don(); 657 Your("helmet falls to the %s!", surface(u.ux, u.uy)); 658 (void) Helmet_off(); 659 dropx(otmp); 660 } 661 } 662 if (nohands(youmonst.data) || verysmall(youmonst.data) || 663 slithy(youmonst.data) || youmonst.data->mlet == S_CENTAUR) { 664 if ((otmp = uarmf) != 0) { 665 if (donning(otmp)) cancel_don(); 666 if (is_whirly(youmonst.data)) 667 Your("boots fall away!"); 668 else Your("boots %s off your feet!", 669 verysmall(youmonst.data) ? "slide" : "are pushed"); 670 (void) Boots_off(); 671 dropx(otmp); 672 } 673 } 674} 675 676STATIC_OVL void 677drop_weapon(alone) 678int alone; 679{ 680 struct obj *otmp; 681 struct obj *otmp2; 682 683 if ((otmp = uwep) != 0) { 684 /* !alone check below is currently superfluous but in the 685 * future it might not be so if there are monsters which cannot 686 * wear gloves but can wield weapons 687 */ 688 if (!alone || cantwield(youmonst.data)) { 689 struct obj *wep = uwep; 690 691 if (alone) You("find you must drop your weapon%s!", 692 u.twoweap ? "s" : ""); 693 otmp2 = u.twoweap ? uswapwep : 0; 694 uwepgone(); 695 if (!wep->cursed || wep->otyp != LOADSTONE) 696 dropx(otmp); 697 if (otmp2 != 0) { 698 uswapwepgone(); 699 if (!otmp2->cursed || otmp2->otyp != LOADSTONE) 700 dropx(otmp2); 701 } 702 untwoweapon(); 703 } else if (!could_twoweap(youmonst.data)) { 704 untwoweapon(); 705 } 706 } 707} 708 709void 710rehumanize() 711{ 712 /* You can't revert back while unchanging */ 713 if (Unchanging && (u.mh < 1)) { 714 killer_format = NO_KILLER_PREFIX; 715 killer = "killed while stuck in creature form"; 716 done(DIED); 717 } 718 719 if (emits_light(youmonst.data)) 720 del_light_source(LS_MONSTER, (genericptr_t)&youmonst); 721 polyman("return to %s form!", urace.adj); 722 723 if (u.uhp < 1) { 724 char kbuf[256]; 725 726 Sprintf(kbuf, "reverting to unhealthy %s form", urace.adj); 727 killer_format = KILLED_BY; 728 killer = kbuf; 729 done(DIED); 730 } 731 if (!uarmg) selftouch("No longer petrify-resistant, you"); 732 nomul(0); 733 734 flags.botl = 1; 735 vision_full_recalc = 1; 736 (void) encumber_msg(); 737} 738 739int 740dobreathe() 741{ 742 struct attack *mattk; 743 744 if (Strangled) { 745 You_cant("breathe. Sorry."); 746 return(0); 747 } 748 if (u.uen < 15) { 749 You("don't have enough energy to breathe!"); 750 return(0); 751 } 752 u.uen -= 15; 753 flags.botl = 1; 754 755 if (!getdir((char *)0)) return(0); 756 757 mattk = attacktype_fordmg(youmonst.data, AT_BREA, AD_ANY); 758 if (!mattk) 759 impossible("bad breath attack?"); /* mouthwash needed... */ 760 else 761 buzz((int) (20 + mattk->adtyp-1), (int)mattk->damn, 762 u.ux, u.uy, u.dx, u.dy); 763 return(1); 764} 765 766int 767dospit() 768{ 769 struct obj *otmp; 770 771 if (!getdir((char *)0)) return(0); 772 otmp = mksobj(u.umonnum==PM_COBRA ? BLINDING_VENOM : ACID_VENOM, 773 TRUE, FALSE); 774 otmp->spe = 1; /* to indicate it's yours */ 775 throwit(otmp, 0L, FALSE); 776 return(1); 777} 778 779int 780doremove() 781{ 782 if (!Punished) { 783 You("are not chained to anything!"); 784 return(0); 785 } 786 unpunish(); 787 return(1); 788} 789 790int 791dospinweb() 792{ 793 register struct trap *ttmp = t_at(u.ux,u.uy); 794 795 if (Levitation || Is_airlevel(&u.uz) 796 || Underwater || Is_waterlevel(&u.uz)) { 797 You("must be on the ground to spin a web."); 798 return(0); 799 } 800 if (u.uswallow) { 801 You("release web fluid inside %s.", mon_nam(u.ustuck)); 802 if (is_animal(u.ustuck->data)) { 803 expels(u.ustuck, u.ustuck->data, TRUE); 804 return(0); 805 } 806 if (is_whirly(u.ustuck->data)) { 807 int i; 808 809 for (i = 0; i < NATTK; i++) 810 if (u.ustuck->data->mattk[i].aatyp == AT_ENGL) 811 break; 812 if (i == NATTK) 813 impossible("Swallower has no engulfing attack?"); 814 else { 815 char sweep[30]; 816 817 sweep[0] = '\0'; 818 switch(u.ustuck->data->mattk[i].adtyp) { 819 case AD_FIRE: 820 Strcpy(sweep, "ignites and "); 821 break; 822 case AD_ELEC: 823 Strcpy(sweep, "fries and "); 824 break; 825 case AD_COLD: 826 Strcpy(sweep, 827 "freezes, shatters and "); 828 break; 829 } 830 pline_The("web %sis swept away!", sweep); 831 } 832 return(0); 833 } /* default: a nasty jelly-like creature */ 834 pline_The("web dissolves into %s.", mon_nam(u.ustuck)); 835 return(0); 836 } 837 if (u.utrap) { 838 You("cannot spin webs while stuck in a trap."); 839 return(0); 840 } 841 exercise(A_DEX, TRUE); 842 if (ttmp) switch (ttmp->ttyp) { 843 case PIT: 844 case SPIKED_PIT: You("spin a web, covering up the pit."); 845 deltrap(ttmp); 846 bury_objs(u.ux, u.uy); 847 newsym(u.ux, u.uy); 848 return(1); 849 case SQKY_BOARD: pline_The("squeaky board is muffled."); 850 deltrap(ttmp); 851 newsym(u.ux, u.uy); 852 return(1); 853 case TELEP_TRAP: 854 case LEVEL_TELEP: 855 case MAGIC_PORTAL: 856 Your("webbing vanishes!"); 857 return(0); 858 case WEB: You("make the web thicker."); 859 return(1); 860 case HOLE: 861 case TRAPDOOR: 862 You("web over the %s.", 863 (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole"); 864 deltrap(ttmp); 865 newsym(u.ux, u.uy); 866 return 1; 867 case ROLLING_BOULDER_TRAP: 868 You("spin a web, jamming the trigger."); 869 deltrap(ttmp); 870 newsym(u.ux, u.uy); 871 return(1); 872 case ARROW_TRAP: 873 case DART_TRAP: 874 case BEAR_TRAP: 875 case ROCKTRAP: 876 case FIRE_TRAP: 877 case LANDMINE: 878 case SLP_GAS_TRAP: 879 case RUST_TRAP: 880 case MAGIC_TRAP: 881 case ANTI_MAGIC: 882 case POLY_TRAP: 883 You("have triggered a trap!"); 884 dotrap(ttmp, 0); 885 return(1); 886 default: 887 impossible("Webbing over trap type %d?", ttmp->ttyp); 888 return(0); 889 } 890 else if (On_stairs(u.ux, u.uy)) { 891 /* cop out: don't let them hide the stairs */ 892 Your("web fails to impede access to the %s.", 893 (levl[u.ux][u.uy].typ == STAIRS) ? "stairs" : "ladder"); 894 return(1); 895 896 } 897 ttmp = maketrap(u.ux, u.uy, WEB); 898 if (ttmp) { 899 ttmp->tseen = 1; 900 ttmp->madeby_u = 1; 901 } 902 newsym(u.ux, u.uy); 903 return(1); 904} 905 906int 907dosummon() 908{ 909 int placeholder; 910 if (u.uen < 10) { 911 You("lack the energy to send forth a call for help!"); 912 return(0); 913 } 914 u.uen -= 10; 915 flags.botl = 1; 916 917 You("call upon your brethren for help!"); 918 exercise(A_WIS, TRUE); 919 if (!were_summon(youmonst.data, TRUE, &placeholder, (char *)0)) 920 pline("But none arrive."); 921 return(1); 922} 923 924int 925dogaze() 926{ 927 register struct monst *mtmp; 928 int looked = 0; 929 char qbuf[QBUFSZ]; 930 int i; 931 uchar adtyp = 0; 932 933 for (i = 0; i < NATTK; i++) { 934 if(youmonst.data->mattk[i].aatyp == AT_GAZE) { 935 adtyp = youmonst.data->mattk[i].adtyp; 936 break; 937 } 938 } 939 if (adtyp != AD_CONF && adtyp != AD_FIRE) { 940 impossible("gaze attack %d?", adtyp); 941 return 0; 942 } 943 944 945 if (Blind) { 946 You_cant("see anything to gaze at."); 947 return 0; 948 } 949 if (u.uen < 15) { 950 You("lack the energy to use your special gaze!"); 951 return(0); 952 } 953 u.uen -= 15; 954 flags.botl = 1; 955 956 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { 957 if (DEADMONSTER(mtmp)) continue; 958 if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my)) { 959 looked++; 960 if (Invis && !perceives(mtmp->data)) 961 pline("%s seems not to notice your gaze.", Monnam(mtmp)); 962 else if (mtmp->minvis && !See_invisible) 963 You_cant("see where to gaze at %s.", Monnam(mtmp)); 964 else if (mtmp->m_ap_type == M_AP_FURNITURE 965 || mtmp->m_ap_type == M_AP_OBJECT) { 966 looked--; 967 continue; 968 } else if (flags.safe_dog && !Confusion && !Hallucination 969 && mtmp->mtame) { 970 You("avoid gazing at %s.", y_monnam(mtmp)); 971 } else { 972 if (flags.confirm && mtmp->mpeaceful && !Confusion 973 && !Hallucination) { 974 Sprintf(qbuf, "Really %s %s?", 975 (adtyp == AD_CONF) ? "confuse" : "attack", 976 mon_nam(mtmp)); 977 if (yn(qbuf) != 'y') continue; 978 setmangry(mtmp); 979 } 980 if (!mtmp->mcanmove || mtmp->mstun || mtmp->msleeping || 981 !mtmp->mcansee || !haseyes(mtmp->data)) { 982 looked--; 983 continue; 984 } 985 /* No reflection check for consistency with when a monster 986 * gazes at *you*--only medusa gaze gets reflected then. 987 */ 988 if (adtyp == AD_CONF) { 989 if (!mtmp->mconf) 990 Your("gaze confuses %s!", mon_nam(mtmp)); 991 else 992 pline("%s is getting more and more confused.", 993 Monnam(mtmp)); 994 mtmp->mconf = 1; 995 } else if (adtyp == AD_FIRE) { 996 int dmg = d(2,6); 997 You("attack %s with a fiery gaze!", mon_nam(mtmp)); 998 if (resists_fire(mtmp)) { 999 pline_The("fire doesn't burn %s!", mon_nam(mtmp)); 1000 dmg = 0; 1001 } 1002 if((int) u.ulevel > rn2(20)) 1003 (void) destroy_mitem(mtmp, SCROLL_CLASS, AD_FIRE); 1004 if((int) u.ulevel > rn2(20)) 1005 (void) destroy_mitem(mtmp, POTION_CLASS, AD_FIRE); 1006 if((int) u.ulevel > rn2(25)) 1007 (void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE); 1008 if (dmg && !DEADMONSTER(mtmp)) mtmp->mhp -= dmg; 1009 if (mtmp->mhp <= 0) killed(mtmp); 1010 } 1011 /* For consistency with passive() in uhitm.c, this only 1012 * affects you if the monster is still alive. 1013 */ 1014 if (!DEADMONSTER(mtmp) && 1015 (mtmp->data==&mons[PM_FLOATING_EYE]) && !mtmp->mcan) { 1016 if (!Free_action) { 1017 You("are frozen by %s gaze!", 1018 s_suffix(mon_nam(mtmp))); 1019 nomul((u.ulevel > 6 || rn2(4)) ? 1020 -d((int)mtmp->m_lev+1, 1021 (int)mtmp->data->mattk[0].damd) 1022 : -200); 1023 return 1; 1024 } else 1025 You("stiffen momentarily under %s gaze.", 1026 s_suffix(mon_nam(mtmp))); 1027 } 1028 /* Technically this one shouldn't affect you at all because 1029 * the Medusa gaze is an active monster attack that only 1030 * works on the monster's turn, but for it to *not* have an 1031 * effect would be too weird. 1032 */ 1033 if (!DEADMONSTER(mtmp) && 1034 (mtmp->data == &mons[PM_MEDUSA]) && !mtmp->mcan) { 1035 pline( 1036 "Gazing at the awake %s is not a very good idea.", 1037 l_monnam(mtmp)); 1038 /* as if gazing at a sleeping anything is fruitful... */ 1039 You("turn to stone..."); 1040 killer_format = KILLED_BY; 1041 killer = "deliberately meeting Medusa's gaze"; 1042 done(STONING); 1043 } 1044 } 1045 } 1046 } 1047 if (!looked) You("gaze at no place in particular."); 1048 return 1; 1049} 1050 1051int 1052dohide() 1053{ 1054 boolean ismimic = youmonst.data->mlet == S_MIMIC; 1055 1056 if (u.uundetected || (ismimic && youmonst.m_ap_type != M_AP_NOTHING)) { 1057 You("are already hiding."); 1058 return(0); 1059 } 1060 if (ismimic) { 1061 /* should bring up a dialog "what would you like to imitate?" */ 1062 youmonst.m_ap_type = M_AP_OBJECT; 1063 youmonst.mappearance = STRANGE_OBJECT; 1064 } else 1065 u.uundetected = 1; 1066 newsym(u.ux,u.uy); 1067 return(1); 1068} 1069 1070int 1071domindblast() 1072{ 1073 struct monst *mtmp, *nmon; 1074 1075 if (u.uen < 10) { 1076 You("concentrate but lack the energy to maintain doing so."); 1077 return(0); 1078 } 1079 u.uen -= 10; 1080 flags.botl = 1; 1081 1082 You("concentrate."); 1083 pline("A wave of psychic energy pours out."); 1084 for(mtmp=fmon; mtmp; mtmp = nmon) { 1085 int u_sen; 1086 1087 nmon = mtmp->nmon; 1088 if (DEADMONSTER(mtmp)) 1089 continue; 1090 if (distu(mtmp->mx, mtmp->my) > BOLT_LIM * BOLT_LIM) 1091 continue; 1092 if(mtmp->mpeaceful) 1093 continue; 1094 u_sen = telepathic(mtmp->data) && !mtmp->mcansee; 1095 if (u_sen || (telepathic(mtmp->data) && rn2(2)) || !rn2(10)) { 1096 You("lock in on %s %s.", s_suffix(mon_nam(mtmp)), 1097 u_sen ? "telepathy" : 1098 telepathic(mtmp->data) ? "latent telepathy" : 1099 "mind"); 1100 mtmp->mhp -= rnd(15); 1101 if (mtmp->mhp <= 0) 1102 killed(mtmp); 1103 } 1104 } 1105 return 1; 1106} 1107 1108STATIC_OVL void 1109uunstick() 1110{ 1111 pline("%s is no longer in your clutches.", Monnam(u.ustuck)); 1112 u.ustuck = 0; 1113} 1114 1115void 1116skinback(silently) 1117boolean silently; 1118{ 1119 if (uskin) { 1120 if (!silently) Your("skin returns to its original form."); 1121 uarm = uskin; 1122 uskin = (struct obj *)0; 1123 /* undo save/restore hack */ 1124 uarm->owornmask &= ~I_SPECIAL; 1125 } 1126} 1127 1128#endif /* OVLB */ 1129#ifdef OVL1 1130 1131const char * 1132mbodypart(mon, part) 1133struct monst *mon; 1134int part; 1135{ 1136 static NEARDATA const char 1137 *humanoid_parts[] = { "arm", "eye", "face", "finger", 1138 "fingertip", "foot", "hand", "handed", "head", "leg", 1139 "light headed", "neck", "spine", "toe", "hair", 1140 "blood", "lung", "nose", "stomach"}, 1141 *jelly_parts[] = { "pseudopod", "dark spot", "front", 1142 "pseudopod extension", "pseudopod extremity", 1143 "pseudopod root", "grasp", "grasped", "cerebral area", 1144 "lower pseudopod", "viscous", "middle", "surface", 1145 "pseudopod extremity", "ripples", "juices", 1146 "surface", "sensor", "stomach" }, 1147 *animal_parts[] = { "forelimb", "eye", "face", "foreclaw", "claw tip", 1148 "rear claw", "foreclaw", "clawed", "head", "rear limb", 1149 "light headed", "neck", "spine", "rear claw tip", 1150 "fur", "blood", "lung", "nose", "stomach" }, 1151 *bird_parts[] = { "wing", "eye", "face", "wing", "wing tip", 1152 "foot", "wing", "winged", "head", "leg", 1153 "light headed", "neck", "spine", "toe", 1154 "feathers", "blood", "lung", "bill", "stomach" }, 1155 *horse_parts[] = { "foreleg", "eye", "face", "forehoof", "hoof tip", 1156 "rear hoof", "foreclaw", "hooved", "head", "rear leg", 1157 "light headed", "neck", "backbone", "rear hoof tip", 1158 "mane", "blood", "lung", "nose", "stomach"}, 1159 *sphere_parts[] = { "appendage", "optic nerve", "body", "tentacle", 1160 "tentacle tip", "lower appendage", "tentacle", "tentacled", 1161 "body", "lower tentacle", "rotational", "equator", "body", 1162 "lower tentacle tip", "cilia", "life force", "retina", 1163 "olfactory nerve", "interior" }, 1164 *fungus_parts[] = { "mycelium", "visual area", "front", "hypha", 1165 "hypha", "root", "strand", "stranded", "cap area", 1166 "rhizome", "sporulated", "stalk", "root", "rhizome tip", 1167 "spores", "juices", "gill", "gill", "interior" }, 1168 *vortex_parts[] = { "region", "eye", "front", "minor current", 1169 "minor current", "lower current", "swirl", "swirled", 1170 "central core", "lower current", "addled", "center", 1171 "currents", "edge", "currents", "life force", 1172 "center", "leading edge", "interior" }, 1173 *snake_parts[] = { "vestigial limb", "eye", "face", "large scale", 1174 "large scale tip", "rear region", "scale gap", "scale gapped", 1175 "head", "rear region", "light headed", "neck", "length", 1176 "rear scale", "scales", "blood", "lung", "forked tongue", "stomach" }, 1177 *fish_parts[] = { "fin", "eye", "premaxillary", "pelvic axillary", 1178 "pelvic fin", "anal fin", "pectoral fin", "finned", "head", "peduncle", 1179 "played out", "gills", "dorsal fin", "caudal fin", 1180 "scales", "blood", "gill", "nostril", "stomach" }; 1181 /* claw attacks are overloaded in mons[]; most humanoids with 1182 such attacks should still reference hands rather than claws */ 1183 static const char not_claws[] = { 1184 S_HUMAN, S_MUMMY, S_ZOMBIE, S_ANGEL, 1185 S_NYMPH, S_LEPRECHAUN, S_QUANTMECH, S_VAMPIRE, 1186 S_ORC, S_GIANT, /* quest nemeses */ 1187 '\0' /* string terminator; assert( S_xxx != 0 ); */ 1188 }; 1189 struct permonst *mptr = mon->data; 1190 1191 if (part == HAND || part == HANDED) { /* some special cases */ 1192 if (mptr->mlet == S_DOG || mptr->mlet == S_FELINE || 1193 mptr->mlet == S_YETI) 1194 return part == HAND ? "paw" : "pawed"; 1195 if (humanoid(mptr) && attacktype(mptr, AT_CLAW) && 1196 !index(not_claws, mptr->mlet) && 1197 mptr != &mons[PM_STONE_GOLEM] && 1198 mptr != &mons[PM_INCUBUS] && mptr != &mons[PM_SUCCUBUS]) 1199 return part == HAND ? "claw" : "clawed"; 1200 } 1201 if ((mptr == &mons[PM_MUMAK] || mptr == &mons[PM_MASTODON]) && 1202 part == NOSE) 1203 return "trunk"; 1204 if (mptr == &mons[PM_SHARK] && part == HAIR) 1205 return "skin"; /* sharks don't have scales */ 1206 if (mptr == &mons[PM_JELLYFISH] && (part == ARM || part == FINGER || 1207 part == HAND || part == FOOT || part == TOE)) 1208 return "tentacle"; 1209 if (mptr == &mons[PM_FLOATING_EYE] && part == EYE) 1210 return "cornea"; 1211 if (humanoid(mptr) && 1212 (part == ARM || part == FINGER || part == FINGERTIP || 1213 part == HAND || part == HANDED)) 1214 return humanoid_parts[part]; 1215 if (mptr == &mons[PM_RAVEN]) 1216 return bird_parts[part]; 1217 if (mptr->mlet == S_CENTAUR || mptr->mlet == S_UNICORN || 1218 (mptr == &mons[PM_ROTHE] && part != HAIR)) 1219 return horse_parts[part]; 1220 if (mptr->mlet == S_LIGHT) { 1221 if (part == HANDED) return "rayed"; 1222 else if (part == ARM || part == FINGER || 1223 part == FINGERTIP || part == HAND) return "ray"; 1224 else return "beam"; 1225 } 1226 if (mptr->mlet == S_EEL && mptr != &mons[PM_JELLYFISH]) 1227 return fish_parts[part]; 1228 if (slithy(mptr) || (mptr->mlet == S_DRAGON && part == HAIR)) 1229 return snake_parts[part]; 1230 if (mptr->mlet == S_EYE) 1231 return sphere_parts[part]; 1232 if (mptr->mlet == S_JELLY || mptr->mlet == S_PUDDING || 1233 mptr->mlet == S_BLOB || mptr == &mons[PM_JELLYFISH]) 1234 return jelly_parts[part]; 1235 if (mptr->mlet == S_VORTEX || mptr->mlet == S_ELEMENTAL) 1236 return vortex_parts[part]; 1237 if (mptr->mlet == S_FUNGUS) 1238 return fungus_parts[part]; 1239 if (humanoid(mptr)) 1240 return humanoid_parts[part]; 1241 return animal_parts[part]; 1242} 1243 1244const char * 1245body_part(part) 1246int part; 1247{ 1248 return mbodypart(&youmonst, part); 1249} 1250 1251#endif /* OVL1 */ 1252#ifdef OVL0 1253 1254int 1255poly_gender() 1256{ 1257/* Returns gender of polymorphed player; 0/1=same meaning as flags.female, 1258 * 2=none. 1259 */ 1260 if (is_neuter(youmonst.data) || !humanoid(youmonst.data)) return 2; 1261 return flags.female; 1262} 1263 1264#endif /* OVL0 */ 1265#ifdef OVLB 1266 1267void 1268ugolemeffects(damtype, dam) 1269int damtype, dam; 1270{ 1271 int heal = 0; 1272 /* We won't bother with "slow"/"haste" since players do not 1273 * have a monster-specific slow/haste so there is no way to 1274 * restore the old velocity once they are back to human. 1275 */ 1276 if (u.umonnum != PM_FLESH_GOLEM && u.umonnum != PM_IRON_GOLEM) 1277 return; 1278 switch (damtype) { 1279 case AD_ELEC: if (u.umonnum == PM_FLESH_GOLEM) 1280 heal = dam / 6; /* Approx 1 per die */ 1281 break; 1282 case AD_FIRE: if (u.umonnum == PM_IRON_GOLEM) 1283 heal = dam; 1284 break; 1285 } 1286 if (heal && (u.mh < u.mhmax)) { 1287 u.mh += heal; 1288 if (u.mh > u.mhmax) u.mh = u.mhmax; 1289 flags.botl = 1; 1290 pline("Strangely, you feel better than before."); 1291 exercise(A_STR, TRUE); 1292 } 1293} 1294 1295STATIC_OVL int 1296armor_to_dragon(atyp) 1297int atyp; 1298{ 1299 switch(atyp) { 1300 case GRAY_DRAGON_SCALE_MAIL: 1301 case GRAY_DRAGON_SCALES: 1302 return PM_GRAY_DRAGON; 1303 case SILVER_DRAGON_SCALE_MAIL: 1304 case SILVER_DRAGON_SCALES: 1305 return PM_SILVER_DRAGON; 1306#if 0 /* DEFERRED */ 1307 case SHIMMERING_DRAGON_SCALE_MAIL: 1308 case SHIMMERING_DRAGON_SCALES: 1309 return PM_SHIMMERING_DRAGON; 1310#endif 1311 case RED_DRAGON_SCALE_MAIL: 1312 case RED_DRAGON_SCALES: 1313 return PM_RED_DRAGON; 1314 case ORANGE_DRAGON_SCALE_MAIL: 1315 case ORANGE_DRAGON_SCALES: 1316 return PM_ORANGE_DRAGON; 1317 case WHITE_DRAGON_SCALE_MAIL: 1318 case WHITE_DRAGON_SCALES: 1319 return PM_WHITE_DRAGON; 1320 case BLACK_DRAGON_SCALE_MAIL: 1321 case BLACK_DRAGON_SCALES: 1322 return PM_BLACK_DRAGON; 1323 case BLUE_DRAGON_SCALE_MAIL: 1324 case BLUE_DRAGON_SCALES: 1325 return PM_BLUE_DRAGON; 1326 case GREEN_DRAGON_SCALE_MAIL: 1327 case GREEN_DRAGON_SCALES: 1328 return PM_GREEN_DRAGON; 1329 case YELLOW_DRAGON_SCALE_MAIL: 1330 case YELLOW_DRAGON_SCALES: 1331 return PM_YELLOW_DRAGON; 1332 default: 1333 return -1; 1334 } 1335} 1336 1337#endif /* OVLB */ 1338 1339/*polyself.c*/ 1340