1/* SCCS Id: @(#)mhitu.c 3.4 2003/11/26 */ 2/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3/* NetHack may be freely redistributed. See license for details. */ 4 5#include "hack.h" 6#include "artifact.h" 7 8STATIC_VAR NEARDATA struct obj *otmp; 9 10STATIC_DCL void FDECL(urustm, (struct monst *, struct obj *)); 11# ifdef OVL1 12STATIC_DCL boolean FDECL(u_slip_free, (struct monst *,struct attack *)); 13STATIC_DCL int FDECL(passiveum, (struct permonst *,struct monst *,struct attack *)); 14# endif /* OVL1 */ 15 16#ifdef OVLB 17# ifdef SEDUCE 18STATIC_DCL void FDECL(mayberem, (struct obj *, const char *)); 19# endif 20#endif /* OVLB */ 21 22STATIC_DCL boolean FDECL(diseasemu, (struct permonst *)); 23STATIC_DCL int FDECL(hitmu, (struct monst *,struct attack *)); 24STATIC_DCL int FDECL(gulpmu, (struct monst *,struct attack *)); 25STATIC_DCL int FDECL(explmu, (struct monst *,struct attack *,BOOLEAN_P)); 26STATIC_DCL void FDECL(missmu,(struct monst *,BOOLEAN_P,struct attack *)); 27STATIC_DCL void FDECL(mswings,(struct monst *,struct obj *)); 28STATIC_DCL void FDECL(wildmiss, (struct monst *,struct attack *)); 29 30STATIC_DCL void FDECL(hurtarmor,(int)); 31STATIC_DCL void FDECL(hitmsg,(struct monst *,struct attack *)); 32 33/* See comment in mhitm.c. If we use this a lot it probably should be */ 34/* changed to a parameter to mhitu. */ 35static int dieroll; 36 37#ifdef OVL1 38 39 40STATIC_OVL void 41hitmsg(mtmp, mattk) 42register struct monst *mtmp; 43register struct attack *mattk; 44{ 45 int compat; 46 47 /* Note: if opposite gender, "seductively" */ 48 /* If same gender, "engagingly" for nymph, normal msg for others */ 49 if((compat = could_seduce(mtmp, &youmonst, mattk)) 50 && !mtmp->mcan && !mtmp->mspec_used) { 51 pline("%s %s you %s.", Monnam(mtmp), 52 Blind ? "talks to" : "smiles at", 53 compat == 2 ? "engagingly" : "seductively"); 54 } else 55 switch (mattk->aatyp) { 56 case AT_BITE: 57 pline("%s bites!", Monnam(mtmp)); 58 break; 59 case AT_KICK: 60 pline("%s kicks%c", Monnam(mtmp), 61 thick_skinned(youmonst.data) ? '.' : '!'); 62 break; 63 case AT_STNG: 64 pline("%s stings!", Monnam(mtmp)); 65 break; 66 case AT_BUTT: 67 pline("%s butts!", Monnam(mtmp)); 68 break; 69 case AT_TUCH: 70 pline("%s touches you!", Monnam(mtmp)); 71 break; 72 case AT_TENT: 73 pline("%s tentacles suck you!", 74 s_suffix(Monnam(mtmp))); 75 break; 76 case AT_EXPL: 77 case AT_BOOM: 78 pline("%s explodes!", Monnam(mtmp)); 79 break; 80 default: 81 pline("%s hits!", Monnam(mtmp)); 82 } 83} 84 85STATIC_OVL void 86missmu(mtmp, nearmiss, mattk) /* monster missed you */ 87register struct monst *mtmp; 88register boolean nearmiss; 89register struct attack *mattk; 90{ 91 if (!canspotmon(mtmp)) 92 map_invisible(mtmp->mx, mtmp->my); 93 94 if(could_seduce(mtmp, &youmonst, mattk) && !mtmp->mcan) 95 pline("%s pretends to be friendly.", Monnam(mtmp)); 96 else { 97 if (!flags.verbose || !nearmiss) 98 pline("%s misses.", Monnam(mtmp)); 99 else 100 pline("%s just misses!", Monnam(mtmp)); 101 } 102 stop_occupation(); 103} 104 105STATIC_OVL void 106mswings(mtmp, otemp) /* monster swings obj */ 107register struct monst *mtmp; 108register struct obj *otemp; 109{ 110 if (!flags.verbose || Blind || !mon_visible(mtmp)) 111 return; 112 pline("%s %s %s %s.", Monnam(mtmp), 113 (objects[otemp->otyp].oc_dir & PIERCE) ? "thrusts" : "swings", 114 mhis(mtmp), singular(otemp, xname)); 115} 116 117/* return how a poison attack was delivered */ 118const char * 119mpoisons_subj(mtmp, mattk) 120struct monst *mtmp; 121struct attack *mattk; 122{ 123 if (mattk->aatyp == AT_WEAP) { 124 struct obj *mwep = (mtmp == &youmonst) ? uwep : MON_WEP(mtmp); 125 /* "Foo's attack was poisoned." is pretty lame, but at least 126 it's better than "sting" when not a stinging attack... */ 127 return (!mwep || !mwep->opoisoned) ? "attack" : "weapon"; 128 } else { 129 return (mattk->aatyp == AT_TUCH) ? "contact" : 130 (mattk->aatyp == AT_GAZE) ? "gaze" : 131 (mattk->aatyp == AT_BITE) ? "bite" : "sting"; 132 } 133} 134 135/* called when your intrinsic speed is taken away */ 136void 137u_slow_down() 138{ 139 HFast = 0L; 140 if (!Fast) 141 You("slow down."); 142 else /* speed boots */ 143 Your("quickness feels less natural."); 144 exercise(A_DEX, FALSE); 145} 146 147#endif /* OVL1 */ 148#ifdef OVLB 149 150STATIC_OVL void 151wildmiss(mtmp, mattk) /* monster attacked your displaced image */ 152 register struct monst *mtmp; 153 register struct attack *mattk; 154{ 155 int compat; 156 157 /* no map_invisible() -- no way to tell where _this_ is coming from */ 158 159 if (!flags.verbose) return; 160 if (!cansee(mtmp->mx, mtmp->my)) return; 161 /* maybe it's attacking an image around the corner? */ 162 163 compat = (mattk->adtyp == AD_SEDU || mattk->adtyp == AD_SSEX) && 164 could_seduce(mtmp, &youmonst, (struct attack *)0); 165 166 if (!mtmp->mcansee || (Invis && !perceives(mtmp->data))) { 167 const char *swings = 168 mattk->aatyp == AT_BITE ? "snaps" : 169 mattk->aatyp == AT_KICK ? "kicks" : 170 (mattk->aatyp == AT_STNG || 171 mattk->aatyp == AT_BUTT || 172 nolimbs(mtmp->data)) ? "lunges" : "swings"; 173 174 if (compat) 175 pline("%s tries to touch you and misses!", Monnam(mtmp)); 176 else 177 switch(rn2(3)) { 178 case 0: pline("%s %s wildly and misses!", Monnam(mtmp), 179 swings); 180 break; 181 case 1: pline("%s attacks a spot beside you.", Monnam(mtmp)); 182 break; 183 case 2: pline("%s strikes at %s!", Monnam(mtmp), 184 levl[mtmp->mux][mtmp->muy].typ == WATER 185 ? "empty water" : "thin air"); 186 break; 187 default:pline("%s %s wildly!", Monnam(mtmp), swings); 188 break; 189 } 190 191 } else if (Displaced) { 192 if (compat) 193 pline("%s smiles %s at your %sdisplaced image...", 194 Monnam(mtmp), 195 compat == 2 ? "engagingly" : "seductively", 196 Invis ? "invisible " : ""); 197 else 198 pline("%s strikes at your %sdisplaced image and misses you!", 199 /* Note: if you're both invisible and displaced, 200 * only monsters which see invisible will attack your 201 * displaced image, since the displaced image is also 202 * invisible. 203 */ 204 Monnam(mtmp), 205 Invis ? "invisible " : ""); 206 207 } else if (Underwater) { 208 /* monsters may miss especially on water level where 209 bubbles shake the player here and there */ 210 if (compat) 211 pline("%s reaches towards your distorted image.",Monnam(mtmp)); 212 else 213 pline("%s is fooled by water reflections and misses!",Monnam(mtmp)); 214 215 } else impossible("%s attacks you without knowing your location?", 216 Monnam(mtmp)); 217} 218 219void 220expels(mtmp, mdat, message) 221register struct monst *mtmp; 222register struct permonst *mdat; /* if mtmp is polymorphed, mdat != mtmp->data */ 223boolean message; 224{ 225 if (message) { 226 if (is_animal(mdat)) 227 You("get regurgitated!"); 228 else { 229 char blast[40]; 230 register int i; 231 232 blast[0] = '\0'; 233 for(i = 0; i < NATTK; i++) 234 if(mdat->mattk[i].aatyp == AT_ENGL) 235 break; 236 if (mdat->mattk[i].aatyp != AT_ENGL) 237 impossible("Swallower has no engulfing attack?"); 238 else { 239 if (is_whirly(mdat)) { 240 switch (mdat->mattk[i].adtyp) { 241 case AD_ELEC: 242 Strcpy(blast, 243 " in a shower of sparks"); 244 break; 245 case AD_COLD: 246 Strcpy(blast, 247 " in a blast of frost"); 248 break; 249 } 250 } else 251 Strcpy(blast, " with a squelch"); 252 You("get expelled from %s%s!", 253 mon_nam(mtmp), blast); 254 } 255 } 256 } 257 unstuck(mtmp); /* ball&chain returned in unstuck() */ 258 mnexto(mtmp); 259 newsym(u.ux,u.uy); 260 spoteffects(TRUE); 261 /* to cover for a case where mtmp is not in a next square */ 262 if(um_dist(mtmp->mx,mtmp->my,1)) 263 pline("Brrooaa... You land hard at some distance."); 264} 265 266#endif /* OVLB */ 267#ifdef OVL0 268 269/* select a monster's next attack, possibly substituting for its usual one */ 270struct attack * 271getmattk(mptr, indx, prev_result, alt_attk_buf) 272struct permonst *mptr; 273int indx, prev_result[]; 274struct attack *alt_attk_buf; 275{ 276 struct attack *attk = &mptr->mattk[indx]; 277 278 /* prevent a monster with two consecutive disease or hunger attacks 279 from hitting with both of them on the same turn; if the first has 280 already hit, switch to a stun attack for the second */ 281 if (indx > 0 && prev_result[indx - 1] > 0 && 282 (attk->adtyp == AD_DISE || 283 attk->adtyp == AD_PEST || 284 attk->adtyp == AD_FAMN) && 285 attk->adtyp == mptr->mattk[indx - 1].adtyp) { 286 *alt_attk_buf = *attk; 287 attk = alt_attk_buf; 288 attk->adtyp = AD_STUN; 289 } 290 return attk; 291} 292 293/* 294 * mattacku: monster attacks you 295 * returns 1 if monster dies (e.g. "yellow light"), 0 otherwise 296 * Note: if you're displaced or invisible the monster might attack the 297 * wrong position... 298 * Assumption: it's attacking you or an empty square; if there's another 299 * monster which it attacks by mistake, the caller had better 300 * take care of it... 301 */ 302int 303mattacku(mtmp) 304 register struct monst *mtmp; 305{ 306 struct attack *mattk, alt_attk; 307 int i, j, tmp, sum[NATTK]; 308 struct permonst *mdat = mtmp->data; 309 boolean ranged = (distu(mtmp->mx, mtmp->my) > 3); 310 /* Is it near you? Affects your actions */ 311 boolean range2 = !monnear(mtmp, mtmp->mux, mtmp->muy); 312 /* Does it think it's near you? Affects its actions */ 313 boolean foundyou = (mtmp->mux==u.ux && mtmp->muy==u.uy); 314 /* Is it attacking you or your image? */ 315 boolean youseeit = canseemon(mtmp); 316 /* Might be attacking your image around the corner, or 317 * invisible, or you might be blind.... 318 */ 319 320 if(!ranged) nomul(0); 321 if(mtmp->mhp <= 0 || (Underwater && !is_swimmer(mtmp->data))) 322 return(0); 323 324 /* If swallowed, can only be affected by u.ustuck */ 325 if(u.uswallow) { 326 if(mtmp != u.ustuck) 327 return(0); 328 u.ustuck->mux = u.ux; 329 u.ustuck->muy = u.uy; 330 range2 = 0; 331 foundyou = 1; 332 if(u.uinvulnerable) return (0); /* stomachs can't hurt you! */ 333 } 334 335#ifdef STEED 336 else if (u.usteed) { 337 if (mtmp == u.usteed) 338 /* Your steed won't attack you */ 339 return (0); 340 /* Orcs like to steal and eat horses and the like */ 341 if (!rn2(is_orc(mtmp->data) ? 2 : 4) && 342 distu(mtmp->mx, mtmp->my) <= 2) { 343 /* Attack your steed instead */ 344 i = mattackm(mtmp, u.usteed); 345 if ((i & MM_AGR_DIED)) 346 return (1); 347 if (i & MM_DEF_DIED || u.umoved) 348 return (0); 349 /* Let your steed retaliate */ 350 return (!!(mattackm(u.usteed, mtmp) & MM_DEF_DIED)); 351 } 352 } 353#endif 354 355 if (u.uundetected && !range2 && foundyou && !u.uswallow) { 356 u.uundetected = 0; 357 if (is_hider(youmonst.data)) { 358 coord cc; /* maybe we need a unexto() function? */ 359 struct obj *obj; 360 361 You("fall from the %s!", ceiling(u.ux,u.uy)); 362 if (enexto(&cc, u.ux, u.uy, youmonst.data)) { 363 remove_monster(mtmp->mx, mtmp->my); 364 newsym(mtmp->mx,mtmp->my); 365 place_monster(mtmp, u.ux, u.uy); 366 if(mtmp->wormno) worm_move(mtmp); 367 teleds(cc.x, cc.y, TRUE); 368 set_apparxy(mtmp); 369 newsym(u.ux,u.uy); 370 } else { 371 pline("%s is killed by a falling %s (you)!", 372 Monnam(mtmp), youmonst.data->mname); 373 killed(mtmp); 374 newsym(u.ux,u.uy); 375 if (mtmp->mhp > 0) return 0; 376 else return 1; 377 } 378 if (youmonst.data->mlet != S_PIERCER) 379 return(0); /* trappers don't attack */ 380 381 obj = which_armor(mtmp, WORN_HELMET); 382 if (obj && is_metallic(obj)) { 383 Your("blow glances off %s helmet.", 384 s_suffix(mon_nam(mtmp))); 385 } else { 386 if (3 + find_mac(mtmp) <= rnd(20)) { 387 pline("%s is hit by a falling piercer (you)!", 388 Monnam(mtmp)); 389 if ((mtmp->mhp -= d(3,6)) < 1) 390 killed(mtmp); 391 } else 392 pline("%s is almost hit by a falling piercer (you)!", 393 Monnam(mtmp)); 394 } 395 } else { 396 if (!youseeit) 397 pline("It tries to move where you are hiding."); 398 else { 399 /* Ugly kludge for eggs. The message is phrased so as 400 * to be directed at the monster, not the player, 401 * which makes "laid by you" wrong. For the 402 * parallelism to work, we can't rephrase it, so we 403 * zap the "laid by you" momentarily instead. 404 */ 405 struct obj *obj = level.objects[u.ux][u.uy]; 406 407 if (obj || 408 (youmonst.data->mlet == S_EEL && is_pool(u.ux, u.uy))) { 409 int save_spe = 0; /* suppress warning */ 410 if (obj) { 411 save_spe = obj->spe; 412 if (obj->otyp == EGG) obj->spe = 0; 413 } 414 if (youmonst.data->mlet == S_EEL) 415 pline("Wait, %s! There's a hidden %s named %s there!", 416 m_monnam(mtmp), youmonst.data->mname, plname); 417 else 418 pline("Wait, %s! There's a %s named %s hiding under %s!", 419 m_monnam(mtmp), youmonst.data->mname, plname, 420 doname(level.objects[u.ux][u.uy])); 421 if (obj) obj->spe = save_spe; 422 } else 423 impossible("hiding under nothing?"); 424 } 425 newsym(u.ux,u.uy); 426 } 427 return(0); 428 } 429 if (youmonst.data->mlet == S_MIMIC && youmonst.m_ap_type && 430 !range2 && foundyou && !u.uswallow) { 431 if (!youseeit) pline("It gets stuck on you."); 432 else pline("Wait, %s! That's a %s named %s!", 433 m_monnam(mtmp), youmonst.data->mname, plname); 434 u.ustuck = mtmp; 435 youmonst.m_ap_type = M_AP_NOTHING; 436 youmonst.mappearance = 0; 437 newsym(u.ux,u.uy); 438 return(0); 439 } 440 441 /* player might be mimicking an object */ 442 if (youmonst.m_ap_type == M_AP_OBJECT && !range2 && foundyou && !u.uswallow) { 443 if (!youseeit) 444 pline("%s %s!", Something, 445 (likes_gold(mtmp->data) && youmonst.mappearance == GOLD_PIECE) ? 446 "tries to pick you up" : "disturbs you"); 447 else pline("Wait, %s! That %s is really %s named %s!", 448 m_monnam(mtmp), 449 mimic_obj_name(&youmonst), 450 an(mons[u.umonnum].mname), 451 plname); 452 if (multi < 0) { /* this should always be the case */ 453 char buf[BUFSZ]; 454 Sprintf(buf, "You appear to be %s again.", 455 Upolyd ? (const char *) an(youmonst.data->mname) : 456 (const char *) "yourself"); 457 unmul(buf); /* immediately stop mimicking */ 458 } 459 return 0; 460 } 461 462/* Work out the armor class differential */ 463 tmp = AC_VALUE(u.uac) + 10; /* tmp ~= 0 - 20 */ 464 tmp += mtmp->m_lev; 465 if(multi < 0) tmp += 4; 466 if((Invis && !perceives(mdat)) || !mtmp->mcansee) 467 tmp -= 2; 468 if(mtmp->mtrapped) tmp -= 2; 469 if(tmp <= 0) tmp = 1; 470 471 /* make eels visible the moment they hit/miss us */ 472 if(mdat->mlet == S_EEL && mtmp->minvis && cansee(mtmp->mx,mtmp->my)) { 473 mtmp->minvis = 0; 474 newsym(mtmp->mx,mtmp->my); 475 } 476 477/* Special demon handling code */ 478 if(!mtmp->cham && is_demon(mdat) && !range2 479 && mtmp->data != &mons[PM_BALROG] 480 && mtmp->data != &mons[PM_SUCCUBUS] 481 && mtmp->data != &mons[PM_INCUBUS]) 482 if(!mtmp->mcan && !rn2(13)) msummon(mtmp); 483 484/* Special lycanthrope handling code */ 485 if(!mtmp->cham && is_were(mdat) && !range2) { 486 487 if(is_human(mdat)) { 488 if(!rn2(5 - (night() * 2)) && !mtmp->mcan) new_were(mtmp); 489 } else if(!rn2(30) && !mtmp->mcan) new_were(mtmp); 490 mdat = mtmp->data; 491 492 if(!rn2(10) && !mtmp->mcan) { 493 int numseen, numhelp; 494 char buf[BUFSZ], genericwere[BUFSZ]; 495 496 Strcpy(genericwere, "creature"); 497 numhelp = were_summon(mdat, FALSE, &numseen, genericwere); 498 if (youseeit) { 499 pline("%s summons help!", Monnam(mtmp)); 500 if (numhelp > 0) { 501 if (numseen == 0) 502 You_feel("hemmed in."); 503 } else pline("But none comes."); 504 } else { 505 const char *from_nowhere; 506 507 if (flags.soundok) { 508 pline("%s %s!", Something, 509 makeplural(growl_sound(mtmp))); 510 from_nowhere = ""; 511 } else from_nowhere = " from nowhere"; 512 if (numhelp > 0) { 513 if (numseen < 1) You_feel("hemmed in."); 514 else { 515 if (numseen == 1) 516 Sprintf(buf, "%s appears", 517 an(genericwere)); 518 else 519 Sprintf(buf, "%s appear", 520 makeplural(genericwere)); 521 pline("%s%s!", upstart(buf), from_nowhere); 522 } 523 } /* else no help came; but you didn't know it tried */ 524 } 525 } 526 } 527 528 if(u.uinvulnerable) { 529 /* monsters won't attack you */ 530 if(mtmp == u.ustuck) 531 pline("%s loosens its grip slightly.", Monnam(mtmp)); 532 else if(!range2) { 533 if (youseeit || sensemon(mtmp)) 534 pline("%s starts to attack you, but pulls back.", 535 Monnam(mtmp)); 536 else 537 You_feel("%s move nearby.", something); 538 } 539 return (0); 540 } 541 542 /* Unlike defensive stuff, don't let them use item _and_ attack. */ 543 if(find_offensive(mtmp)) { 544 int foo = use_offensive(mtmp); 545 546 if (foo != 0) return(foo==1); 547 } 548 549 for(i = 0; i < NATTK; i++) { 550 551 sum[i] = 0; 552 mattk = getmattk(mdat, i, sum, &alt_attk); 553 if (u.uswallow && (mattk->aatyp != AT_ENGL)) 554 continue; 555 switch(mattk->aatyp) { 556 case AT_CLAW: /* "hand to hand" attacks */ 557 case AT_KICK: 558 case AT_BITE: 559 case AT_STNG: 560 case AT_TUCH: 561 case AT_BUTT: 562 case AT_TENT: 563 if(!range2 && (!MON_WEP(mtmp) || mtmp->mconf || Conflict || 564 !touch_petrifies(youmonst.data))) { 565 if (foundyou) { 566 if(tmp > (j = rnd(20+i))) { 567 if (mattk->aatyp != AT_KICK || 568 !thick_skinned(youmonst.data)) 569 sum[i] = hitmu(mtmp, mattk); 570 } else 571 missmu(mtmp, (tmp == j), mattk); 572 } else 573 wildmiss(mtmp, mattk); 574 } 575 break; 576 577 case AT_HUGS: /* automatic if prev two attacks succeed */ 578 /* Note: if displaced, prev attacks never succeeded */ 579 if((!range2 && i>=2 && sum[i-1] && sum[i-2]) 580 || mtmp == u.ustuck) 581 sum[i]= hitmu(mtmp, mattk); 582 break; 583 584 case AT_GAZE: /* can affect you either ranged or not */ 585 /* Medusa gaze already operated through m_respond in 586 * dochug(); don't gaze more than once per round. 587 */ 588 if (mdat != &mons[PM_MEDUSA]) 589 sum[i] = gazemu(mtmp, mattk); 590 break; 591 592 case AT_EXPL: /* automatic hit if next to, and aimed at you */ 593 if(!range2) sum[i] = explmu(mtmp, mattk, foundyou); 594 break; 595 596 case AT_ENGL: 597 if (!range2) { 598 if(foundyou) { 599 if(u.uswallow || tmp > (j = rnd(20+i))) { 600 /* Force swallowing monster to be 601 * displayed even when player is 602 * moving away */ 603 flush_screen(1); 604 sum[i] = gulpmu(mtmp, mattk); 605 } else { 606 missmu(mtmp, (tmp == j), mattk); 607 } 608 } else if (is_animal(mtmp->data)) { 609 pline("%s gulps some air!", Monnam(mtmp)); 610 } else { 611 if (youseeit) 612 pline("%s lunges forward and recoils!", 613 Monnam(mtmp)); 614 else 615 You_hear("a %s nearby.", 616 is_whirly(mtmp->data) ? 617 "rushing noise" : "splat"); 618 } 619 } 620 break; 621 case AT_BREA: 622 if(range2) sum[i] = breamu(mtmp, mattk); 623 /* Note: breamu takes care of displacement */ 624 break; 625 case AT_SPIT: 626 if(range2) sum[i] = spitmu(mtmp, mattk); 627 /* Note: spitmu takes care of displacement */ 628 break; 629 case AT_WEAP: 630 if(range2) { 631#ifdef REINCARNATION 632 if (!Is_rogue_level(&u.uz)) 633#endif 634 thrwmu(mtmp); 635 } else { 636 int hittmp = 0; 637 638 /* Rare but not impossible. Normally the monster 639 * wields when 2 spaces away, but it can be 640 * teleported or whatever.... 641 */ 642 if (mtmp->weapon_check == NEED_WEAPON || 643 !MON_WEP(mtmp)) { 644 mtmp->weapon_check = NEED_HTH_WEAPON; 645 /* mon_wield_item resets weapon_check as 646 * appropriate */ 647 if (mon_wield_item(mtmp) != 0) break; 648 } 649 if (foundyou) { 650 otmp = MON_WEP(mtmp); 651 if(otmp) { 652 hittmp = hitval(otmp, &youmonst); 653 tmp += hittmp; 654 mswings(mtmp, otmp); 655 } 656 if(tmp > (j = dieroll = rnd(20+i))) 657 sum[i] = hitmu(mtmp, mattk); 658 else 659 missmu(mtmp, (tmp == j), mattk); 660 /* KMH -- Don't accumulate to-hit bonuses */ 661 if (otmp) 662 tmp -= hittmp; 663 } else 664 wildmiss(mtmp, mattk); 665 } 666 break; 667 case AT_MAGC: 668 if (range2) 669 sum[i] = buzzmu(mtmp, mattk); 670 else { 671 if (foundyou) 672 sum[i] = castmu(mtmp, mattk, TRUE, TRUE); 673 else 674 sum[i] = castmu(mtmp, mattk, TRUE, FALSE); 675 } 676 break; 677 678 default: /* no attack */ 679 break; 680 } 681 if(flags.botl) bot(); 682 /* give player a chance of waking up before dying -kaa */ 683 if(sum[i] == 1) { /* successful attack */ 684 if (u.usleep && u.usleep < monstermoves && !rn2(10)) { 685 multi = -1; 686 nomovemsg = "The combat suddenly awakens you."; 687 } 688 } 689 if(sum[i] == 2) return 1; /* attacker dead */ 690 if(sum[i] == 3) break; /* attacker teleported, no more attacks */ 691 /* sum[i] == 0: unsuccessful attack */ 692 } 693 return(0); 694} 695 696#endif /* OVL0 */ 697#ifdef OVLB 698 699/* 700 * helper function for some compilers that have trouble with hitmu 701 */ 702 703STATIC_OVL void 704hurtarmor(attk) 705int attk; 706{ 707 int hurt; 708 709 switch(attk) { 710 /* 0 is burning, which we should never be called with */ 711 case AD_RUST: hurt = 1; break; 712 case AD_CORR: hurt = 3; break; 713 default: hurt = 2; break; 714 } 715 716 /* What the following code does: it keeps looping until it 717 * finds a target for the rust monster. 718 * Head, feet, etc... not covered by metal, or covered by 719 * rusty metal, are not targets. However, your body always 720 * is, no matter what covers it. 721 */ 722 while (1) { 723 switch(rn2(5)) { 724 case 0: 725 if (!uarmh || !rust_dmg(uarmh, xname(uarmh), hurt, FALSE, &youmonst)) 726 continue; 727 break; 728 case 1: 729 if (uarmc) { 730 (void)rust_dmg(uarmc, xname(uarmc), hurt, TRUE, &youmonst); 731 break; 732 } 733 /* Note the difference between break and continue; 734 * break means it was hit and didn't rust; continue 735 * means it wasn't a target and though it didn't rust 736 * something else did. 737 */ 738 if (uarm) 739 (void)rust_dmg(uarm, xname(uarm), hurt, TRUE, &youmonst); 740#ifdef TOURIST 741 else if (uarmu) 742 (void)rust_dmg(uarmu, xname(uarmu), hurt, TRUE, &youmonst); 743#endif 744 break; 745 case 2: 746 if (!uarms || !rust_dmg(uarms, xname(uarms), hurt, FALSE, &youmonst)) 747 continue; 748 break; 749 case 3: 750 if (!uarmg || !rust_dmg(uarmg, xname(uarmg), hurt, FALSE, &youmonst)) 751 continue; 752 break; 753 case 4: 754 if (!uarmf || !rust_dmg(uarmf, xname(uarmf), hurt, FALSE, &youmonst)) 755 continue; 756 break; 757 } 758 break; /* Out of while loop */ 759 } 760} 761 762#endif /* OVLB */ 763#ifdef OVL1 764 765STATIC_OVL boolean 766diseasemu(mdat) 767struct permonst *mdat; 768{ 769 if (Sick_resistance) { 770 You_feel("a slight illness."); 771 return FALSE; 772 } else { 773 make_sick(Sick ? Sick/3L + 1L : (long)rn1(ACURR(A_CON), 20), 774 mdat->mname, TRUE, SICK_NONVOMITABLE); 775 return TRUE; 776 } 777} 778 779/* check whether slippery clothing protects from hug or wrap attack */ 780STATIC_OVL boolean 781u_slip_free(mtmp, mattk) 782struct monst *mtmp; 783struct attack *mattk; 784{ 785 struct obj *obj = (uarmc ? uarmc : uarm); 786 787#ifdef TOURIST 788 if (!obj) obj = uarmu; 789#endif 790 if (mattk->adtyp == AD_DRIN) obj = uarmh; 791 792 /* if your cloak/armor is greased, monster slips off; this 793 protection might fail (33% chance) when the armor is cursed */ 794 if (obj && (obj->greased || obj->otyp == OILSKIN_CLOAK) && 795 (!obj->cursed || rn2(3))) { 796 pline("%s %s your %s %s!", 797 Monnam(mtmp), 798 (mattk->adtyp == AD_WRAP) ? 799 "slips off of" : "grabs you, but cannot hold onto", 800 obj->greased ? "greased" : "slippery", 801 /* avoid "slippery slippery cloak" 802 for undiscovered oilskin cloak */ 803 (obj->greased || objects[obj->otyp].oc_name_known) ? 804 xname(obj) : cloak_simple_name(obj)); 805 806 if (obj->greased && !rn2(2)) { 807 pline_The("grease wears off."); 808 obj->greased = 0; 809 update_inventory(); 810 } 811 return TRUE; 812 } 813 return FALSE; 814} 815 816/* armor that sufficiently covers the body might be able to block magic */ 817int 818magic_negation(mon) 819struct monst *mon; 820{ 821 struct obj *armor; 822 int armpro = 0; 823 824 armor = (mon == &youmonst) ? uarm : which_armor(mon, W_ARM); 825 if (armor && armpro < objects[armor->otyp].a_can) 826 armpro = objects[armor->otyp].a_can; 827 armor = (mon == &youmonst) ? uarmc : which_armor(mon, W_ARMC); 828 if (armor && armpro < objects[armor->otyp].a_can) 829 armpro = objects[armor->otyp].a_can; 830 armor = (mon == &youmonst) ? uarmh : which_armor(mon, W_ARMH); 831 if (armor && armpro < objects[armor->otyp].a_can) 832 armpro = objects[armor->otyp].a_can; 833 834 /* armor types for shirt, gloves, shoes, and shield don't currently 835 provide any magic cancellation but we might as well be complete */ 836#ifdef TOURIST 837 armor = (mon == &youmonst) ? uarmu : which_armor(mon, W_ARMU); 838 if (armor && armpro < objects[armor->otyp].a_can) 839 armpro = objects[armor->otyp].a_can; 840#endif 841 armor = (mon == &youmonst) ? uarmg : which_armor(mon, W_ARMG); 842 if (armor && armpro < objects[armor->otyp].a_can) 843 armpro = objects[armor->otyp].a_can; 844 armor = (mon == &youmonst) ? uarmf : which_armor(mon, W_ARMF); 845 if (armor && armpro < objects[armor->otyp].a_can) 846 armpro = objects[armor->otyp].a_can; 847 armor = (mon == &youmonst) ? uarms : which_armor(mon, W_ARMS); 848 if (armor && armpro < objects[armor->otyp].a_can) 849 armpro = objects[armor->otyp].a_can; 850 851#ifdef STEED 852 /* this one is really a stretch... */ 853 armor = (mon == &youmonst) ? 0 : which_armor(mon, W_SADDLE); 854 if (armor && armpro < objects[armor->otyp].a_can) 855 armpro = objects[armor->otyp].a_can; 856#endif 857 858 return armpro; 859} 860 861/* 862 * hitmu: monster hits you 863 * returns 2 if monster dies (e.g. "yellow light"), 1 otherwise 864 * 3 if the monster lives but teleported/paralyzed, so it can't keep 865 * attacking you 866 */ 867STATIC_OVL int 868hitmu(mtmp, mattk) 869 register struct monst *mtmp; 870 register struct attack *mattk; 871{ 872 register struct permonst *mdat = mtmp->data; 873 register int uncancelled, ptmp; 874 int dmg, armpro, permdmg; 875 char buf[BUFSZ]; 876 struct permonst *olduasmon = youmonst.data; 877 int res; 878 879 if (!canspotmon(mtmp)) 880 map_invisible(mtmp->mx, mtmp->my); 881 882/* If the monster is undetected & hits you, you should know where 883 * the attack came from. 884 */ 885 if(mtmp->mundetected && (hides_under(mdat) || mdat->mlet == S_EEL)) { 886 mtmp->mundetected = 0; 887 if (!(Blind ? Blind_telepat : Unblind_telepat)) { 888 struct obj *obj; 889 const char *what; 890 891 if ((obj = level.objects[mtmp->mx][mtmp->my]) != 0) { 892 if (Blind && !obj->dknown) 893 what = something; 894 else if (is_pool(mtmp->mx, mtmp->my) && !Underwater) 895 what = "the water"; 896 else 897 what = doname(obj); 898 899 pline("%s was hidden under %s!", Amonnam(mtmp), what); 900 } 901 newsym(mtmp->mx, mtmp->my); 902 } 903 } 904 905/* First determine the base damage done */ 906 dmg = d((int)mattk->damn, (int)mattk->damd); 907 if(is_undead(mdat) && midnight()) 908 dmg += d((int)mattk->damn, (int)mattk->damd); /* extra damage */ 909 910/* Next a cancellation factor */ 911/* Use uncancelled when the cancellation factor takes into account certain 912 * armor's special magic protection. Otherwise just use !mtmp->mcan. 913 */ 914 armpro = magic_negation(&youmonst); 915 uncancelled = !mtmp->mcan && ((rn2(3) >= armpro) || !rn2(50)); 916 917 permdmg = 0; 918/* Now, adjust damages via resistances or specific attacks */ 919 switch(mattk->adtyp) { 920 case AD_PHYS: 921 if (mattk->aatyp == AT_HUGS && !sticks(youmonst.data)) { 922 if(!u.ustuck && rn2(2)) { 923 if (u_slip_free(mtmp, mattk)) { 924 dmg = 0; 925 } else { 926 u.ustuck = mtmp; 927 pline("%s grabs you!", Monnam(mtmp)); 928 } 929 } else if(u.ustuck == mtmp) { 930 exercise(A_STR, FALSE); 931 You("are being %s.", 932 (mtmp->data == &mons[PM_ROPE_GOLEM]) 933 ? "choked" : "crushed"); 934 } 935 } else { /* hand to hand weapon */ 936 if(mattk->aatyp == AT_WEAP && otmp) { 937 if (otmp->otyp == CORPSE 938 && touch_petrifies(&mons[otmp->corpsenm])) { 939 dmg = 1; 940 pline("%s hits you with the %s corpse.", 941 Monnam(mtmp), mons[otmp->corpsenm].mname); 942 if (!Stoned) 943 goto do_stone; 944 } 945 dmg += dmgval(otmp, &youmonst); 946 if (dmg <= 0) dmg = 1; 947 if (!(otmp->oartifact && 948 artifact_hit(mtmp, &youmonst, otmp, &dmg,dieroll))) 949 hitmsg(mtmp, mattk); 950 if (!dmg) break; 951 if (u.mh > 1 && u.mh > ((u.uac>0) ? dmg : dmg+u.uac) && 952 objects[otmp->otyp].oc_material == IRON && 953 (u.umonnum==PM_BLACK_PUDDING 954 || u.umonnum==PM_BROWN_PUDDING)) { 955 /* This redundancy necessary because you have to 956 * take the damage _before_ being cloned. 957 */ 958 if (u.uac < 0) dmg += u.uac; 959 if (dmg < 1) dmg = 1; 960 if (dmg > 1) exercise(A_STR, FALSE); 961 u.mh -= dmg; 962 flags.botl = 1; 963 dmg = 0; 964 if(cloneu()) 965 You("divide as %s hits you!",mon_nam(mtmp)); 966 } 967 urustm(mtmp, otmp); 968 } else if (mattk->aatyp != AT_TUCH || dmg != 0 || 969 mtmp != u.ustuck) 970 hitmsg(mtmp, mattk); 971 } 972 break; 973 case AD_DISE: 974 hitmsg(mtmp, mattk); 975 if (!diseasemu(mdat)) dmg = 0; 976 break; 977 case AD_FIRE: 978 hitmsg(mtmp, mattk); 979 if (uncancelled) { 980 pline("You're %s!", on_fire(youmonst.data, mattk)); 981 if (youmonst.data == &mons[PM_STRAW_GOLEM] || 982 youmonst.data == &mons[PM_PAPER_GOLEM]) { 983 You("roast!"); 984 /* KMH -- this is okay with unchanging */ 985 rehumanize(); 986 break; 987 } else if (Fire_resistance) { 988 pline_The("fire doesn't feel hot!"); 989 dmg = 0; 990 } 991 if((int) mtmp->m_lev > rn2(20)) 992 destroy_item(SCROLL_CLASS, AD_FIRE); 993 if((int) mtmp->m_lev > rn2(20)) 994 destroy_item(POTION_CLASS, AD_FIRE); 995 if((int) mtmp->m_lev > rn2(25)) 996 destroy_item(SPBOOK_CLASS, AD_FIRE); 997 burn_away_slime(); 998 } else dmg = 0; 999 break; 1000 case AD_COLD: 1001 hitmsg(mtmp, mattk); 1002 if (uncancelled) { 1003 pline("You're covered in frost!"); 1004 if (Cold_resistance) { 1005 pline_The("frost doesn't seem cold!"); 1006 dmg = 0; 1007 } 1008 if((int) mtmp->m_lev > rn2(20)) 1009 destroy_item(POTION_CLASS, AD_COLD); 1010 } else dmg = 0; 1011 break; 1012 case AD_ELEC: 1013 hitmsg(mtmp, mattk); 1014 if (uncancelled) { 1015 You("get zapped!"); 1016 if (Shock_resistance) { 1017 pline_The("zap doesn't shock you!"); 1018 dmg = 0; 1019 } 1020 if((int) mtmp->m_lev > rn2(20)) 1021 destroy_item(WAND_CLASS, AD_ELEC); 1022 if((int) mtmp->m_lev > rn2(20)) 1023 destroy_item(RING_CLASS, AD_ELEC); 1024 } else dmg = 0; 1025 break; 1026 case AD_SLEE: 1027 hitmsg(mtmp, mattk); 1028 if (uncancelled && multi >= 0 && !rn2(5)) { 1029 if (Sleep_resistance) break; 1030 fall_asleep(-rnd(10), TRUE); 1031 if (Blind) You("are put to sleep!"); 1032 else You("are put to sleep by %s!", mon_nam(mtmp)); 1033 } 1034 break; 1035 case AD_BLND: 1036 if (can_blnd(mtmp, &youmonst, mattk->aatyp, (struct obj*)0)) { 1037 if (!Blind) pline("%s blinds you!", Monnam(mtmp)); 1038 make_blinded(Blinded+(long)dmg,FALSE); 1039 if (!Blind) Your(vision_clears); 1040 } 1041 dmg = 0; 1042 break; 1043 case AD_DRST: 1044 ptmp = A_STR; 1045 goto dopois; 1046 case AD_DRDX: 1047 ptmp = A_DEX; 1048 goto dopois; 1049 case AD_DRCO: 1050 ptmp = A_CON; 1051dopois: 1052 hitmsg(mtmp, mattk); 1053 if (uncancelled && !rn2(8)) { 1054 Sprintf(buf, "%s %s", 1055 s_suffix(Monnam(mtmp)), mpoisons_subj(mtmp, mattk)); 1056 poisoned(buf, ptmp, mdat->mname, 30); 1057 } 1058 break; 1059 case AD_DRIN: 1060 hitmsg(mtmp, mattk); 1061 if (defends(AD_DRIN, uwep) || !has_head(youmonst.data)) { 1062 You("don't seem harmed."); 1063 /* Not clear what to do for green slimes */ 1064 break; 1065 } 1066 if (u_slip_free(mtmp,mattk)) break; 1067 1068 if (uarmh && rn2(8)) { 1069 /* not body_part(HEAD) */ 1070 Your("helmet blocks the attack to your head."); 1071 break; 1072 } 1073 if (Half_physical_damage) dmg = (dmg+1) / 2; 1074 mdamageu(mtmp, dmg); 1075 1076 if (!uarmh || uarmh->otyp != DUNCE_CAP) { 1077 Your("brain is eaten!"); 1078 /* No such thing as mindless players... */ 1079 if (ABASE(A_INT) <= ATTRMIN(A_INT)) { 1080 int lifesaved = 0; 1081 struct obj *wore_amulet = uamul; 1082 1083 while(1) { 1084 /* avoid looping on "die(y/n)?" */ 1085 if (lifesaved && (discover || wizard)) { 1086 if (wore_amulet && !uamul) { 1087 /* used up AMULET_OF_LIFE_SAVING; still 1088 subject to dying from brainlessness */ 1089 wore_amulet = 0; 1090 } else { 1091 /* explicitly chose not to die; 1092 arbitrarily boost intelligence */ 1093 ABASE(A_INT) = ATTRMIN(A_INT) + 2; 1094 You_feel("like a scarecrow."); 1095 break; 1096 } 1097 } 1098 1099 if (lifesaved) 1100 pline("Unfortunately your brain is still gone."); 1101 else 1102 Your("last thought fades away."); 1103 killer = "brainlessness"; 1104 killer_format = KILLED_BY; 1105 done(DIED); 1106 lifesaved++; 1107 } 1108 } 1109 } 1110 /* adjattrib gives dunce cap message when appropriate */ 1111 (void) adjattrib(A_INT, -rnd(2), FALSE); 1112 forget_levels(25); /* lose memory of 25% of levels */ 1113 forget_objects(25); /* lose memory of 25% of objects */ 1114 exercise(A_WIS, FALSE); 1115 break; 1116 case AD_PLYS: 1117 hitmsg(mtmp, mattk); 1118 if (uncancelled && multi >= 0 && !rn2(3)) { 1119 if (Free_action) { 1120 You("momentarily stiffen."); 1121 } else { 1122 if (Blind) You("are frozen!"); 1123 else You("are frozen by %s!", mon_nam(mtmp)); 1124 nomovemsg = 0; /* default: "you can move again" */ 1125 nomul(-rnd(10)); 1126 exercise(A_DEX, FALSE); 1127 } 1128 } 1129 break; 1130 case AD_DRLI: 1131 hitmsg(mtmp, mattk); 1132 if (uncancelled && !rn2(3) && !Drain_resistance) { 1133 losexp("life drainage"); 1134 } 1135 break; 1136 case AD_LEGS: 1137 { register long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE; 1138 const char *sidestr = (side == RIGHT_SIDE) ? "right" : "left"; 1139 1140 /* This case is too obvious to ignore, but Nethack is not in 1141 * general very good at considering height--most short monsters 1142 * still _can_ attack you when you're flying or mounted. 1143 * [FIXME: why can't a flying attacker overcome this?] 1144 */ 1145 if ( 1146#ifdef STEED 1147 u.usteed || 1148#endif 1149 Levitation || Flying) { 1150 pline("%s tries to reach your %s %s!", Monnam(mtmp), 1151 sidestr, body_part(LEG)); 1152 dmg = 0; 1153 } else if (mtmp->mcan) { 1154 pline("%s nuzzles against your %s %s!", Monnam(mtmp), 1155 sidestr, body_part(LEG)); 1156 dmg = 0; 1157 } else { 1158 if (uarmf) { 1159 if (rn2(2) && (uarmf->otyp == LOW_BOOTS || 1160 uarmf->otyp == IRON_SHOES)) 1161 pline("%s pricks the exposed part of your %s %s!", 1162 Monnam(mtmp), sidestr, body_part(LEG)); 1163 else if (!rn2(5)) 1164 pline("%s pricks through your %s boot!", 1165 Monnam(mtmp), sidestr); 1166 else { 1167 pline("%s scratches your %s boot!", Monnam(mtmp), 1168 sidestr); 1169 dmg = 0; 1170 break; 1171 } 1172 } else pline("%s pricks your %s %s!", Monnam(mtmp), 1173 sidestr, body_part(LEG)); 1174 set_wounded_legs(side, rnd(60-ACURR(A_DEX))); 1175 exercise(A_STR, FALSE); 1176 exercise(A_DEX, FALSE); 1177 } 1178 break; 1179 } 1180 case AD_STON: /* cockatrice */ 1181 hitmsg(mtmp, mattk); 1182 if(!rn2(3)) { 1183 if (mtmp->mcan) { 1184 if (flags.soundok) 1185 You_hear("a cough from %s!", mon_nam(mtmp)); 1186 } else { 1187 if (flags.soundok) 1188 You_hear("%s hissing!", s_suffix(mon_nam(mtmp))); 1189 if(!rn2(10) || 1190 (flags.moonphase == NEW_MOON && !have_lizard())) { 1191 do_stone: 1192 if (!Stoned && !Stone_resistance 1193 && !(poly_when_stoned(youmonst.data) && 1194 polymon(PM_STONE_GOLEM))) { 1195 Stoned = 5; 1196 delayed_killer = mtmp->data->mname; 1197 if (mtmp->data->geno & G_UNIQ) { 1198 if (!type_is_pname(mtmp->data)) { 1199 static char kbuf[BUFSZ]; 1200 1201 /* "the" buffer may be reallocated */ 1202 Strcpy(kbuf, the(delayed_killer)); 1203 delayed_killer = kbuf; 1204 } 1205 killer_format = KILLED_BY; 1206 } else killer_format = KILLED_BY_AN; 1207 return(1); 1208 /* You("turn to stone..."); */ 1209 /* done_in_by(mtmp); */ 1210 } 1211 } 1212 } 1213 } 1214 break; 1215 case AD_STCK: 1216 hitmsg(mtmp, mattk); 1217 if (uncancelled && !u.ustuck && !sticks(youmonst.data)) 1218 u.ustuck = mtmp; 1219 break; 1220 case AD_WRAP: 1221 if ((!mtmp->mcan || u.ustuck == mtmp) && !sticks(youmonst.data)) { 1222 if (!u.ustuck && !rn2(10)) { 1223 if (u_slip_free(mtmp, mattk)) { 1224 dmg = 0; 1225 } else { 1226 pline("%s swings itself around you!", 1227 Monnam(mtmp)); 1228 u.ustuck = mtmp; 1229 } 1230 } else if(u.ustuck == mtmp) { 1231 if (is_pool(mtmp->mx,mtmp->my) && !Swimming 1232 && !Amphibious) { 1233 boolean moat = 1234 (levl[mtmp->mx][mtmp->my].typ != POOL) && 1235 (levl[mtmp->mx][mtmp->my].typ != WATER) && 1236 !Is_medusa_level(&u.uz) && 1237 !Is_waterlevel(&u.uz); 1238 1239 pline("%s drowns you...", Monnam(mtmp)); 1240 killer_format = KILLED_BY_AN; 1241 Sprintf(buf, "%s by %s", 1242 moat ? "moat" : "pool of water", 1243 an(mtmp->data->mname)); 1244 killer = buf; 1245 done(DROWNING); 1246 } else if(mattk->aatyp == AT_HUGS) 1247 You("are being crushed."); 1248 } else { 1249 dmg = 0; 1250 if(flags.verbose) 1251 pline("%s brushes against your %s.", Monnam(mtmp), 1252 body_part(LEG)); 1253 } 1254 } else dmg = 0; 1255 break; 1256 case AD_WERE: 1257 hitmsg(mtmp, mattk); 1258 if (uncancelled && !rn2(4) && u.ulycn == NON_PM && 1259 !Protection_from_shape_changers && 1260 !defends(AD_WERE,uwep)) { 1261 You_feel("feverish."); 1262 exercise(A_CON, FALSE); 1263 u.ulycn = monsndx(mdat); 1264 } 1265 break; 1266 case AD_SGLD: 1267 hitmsg(mtmp, mattk); 1268 if (youmonst.data->mlet == mdat->mlet) break; 1269 if(!mtmp->mcan) stealgold(mtmp); 1270 break; 1271 1272 case AD_SITM: /* for now these are the same */ 1273 case AD_SEDU: 1274 if (is_animal(mtmp->data)) { 1275 hitmsg(mtmp, mattk); 1276 if (mtmp->mcan) break; 1277 /* Continue below */ 1278 } else if (dmgtype(youmonst.data, AD_SEDU) 1279#ifdef SEDUCE 1280 || dmgtype(youmonst.data, AD_SSEX) 1281#endif 1282 ) { 1283 pline("%s %s.", Monnam(mtmp), mtmp->minvent ? 1284 "brags about the goods some dungeon explorer provided" : 1285 "makes some remarks about how difficult theft is lately"); 1286 if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE); 1287 return 3; 1288 } else if (mtmp->mcan) { 1289 if (!Blind) { 1290 pline("%s tries to %s you, but you seem %s.", 1291 Adjmonnam(mtmp, "plain"), 1292 flags.female ? "charm" : "seduce", 1293 flags.female ? "unaffected" : "uninterested"); 1294 } 1295 if(rn2(3)) { 1296 if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE); 1297 return 3; 1298 } 1299 break; 1300 } 1301 buf[0] = '\0'; 1302 switch (steal(mtmp, buf)) { 1303 case -1: 1304 return 2; 1305 case 0: 1306 break; 1307 default: 1308 if (!is_animal(mtmp->data) && !tele_restrict(mtmp)) 1309 (void) rloc(mtmp, FALSE); 1310 if (is_animal(mtmp->data) && *buf) { 1311 if (canseemon(mtmp)) 1312 pline("%s tries to %s away with %s.", 1313 Monnam(mtmp), 1314 locomotion(mtmp->data, "run"), 1315 buf); 1316 } 1317 monflee(mtmp, 0, FALSE, FALSE); 1318 return 3; 1319 } 1320 break; 1321#ifdef SEDUCE 1322 case AD_SSEX: 1323 if(could_seduce(mtmp, &youmonst, mattk) == 1 1324 && !mtmp->mcan) 1325 if (doseduce(mtmp)) 1326 return 3; 1327 break; 1328#endif 1329 case AD_SAMU: 1330 hitmsg(mtmp, mattk); 1331 /* when the Wiz hits, 1/20 steals the amulet */ 1332 if (u.uhave.amulet || 1333 u.uhave.bell || u.uhave.book || u.uhave.menorah 1334 || u.uhave.questart) /* carrying the Quest Artifact */ 1335 if (!rn2(20)) stealamulet(mtmp); 1336 break; 1337 1338 case AD_TLPT: 1339 hitmsg(mtmp, mattk); 1340 if (uncancelled) { 1341 if(flags.verbose) 1342 Your("position suddenly seems very uncertain!"); 1343 tele(); 1344 } 1345 break; 1346 case AD_RUST: 1347 hitmsg(mtmp, mattk); 1348 if (mtmp->mcan) break; 1349 if (u.umonnum == PM_IRON_GOLEM) { 1350 You("rust!"); 1351 /* KMH -- this is okay with unchanging */ 1352 rehumanize(); 1353 break; 1354 } 1355 hurtarmor(AD_RUST); 1356 break; 1357 case AD_CORR: 1358 hitmsg(mtmp, mattk); 1359 if (mtmp->mcan) break; 1360 hurtarmor(AD_CORR); 1361 break; 1362 case AD_DCAY: 1363 hitmsg(mtmp, mattk); 1364 if (mtmp->mcan) break; 1365 if (u.umonnum == PM_WOOD_GOLEM || 1366 u.umonnum == PM_LEATHER_GOLEM) { 1367 You("rot!"); 1368 /* KMH -- this is okay with unchanging */ 1369 rehumanize(); 1370 break; 1371 } 1372 hurtarmor(AD_DCAY); 1373 break; 1374 case AD_HEAL: 1375 /* a cancelled nurse is just an ordinary monster */ 1376 if (mtmp->mcan) { 1377 hitmsg(mtmp, mattk); 1378 break; 1379 } 1380 if(!uwep 1381#ifdef TOURIST 1382 && !uarmu 1383#endif 1384 && !uarm && !uarmh && !uarms && !uarmg && !uarmc && !uarmf) { 1385 boolean goaway = FALSE; 1386 pline("%s hits! (I hope you don't mind.)", Monnam(mtmp)); 1387 if (Upolyd) { 1388 u.mh += rnd(7); 1389 if (!rn2(7)) { 1390 /* no upper limit necessary; effect is temporary */ 1391 u.mhmax++; 1392 if (!rn2(13)) goaway = TRUE; 1393 } 1394 if (u.mh > u.mhmax) u.mh = u.mhmax; 1395 } else { 1396 u.uhp += rnd(7); 1397 if (!rn2(7)) { 1398 /* hard upper limit via nurse care: 25 * ulevel */ 1399 if (u.uhpmax < 5 * u.ulevel + d(2 * u.ulevel, 10)) 1400 u.uhpmax++; 1401 if (!rn2(13)) goaway = TRUE; 1402 } 1403 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax; 1404 } 1405 if (!rn2(3)) exercise(A_STR, TRUE); 1406 if (!rn2(3)) exercise(A_CON, TRUE); 1407 if (Sick) make_sick(0L, (char *) 0, FALSE, SICK_ALL); 1408 flags.botl = 1; 1409 if (goaway) { 1410 mongone(mtmp); 1411 return 2; 1412 } else if (!rn2(33)) { 1413 if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE); 1414 monflee(mtmp, d(3, 6), TRUE, FALSE); 1415 return 3; 1416 } 1417 dmg = 0; 1418 } else { 1419 if (Role_if(PM_HEALER)) { 1420 if (flags.soundok && !(moves % 5)) 1421 verbalize("Doc, I can't help you unless you cooperate."); 1422 dmg = 0; 1423 } else hitmsg(mtmp, mattk); 1424 } 1425 break; 1426 case AD_CURS: 1427 hitmsg(mtmp, mattk); 1428 if(!night() && mdat == &mons[PM_GREMLIN]) break; 1429 if(!mtmp->mcan && !rn2(10)) { 1430 if (flags.soundok) { 1431 if (Blind) You_hear("laughter."); 1432 else pline("%s chuckles.", Monnam(mtmp)); 1433 } 1434 if (u.umonnum == PM_CLAY_GOLEM) { 1435 pline("Some writing vanishes from your head!"); 1436 /* KMH -- this is okay with unchanging */ 1437 rehumanize(); 1438 break; 1439 } 1440 attrcurse(); 1441 } 1442 break; 1443 case AD_STUN: 1444 hitmsg(mtmp, mattk); 1445 if(!mtmp->mcan && !rn2(4)) { 1446 make_stunned(HStun + dmg, TRUE); 1447 dmg /= 2; 1448 } 1449 break; 1450 case AD_ACID: 1451 hitmsg(mtmp, mattk); 1452 if (!mtmp->mcan && !rn2(3)) 1453 if (Acid_resistance) { 1454 pline("You're covered in acid, but it seems harmless."); 1455 dmg = 0; 1456 } else { 1457 pline("You're covered in acid! It burns!"); 1458 exercise(A_STR, FALSE); 1459 } 1460 else dmg = 0; 1461 break; 1462 case AD_SLOW: 1463 hitmsg(mtmp, mattk); 1464 if (uncancelled && HFast && 1465 !defends(AD_SLOW, uwep) && !rn2(4)) 1466 u_slow_down(); 1467 break; 1468 case AD_DREN: 1469 hitmsg(mtmp, mattk); 1470 if (uncancelled && !rn2(4)) 1471 drain_en(dmg); 1472 dmg = 0; 1473 break; 1474 case AD_CONF: 1475 hitmsg(mtmp, mattk); 1476 if(!mtmp->mcan && !rn2(4) && !mtmp->mspec_used) { 1477 mtmp->mspec_used = mtmp->mspec_used + (dmg + rn2(6)); 1478 if(Confusion) 1479 You("are getting even more confused."); 1480 else You("are getting confused."); 1481 make_confused(HConfusion + dmg, FALSE); 1482 } 1483 dmg = 0; 1484 break; 1485 case AD_DETH: 1486 pline("%s reaches out with its deadly touch.", Monnam(mtmp)); 1487 if (is_undead(youmonst.data)) { 1488 /* Still does normal damage */ 1489 pline("Was that the touch of death?"); 1490 break; 1491 } 1492 switch (rn2(20)) { 1493 case 19: case 18: case 17: 1494 if (!Antimagic) { 1495 killer_format = KILLED_BY_AN; 1496 killer = "touch of death"; 1497 done(DIED); 1498 dmg = 0; 1499 break; 1500 } /* else FALLTHRU */ 1501 default: /* case 16: ... case 5: */ 1502 You_feel("your life force draining away..."); 1503 permdmg = 1; /* actual damage done below */ 1504 break; 1505 case 4: case 3: case 2: case 1: case 0: 1506 if (Antimagic) shieldeff(u.ux, u.uy); 1507 pline("Lucky for you, it didn't work!"); 1508 dmg = 0; 1509 break; 1510 } 1511 break; 1512 case AD_PEST: 1513 pline("%s reaches out, and you feel fever and chills.", 1514 Monnam(mtmp)); 1515 (void) diseasemu(mdat); /* plus the normal damage */ 1516 break; 1517 case AD_FAMN: 1518 pline("%s reaches out, and your body shrivels.", 1519 Monnam(mtmp)); 1520 exercise(A_CON, FALSE); 1521 if (!is_fainted()) morehungry(rn1(40,40)); 1522 /* plus the normal damage */ 1523 break; 1524 case AD_SLIM: 1525 hitmsg(mtmp, mattk); 1526 if (!uncancelled) break; 1527 if (flaming(youmonst.data)) { 1528 pline_The("slime burns away!"); 1529 dmg = 0; 1530 } else if (Unchanging || 1531 youmonst.data == &mons[PM_GREEN_SLIME]) { 1532 You("are unaffected."); 1533 dmg = 0; 1534 } else if (!Slimed) { 1535 You("don't feel very well."); 1536 Slimed = 10L; 1537 flags.botl = 1; 1538 killer_format = KILLED_BY_AN; 1539 delayed_killer = mtmp->data->mname; 1540 } else 1541 pline("Yuck!"); 1542 break; 1543 case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */ 1544 hitmsg(mtmp, mattk); 1545 /* uncancelled is sufficient enough; please 1546 don't make this attack less frequent */ 1547 if (uncancelled) { 1548 struct obj *obj = some_armor(&youmonst); 1549 1550 if (drain_item(obj)) { 1551 Your("%s less effective.", aobjnam(obj, "seem")); 1552 } 1553 } 1554 break; 1555 default: dmg = 0; 1556 break; 1557 } 1558 if(u.uhp < 1) done_in_by(mtmp); 1559 1560/* Negative armor class reduces damage done instead of fully protecting 1561 * against hits. 1562 */ 1563 if (dmg && u.uac < 0) { 1564 dmg -= rnd(-u.uac); 1565 if (dmg < 1) dmg = 1; 1566 } 1567 1568 if(dmg) { 1569 if (Half_physical_damage 1570 /* Mitre of Holiness */ 1571 || (Role_if(PM_PRIEST) && uarmh && is_quest_artifact(uarmh) && 1572 (is_undead(mtmp->data) || is_demon(mtmp->data)))) 1573 dmg = (dmg+1) / 2; 1574 1575 if (permdmg) { /* Death's life force drain */ 1576 int lowerlimit, *hpmax_p; 1577 /* 1578 * Apply some of the damage to permanent hit points: 1579 * polymorphed 100% against poly'd hpmax 1580 * hpmax > 25*lvl 100% against normal hpmax 1581 * hpmax > 10*lvl 50..100% 1582 * hpmax > 5*lvl 25..75% 1583 * otherwise 0..50% 1584 * Never reduces hpmax below 1 hit point per level. 1585 */ 1586 permdmg = rn2(dmg / 2 + 1); 1587 if (Upolyd || u.uhpmax > 25 * u.ulevel) permdmg = dmg; 1588 else if (u.uhpmax > 10 * u.ulevel) permdmg += dmg / 2; 1589 else if (u.uhpmax > 5 * u.ulevel) permdmg += dmg / 4; 1590 1591 if (Upolyd) { 1592 hpmax_p = &u.mhmax; 1593 /* [can't use youmonst.m_lev] */ 1594 lowerlimit = min((int)youmonst.data->mlevel, u.ulevel); 1595 } else { 1596 hpmax_p = &u.uhpmax; 1597 lowerlimit = u.ulevel; 1598 } 1599 if (*hpmax_p - permdmg > lowerlimit) 1600 *hpmax_p -= permdmg; 1601 else if (*hpmax_p > lowerlimit) 1602 *hpmax_p = lowerlimit; 1603 else /* unlikely... */ 1604 ; /* already at or below minimum threshold; do nothing */ 1605 flags.botl = 1; 1606 } 1607 1608 mdamageu(mtmp, dmg); 1609 } 1610 1611 if (dmg) 1612 res = passiveum(olduasmon, mtmp, mattk); 1613 else 1614 res = 1; 1615 stop_occupation(); 1616 return res; 1617} 1618 1619#endif /* OVL1 */ 1620#ifdef OVLB 1621 1622STATIC_OVL int 1623gulpmu(mtmp, mattk) /* monster swallows you, or damage if u.uswallow */ 1624 register struct monst *mtmp; 1625 register struct attack *mattk; 1626{ 1627 struct trap *t = t_at(u.ux, u.uy); 1628 int tmp = d((int)mattk->damn, (int)mattk->damd); 1629 int tim_tmp; 1630 register struct obj *otmp2; 1631 int i; 1632 1633 if (!u.uswallow) { /* swallows you */ 1634 if (youmonst.data->msize >= MZ_HUGE) return(0); 1635 if ((t && ((t->ttyp == PIT) || (t->ttyp == SPIKED_PIT))) && 1636 sobj_at(BOULDER, u.ux, u.uy)) 1637 return(0); 1638 1639 if (Punished) unplacebc(); /* ball&chain go away */ 1640 remove_monster(mtmp->mx, mtmp->my); 1641 mtmp->mtrapped = 0; /* no longer on old trap */ 1642 place_monster(mtmp, u.ux, u.uy); 1643 u.ustuck = mtmp; 1644 newsym(mtmp->mx,mtmp->my); 1645#ifdef STEED 1646 if (is_animal(mtmp->data) && u.usteed) { 1647 char buf[BUFSZ]; 1648 /* Too many quirks presently if hero and steed 1649 * are swallowed. Pretend purple worms don't 1650 * like horses for now :-) 1651 */ 1652 Strcpy(buf, mon_nam(u.usteed)); 1653 pline ("%s lunges forward and plucks you off %s!", 1654 Monnam(mtmp), buf); 1655 dismount_steed(DISMOUNT_ENGULFED); 1656 } else 1657#endif 1658 pline("%s engulfs you!", Monnam(mtmp)); 1659 stop_occupation(); 1660 reset_occupations(); /* behave as if you had moved */ 1661 1662 if (u.utrap) { 1663 You("are released from the %s!", 1664 u.utraptype==TT_WEB ? "web" : "trap"); 1665 u.utrap = 0; 1666 } 1667 1668 i = number_leashed(); 1669 if (i > 0) { 1670 const char *s = (i > 1) ? "leashes" : "leash"; 1671 pline_The("%s %s loose.", s, vtense(s, "snap")); 1672 unleash_all(); 1673 } 1674 1675 if (touch_petrifies(youmonst.data) && !resists_ston(mtmp)) { 1676 minstapetrify(mtmp, TRUE); 1677 if (mtmp->mhp > 0) return 0; 1678 else return 2; 1679 } 1680 1681 display_nhwindow(WIN_MESSAGE, FALSE); 1682 vision_recalc(2); /* hero can't see anything */ 1683 u.uswallow = 1; 1684 /* u.uswldtim always set > 1 */ 1685 tim_tmp = 25 - (int)mtmp->m_lev; 1686 if (tim_tmp > 0) tim_tmp = rnd(tim_tmp) / 2; 1687 else if (tim_tmp < 0) tim_tmp = -(rnd(-tim_tmp) / 2); 1688 tim_tmp += -u.uac + 10; 1689 u.uswldtim = (unsigned)((tim_tmp < 2) ? 2 : tim_tmp); 1690 swallowed(1); 1691 for (otmp2 = invent; otmp2; otmp2 = otmp2->nobj) 1692 (void) snuff_lit(otmp2); 1693 } 1694 1695 if (mtmp != u.ustuck) return(0); 1696 if (u.uswldtim > 0) u.uswldtim -= 1; 1697 1698 switch(mattk->adtyp) { 1699 1700 case AD_DGST: 1701 if (Slow_digestion) { 1702 /* Messages are handled below */ 1703 u.uswldtim = 0; 1704 tmp = 0; 1705 } else if (u.uswldtim == 0) { 1706 pline("%s totally digests you!", Monnam(mtmp)); 1707 tmp = u.uhp; 1708 if (Half_physical_damage) tmp *= 2; /* sorry */ 1709 } else { 1710 pline("%s%s digests you!", Monnam(mtmp), 1711 (u.uswldtim == 2) ? " thoroughly" : 1712 (u.uswldtim == 1) ? " utterly" : ""); 1713 exercise(A_STR, FALSE); 1714 } 1715 break; 1716 case AD_PHYS: 1717 if (mtmp->data == &mons[PM_FOG_CLOUD]) { 1718 You("are laden with moisture and %s", 1719 flaming(youmonst.data) ? "are smoldering out!" : 1720 Breathless ? "find it mildly uncomfortable." : 1721 amphibious(youmonst.data) ? "feel comforted." : 1722 "can barely breathe!"); 1723 /* NB: Amphibious includes Breathless */ 1724 if (Amphibious && !flaming(youmonst.data)) tmp = 0; 1725 } else { 1726 You("are pummeled with debris!"); 1727 exercise(A_STR, FALSE); 1728 } 1729 break; 1730 case AD_ACID: 1731 if (Acid_resistance) { 1732 You("are covered with a seemingly harmless goo."); 1733 tmp = 0; 1734 } else { 1735 if (Hallucination) pline("Ouch! You've been slimed!"); 1736 else You("are covered in slime! It burns!"); 1737 exercise(A_STR, FALSE); 1738 } 1739 break; 1740 case AD_BLND: 1741 if (can_blnd(mtmp, &youmonst, mattk->aatyp, (struct obj*)0)) { 1742 if(!Blind) { 1743 You_cant("see in here!"); 1744 make_blinded((long)tmp,FALSE); 1745 if (!Blind) Your(vision_clears); 1746 } else 1747 /* keep him blind until disgorged */ 1748 make_blinded(Blinded+1,FALSE); 1749 } 1750 tmp = 0; 1751 break; 1752 case AD_ELEC: 1753 if(!mtmp->mcan && rn2(2)) { 1754 pline_The("air around you crackles with electricity."); 1755 if (Shock_resistance) { 1756 shieldeff(u.ux, u.uy); 1757 You("seem unhurt."); 1758 ugolemeffects(AD_ELEC,tmp); 1759 tmp = 0; 1760 } 1761 } else tmp = 0; 1762 break; 1763 case AD_COLD: 1764 if(!mtmp->mcan && rn2(2)) { 1765 if (Cold_resistance) { 1766 shieldeff(u.ux, u.uy); 1767 You_feel("mildly chilly."); 1768 ugolemeffects(AD_COLD,tmp); 1769 tmp = 0; 1770 } else You("are freezing to death!"); 1771 } else tmp = 0; 1772 break; 1773 case AD_FIRE: 1774 if(!mtmp->mcan && rn2(2)) { 1775 if (Fire_resistance) { 1776 shieldeff(u.ux, u.uy); 1777 You_feel("mildly hot."); 1778 ugolemeffects(AD_FIRE,tmp); 1779 tmp = 0; 1780 } else You("are burning to a crisp!"); 1781 burn_away_slime(); 1782 } else tmp = 0; 1783 break; 1784 case AD_DISE: 1785 if (!diseasemu(mtmp->data)) tmp = 0; 1786 break; 1787 default: 1788 tmp = 0; 1789 break; 1790 } 1791 1792 if (Half_physical_damage) tmp = (tmp+1) / 2; 1793 1794 mdamageu(mtmp, tmp); 1795 if (tmp) stop_occupation(); 1796 1797 if (touch_petrifies(youmonst.data) && !resists_ston(mtmp)) { 1798 pline("%s very hurriedly %s you!", Monnam(mtmp), 1799 is_animal(mtmp->data)? "regurgitates" : "expels"); 1800 expels(mtmp, mtmp->data, FALSE); 1801 } else if (!u.uswldtim || youmonst.data->msize >= MZ_HUGE) { 1802 You("get %s!", is_animal(mtmp->data)? "regurgitated" : "expelled"); 1803 if (flags.verbose && (is_animal(mtmp->data) || 1804 (dmgtype(mtmp->data, AD_DGST) && Slow_digestion))) 1805 pline("Obviously %s doesn't like your taste.", mon_nam(mtmp)); 1806 expels(mtmp, mtmp->data, FALSE); 1807 } 1808 return(1); 1809} 1810 1811STATIC_OVL int 1812explmu(mtmp, mattk, ufound) /* monster explodes in your face */ 1813register struct monst *mtmp; 1814register struct attack *mattk; 1815boolean ufound; 1816{ 1817 if (mtmp->mcan) return(0); 1818 1819 if (!ufound) 1820 pline("%s explodes at a spot in %s!", 1821 canseemon(mtmp) ? Monnam(mtmp) : "It", 1822 levl[mtmp->mux][mtmp->muy].typ == WATER 1823 ? "empty water" : "thin air"); 1824 else { 1825 register int tmp = d((int)mattk->damn, (int)mattk->damd); 1826 register boolean not_affected = defends((int)mattk->adtyp, uwep); 1827 1828 hitmsg(mtmp, mattk); 1829 1830 switch (mattk->adtyp) { 1831 case AD_COLD: 1832 not_affected |= Cold_resistance; 1833 goto common; 1834 case AD_FIRE: 1835 not_affected |= Fire_resistance; 1836 goto common; 1837 case AD_ELEC: 1838 not_affected |= Shock_resistance; 1839common: 1840 1841 if (!not_affected) { 1842 if (ACURR(A_DEX) > rnd(20)) { 1843 You("duck some of the blast."); 1844 tmp = (tmp+1) / 2; 1845 } else { 1846 if (flags.verbose) You("get blasted!"); 1847 } 1848 if (mattk->adtyp == AD_FIRE) burn_away_slime(); 1849 if (Half_physical_damage) tmp = (tmp+1) / 2; 1850 mdamageu(mtmp, tmp); 1851 } 1852 break; 1853 1854 case AD_BLND: 1855 not_affected = resists_blnd(&youmonst); 1856 if (!not_affected) { 1857 /* sometimes you're affected even if it's invisible */ 1858 if (mon_visible(mtmp) || (rnd(tmp /= 2) > u.ulevel)) { 1859 You("are blinded by a blast of light!"); 1860 make_blinded((long)tmp, FALSE); 1861 if (!Blind) Your(vision_clears); 1862 } else if (flags.verbose) 1863 You("get the impression it was not terribly bright."); 1864 } 1865 break; 1866 1867 case AD_HALU: 1868 not_affected |= Blind || 1869 (u.umonnum == PM_BLACK_LIGHT || 1870 u.umonnum == PM_VIOLET_FUNGUS || 1871 dmgtype(youmonst.data, AD_STUN)); 1872 if (!not_affected) { 1873 boolean chg; 1874 if (!Hallucination) 1875 You("are caught in a blast of kaleidoscopic light!"); 1876 chg = make_hallucinated(HHallucination + (long)tmp,FALSE,0L); 1877 You("%s.", chg ? "are freaked out" : "seem unaffected"); 1878 } 1879 break; 1880 1881 default: 1882 break; 1883 } 1884 if (not_affected) { 1885 You("seem unaffected by it."); 1886 ugolemeffects((int)mattk->adtyp, tmp); 1887 } 1888 } 1889 mondead(mtmp); 1890 wake_nearto(mtmp->mx, mtmp->my, 7*7); 1891 if (mtmp->mhp > 0) return(0); 1892 return(2); /* it dies */ 1893} 1894 1895int 1896gazemu(mtmp, mattk) /* monster gazes at you */ 1897 register struct monst *mtmp; 1898 register struct attack *mattk; 1899{ 1900 switch(mattk->adtyp) { 1901 case AD_STON: 1902 if (mtmp->mcan || !mtmp->mcansee) { 1903 if (!canseemon(mtmp)) break; /* silently */ 1904 pline("%s %s.", Monnam(mtmp), 1905 (mtmp->data == &mons[PM_MEDUSA] && mtmp->mcan) ? 1906 "doesn't look all that ugly" : 1907 "gazes ineffectually"); 1908 break; 1909 } 1910 if (Reflecting && couldsee(mtmp->mx, mtmp->my) && 1911 mtmp->data == &mons[PM_MEDUSA]) { 1912 /* hero has line of sight to Medusa and she's not blind */ 1913 boolean useeit = canseemon(mtmp); 1914 1915 if (useeit) 1916 (void) ureflects("%s gaze is reflected by your %s.", 1917 s_suffix(Monnam(mtmp))); 1918 if (mon_reflects(mtmp, !useeit ? (char *)0 : 1919 "The gaze is reflected away by %s %s!")) 1920 break; 1921 if (!m_canseeu(mtmp)) { /* probably you're invisible */ 1922 if (useeit) 1923 pline( 1924 "%s doesn't seem to notice that %s gaze was reflected.", 1925 Monnam(mtmp), mhis(mtmp)); 1926 break; 1927 } 1928 if (useeit) 1929 pline("%s is turned to stone!", Monnam(mtmp)); 1930 stoned = TRUE; 1931 killed(mtmp); 1932 1933 if (mtmp->mhp > 0) break; 1934 return 2; 1935 } 1936 if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my) && 1937 !Stone_resistance) { 1938 You("meet %s gaze.", s_suffix(mon_nam(mtmp))); 1939 stop_occupation(); 1940 if(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) 1941 break; 1942 You("turn to stone..."); 1943 killer_format = KILLED_BY; 1944 killer = mtmp->data->mname; 1945 done(STONING); 1946 } 1947 break; 1948 case AD_CONF: 1949 if(!mtmp->mcan && canseemon(mtmp) && 1950 couldsee(mtmp->mx, mtmp->my) && 1951 mtmp->mcansee && !mtmp->mspec_used && rn2(5)) { 1952 int conf = d(3,4); 1953 1954 mtmp->mspec_used = mtmp->mspec_used + (conf + rn2(6)); 1955 if(!Confusion) 1956 pline("%s gaze confuses you!", 1957 s_suffix(Monnam(mtmp))); 1958 else 1959 You("are getting more and more confused."); 1960 make_confused(HConfusion + conf, FALSE); 1961 stop_occupation(); 1962 } 1963 break; 1964 case AD_STUN: 1965 if(!mtmp->mcan && canseemon(mtmp) && 1966 couldsee(mtmp->mx, mtmp->my) && 1967 mtmp->mcansee && !mtmp->mspec_used && rn2(5)) { 1968 int stun = d(2,6); 1969 1970 mtmp->mspec_used = mtmp->mspec_used + (stun + rn2(6)); 1971 pline("%s stares piercingly at you!", Monnam(mtmp)); 1972 make_stunned(HStun + stun, TRUE); 1973 stop_occupation(); 1974 } 1975 break; 1976 case AD_BLND: 1977 if (!mtmp->mcan && canseemon(mtmp) && !resists_blnd(&youmonst) 1978 && distu(mtmp->mx,mtmp->my) <= BOLT_LIM*BOLT_LIM) { 1979 int blnd = d((int)mattk->damn, (int)mattk->damd); 1980 1981 You("are blinded by %s radiance!", 1982 s_suffix(mon_nam(mtmp))); 1983 make_blinded((long)blnd,FALSE); 1984 stop_occupation(); 1985 /* not blind at this point implies you're wearing 1986 the Eyes of the Overworld; make them block this 1987 particular stun attack too */ 1988 if (!Blind) Your(vision_clears); 1989 else make_stunned((long)d(1,3),TRUE); 1990 } 1991 break; 1992 case AD_FIRE: 1993 if (!mtmp->mcan && canseemon(mtmp) && 1994 couldsee(mtmp->mx, mtmp->my) && 1995 mtmp->mcansee && !mtmp->mspec_used && rn2(5)) { 1996 int dmg = d(2,6); 1997 1998 pline("%s attacks you with a fiery gaze!", Monnam(mtmp)); 1999 stop_occupation(); 2000 if (Fire_resistance) { 2001 pline_The("fire doesn't feel hot!"); 2002 dmg = 0; 2003 } 2004 burn_away_slime(); 2005 if ((int) mtmp->m_lev > rn2(20)) 2006 destroy_item(SCROLL_CLASS, AD_FIRE); 2007 if ((int) mtmp->m_lev > rn2(20)) 2008 destroy_item(POTION_CLASS, AD_FIRE); 2009 if ((int) mtmp->m_lev > rn2(25)) 2010 destroy_item(SPBOOK_CLASS, AD_FIRE); 2011 if (dmg) mdamageu(mtmp, dmg); 2012 } 2013 break; 2014#ifdef PM_BEHOLDER /* work in progress */ 2015 case AD_SLEE: 2016 if(!mtmp->mcan && canseemon(mtmp) && 2017 couldsee(mtmp->mx, mtmp->my) && mtmp->mcansee && 2018 multi >= 0 && !rn2(5) && !Sleep_resistance) { 2019 2020 fall_asleep(-rnd(10), TRUE); 2021 pline("%s gaze makes you very sleepy...", 2022 s_suffix(Monnam(mtmp))); 2023 } 2024 break; 2025 case AD_SLOW: 2026 if(!mtmp->mcan && canseemon(mtmp) && mtmp->mcansee && 2027 (HFast & (INTRINSIC|TIMEOUT)) && 2028 !defends(AD_SLOW, uwep) && !rn2(4)) 2029 2030 u_slow_down(); 2031 stop_occupation(); 2032 break; 2033#endif 2034 default: impossible("Gaze attack %d?", mattk->adtyp); 2035 break; 2036 } 2037 return(0); 2038} 2039 2040#endif /* OVLB */ 2041#ifdef OVL1 2042 2043void 2044mdamageu(mtmp, n) /* mtmp hits you for n points damage */ 2045register struct monst *mtmp; 2046register int n; 2047{ 2048 flags.botl = 1; 2049 if (Upolyd) { 2050 u.mh -= n; 2051 if (u.mh < 1) rehumanize(); 2052 } else { 2053 u.uhp -= n; 2054 if(u.uhp < 1) done_in_by(mtmp); 2055 } 2056} 2057 2058#endif /* OVL1 */ 2059#ifdef OVLB 2060 2061STATIC_OVL void 2062urustm(mon, obj) 2063register struct monst *mon; 2064register struct obj *obj; 2065{ 2066 boolean vis; 2067 boolean is_acid; 2068 2069 if (!mon || !obj) return; /* just in case */ 2070 if (dmgtype(youmonst.data, AD_CORR)) 2071 is_acid = TRUE; 2072 else if (dmgtype(youmonst.data, AD_RUST)) 2073 is_acid = FALSE; 2074 else 2075 return; 2076 2077 vis = cansee(mon->mx, mon->my); 2078 2079 if ((is_acid ? is_corrodeable(obj) : is_rustprone(obj)) && 2080 (is_acid ? obj->oeroded2 : obj->oeroded) < MAX_ERODE) { 2081 if (obj->greased || obj->oerodeproof || (obj->blessed && rn2(3))) { 2082 if (vis) 2083 pline("Somehow, %s weapon is not affected.", 2084 s_suffix(mon_nam(mon))); 2085 if (obj->greased && !rn2(2)) obj->greased = 0; 2086 } else { 2087 if (vis) 2088 pline("%s %s%s!", 2089 s_suffix(Monnam(mon)), 2090 aobjnam(obj, (is_acid ? "corrode" : "rust")), 2091 (is_acid ? obj->oeroded2 : obj->oeroded) 2092 ? " further" : ""); 2093 if (is_acid) obj->oeroded2++; 2094 else obj->oeroded++; 2095 } 2096 } 2097} 2098 2099#endif /* OVLB */ 2100#ifdef OVL1 2101 2102int 2103could_seduce(magr,mdef,mattk) 2104struct monst *magr, *mdef; 2105struct attack *mattk; 2106/* returns 0 if seduction impossible, 2107 * 1 if fine, 2108 * 2 if wrong gender for nymph */ 2109{ 2110 register struct permonst *pagr; 2111 boolean agrinvis, defperc; 2112 xchar genagr, gendef; 2113 2114 if (is_animal(magr->data)) return (0); 2115 if(magr == &youmonst) { 2116 pagr = youmonst.data; 2117 agrinvis = (Invis != 0); 2118 genagr = poly_gender(); 2119 } else { 2120 pagr = magr->data; 2121 agrinvis = magr->minvis; 2122 genagr = gender(magr); 2123 } 2124 if(mdef == &youmonst) { 2125 defperc = (See_invisible != 0); 2126 gendef = poly_gender(); 2127 } else { 2128 defperc = perceives(mdef->data); 2129 gendef = gender(mdef); 2130 } 2131 2132 if(agrinvis && !defperc 2133#ifdef SEDUCE 2134 && mattk && mattk->adtyp != AD_SSEX 2135#endif 2136 ) 2137 return 0; 2138 2139 if(pagr->mlet != S_NYMPH 2140 && ((pagr != &mons[PM_INCUBUS] && pagr != &mons[PM_SUCCUBUS]) 2141#ifdef SEDUCE 2142 || (mattk && mattk->adtyp != AD_SSEX) 2143#endif 2144 )) 2145 return 0; 2146 2147 if(genagr == 1 - gendef) 2148 return 1; 2149 else 2150 return (pagr->mlet == S_NYMPH) ? 2 : 0; 2151} 2152 2153#endif /* OVL1 */ 2154#ifdef OVLB 2155 2156#ifdef SEDUCE 2157/* Returns 1 if monster teleported */ 2158int 2159doseduce(mon) 2160register struct monst *mon; 2161{ 2162 register struct obj *ring, *nring; 2163 boolean fem = (mon->data == &mons[PM_SUCCUBUS]); /* otherwise incubus */ 2164 char qbuf[QBUFSZ]; 2165 2166 if (mon->mcan || mon->mspec_used) { 2167 pline("%s acts as though %s has got a %sheadache.", 2168 Monnam(mon), mhe(mon), 2169 mon->mcan ? "severe " : ""); 2170 return 0; 2171 } 2172 2173 if (unconscious()) { 2174 pline("%s seems dismayed at your lack of response.", 2175 Monnam(mon)); 2176 return 0; 2177 } 2178 2179 if (Blind) pline("It caresses you..."); 2180 else You_feel("very attracted to %s.", mon_nam(mon)); 2181 2182 for(ring = invent; ring; ring = nring) { 2183 nring = ring->nobj; 2184 if (ring->otyp != RIN_ADORNMENT) continue; 2185 if (fem) { 2186 if (rn2(20) < ACURR(A_CHA)) { 2187 Sprintf(qbuf, "\"That %s looks pretty. May I have it?\"", 2188 safe_qbuf("",sizeof("\"That looks pretty. May I have it?\""), 2189 xname(ring), simple_typename(ring->otyp), "ring")); 2190 makeknown(RIN_ADORNMENT); 2191 if (yn(qbuf) == 'n') continue; 2192 } else pline("%s decides she'd like your %s, and takes it.", 2193 Blind ? "She" : Monnam(mon), xname(ring)); 2194 makeknown(RIN_ADORNMENT); 2195 if (ring==uleft || ring==uright) Ring_gone(ring); 2196 if (ring==uwep) setuwep((struct obj *)0); 2197 if (ring==uswapwep) setuswapwep((struct obj *)0); 2198 if (ring==uquiver) setuqwep((struct obj *)0); 2199 freeinv(ring); 2200 (void) mpickobj(mon,ring); 2201 } else { 2202 char buf[BUFSZ]; 2203 2204 if (uleft && uright && uleft->otyp == RIN_ADORNMENT 2205 && uright->otyp==RIN_ADORNMENT) 2206 break; 2207 if (ring==uleft || ring==uright) continue; 2208 if (rn2(20) < ACURR(A_CHA)) { 2209 Sprintf(qbuf,"\"That %s looks pretty. Would you wear it for me?\"", 2210 safe_qbuf("", 2211 sizeof("\"That looks pretty. Would you wear it for me?\""), 2212 xname(ring), simple_typename(ring->otyp), "ring")); 2213 makeknown(RIN_ADORNMENT); 2214 if (yn(qbuf) == 'n') continue; 2215 } else { 2216 pline("%s decides you'd look prettier wearing your %s,", 2217 Blind ? "He" : Monnam(mon), xname(ring)); 2218 pline("and puts it on your finger."); 2219 } 2220 makeknown(RIN_ADORNMENT); 2221 if (!uright) { 2222 pline("%s puts %s on your right %s.", 2223 Blind ? "He" : Monnam(mon), the(xname(ring)), body_part(HAND)); 2224 setworn(ring, RIGHT_RING); 2225 } else if (!uleft) { 2226 pline("%s puts %s on your left %s.", 2227 Blind ? "He" : Monnam(mon), the(xname(ring)), body_part(HAND)); 2228 setworn(ring, LEFT_RING); 2229 } else if (uright && uright->otyp != RIN_ADORNMENT) { 2230 Strcpy(buf, xname(uright)); 2231 pline("%s replaces your %s with your %s.", 2232 Blind ? "He" : Monnam(mon), buf, xname(ring)); 2233 Ring_gone(uright); 2234 setworn(ring, RIGHT_RING); 2235 } else if (uleft && uleft->otyp != RIN_ADORNMENT) { 2236 Strcpy(buf, xname(uleft)); 2237 pline("%s replaces your %s with your %s.", 2238 Blind ? "He" : Monnam(mon), buf, xname(ring)); 2239 Ring_gone(uleft); 2240 setworn(ring, LEFT_RING); 2241 } else impossible("ring replacement"); 2242 Ring_on(ring); 2243 prinv((char *)0, ring, 0L); 2244 } 2245 } 2246 2247 if (!uarmc && !uarmf && !uarmg && !uarms && !uarmh 2248#ifdef TOURIST 2249 && !uarmu 2250#endif 2251 ) 2252 pline("%s murmurs sweet nothings into your ear.", 2253 Blind ? (fem ? "She" : "He") : Monnam(mon)); 2254 else 2255 pline("%s murmurs in your ear, while helping you undress.", 2256 Blind ? (fem ? "She" : "He") : Monnam(mon)); 2257 mayberem(uarmc, cloak_simple_name(uarmc)); 2258 if(!uarmc) 2259 mayberem(uarm, "suit"); 2260 mayberem(uarmf, "boots"); 2261 if(!uwep || !welded(uwep)) 2262 mayberem(uarmg, "gloves"); 2263 mayberem(uarms, "shield"); 2264 mayberem(uarmh, "helmet"); 2265#ifdef TOURIST 2266 if(!uarmc && !uarm) 2267 mayberem(uarmu, "shirt"); 2268#endif 2269 2270 if (uarm || uarmc) { 2271 verbalize("You're such a %s; I wish...", 2272 flags.female ? "sweet lady" : "nice guy"); 2273 if (!tele_restrict(mon)) (void) rloc(mon, FALSE); 2274 return 1; 2275 } 2276 if (u.ualign.type == A_CHAOTIC) 2277 adjalign(1); 2278 2279 /* by this point you have discovered mon's identity, blind or not... */ 2280 pline("Time stands still while you and %s lie in each other's arms...", 2281 noit_mon_nam(mon)); 2282 if (rn2(35) > ACURR(A_CHA) + ACURR(A_INT)) { 2283 /* Don't bother with mspec_used here... it didn't get tired! */ 2284 pline("%s seems to have enjoyed it more than you...", 2285 noit_Monnam(mon)); 2286 switch (rn2(5)) { 2287 case 0: You_feel("drained of energy."); 2288 u.uen = 0; 2289 u.uenmax -= rnd(Half_physical_damage ? 5 : 10); 2290 exercise(A_CON, FALSE); 2291 if (u.uenmax < 0) u.uenmax = 0; 2292 break; 2293 case 1: You("are down in the dumps."); 2294 (void) adjattrib(A_CON, -1, TRUE); 2295 exercise(A_CON, FALSE); 2296 flags.botl = 1; 2297 break; 2298 case 2: Your("senses are dulled."); 2299 (void) adjattrib(A_WIS, -1, TRUE); 2300 exercise(A_WIS, FALSE); 2301 flags.botl = 1; 2302 break; 2303 case 3: 2304 if (!resists_drli(&youmonst)) { 2305 You_feel("out of shape."); 2306 losexp("overexertion"); 2307 } else { 2308 You("have a curious feeling..."); 2309 } 2310 break; 2311 case 4: { 2312 int tmp; 2313 You_feel("exhausted."); 2314 exercise(A_STR, FALSE); 2315 tmp = rn1(10, 6); 2316 if(Half_physical_damage) tmp = (tmp+1) / 2; 2317 losehp(tmp, "exhaustion", KILLED_BY); 2318 break; 2319 } 2320 } 2321 } else { 2322 mon->mspec_used = rnd(100); /* monster is worn out */ 2323 You("seem to have enjoyed it more than %s...", 2324 noit_mon_nam(mon)); 2325 switch (rn2(5)) { 2326 case 0: You_feel("raised to your full potential."); 2327 exercise(A_CON, TRUE); 2328 u.uen = (u.uenmax += rnd(5)); 2329 break; 2330 case 1: You_feel("good enough to do it again."); 2331 (void) adjattrib(A_CON, 1, TRUE); 2332 exercise(A_CON, TRUE); 2333 flags.botl = 1; 2334 break; 2335 case 2: You("will always remember %s...", noit_mon_nam(mon)); 2336 (void) adjattrib(A_WIS, 1, TRUE); 2337 exercise(A_WIS, TRUE); 2338 flags.botl = 1; 2339 break; 2340 case 3: pline("That was a very educational experience."); 2341 pluslvl(FALSE); 2342 exercise(A_WIS, TRUE); 2343 break; 2344 case 4: You_feel("restored to health!"); 2345 u.uhp = u.uhpmax; 2346 if (Upolyd) u.mh = u.mhmax; 2347 exercise(A_STR, TRUE); 2348 flags.botl = 1; 2349 break; 2350 } 2351 } 2352 2353 if (mon->mtame) /* don't charge */ ; 2354 else if (rn2(20) < ACURR(A_CHA)) { 2355 pline("%s demands that you pay %s, but you refuse...", 2356 noit_Monnam(mon), 2357 Blind ? (fem ? "her" : "him") : mhim(mon)); 2358 } else if (u.umonnum == PM_LEPRECHAUN) 2359 pline("%s tries to take your money, but fails...", 2360 noit_Monnam(mon)); 2361 else { 2362#ifndef GOLDOBJ 2363 long cost; 2364 2365 if (u.ugold > (long)LARGEST_INT - 10L) 2366 cost = (long) rnd(LARGEST_INT) + 500L; 2367 else 2368 cost = (long) rnd((int)u.ugold + 10) + 500L; 2369 if (mon->mpeaceful) { 2370 cost /= 5L; 2371 if (!cost) cost = 1L; 2372 } 2373 if (cost > u.ugold) cost = u.ugold; 2374 if (!cost) verbalize("It's on the house!"); 2375 else { 2376 pline("%s takes %ld %s for services rendered!", 2377 noit_Monnam(mon), cost, currency(cost)); 2378 u.ugold -= cost; 2379 mon->mgold += cost; 2380 flags.botl = 1; 2381 } 2382#else 2383 long cost; 2384 long umoney = money_cnt(invent); 2385 2386 if (umoney > (long)LARGEST_INT - 10L) 2387 cost = (long) rnd(LARGEST_INT) + 500L; 2388 else 2389 cost = (long) rnd((int)umoney + 10) + 500L; 2390 if (mon->mpeaceful) { 2391 cost /= 5L; 2392 if (!cost) cost = 1L; 2393 } 2394 if (cost > umoney) cost = umoney; 2395 if (!cost) verbalize("It's on the house!"); 2396 else { 2397 pline("%s takes %ld %s for services rendered!", 2398 noit_Monnam(mon), cost, currency(cost)); 2399 money2mon(mon, cost); 2400 flags.botl = 1; 2401 } 2402#endif 2403 } 2404 if (!rn2(25)) mon->mcan = 1; /* monster is worn out */ 2405 if (!tele_restrict(mon)) (void) rloc(mon, FALSE); 2406 return 1; 2407} 2408 2409STATIC_OVL void 2410mayberem(obj, str) 2411register struct obj *obj; 2412const char *str; 2413{ 2414 char qbuf[QBUFSZ]; 2415 2416 if (!obj || !obj->owornmask) return; 2417 2418 if (rn2(20) < ACURR(A_CHA)) { 2419 Sprintf(qbuf,"\"Shall I remove your %s, %s?\"", 2420 str, 2421 (!rn2(2) ? "lover" : !rn2(2) ? "dear" : "sweetheart")); 2422 if (yn(qbuf) == 'n') return; 2423 } else { 2424 char hairbuf[BUFSZ]; 2425 2426 Sprintf(hairbuf, "let me run my fingers through your %s", 2427 body_part(HAIR)); 2428 verbalize("Take off your %s; %s.", str, 2429 (obj == uarm) ? "let's get a little closer" : 2430 (obj == uarmc || obj == uarms) ? "it's in the way" : 2431 (obj == uarmf) ? "let me rub your feet" : 2432 (obj == uarmg) ? "they're too clumsy" : 2433#ifdef TOURIST 2434 (obj == uarmu) ? "let me massage you" : 2435#endif 2436 /* obj == uarmh */ 2437 hairbuf); 2438 } 2439 remove_worn_item(obj, TRUE); 2440} 2441#endif /* SEDUCE */ 2442 2443#endif /* OVLB */ 2444 2445#ifdef OVL1 2446 2447STATIC_OVL int 2448passiveum(olduasmon,mtmp,mattk) 2449struct permonst *olduasmon; 2450register struct monst *mtmp; 2451register struct attack *mattk; 2452{ 2453 int i, tmp; 2454 2455 for (i = 0; ; i++) { 2456 if (i >= NATTK) return 1; 2457 if (olduasmon->mattk[i].aatyp == AT_NONE || 2458 olduasmon->mattk[i].aatyp == AT_BOOM) break; 2459 } 2460 if (olduasmon->mattk[i].damn) 2461 tmp = d((int)olduasmon->mattk[i].damn, 2462 (int)olduasmon->mattk[i].damd); 2463 else if(olduasmon->mattk[i].damd) 2464 tmp = d((int)olduasmon->mlevel+1, (int)olduasmon->mattk[i].damd); 2465 else 2466 tmp = 0; 2467 2468 /* These affect the enemy even if you were "killed" (rehumanized) */ 2469 switch(olduasmon->mattk[i].adtyp) { 2470 case AD_ACID: 2471 if (!rn2(2)) { 2472 pline("%s is splashed by your acid!", Monnam(mtmp)); 2473 if (resists_acid(mtmp)) { 2474 pline("%s is not affected.", Monnam(mtmp)); 2475 tmp = 0; 2476 } 2477 } else tmp = 0; 2478 if (!rn2(30)) erode_armor(mtmp, TRUE); 2479 if (!rn2(6)) erode_obj(MON_WEP(mtmp), TRUE, TRUE); 2480 goto assess_dmg; 2481 case AD_STON: /* cockatrice */ 2482 { 2483 long protector = attk_protection((int)mattk->aatyp), 2484 wornitems = mtmp->misc_worn_check; 2485 2486 /* wielded weapon gives same protection as gloves here */ 2487 if (MON_WEP(mtmp) != 0) wornitems |= W_ARMG; 2488 2489 if (!resists_ston(mtmp) && (protector == 0L || 2490 (protector != ~0L && 2491 (wornitems & protector) != protector))) { 2492 if (poly_when_stoned(mtmp->data)) { 2493 mon_to_stone(mtmp); 2494 return (1); 2495 } 2496 pline("%s turns to stone!", Monnam(mtmp)); 2497 stoned = 1; 2498 xkilled(mtmp, 0); 2499 if (mtmp->mhp > 0) return 1; 2500 return 2; 2501 } 2502 return 1; 2503 } 2504 case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */ 2505 if (otmp) { 2506 (void) drain_item(otmp); 2507 /* No message */ 2508 } 2509 return (1); 2510 default: 2511 break; 2512 } 2513 if (!Upolyd) return 1; 2514 2515 /* These affect the enemy only if you are still a monster */ 2516 if (rn2(3)) switch(youmonst.data->mattk[i].adtyp) { 2517 case AD_PHYS: 2518 if (youmonst.data->mattk[i].aatyp == AT_BOOM) { 2519 You("explode!"); 2520 /* KMH, balance patch -- this is okay with unchanging */ 2521 rehumanize(); 2522 goto assess_dmg; 2523 } 2524 break; 2525 case AD_PLYS: /* Floating eye */ 2526 if (tmp > 127) tmp = 127; 2527 if (u.umonnum == PM_FLOATING_EYE) { 2528 if (!rn2(4)) tmp = 127; 2529 if (mtmp->mcansee && haseyes(mtmp->data) && rn2(3) && 2530 (perceives(mtmp->data) || !Invis)) { 2531 if (Blind) 2532 pline("As a blind %s, you cannot defend yourself.", 2533 youmonst.data->mname); 2534 else { 2535 if (mon_reflects(mtmp, 2536 "Your gaze is reflected by %s %s.")) 2537 return 1; 2538 pline("%s is frozen by your gaze!", Monnam(mtmp)); 2539 mtmp->mcanmove = 0; 2540 mtmp->mfrozen = tmp; 2541 return 3; 2542 } 2543 } 2544 } else { /* gelatinous cube */ 2545 pline("%s is frozen by you.", Monnam(mtmp)); 2546 mtmp->mcanmove = 0; 2547 mtmp->mfrozen = tmp; 2548 return 3; 2549 } 2550 return 1; 2551 case AD_COLD: /* Brown mold or blue jelly */ 2552 if (resists_cold(mtmp)) { 2553 shieldeff(mtmp->mx, mtmp->my); 2554 pline("%s is mildly chilly.", Monnam(mtmp)); 2555 golemeffects(mtmp, AD_COLD, tmp); 2556 tmp = 0; 2557 break; 2558 } 2559 pline("%s is suddenly very cold!", Monnam(mtmp)); 2560 u.mh += tmp / 2; 2561 if (u.mhmax < u.mh) u.mhmax = u.mh; 2562 if (u.mhmax > ((youmonst.data->mlevel+1) * 8)) 2563 (void)split_mon(&youmonst, mtmp); 2564 break; 2565 case AD_STUN: /* Yellow mold */ 2566 if (!mtmp->mstun) { 2567 mtmp->mstun = 1; 2568 pline("%s %s.", Monnam(mtmp), 2569 makeplural(stagger(mtmp->data, "stagger"))); 2570 } 2571 tmp = 0; 2572 break; 2573 case AD_FIRE: /* Red mold */ 2574 if (resists_fire(mtmp)) { 2575 shieldeff(mtmp->mx, mtmp->my); 2576 pline("%s is mildly warm.", Monnam(mtmp)); 2577 golemeffects(mtmp, AD_FIRE, tmp); 2578 tmp = 0; 2579 break; 2580 } 2581 pline("%s is suddenly very hot!", Monnam(mtmp)); 2582 break; 2583 case AD_ELEC: 2584 if (resists_elec(mtmp)) { 2585 shieldeff(mtmp->mx, mtmp->my); 2586 pline("%s is slightly tingled.", Monnam(mtmp)); 2587 golemeffects(mtmp, AD_ELEC, tmp); 2588 tmp = 0; 2589 break; 2590 } 2591 pline("%s is jolted with your electricity!", Monnam(mtmp)); 2592 break; 2593 default: tmp = 0; 2594 break; 2595 } 2596 else tmp = 0; 2597 2598 assess_dmg: 2599 if((mtmp->mhp -= tmp) <= 0) { 2600 pline("%s dies!", Monnam(mtmp)); 2601 xkilled(mtmp,0); 2602 if (mtmp->mhp > 0) return 1; 2603 return 2; 2604 } 2605 return 1; 2606} 2607 2608#endif /* OVL1 */ 2609#ifdef OVLB 2610 2611#include "edog.h" 2612struct monst * 2613cloneu() 2614{ 2615 register struct monst *mon; 2616 int mndx = monsndx(youmonst.data); 2617 2618 if (u.mh <= 1) return(struct monst *)0; 2619 if (mvitals[mndx].mvflags & G_EXTINCT) return(struct monst *)0; 2620 mon = makemon(youmonst.data, u.ux, u.uy, NO_MINVENT|MM_EDOG); 2621 mon = christen_monst(mon, plname); 2622 initedog(mon); 2623 mon->m_lev = youmonst.data->mlevel; 2624 mon->mhpmax = u.mhmax; 2625 mon->mhp = u.mh / 2; 2626 u.mh -= mon->mhp; 2627 flags.botl = 1; 2628 return(mon); 2629} 2630 2631#endif /* OVLB */ 2632 2633/*mhitu.c*/ 2634