1 | /* SCCS Id: @(#)mhitm.c 3.3 2000/07/29 */ 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 | #include "edog.h" 8 | 9 | extern boolean notonhead; 10 | 11 | #ifdef OVLB 12 | 13 | static NEARDATA boolean vis, far_noise; 14 | static NEARDATA long noisetime; 15 | static NEARDATA struct obj *otmp; 16 | 17 | static const char brief_feeling[] = 18 | "have a %s feeling for a moment, then it passes."; 19 | 20 | STATIC_DCL char *FDECL(mon_nam_too, (char *,struct monst *,struct monst *)); 21 | STATIC_DCL void FDECL(mrustm, (struct monst *, struct monst *, struct obj *)); 22 | STATIC_DCL int FDECL(hitmm, (struct monst *,struct monst *,struct attack *)); 23 | STATIC_DCL int FDECL(gazemm, (struct monst *,struct monst *,struct attack *)); 24 | STATIC_DCL int FDECL(gulpmm, (struct monst *,struct monst *,struct attack *)); 25 | STATIC_DCL int FDECL(explmm, (struct monst *,struct monst *,struct attack *)); 26 | STATIC_DCL int FDECL(mdamagem, (struct monst *,struct monst *,struct attack *)); 27 | STATIC_DCL void FDECL(mswingsm, (struct monst *, struct monst *, struct obj *)); 28 | STATIC_DCL void FDECL(noises,(struct monst *,struct attack *)); 29 | STATIC_DCL void FDECL(missmm,(struct monst *,struct monst *,struct attack *)); 30 | STATIC_DCL int FDECL(passivemm, (struct monst *, struct monst *, BOOLEAN_P, int)); 31 | 32 | /* Needed for the special case of monsters wielding vorpal blades (rare). 33 | * If we use this a lot it should probably be a parameter to mdamagem() 34 | * instead of a global variable. 35 | */ 36 | static int dieroll; 37 | 38 | /* returns mon_nam(mon) relative to other_mon; normal name unless they're 39 | the same, in which case the reference is to {him|her|it} self */ 40 | STATIC_OVL char * 41 | mon_nam_too(outbuf, mon, other_mon) 42 | char *outbuf; 43 | struct monst *mon, *other_mon; 44 | { 45 | Strcpy(outbuf, mon_nam(mon)); 46 | if (mon == other_mon) 47 | switch (pronoun_gender(mon)) { 48 | case 0: Strcpy(outbuf, "himself"); break; 49 | case 1: Strcpy(outbuf, "herself"); break; 50 | default: Strcpy(outbuf, "itself"); break; 51 | } 52 | return outbuf; 53 | } 54 | 55 | STATIC_OVL void 56 | noises(magr, mattk) 57 | register struct monst *magr; 58 | register struct attack *mattk; 59 | { 60 | boolean farq = (distu(magr->mx, magr->my) > 15); 61 | 62 | if(flags.soundok && (farq != far_noise || moves-noisetime > 10)) { 63 | far_noise = farq; 64 | noisetime = moves; 65 | You_hear("%s%s.", 66 | (mattk->aatyp == AT_EXPL) ? "an explosion" : "some noises", 67 | farq ? " in the distance" : ""); 68 | } 69 | } 70 | 71 | STATIC_OVL 72 | void 73 | missmm(magr, mdef, mattk) 74 | register struct monst *magr, *mdef; 75 | struct attack *mattk; 76 | { 77 | const char *fmt; 78 | char buf[BUFSZ], mdef_name[BUFSZ]; 79 | 80 | if (vis) { 81 | if (!canspotmon(mdef)) 82 | map_invisible(mdef->mx, mdef->my); 83 | if (mdef->m_ap_type) seemimic(mdef); 84 | if (magr->m_ap_type) seemimic(magr); 85 | fmt = (could_seduce(magr,mdef,mattk) && !magr->mcan) ? 86 | "%s pretends to be friendly to" : "%s misses"; 87 | Sprintf(buf, fmt, Monnam(magr)); 88 | pline("%s %s.", buf, mon_nam_too(mdef_name, mdef, magr)); 89 | } else noises(magr, mattk); 90 | } 91 | 92 | /* 93 | * fightm() -- fight some other monster 94 | * 95 | * Returns: 96 | * 0 - Monster did nothing. 97 | * 1 - If the monster made an attack. The monster might have died. 98 | * 99 | * There is an exception to the above. If mtmp has the hero swallowed, 100 | * then we report that the monster did nothing so it will continue to 101 | * digest the hero. 102 | */ 103 | int 104 | fightm(mtmp) /* have monsters fight each other */ 105 | register struct monst *mtmp; 106 | { 107 | register struct monst *mon, *nmon; 108 | int result, has_u_swallowed; 109 | #ifdef LINT 110 | nmon = 0; 111 | #endif 112 | /* perhaps the monster will resist Conflict */ 113 | if(resist(mtmp, RING_CLASS, 0, 0)) 114 | return(0); 115 | 116 | if(u.ustuck == mtmp) { 117 | /* perhaps we're holding it... */ 118 | if(itsstuck(mtmp)) 119 | return(0); 120 | } 121 | has_u_swallowed = (u.uswallow && (mtmp == u.ustuck)); 122 | 123 | for(mon = fmon; mon; mon = nmon) { 124 | nmon = mon->nmon; 125 | if(nmon == mtmp) nmon = mtmp->nmon; 126 | /* Be careful to ignore monsters that are already dead, since we 127 | * might be calling this before we've cleaned them up. This can 128 | * happen if the monster attacked a cockatrice bare-handedly, for 129 | * instance. 130 | */ 131 | if(mon != mtmp && !DEADMONSTER(mon)) { 132 | if(monnear(mtmp,mon->mx,mon->my)) { 133 | if(!u.uswallow && (mtmp == u.ustuck)) { 134 | if(!rn2(4)) { 135 | pline("%s releases you!", Monnam(mtmp)); 136 | u.ustuck = 0; 137 | } else 138 | break; 139 | } 140 | 141 | /* mtmp can be killed */ 142 | bhitpos.x = mon->mx; 143 | bhitpos.y = mon->my; 144 | notonhead = 0; 145 | result = mattackm(mtmp,mon); 146 | 147 | if (result & MM_AGR_DIED) return 1; /* mtmp died */ 148 | /* 149 | * If mtmp has the hero swallowed, lie and say there 150 | * was no attack (this allows mtmp to digest the hero). 151 | */ 152 | if (has_u_swallowed) return 0; 153 | 154 | return ((result & MM_HIT) ? 1 : 0); 155 | } 156 | } 157 | } 158 | return 0; 159 | } 160 | 161 | /* 162 | * mattackm() -- a monster attacks another monster. 163 | * 164 | * This function returns a result bitfield: 165 | * 166 | * --------- aggressor died 167 | * / ------- defender died 168 | * / / ----- defender was hit 169 | * / / / 170 | * x x x 171 | * 172 | * 0x4 MM_AGR_DIED 173 | * 0x2 MM_DEF_DIED 174 | * 0x1 MM_HIT 175 | * 0x0 MM_MISS 176 | * 177 | * Each successive attack has a lower probability of hitting. Some rely on the 178 | * success of previous attacks. ** this doen't seem to be implemented -dl ** 179 | * 180 | * In the case of exploding monsters, the monster dies as well. 181 | */ 182 | int 183 | mattackm(magr, mdef) 184 | register struct monst *magr,*mdef; 185 | { 186 | int i, /* loop counter */ 187 | tmp, /* amour class difference */ 188 | strike, /* hit this attack */ 189 | attk, /* attack attempted this time */ 190 | struck = 0, /* hit at least once */ 191 | res[NATTK]; /* results of all attacks */ 192 | struct attack *mattk; 193 | struct permonst *pa, *pd; 194 | 195 | if (!magr || !mdef) return(MM_MISS); /* mike@genat */ 196 | if (!magr->mcanmove) return(MM_MISS); /* riv05!a3 */ 197 | pa = magr->data; pd = mdef->data; 198 | 199 | /* Grid bugs cannot attack at an angle. */ 200 | if (pa == &mons[PM_GRID_BUG] && magr->mx != mdef->mx 201 | && magr->my != mdef->my) 202 | return(MM_MISS); 203 | 204 | /* Calculate the armour class differential. */ 205 | tmp = find_mac(mdef) + magr->m_lev; 206 | if (mdef->mconf || !mdef->mcanmove || mdef->msleeping) { 207 | tmp += 4; 208 | mdef->msleeping = 0; 209 | } 210 | 211 | /* undetect monsters become un-hidden if they are attacked */ 212 | if (mdef->mundetected) { 213 | mdef->mundetected = 0; 214 | newsym(mdef->mx, mdef->my); 215 | if(canseemon(mdef) && !sensemon(mdef)) 216 | pline("Suddenly, you notice %s.", a_monnam(mdef)); 217 | } 218 | 219 | /* Elves hate orcs. */ 220 | if (is_elf(pa) && is_orc(pd)) tmp++; 221 | 222 | 223 | /* Set up the visibility of action */ 224 | vis = (cansee(magr->mx,magr->my) && cansee(mdef->mx,mdef->my)); 225 | 226 | /* Set flag indicating monster has moved this turn. Necessary since a 227 | * monster might get an attack out of sequence (i.e. before its move) in 228 | * some cases, in which case this still counts as its move for the round 229 | * and it shouldn't move again. 230 | */ 231 | magr->mlstmv = monstermoves; 232 | 233 | /* Now perform all attacks for the monster. */ 234 | for (i = 0; i < NATTK; i++) { 235 | res[i] = MM_MISS; 236 | mattk = &(pa->mattk[i]); 237 | otmp = (struct obj *)0; 238 | attk = 1; 239 | switch (mattk->aatyp) { 240 | case AT_WEAP: /* "hand to hand" attacks */ 241 | if (magr->weapon_check == NEED_WEAPON || !MON_WEP(magr)) { 242 | magr->weapon_check = NEED_HTH_WEAPON; 243 | if (mon_wield_item(magr) != 0) return 0; 244 | } 245 | possibly_unwield(magr); 246 | otmp = MON_WEP(magr); 247 | 248 | if (otmp) { 249 | if (vis) mswingsm(magr, mdef, otmp); 250 | tmp += hitval(otmp, mdef); 251 | } 252 | /* fall through */ 253 | case AT_CLAW: 254 | case AT_KICK: 255 | case AT_BITE: 256 | case AT_STNG: 257 | case AT_TUCH: 258 | case AT_BUTT: 259 | case AT_TENT: 260 | /* Nymph that teleported away on first attack? */ 261 | if (distmin(magr->mx,magr->my,mdef->mx,mdef->my) > 1) 262 | return MM_MISS; 263 | /* Monsters won't attack cockatrices physically if they 264 | * have a weapon instead. This instinct doesn't work for 265 | * players, or under conflict or confusion. 266 | */ 267 | if (!magr->mconf && !Conflict && otmp && 268 | mattk->aatyp != AT_WEAP && touch_petrifies(mdef->data)) { 269 | strike = 0; 270 | break; 271 | } 272 | dieroll = rnd(20 + i); 273 | strike = (tmp > dieroll); 274 | /* KMH -- don't accumulate to-hit bonuses */ 275 | if (otmp) 276 | tmp -= hitval(otmp, mdef); 277 | if (strike) 278 | res[i] = hitmm(magr, mdef, mattk); 279 | else 280 | missmm(magr, mdef, mattk); 281 | break; 282 | 283 | case AT_HUGS: /* automatic if prev two attacks succeed */ 284 | strike = (i >= 2 && res[i-1] == MM_HIT && res[i-2] == MM_HIT); 285 | if (strike) 286 | res[i] = hitmm(magr, mdef, mattk); 287 | 288 | break; 289 | 290 | case AT_GAZE: 291 | strike = 0; /* will not wake up a sleeper */ 292 | res[i] = gazemm(magr, mdef, mattk); 293 | break; 294 | 295 | case AT_EXPL: 296 | strike = 1; /* automatic hit */ 297 | res[i] = explmm(magr, mdef, mattk); 298 | break; 299 | 300 | case AT_ENGL: 301 | #ifdef STEED 302 | if (u.usteed && (mdef == u.usteed)) { 303 | strike = 0; 304 | break; 305 | } 306 | #endif 307 | /* Engulfing attacks are directed at the hero if 308 | * possible. -dlc 309 | */ 310 | if (u.uswallow && magr == u.ustuck) 311 | strike = 0; 312 | else { 313 | if ((strike = (tmp > rnd(20+i)))) 314 | res[i] = gulpmm(magr, mdef, mattk); 315 | else 316 | missmm(magr, mdef, mattk); 317 | } 318 | break; 319 | 320 | default: /* no attack */ 321 | strike = 0; 322 | attk = 0; 323 | break; 324 | } 325 | 326 | if (attk && !(res[i] & MM_AGR_DIED)) 327 | res[i] = passivemm(magr, mdef, strike, res[i] & MM_DEF_DIED); 328 | 329 | if (res[i] & MM_DEF_DIED) return res[i]; 330 | 331 | /* 332 | * Wake up the defender. NOTE: this must follow the check 333 | * to see if the defender died. We don't want to modify 334 | * unallocated monsters! 335 | */ 336 | if (strike) mdef->msleeping = 0; 337 | 338 | if (res[i] & MM_AGR_DIED) return res[i]; 339 | /* return if aggressor can no longer attack */ 340 | if (!magr->mcanmove || magr->msleeping) return res[i]; 341 | if (res[i] & MM_HIT) struck = 1; /* at least one hit */ 342 | } 343 | 344 | return(struck ? MM_HIT : MM_MISS); 345 | } 346 | 347 | /* Returns the result of mdamagem(). */ 348 | STATIC_OVL int 349 | hitmm(magr, mdef, mattk) 350 | register struct monst *magr,*mdef; 351 | struct attack *mattk; 352 | { 353 | if(vis){ 354 | int compat; 355 | char buf[BUFSZ], mdef_name[BUFSZ]; 356 | 357 | if (!canspotmon(mdef)) 358 | map_invisible(mdef->mx, mdef->my); 359 | if(mdef->m_ap_type) seemimic(mdef); 360 | if(magr->m_ap_type) seemimic(magr); 361 | if((compat = could_seduce(magr,mdef,mattk)) && !magr->mcan) { 362 | Sprintf(buf, "%s %s", Monnam(magr), 363 | mdef->mcansee ? "smiles at" : "talks to"); 364 | pline("%s %s %s.", buf, mon_nam(mdef), 365 | compat == 2 ? 366 | "engagingly" : "seductively"); 367 | } else { 368 | char magr_name[BUFSZ]; 369 | 370 | Strcpy(magr_name, Monnam(magr)); 371 | switch (mattk->aatyp) { 372 | case AT_BITE: 373 | Sprintf(buf,"%s bites", magr_name); 374 | break; 375 | case AT_STNG: 376 | Sprintf(buf,"%s stings", magr_name); 377 | break; 378 | case AT_BUTT: 379 | Sprintf(buf,"%s butts", magr_name); 380 | break; 381 | case AT_TUCH: 382 | Sprintf(buf,"%s touches", magr_name); 383 | break; 384 | case AT_TENT: 385 | Sprintf(buf, "%s tentacles suck", 386 | s_suffix(magr_name)); 387 | break; 388 | case AT_HUGS: 389 | if (magr != u.ustuck) { 390 | Sprintf(buf,"%s squeezes", magr_name); 391 | break; 392 | } 393 | default: 394 | Sprintf(buf,"%s hits", magr_name); 395 | } 396 | } 397 | pline("%s %s.", buf, mon_nam_too(mdef_name, mdef, magr)); 398 | } else noises(magr, mattk); 399 | return(mdamagem(magr, mdef, mattk)); 400 | } 401 | 402 | /* Returns the same values as mdamagem(). */ 403 | STATIC_OVL int 404 | gazemm(magr, mdef, mattk) 405 | register struct monst *magr, *mdef; 406 | struct attack *mattk; 407 | { 408 | char buf[BUFSZ]; 409 | 410 | if(vis) { 411 | Sprintf(buf,"%s gazes at", Monnam(magr)); 412 | pline("%s %s...", buf, mon_nam(mdef)); 413 | } 414 | 415 | if (!mdef->mcansee || mdef->msleeping) { 416 | if(vis) pline("but nothing happens."); 417 | return(MM_MISS); 418 | } 419 | 420 | return(mdamagem(magr, mdef, mattk)); 421 | } 422 | 423 | /* Returns the same values as mattackm(). */ 424 | STATIC_OVL int 425 | gulpmm(magr, mdef, mattk) 426 | register struct monst *magr, *mdef; 427 | register struct attack *mattk; 428 | { 429 | xchar ax, ay, dx, dy; 430 | int status; 431 | char buf[BUFSZ]; 432 | struct obj *obj; 433 | 434 | if (mdef->data->msize >= MZ_HUGE) return MM_MISS; 435 | 436 | if (vis) { 437 | Sprintf(buf,"%s swallows", Monnam(magr)); 438 | pline("%s %s.", buf, mon_nam(mdef)); 439 | } 440 | for (obj = mdef->minvent; obj; obj = obj->nobj) 441 | (void) snuff_lit(obj); 442 | 443 | /* 444 | * All of this maniuplation is needed to keep the display correct. 445 | * There is a flush at the next pline(). 446 | */ 447 | ax = magr->mx; 448 | ay = magr->my; 449 | dx = mdef->mx; 450 | dy = mdef->my; 451 | /* 452 | * Leave the defender in the monster chain at it's current position, 453 | * but don't leave it on the screen. Move the agressor to the def- 454 | * ender's position. 455 | */ 456 | remove_monster(ax, ay); 457 | place_monster(magr, dx, dy); 458 | newsym(ax,ay); /* erase old position */ 459 | newsym(dx,dy); /* update new position */ 460 | 461 | status = mdamagem(magr, mdef, mattk); 462 | 463 | if ((status & MM_AGR_DIED) && (status & MM_DEF_DIED)) { 464 | ; /* both died -- do nothing */ 465 | } 466 | else if (status & MM_DEF_DIED) { /* defender died */ 467 | /* 468 | * Note: remove_monster() was called in relmon(), wiping out 469 | * magr from level.monsters[mdef->mx][mdef->my]. We need to 470 | * put it back and display it. -kd 471 | */ 472 | place_monster(magr, dx, dy); 473 | newsym(dx, dy); 474 | } 475 | else if (status & MM_AGR_DIED) { /* agressor died */ 476 | place_monster(mdef, dx, dy); 477 | newsym(dx, dy); 478 | } 479 | else { /* both alive, put them back */ 480 | if (cansee(dx, dy)) 481 | pline("%s is regurgitated!", Monnam(mdef)); 482 | 483 | place_monster(magr, ax, ay); 484 | place_monster(mdef, dx, dy); 485 | newsym(ax, ay); 486 | newsym(dx, dy); 487 | } 488 | 489 | return status; 490 | } 491 | 492 | STATIC_OVL int 493 | explmm(magr, mdef, mattk) 494 | register struct monst *magr, *mdef; 495 | register struct attack *mattk; 496 | { 497 | int result; 498 | 499 | if(cansee(magr->mx, magr->my)) 500 | pline("%s explodes!", Monnam(magr)); 501 | else noises(magr, mattk); 502 | 503 | result = mdamagem(magr, mdef, mattk); 504 | 505 | /* Kill off agressor if it didn't die. */ 506 | if (!(result & MM_AGR_DIED)) { 507 | mondead(magr); 508 | if (magr->mhp > 0) return result; /* life saved */ 509 | result |= MM_AGR_DIED; 510 | } 511 | if (magr->mtame) /* give this one even if it was visible */ 512 | You(brief_feeling, "melancholy"); 513 | 514 | return result; 515 | } 516 | 517 | /* 518 | * See comment at top of mattackm(), for return values. 519 | */ 520 | STATIC_OVL int 521 | mdamagem(magr, mdef, mattk) 522 | register struct monst *magr, *mdef; 523 | register struct attack *mattk; 524 | { 525 | struct permonst *pa = magr->data, *pd = mdef->data; 526 | int tmp = d((int)mattk->damn,(int)mattk->damd); 527 | struct obj *obj; 528 | char buf[BUFSZ]; 529 | 530 | if (touch_petrifies(pd) && !resists_ston(magr) && 531 | (mattk->aatyp != AT_WEAP || !otmp) && 532 | (mattk->aatyp != AT_GAZE && mattk->aatyp != AT_EXPL) && 533 | !(magr->misc_worn_check & W_ARMG)) { 534 | if (poly_when_stoned(pa)) { 535 | mon_to_stone(magr); 536 | return MM_HIT; /* no damage during the polymorph */ 537 | } 538 | if (vis) pline("%s turns to stone!", Monnam(magr)); 539 | monstone(magr); 540 | if (magr->mhp > 0) return 0; 541 | else if (magr->mtame && !vis) 542 | You(brief_feeling, "peculiarly sad"); 543 | return MM_AGR_DIED; 544 | } 545 | 546 | switch(mattk->adtyp) { 547 | case AD_DGST: 548 | /* eating a Rider or its corpse is fatal */ 549 | if (is_rider(mdef->data)) { 550 | if (vis) 551 | pline("%s %s!", Monnam(magr), 552 | mdef->data == &mons[PM_FAMINE] ? 553 | "belches feebly, shrivels up and dies" : 554 | mdef->data == &mons[PM_PESTILENCE] ? 555 | "coughs spasmodically and collapses" : 556 | "vomits violently and drops dead"); 557 | mondied(magr); 558 | if (magr->mhp > 0) return 0; /* lifesaved */ 559 | else if (magr->mtame && !vis) 560 | You(brief_feeling, "queasy"); 561 | return MM_AGR_DIED; 562 | } 563 | if(flags.verbose && flags.soundok) verbalize("Burrrrp!"); 564 | tmp = mdef->mhp; 565 | /* Use up amulet of life saving */ 566 | if (!!(obj = mlifesaver(mdef))) m_useup(mdef, obj); 567 | break; 568 | case AD_STUN: 569 | if (magr->mcan) break; 570 | if(vis) pline("%s staggers for a moment.", Monnam(mdef)); 571 | mdef->mstun = 1; 572 | /* fall through */ 573 | case AD_WERE: 574 | case AD_HEAL: 575 | case AD_LEGS: 576 | case AD_PHYS: 577 | if (mattk->aatyp == AT_KICK && thick_skinned(pd)) 578 | tmp = 0; 579 | else if(mattk->aatyp == AT_WEAP) { 580 | if(otmp) { 581 | if (otmp->otyp == CORPSE && 582 | touch_petrifies(&mons[otmp->corpsenm])) 583 | goto do_stone_goto_label; 584 | tmp += dmgval(otmp, mdef); 585 | if (otmp->oartifact) { 586 | (void)artifact_hit(magr,mdef, otmp, &tmp, dieroll); 587 | if (mdef->mhp <= 0) 588 | return (MM_DEF_DIED | 589 | (grow_up(magr,mdef) ? 0 : MM_AGR_DIED)); 590 | } 591 | if (tmp) 592 | mrustm(magr, mdef, otmp); 593 | } 594 | } else if (magr->data == &mons[PM_PURPLE_WORM] && 595 | mdef->data == &mons[PM_SHRIEKER]) { 596 | /* hack to enhance mm_aggression(); we don't want purple 597 | worm's bite attack to kill a shrieker because then it 598 | won't swallow the corpse; but if the target survives, 599 | the subsequent engulf attack should accomplish that */ 600 | if (tmp >= mdef->mhp) tmp = mdef->mhp - 1; 601 | } 602 | break; 603 | case AD_FIRE: 604 | if (magr->mcan) { 605 | tmp = 0; 606 | break; 607 | } 608 | if (vis) 609 | pline("%s is %s!", Monnam(mdef), 610 | mattk->aatyp == AT_HUGS ? 611 | "being roasted" : "on fire"); 612 | if (pd == &mons[PM_STRAW_GOLEM] || 613 | pd == &mons[PM_PAPER_GOLEM]) { 614 | if (vis) pline("%s burns completely!", Monnam(mdef)); 615 | mondied(mdef); 616 | if (mdef->mhp > 0) return 0; 617 | else if (mdef->mtame && !vis) 618 | pline("May %s roast in peace.", mon_nam(mdef)); 619 | return (MM_DEF_DIED | (grow_up(magr,mdef) ? 620 | 0 : MM_AGR_DIED)); 621 | } 622 | tmp += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE); 623 | tmp += destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE); 624 | if (resists_fire(mdef)) { 625 | if (vis) 626 | pline_The("fire doesn't seem to burn %s!", 627 | mon_nam(mdef)); 628 | shieldeff(mdef->mx, mdef->my); 629 | golemeffects(mdef, AD_FIRE, tmp); 630 | tmp = 0; 631 | } 632 | /* only potions damage resistant players in destroy_item */ 633 | tmp += destroy_mitem(mdef, POTION_CLASS, AD_FIRE); 634 | break; 635 | case AD_COLD: 636 | if (magr->mcan) { 637 | tmp = 0; 638 | break; 639 | } 640 | if (vis) pline("%s is covered in frost!", Monnam(mdef)); 641 | if (resists_cold(mdef)) { 642 | if (vis) 643 | pline_The("frost doesn't seem to chill %s!", 644 | mon_nam(mdef)); 645 | shieldeff(mdef->mx, mdef->my); 646 | golemeffects(mdef, AD_COLD, tmp); 647 | tmp = 0; 648 | } 649 | tmp += destroy_mitem(mdef, POTION_CLASS, AD_COLD); 650 | break; 651 | case AD_ELEC: 652 | if (magr->mcan) { 653 | tmp = 0; 654 | break; 655 | } 656 | if (vis) pline("%s gets zapped!", Monnam(mdef)); 657 | tmp += destroy_mitem(mdef, WAND_CLASS, AD_ELEC); 658 | if (resists_elec(mdef)) { 659 | if (vis) pline_The("zap doesn't shock %s!", mon_nam(mdef)); 660 | shieldeff(mdef->mx, mdef->my); 661 | golemeffects(mdef, AD_ELEC, tmp); 662 | tmp = 0; 663 | } 664 | /* only rings damage resistant players in destroy_item */ 665 | tmp += destroy_mitem(mdef, RING_CLASS, AD_ELEC); 666 | break; 667 | case AD_ACID: 668 | if (magr->mcan) { 669 | tmp = 0; 670 | break; 671 | } 672 | if (resists_acid(mdef)) { 673 | if (vis) 674 | pline("%s is covered in acid, but it seems harmless.", 675 | Monnam(mdef)); 676 | tmp = 0; 677 | } else if (vis) { 678 | pline("%s is covered in acid!", Monnam(mdef)); 679 | pline("It burns %s!", mon_nam(mdef)); 680 | } 681 | if (!rn2(30)) erode_armor(mdef, TRUE); 682 | if (!rn2(6)) erode_weapon(MON_WEP(mdef), TRUE); 683 | break; 684 | case AD_RUST: 685 | if (!magr->mcan && pd == &mons[PM_IRON_GOLEM]) { 686 | if (vis) pline("%s falls to pieces!", Monnam(mdef)); 687 | mondied(mdef); 688 | if (mdef->mhp > 0) return 0; 689 | else if (mdef->mtame && !vis) 690 | pline("May %s rust in peace.", mon_nam(mdef)); 691 | return (MM_DEF_DIED | (grow_up(magr,mdef) ? 692 | 0 : MM_AGR_DIED)); 693 | } 694 | hurtmarmor(mdef, AD_RUST); 695 | tmp = 0; 696 | break; 697 | case AD_CORRODE: 698 | hurtmarmor(mdef, AD_CORRODE); 699 | tmp = 0; 700 | break; 701 | case AD_DCAY: 702 | if (!magr->mcan && (pd == &mons[PM_WOOD_GOLEM] || 703 | pd == &mons[PM_LEATHER_GOLEM])) { 704 | if (vis) pline("%s falls to pieces!", Monnam(mdef)); 705 | mondied(mdef); 706 | if (mdef->mhp > 0) return 0; 707 | else if (mdef->mtame && !vis) 708 | pline("May %s rot in peace.", mon_nam(mdef)); 709 | return (MM_DEF_DIED | (grow_up(magr,mdef) ? 710 | 0 : MM_AGR_DIED)); 711 | } 712 | hurtmarmor(mdef, AD_DCAY); 713 | tmp = 0; 714 | break; 715 | case AD_STON: 716 | do_stone_goto_label: 717 | /* may die from the acid if it eats a stone-curing corpse */ 718 | if (munstone(mdef, FALSE)) goto label2; 719 | if (poly_when_stoned(pd)) { 720 | mon_to_stone(mdef); 721 | tmp = 0; 722 | break; 723 | } 724 | if (!resists_ston(mdef)) { 725 | if (vis) pline("%s turns to stone!", Monnam(mdef)); 726 | monstone(mdef); 727 | label2: if (mdef->mhp > 0) return 0; 728 | else if (mdef->mtame && !vis) 729 | You(brief_feeling, "peculiarly sad"); 730 | return (MM_DEF_DIED | (grow_up(magr,mdef) ? 731 | 0 : MM_AGR_DIED)); 732 | } 733 | tmp = (mattk->adtyp == AD_STON ? 0 : 1); 734 | break; 735 | case AD_TLPT: 736 | if (!magr->mcan && tmp < mdef->mhp && !tele_restrict(mdef)) { 737 | char mdef_Monnam[BUFSZ]; 738 | /* save the name before monster teleports, otherwise 739 | we'll get "it" in the suddenly disappears message */ 740 | if (vis) Strcpy(mdef_Monnam, Monnam(mdef)); 741 | rloc(mdef); 742 | if (vis && !canspotmon(mdef) 743 | #ifdef STEED 744 | && mdef != u.usteed 745 | #endif 746 | ) 747 | pline("%s suddenly disappears!", mdef_Monnam); 748 | } 749 | break; 750 | case AD_SLEE: 751 | if (!magr->mcan && !mdef->msleeping && 752 | sleep_monst(mdef, rnd(10), -1)) { 753 | if (vis) { 754 | Strcpy(buf, Monnam(mdef)); 755 | pline("%s is put to sleep by %s.", buf, mon_nam(magr)); 756 | } 757 | slept_monst(mdef); 758 | } 759 | break; 760 | case AD_PLYS: 761 | if(!magr->mcan && mdef->mcanmove) { 762 | if (vis) { 763 | Strcpy(buf, Monnam(mdef)); 764 | pline("%s is frozen by %s.", buf, mon_nam(magr)); 765 | } 766 | mdef->mcanmove = 0; 767 | mdef->mfrozen = rnd(10); 768 | } 769 | break; 770 | case AD_SLOW: 771 | if (!magr->mcan && vis && mdef->mspeed != MSLOW) { 772 | unsigned int oldspeed = mdef->mspeed; 773 | 774 | mon_adjust_speed(mdef, -1); 775 | if (mdef->mspeed != oldspeed && vis) 776 | pline("%s slows down.", Monnam(mdef)); 777 | } 778 | break; 779 | case AD_CONF: 780 | /* Since confusing another monster doesn't have a real time 781 | * limit, setting spec_used would not really be right (though 782 | * we still should check for it). 783 | */ 784 | if (!magr->mcan && !mdef->mconf && !magr->mspec_used) { 785 | if (vis) pline("%s looks confused.", Monnam(mdef)); 786 | mdef->mconf = 1; 787 | } 788 | break; 789 | case AD_BLND: 790 | if (can_blnd(magr, mdef, mattk->aatyp, (struct obj*)0)) { 791 | register unsigned rnd_tmp; 792 | 793 | if (vis && mdef->mcansee) 794 | pline("%s is blinded.", Monnam(mdef)); 795 | rnd_tmp = d((int)mattk->damn, (int)mattk->damd); 796 | if ((rnd_tmp += mdef->mblinded) > 127) rnd_tmp = 127; 797 | mdef->mblinded = rnd_tmp; 798 | mdef->mcansee = 0; 799 | } 800 | tmp = 0; 801 | break; 802 | case AD_HALU: 803 | if (!magr->mcan && haseyes(pd) && mdef->mcansee) { 804 | if (vis) pline("%s looks %sconfused.", 805 | Monnam(mdef), mdef->mconf ? "more " : ""); 806 | mdef->mconf = 1; 807 | } 808 | tmp = 0; 809 | break; 810 | case AD_CURS: 811 | if (!night() && (pa == &mons[PM_GREMLIN])) break; 812 | if (!magr->mcan && !rn2(10)) { 813 | mdef->mcan = 1; /* cancelled regardless of lifesave */ 814 | if (is_were(pd) && pd->mlet != S_HUMAN) 815 | were_change(mdef); 816 | if (pd == &mons[PM_CLAY_GOLEM]) { 817 | if (vis) { 818 | pline("Some writing vanishes from %s head!", 819 | s_suffix(mon_nam(mdef))); 820 | pline("%s is destroyed!", Monnam(mdef)); 821 | } 822 | mondied(mdef); 823 | if (mdef->mhp > 0) return 0; 824 | else if (mdef->mtame && !vis) 825 | You(brief_feeling, "strangely sad"); 826 | return (MM_DEF_DIED | (grow_up(magr,mdef) ? 827 | 0 : MM_AGR_DIED)); 828 | } 829 | if (flags.soundok) { 830 | if (!vis) You_hear("laughter."); 831 | else pline("%s chuckles.", Monnam(magr)); 832 | } 833 | } 834 | break; 835 | case AD_SGLD: 836 | tmp = 0; 837 | if (magr->mcan || !mdef->mgold) break; 838 | /* technically incorrect; no check for stealing gold from 839 | * between mdef's feet... 840 | */ 841 | magr->mgold += mdef->mgold; 842 | mdef->mgold = 0; 843 | if (vis) { 844 | Strcpy(buf, Monnam(magr)); 845 | pline("%s steals some gold from %s.", buf, mon_nam(mdef)); 846 | } 847 | if (!tele_restrict(magr)) { 848 | rloc(magr); 849 | if (vis && !canspotmon(magr)) 850 | pline("%s suddenly disappears!", buf); 851 | } 852 | break; 853 | case AD_DRLI: 854 | if (rn2(2) && !resists_drli(mdef)) { 855 | tmp = d(2,6); 856 | if (vis) 857 | pline("%s suddenly seems weaker!", Monnam(mdef)); 858 | mdef->mhpmax -= tmp; 859 | if (mdef->m_lev == 0) 860 | tmp = mdef->mhp; 861 | else mdef->m_lev--; 862 | /* Automatic kill if drained past level 0 */ 863 | } 864 | break; 865 | #ifdef SEDUCE 866 | case AD_SSEX: 867 | #endif 868 | case AD_SITM: /* for now these are the same */ 869 | case AD_SEDU: 870 | if (!magr->mcan && mdef->minvent) { 871 | char onambuf[BUFSZ], mdefnambuf[BUFSZ]; 872 | 873 | /* make a special x_monnam() call that never omits 874 | the saddle, and save it for later messages */ 875 | Strcpy(mdefnambuf, x_monnam(mdef, ARTICLE_THE, (char *)0, 0, FALSE)); 876 | 877 | otmp = mdef->minvent; 878 | #ifdef STEED 879 | if (u.usteed == mdef && 880 | otmp == which_armor(mdef, W_SADDLE)) 881 | /* "You can no longer ride <steed>." */ 882 | dismount_steed(DISMOUNT_POLY); 883 | #endif 884 | obj_extract_self(otmp); 885 | if (otmp->owornmask) { 886 | mdef->misc_worn_check &= ~otmp->owornmask; 887 | otmp->owornmask = 0L; 888 | update_mon_intrinsics(mdef, otmp, FALSE); 889 | } 890 | /* add_to_minv() might free otmp [if it merges] */ 891 | if (vis) 892 | Strcpy(onambuf, doname(otmp)); 893 | (void) add_to_minv(magr, otmp); 894 | if (vis) { 895 | Strcpy(buf, Monnam(magr)); 896 | pline("%s steals %s from %s!", buf, 897 | onambuf, mdefnambuf); 898 | } 899 | possibly_unwield(mdef); 900 | mselftouch(mdef, (const char *)0, FALSE); 901 | if (mdef->mhp <= 0) 902 | return (MM_DEF_DIED | (grow_up(magr,mdef) ? 903 | 0 : MM_AGR_DIED)); 904 | if (magr->data->mlet == S_NYMPH && 905 | !tele_restrict(magr)) { 906 | rloc(magr); 907 | if (vis && !canspotmon(magr)) 908 | pline("%s suddenly disappears!", buf); 909 | } 910 | } 911 | tmp = 0; 912 | break; 913 | case AD_DRST: 914 | case AD_DRDX: 915 | case AD_DRCO: 916 | if (!magr->mcan && !rn2(8)) { 917 | if (vis) 918 | pline("%s %s was poisoned!", s_suffix(Monnam(magr)), 919 | mpoisons_subj(magr, mattk)); 920 | if (resists_poison(mdef)) { 921 | if (vis) 922 | pline_The("poison doesn't seem to affect %s.", 923 | mon_nam(mdef)); 924 | } else { 925 | if (rn2(10)) tmp += rn1(10,6); 926 | else { 927 | if (vis) pline_The("poison was deadly..."); 928 | tmp = mdef->mhp; 929 | } 930 | } 931 | } 932 | break; 933 | case AD_DRIN: 934 | if (notonhead || !has_head(pd)) { 935 | if (vis) pline("%s doesn't seem harmed.", Monnam(mdef)); 936 | tmp = 0; 937 | break; 938 | } 939 | if ((mdef->misc_worn_check & W_ARMH) && rn2(8)) { 940 | if (vis) { 941 | Strcpy(buf, s_suffix(Monnam(mdef))); 942 | pline("%s helmet blocks %s attack to %s head.", 943 | buf, s_suffix(mon_nam(magr)), 944 | his[pronoun_gender(mdef)]); 945 | } 946 | break; 947 | } 948 | if (vis) pline("%s brain is eaten!", s_suffix(Monnam(mdef))); 949 | if (mindless(pd)) { 950 | if (vis) pline("%s doesn't notice.", Monnam(mdef)); 951 | break; 952 | } 953 | tmp += rnd(10); /* fakery, since monsters lack INT scores */ 954 | if (magr->mtame && !magr->isminion) { 955 | EDOG(magr)->hungrytime += rnd(60); 956 | magr->mconf = 0; 957 | } 958 | if (tmp >= mdef->mhp && vis) 959 | pline("%s last thought fades away...", 960 | s_suffix(Monnam(mdef))); 961 | break; 962 | case AD_SLIM: 963 | if (!rn2(4) && mdef->data != &mons[PM_FIRE_VORTEX] && 964 | mdef->data != &mons[PM_FIRE_ELEMENTAL] && 965 | mdef->data != &mons[PM_GREEN_SLIME]) { 966 | if (vis) pline("%s turns into slime.", Monnam(mdef)); 967 | (void) newcham(mdef, &mons[PM_GREEN_SLIME]); 968 | tmp = 0; 969 | } 970 | break; 971 | case AD_STCK: 972 | case AD_WRAP: /* monsters cannot grab one another, it's too hard */ 973 | case AD_ENCH: /* There's no msomearmor() function, so just do damage */ 974 | break; 975 | default: tmp = 0; 976 | break; 977 | } 978 | if(!tmp) return(MM_MISS); 979 | 980 | if((mdef->mhp -= tmp) < 1) { 981 | if (m_at(mdef->mx, mdef->my) == magr) { /* see gulpmm() */ 982 | remove_monster(mdef->mx, mdef->my); 983 | mdef->mhp = 1; /* otherwise place_monster will complain */ 984 | place_monster(mdef, mdef->mx, mdef->my); 985 | mdef->mhp = 0; 986 | } 987 | monkilled(mdef, "", (int)mattk->adtyp); 988 | if (mdef->mhp > 0) return 0; /* mdef lifesaved */ 989 | return (MM_DEF_DIED | (grow_up(magr,mdef) ? 0 : MM_AGR_DIED)); 990 | } 991 | return(MM_HIT); 992 | } 993 | 994 | #endif /* OVLB */ 995 | 996 | 997 | #ifdef OVL0 998 | 999 | int 1000 | noattacks(ptr) /* returns 1 if monster doesn't attack */ 1001 | struct permonst *ptr; 1002 | { 1003 | int i; 1004 | 1005 | for(i = 0; i < NATTK; i++) 1006 | if(ptr->mattk[i].aatyp) return(0); 1007 | 1008 | return(1); 1009 | } 1010 | 1011 | /* `mon' is hit by a sleep attack; return 1 if it's affected, 0 otherwise */ 1012 | int 1013 | sleep_monst(mon, amt, how) 1014 | struct monst *mon; 1015 | int amt, how; 1016 | { 1017 | if (resists_sleep(mon) || 1018 | (how >= 0 && resist(mon, (char)how, 0, NOTELL))) { 1019 | shieldeff(mon->mx, mon->my); 1020 | } else if (mon->mcanmove) { 1021 | amt += (int) mon->mfrozen; 1022 | if (amt > 0) { /* sleep for N turns */ 1023 | mon->mcanmove = 0; 1024 | mon->mfrozen = min(amt, 127); 1025 | } else { /* sleep until awakened */ 1026 | mon->msleeping = 1; 1027 | } 1028 | return 1; 1029 | } 1030 | return 0; 1031 | } 1032 | 1033 | /* sleeping grabber releases, engulfer doesn't; don't use for paralysis! */ 1034 | void 1035 | slept_monst(mon) 1036 | struct monst *mon; 1037 | { 1038 | if ((mon->msleeping || !mon->mcanmove) && mon == u.ustuck && 1039 | !sticks(youmonst.data) && !u.uswallow) { 1040 | pline("%s grip relaxes.", s_suffix(Monnam(mon))); 1041 | unstuck(mon); 1042 | } 1043 | } 1044 | 1045 | #endif /* OVL0 */ 1046 | #ifdef OVLB 1047 | 1048 | STATIC_OVL void 1049 | mrustm(magr, mdef, obj) 1050 | register struct monst *magr, *mdef; 1051 | register struct obj *obj; 1052 | { 1053 | boolean is_acid; 1054 | 1055 | if (!magr || !mdef || !obj) return; /* just in case */ 1056 | 1057 | if (dmgtype(mdef->data, AD_CORRODE)) 1058 | is_acid = TRUE; 1059 | else if (dmgtype(mdef->data, AD_RUST)) 1060 | is_acid = FALSE; 1061 | else 1062 | return; 1063 | 1064 | if (!mdef->mcan && 1065 | (is_acid ? is_corrodeable(obj) : is_rustprone(obj)) && 1066 | (is_acid ? obj->oeroded2 : obj->oeroded) < MAX_ERODE) { 1067 | if (obj->greased || obj->oerodeproof || (obj->blessed && rn2(3))) { 1068 | if (cansee(mdef->mx, mdef->my) && flags.verbose) 1069 | pline("%s weapon is not affected.", 1070 | s_suffix(Monnam(magr))); 1071 | if (obj->greased && !rn2(2)) obj->greased = 0; 1072 | } else { 1073 | if (cansee(mdef->mx, mdef->my)) { 1074 | pline("%s %s%s!", s_suffix(Monnam(magr)), 1075 | aobjnam(obj, (is_acid ? "corrode" : "rust")), 1076 | (is_acid ? obj->oeroded2 : obj->oeroded) 1077 | ? " further" : ""); 1078 | } 1079 | if (is_acid) obj->oeroded2++; 1080 | else obj->oeroded++; 1081 | } 1082 | } 1083 | } 1084 | 1085 | STATIC_OVL void 1086 | mswingsm(magr, mdef, otemp) 1087 | register struct monst *magr, *mdef; 1088 | register struct obj *otemp; 1089 | { 1090 | char buf[BUFSZ]; 1091 | Strcpy(buf, mon_nam(mdef)); 1092 | if (!flags.verbose || Blind) return; 1093 | pline("%s %s %s %s at %s.", Monnam(magr), 1094 | (objects[otemp->otyp].oc_dir & PIERCE) ? "thrusts" : "swings", 1095 | his[pronoun_gender(magr)], xname(otemp), buf); 1096 | } 1097 | 1098 | /* 1099 | * Passive responses by defenders. Does not replicate responses already 1100 | * handled above. Returns same values as mattackm. 1101 | */ 1102 | STATIC_OVL int 1103 | passivemm(magr,mdef,mhit,mdead) 1104 | register struct monst *magr, *mdef; 1105 | boolean mhit; 1106 | int mdead; 1107 | { 1108 | register struct permonst *mddat = mdef->data; 1109 | register struct permonst *madat = magr->data; 1110 | char buf[BUFSZ]; 1111 | int i, tmp; 1112 | 1113 | for(i = 0; ; i++) { 1114 | if(i >= NATTK) return (mdead | mhit); /* no passive attacks */ 1115 | if(mddat->mattk[i].aatyp == AT_NONE) break; 1116 | } 1117 | if (mddat->mattk[i].damn) 1118 | tmp = d((int)mddat->mattk[i].damn, 1119 | (int)mddat->mattk[i].damd); 1120 | else if(mddat->mattk[i].damd) 1121 | tmp = d((int)mddat->mlevel+1, (int)mddat->mattk[i].damd); 1122 | else 1123 | tmp = 0; 1124 | 1125 | /* These affect the enemy even if defender killed */ 1126 | switch(mddat->mattk[i].adtyp) { 1127 | case AD_ACID: 1128 | if (mhit && !rn2(2)) { 1129 | Strcpy(buf, Monnam(magr)); 1130 | if(canseemon(magr)) 1131 | pline("%s is splashed by %s acid!", 1132 | buf, s_suffix(mon_nam(mdef))); 1133 | if (resists_acid(magr)) { 1134 | if(canseemon(magr)) 1135 | pline("%s is not affected.", Monnam(magr)); 1136 | tmp = 0; 1137 | } 1138 | } else tmp = 0; 1139 | goto assess_dmg; 1140 | case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */ 1141 | if (mhit && !mdef->mcan && otmp) { 1142 | (void) drain_item(otmp); 1143 | /* No message */ 1144 | } 1145 | break; 1146 | default: 1147 | break; 1148 | } 1149 | if (mdead || mdef->mcan) return (mdead|mhit); 1150 | 1151 | /* These affect the enemy only if defender is still alive */ 1152 | if (rn2(3)) switch(mddat->mattk[i].adtyp) { 1153 | case AD_PLYS: /* Floating eye */ 1154 | if (tmp > 127) tmp = 127; 1155 | if (mddat == &mons[PM_FLOATING_EYE]) { 1156 | if (!rn2(4)) tmp = 127; 1157 | if (magr->mcansee && haseyes(madat) && mdef->mcansee && 1158 | (perceives(madat) || !mdef->minvis)) { 1159 | Sprintf(buf, "%s gaze is reflected by %%s %%s.", 1160 | s_suffix(mon_nam(mdef))); 1161 | if (mon_reflects(magr, 1162 | canseemon(magr) ? buf : (char *)0)) 1163 | return(mdead|mhit); 1164 | Strcpy(buf, Monnam(magr)); 1165 | if(canseemon(magr)) 1166 | pline("%s is frozen by %s gaze!", 1167 | buf, s_suffix(mon_nam(mdef))); 1168 | magr->mcanmove = 0; 1169 | magr->mfrozen = tmp; 1170 | return (mdead|mhit); 1171 | } 1172 | } else { /* gelatinous cube */ 1173 | Strcpy(buf, Monnam(magr)); 1174 | if(canseemon(magr)) 1175 | pline("%s is frozen by %s.", buf, mon_nam(mdef)); 1176 | magr->mcanmove = 0; 1177 | magr->mfrozen = tmp; 1178 | return (mdead|mhit); 1179 | } 1180 | return 1; 1181 | case AD_COLD: 1182 | if (resists_cold(magr)) { 1183 | if (canseemon(magr)) { 1184 | pline("%s is mildly chilly.", Monnam(magr)); 1185 | golemeffects(magr, AD_COLD, tmp); 1186 | } 1187 | tmp = 0; 1188 | break; 1189 | } 1190 | if(canseemon(magr)) 1191 | pline("%s is suddenly very cold!", Monnam(magr)); 1192 | mdef->mhp += tmp / 2; 1193 | if (mdef->mhpmax < mdef->mhp) mdef->mhpmax = mdef->mhp; 1194 | if (mdef->mhpmax > ((int) (mdef->m_lev+1) * 8)) 1195 | (void)split_mon(mdef, magr); 1196 | break; 1197 | case AD_STUN: 1198 | if (!magr->mstun) { 1199 | magr->mstun = 1; 1200 | if (canseemon(magr)) 1201 | pline("%s staggers...", Monnam(magr)); 1202 | } 1203 | tmp = 0; 1204 | break; 1205 | case AD_FIRE: 1206 | if (resists_fire(magr)) { 1207 | if (canseemon(magr)) { 1208 | pline("%s is mildly warmed.", Monnam(magr)); 1209 | golemeffects(magr, AD_FIRE, tmp); 1210 | } 1211 | tmp = 0; 1212 | break; 1213 | } 1214 | if(canseemon(magr)) 1215 | pline("%s is suddenly very hot!", Monnam(magr)); 1216 | break; 1217 | case AD_ELEC: 1218 | if (resists_elec(magr)) { 1219 | if (canseemon(magr)) { 1220 | pline("%s is mildly tingled.", Monnam(magr)); 1221 | golemeffects(magr, AD_ELEC, tmp); 1222 | } 1223 | tmp = 0; 1224 | break; 1225 | } 1226 | if(canseemon(magr)) 1227 | pline("%s is jolted with electricity!", Monnam(magr)); 1228 | break; 1229 | default: tmp = 0; 1230 | break; 1231 | } 1232 | else tmp = 0; 1233 | 1234 | assess_dmg: 1235 | if((magr->mhp -= tmp) <= 0) { 1236 | monkilled(magr, "", (int)mddat->mattk[i].adtyp); 1237 | return (mdead | mhit | MM_AGR_DIED); 1238 | } 1239 | return (mdead | mhit); 1240 | } 1241 | 1242 | #endif /* OVLB */ 1243 | 1244 | /*mhitm.c*/ 1245 |