1 /* aNetHack 0.0.1 mhitm.c $ANH-Date: 1470819842 2016/08/10 09:04:02 $ $ANH-Branch: master $:$ANH-Revision: 1.92 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* aNetHack may be freely redistributed. See license for details. */
8 extern boolean notonhead
;
10 static NEARDATA boolean vis
, far_noise
;
11 static NEARDATA
long noisetime
;
12 static NEARDATA
struct obj
*otmp
;
14 static const char brief_feeling
[] =
15 "have a %s feeling for a moment, then it passes.";
17 STATIC_DCL
char *FDECL(mon_nam_too
, (char *, struct monst
*, struct monst
*));
18 STATIC_DCL
int FDECL(hitmm
, (struct monst
*, struct monst
*,
20 STATIC_DCL
int FDECL(gazemm
, (struct monst
*, struct monst
*,
22 STATIC_DCL
int FDECL(gulpmm
, (struct monst
*, struct monst
*,
24 STATIC_DCL
int FDECL(explmm
, (struct monst
*, struct monst
*,
26 STATIC_DCL
int FDECL(mdamagem
, (struct monst
*, struct monst
*,
28 STATIC_DCL
void FDECL(mswingsm
, (struct monst
*, struct monst
*,
30 STATIC_DCL
void FDECL(noises
, (struct monst
*, struct attack
*));
31 STATIC_DCL
void FDECL(missmm
, (struct monst
*, struct monst
*,
33 STATIC_DCL
int FDECL(passivemm
, (struct monst
*, struct monst
*,
36 /* Needed for the special case of monsters wielding vorpal blades (rare).
37 * If we use this a lot it should probably be a parameter to mdamagem()
38 * instead of a global variable.
42 /* returns mon_nam(mon) relative to other_mon; normal name unless they're
43 the same, in which case the reference is to {him|her|it} self */
45 mon_nam_too(outbuf
, mon
, other_mon
)
47 struct monst
*mon
, *other_mon
;
49 Strcpy(outbuf
, mon_nam(mon
));
51 switch (pronoun_gender(mon
)) {
53 Strcpy(outbuf
, "himself");
56 Strcpy(outbuf
, "herself");
59 Strcpy(outbuf
, "itself");
67 register struct monst
*magr
;
68 register struct attack
*mattk
;
70 boolean farq
= (distu(magr
->mx
, magr
->my
) > 15);
72 if (!Deaf
&& (farq
!= far_noise
|| moves
- noisetime
> 10)) {
76 (mattk
->aatyp
== AT_EXPL
) ? "an explosion" : "some noises",
77 farq
? " in the distance" : "");
83 missmm(magr
, mdef
, mattk
)
84 register struct monst
*magr
, *mdef
;
88 char buf
[BUFSZ
], mdef_name
[BUFSZ
];
91 if (!canspotmon(magr
))
92 map_invisible(magr
->mx
, magr
->my
);
93 if (!canspotmon(mdef
))
94 map_invisible(mdef
->mx
, mdef
->my
);
99 fmt
= (could_seduce(magr
, mdef
, mattk
) && !magr
->mcan
)
100 ? "%s pretends to be friendly to"
102 Sprintf(buf
, fmt
, Monnam(magr
));
103 pline("%s %s.", buf
, mon_nam_too(mdef_name
, mdef
, magr
));
109 * fightm() -- fight some other monster
112 * 0 - Monster did nothing.
113 * 1 - If the monster made an attack. The monster might have died.
115 * There is an exception to the above. If mtmp has the hero swallowed,
116 * then we report that the monster did nothing so it will continue to
119 /* have monsters fight each other */
122 register struct monst
*mtmp
;
124 register struct monst
*mon
, *nmon
;
125 int result
, has_u_swallowed
;
129 /* perhaps the monster will resist Conflict */
130 if (resist(mtmp
, RING_CLASS
, 0, 0))
133 if (u
.ustuck
== mtmp
) {
134 /* perhaps we're holding it... */
138 has_u_swallowed
= (u
.uswallow
&& (mtmp
== u
.ustuck
));
140 for (mon
= fmon
; mon
; mon
= nmon
) {
144 /* Be careful to ignore monsters that are already dead, since we
145 * might be calling this before we've cleaned them up. This can
146 * happen if the monster attacked a cockatrice bare-handedly, for
149 if (mon
!= mtmp
&& !DEADMONSTER(mon
)) {
150 if (monnear(mtmp
, mon
->mx
, mon
->my
)) {
151 if (!u
.uswallow
&& (mtmp
== u
.ustuck
)) {
153 pline("%s releases you!", Monnam(mtmp
));
159 /* mtmp can be killed */
163 result
= mattackm(mtmp
, mon
);
165 if (result
& MM_AGR_DIED
)
166 return 1; /* mtmp died */
168 * If mtmp has the hero swallowed, lie and say there
169 * was no attack (this allows mtmp to digest the hero).
174 /* Allow attacked monsters a chance to hit back. Primarily
175 * to allow monsters that resist conflict to respond.
177 if ((result
& MM_HIT
) && !(result
& MM_DEF_DIED
) && rn2(4)
178 && mon
->movement
>= NORMAL_SPEED
) {
179 mon
->movement
-= NORMAL_SPEED
;
181 (void) mattackm(mon
, mtmp
); /* return attack */
184 return (result
& MM_HIT
) ? 1 : 0;
192 * mdisplacem() -- attacker moves defender out of the way;
193 * returns same results as mattackm().
196 mdisplacem(magr
, mdef
, quietly
)
197 register struct monst
*magr
, *mdef
;
200 struct permonst
*pa
, *pd
;
203 /* sanity checks; could matter if we unexpectedly get a long worm */
204 if (!magr
|| !mdef
|| magr
== mdef
)
206 pa
= magr
->data
, pd
= mdef
->data
;
207 tx
= mdef
->mx
, ty
= mdef
->my
; /* destination */
208 fx
= magr
->mx
, fy
= magr
->my
; /* current location */
209 if (m_at(fx
, fy
) != magr
|| m_at(tx
, ty
) != mdef
)
212 /* The 1 in 7 failure below matches the chance in attack()
213 * for pet displacement.
218 /* Grid bugs cannot displace at an angle. */
219 if (pa
== &mons
[PM_GRID_BUG
] && magr
->mx
!= mdef
->mx
220 && magr
->my
!= mdef
->my
)
223 /* undetected monster becomes un-hidden if it is displaced */
224 if (mdef
->mundetected
)
225 mdef
->mundetected
= 0;
226 if (mdef
->m_ap_type
&& mdef
->m_ap_type
!= M_AP_MONSTER
)
228 /* wake up the displaced defender */
230 mdef
->mstrategy
&= ~STRAT_WAITMASK
;
231 finish_meating(mdef
);
234 * Set up the visibility of action.
235 * You can observe monster displacement if you can see both of
236 * the monsters involved.
238 vis
= (canspotmon(magr
) && canspotmon(mdef
));
240 if (touch_petrifies(pd
) && !resists_ston(magr
)) {
241 if (which_armor(magr
, W_ARMG
) != 0) {
242 if (poly_when_stoned(pa
)) {
244 return MM_HIT
; /* no damage during the polymorph */
246 if (!quietly
&& canspotmon(magr
))
247 pline("%s turns to stone!", Monnam(magr
));
250 return MM_HIT
; /* lifesaved */
251 else if (magr
->mtame
&& !vis
)
252 You(brief_feeling
, "peculiarly sad");
257 remove_monster(fx
, fy
); /* pick up from orig position */
258 remove_monster(tx
, ty
);
259 place_monster(magr
, tx
, ty
); /* put down at target spot */
260 place_monster(mdef
, fx
, fy
);
262 pline("%s moves %s out of %s way!", Monnam(magr
), mon_nam(mdef
),
263 is_rider(pa
) ? "the" : mhis(magr
));
264 newsym(fx
, fy
); /* see it */
265 newsym(tx
, ty
); /* all happen */
266 flush_screen(0); /* make sure it shows up */
272 * mattackm() -- a monster attacks another monster.
274 * --------- aggressor died
275 * / ------- defender died
276 * / / ----- defender was hit
285 * Each successive attack has a lower probability of hitting. Some rely on
286 * success of previous attacks. ** this doen't seem to be implemented -dl **
288 * In the case of exploding monsters, the monster dies as well.
292 register struct monst
*magr
, *mdef
;
294 int i
, /* loop counter */
295 tmp
, /* amour class difference */
296 strike
= 0, /* hit this attack */
297 attk
, /* attack attempted this time */
298 struck
= 0, /* hit at least once */
299 res
[NATTK
]; /* results of all attacks */
300 struct attack
*mattk
, alt_attk
;
301 struct permonst
*pa
, *pd
;
304 return MM_MISS
; /* mike@genat */
305 if (!magr
->mcanmove
|| magr
->msleeping
)
310 /* Grid bugs cannot attack at an angle. */
311 if (pa
== &mons
[PM_GRID_BUG
] && magr
->mx
!= mdef
->mx
312 && magr
->my
!= mdef
->my
)
315 /* Calculate the armour class differential. */
316 tmp
= find_mac(mdef
) + magr
->m_lev
;
317 if (mdef
->mconf
|| !mdef
->mcanmove
|| mdef
->msleeping
) {
322 /* undetect monsters become un-hidden if they are attacked */
323 if (mdef
->mundetected
) {
324 mdef
->mundetected
= 0;
325 newsym(mdef
->mx
, mdef
->my
);
326 if (canseemon(mdef
) && !sensemon(mdef
)) {
328 You("dream of %s.", (mdef
->data
->geno
& G_UNIQ
)
330 : makeplural(m_monnam(mdef
)));
332 pline("Suddenly, you notice %s.", a_monnam(mdef
));
336 /* Elves hate orcs. */
337 if (is_elf(pa
) && is_orc(pd
))
340 /* Set up the visibility of action */
341 vis
= (cansee(magr
->mx
, magr
->my
) && cansee(mdef
->mx
, mdef
->my
)
342 && (canspotmon(magr
) || canspotmon(mdef
)));
344 /* Set flag indicating monster has moved this turn. Necessary since a
345 * monster might get an attack out of sequence (i.e. before its move) in
346 * some cases, in which case this still counts as its move for the round
347 * and it shouldn't move again.
349 magr
->mlstmv
= monstermoves
;
351 /* Now perform all attacks for the monster. */
352 for (i
= 0; i
< NATTK
; i
++) {
354 mattk
= getmattk(magr
, mdef
, i
, res
, &alt_attk
);
355 otmp
= (struct obj
*) 0;
357 switch (mattk
->aatyp
) {
358 case AT_WEAP
: /* "hand to hand" attacks */
359 if (distmin(magr
->mx
, magr
->my
, mdef
->mx
, mdef
->my
) > 1) {
360 /* D: Do a ranged attack here! */
361 strike
= thrwmm(magr
, mdef
);
362 if (DEADMONSTER(mdef
))
363 res
[i
] = MM_DEF_DIED
;
364 if (DEADMONSTER(magr
))
365 res
[i
] |= MM_AGR_DIED
;
368 if (magr
->weapon_check
== NEED_WEAPON
|| !MON_WEP(magr
)) {
369 magr
->weapon_check
= NEED_HTH_WEAPON
;
370 if (mon_wield_item(magr
) != 0)
373 possibly_unwield(magr
, FALSE
);
374 otmp
= MON_WEP(magr
);
378 mswingsm(magr
, mdef
, otmp
);
379 tmp
+= hitval(otmp
, mdef
);
389 /* Nymph that teleported away on first attack? */
390 if (distmin(magr
->mx
, magr
->my
, mdef
->mx
, mdef
->my
) > 1)
391 /* Continue because the monster may have a ranged attack. */
393 /* Monsters won't attack cockatrices physically if they
394 * have a weapon instead. This instinct doesn't work for
395 * players, or under conflict or confusion.
397 if (!magr
->mconf
&& !Conflict
&& otmp
&& mattk
->aatyp
!= AT_WEAP
398 && touch_petrifies(mdef
->data
)) {
402 dieroll
= rnd(20 + i
);
403 strike
= (tmp
> dieroll
);
404 /* KMH -- don't accumulate to-hit bonuses */
406 tmp
-= hitval(otmp
, mdef
);
408 res
[i
] = hitmm(magr
, mdef
, mattk
);
409 if ((mdef
->data
== &mons
[PM_BLACK_PUDDING
]
410 || mdef
->data
== &mons
[PM_BROWN_PUDDING
]) && otmp
411 && objects
[otmp
->otyp
].oc_material
== IRON
414 if (clone_mon(mdef
, 0, 0)) {
415 if (vis
&& canspotmon(mdef
)) {
418 Strcpy(buf
, Monnam(mdef
));
419 pline("%s divides as %s hits it!", buf
,
425 missmm(magr
, mdef
, mattk
);
428 case AT_HUGS
: /* automatic if prev two attacks succeed */
429 strike
= (i
>= 2 && res
[i
- 1] == MM_HIT
&& res
[i
- 2] == MM_HIT
);
431 res
[i
] = hitmm(magr
, mdef
, mattk
);
437 res
[i
] = gazemm(magr
, mdef
, mattk
);
441 /* D: Prevent explosions from a distance */
442 if (distmin(magr
->mx
,magr
->my
,mdef
->mx
,mdef
->my
) > 1)
445 res
[i
] = explmm(magr
, mdef
, mattk
);
446 if (res
[i
] == MM_MISS
) { /* cancelled--no attack */
450 strike
= 1; /* automatic hit */
454 if (u
.usteed
&& mdef
== u
.usteed
) {
458 /* D: Prevent engulf from a distance */
459 if (distmin(magr
->mx
, magr
->my
, mdef
->mx
, mdef
->my
) > 1)
461 /* Engulfing attacks are directed at the hero if possible. -dlc */
462 if (u
.uswallow
&& magr
== u
.ustuck
)
464 else if ((strike
= (tmp
> rnd(20 + i
))) != 0)
465 res
[i
] = gulpmm(magr
, mdef
, mattk
);
467 missmm(magr
, mdef
, mattk
);
471 if (!monnear(magr
, mdef
->mx
, mdef
->my
)) {
472 strike
= breamm(magr
, mattk
, mdef
);
474 /* We don't really know if we hit or not; pretend we did. */
477 if (DEADMONSTER(mdef
))
478 res
[i
] = MM_DEF_DIED
;
479 if (DEADMONSTER(magr
))
480 res
[i
] |= MM_AGR_DIED
;
487 if (!monnear(magr
, mdef
->mx
, mdef
->my
)) {
488 strike
= spitmm(magr
, mattk
, mdef
);
490 /* We don't really know if we hit or not; pretend we did. */
493 if (DEADMONSTER(mdef
))
494 res
[i
] = MM_DEF_DIED
;
495 if (DEADMONSTER(magr
))
496 res
[i
] |= MM_AGR_DIED
;
500 default: /* no attack */
506 if (attk
&& !(res
[i
] & MM_AGR_DIED
)
507 && distmin(magr
->mx
, magr
->my
, mdef
->mx
, mdef
->my
) <= 1)
508 res
[i
] = passivemm(magr
, mdef
, strike
, res
[i
] & MM_DEF_DIED
);
510 if (res
[i
] & MM_DEF_DIED
)
512 if (res
[i
] & MM_AGR_DIED
)
514 /* return if aggressor can no longer attack */
515 if (!magr
->mcanmove
|| magr
->msleeping
)
518 struck
= 1; /* at least one hit */
521 return (struck
? MM_HIT
: MM_MISS
);
524 /* Returns the result of mdamagem(). */
526 hitmm(magr
, mdef
, mattk
)
527 register struct monst
*magr
, *mdef
;
528 struct attack
*mattk
;
532 char buf
[BUFSZ
], mdef_name
[BUFSZ
];
534 if (!canspotmon(magr
))
535 map_invisible(magr
->mx
, magr
->my
);
536 if (!canspotmon(mdef
))
537 map_invisible(mdef
->mx
, mdef
->my
);
542 if ((compat
= could_seduce(magr
, mdef
, mattk
)) && !magr
->mcan
) {
543 Sprintf(buf
, "%s %s", Monnam(magr
),
544 mdef
->mcansee
? "smiles at" : "talks to");
545 pline("%s %s %s.", buf
, mon_nam(mdef
),
546 compat
== 2 ? "engagingly" : "seductively");
548 char magr_name
[BUFSZ
];
550 Strcpy(magr_name
, Monnam(magr
));
551 switch (mattk
->aatyp
) {
553 Sprintf(buf
, "%s bites", magr_name
);
556 Sprintf(buf
, "%s stings", magr_name
);
559 Sprintf(buf
, "%s butts", magr_name
);
562 Sprintf(buf
, "%s touches", magr_name
);
565 Sprintf(buf
, "%s tentacles suck", s_suffix(magr_name
));
568 if (magr
!= u
.ustuck
) {
569 Sprintf(buf
, "%s squeezes", magr_name
);
573 Sprintf(buf
, "%s hits", magr_name
);
575 pline("%s %s.", buf
, mon_nam_too(mdef_name
, mdef
, magr
));
580 return mdamagem(magr
, mdef
, mattk
);
583 /* Returns the same values as mdamagem(). */
585 gazemm(magr
, mdef
, mattk
)
586 register struct monst
*magr
, *mdef
;
587 struct attack
*mattk
;
592 if (mdef
->data
->mlet
== S_MIMIC
593 && mdef
->m_ap_type
!= M_AP_NOTHING
)
595 Sprintf(buf
, "%s gazes at", Monnam(magr
));
596 pline("%s %s...", buf
,
597 canspotmon(mdef
) ? mon_nam(mdef
) : "something");
600 if (magr
->mcan
|| !magr
->mcansee
|| !mdef
->mcansee
601 || (magr
->minvis
&& !perceives(mdef
->data
)) || mdef
->msleeping
) {
602 if (vis
&& canspotmon(mdef
))
603 pline("but nothing happens.");
606 /* call mon_reflects 2x, first test, then, if visible, print message */
607 if (magr
->data
== &mons
[PM_MEDUSA
] && mon_reflects(mdef
, (char *) 0)) {
609 (void) mon_reflects(mdef
, "The gaze is reflected away by %s %s.");
611 if (mon_reflects(magr
, (char *) 0)) {
613 (void) mon_reflects(magr
,
614 "The gaze is reflected away by %s %s.");
617 if (mdef
->minvis
&& !perceives(magr
->data
)) {
618 if (canseemon(magr
)) {
620 "%s doesn't seem to notice that %s gaze was reflected.",
621 Monnam(magr
), mhis(magr
));
626 pline("%s is turned to stone!", Monnam(magr
));
634 return mdamagem(magr
, mdef
, mattk
);
637 /* return True if magr is allowed to swallow mdef, False otherwise */
639 engulf_target(magr
, mdef
)
640 struct monst
*magr
, *mdef
;
645 /* can't swallow something that's too big */
646 if (mdef
->data
->msize
>= MZ_HUGE
)
649 /* (hypothetical) engulfers who can pass through walls aren't
650 limited by rock|trees|bars */
651 if ((magr
== &youmonst
) ? Passes_walls
: passes_walls(magr
->data
))
654 /* don't swallow something in a spot where attacker wouldn't
655 otherwise be able to move onto; we don't want to engulf
656 a wall-phaser and end up with a non-phaser inside a wall */
657 dx
= mdef
->mx
, dy
= mdef
->my
;
658 if (mdef
== &youmonst
)
659 dx
= u
.ux
, dy
= u
.uy
;
661 if (IS_ROCK(lev
->typ
) || closed_door(dx
, dy
) || IS_TREE(lev
->typ
)
662 /* not passes_bars(); engulfer isn't squeezing through */
663 || (lev
->typ
== IRONBARS
&& !is_whirly(magr
->data
)))
669 /* Returns the same values as mattackm(). */
671 gulpmm(magr
, mdef
, mattk
)
672 register struct monst
*magr
, *mdef
;
673 register struct attack
*mattk
;
675 xchar ax
, ay
, dx
, dy
;
680 if (!engulf_target(magr
, mdef
))
684 /* [this two-part formatting dates back to when only one x_monnam
685 result could be included in an expression because the next one
686 would overwrite first's result -- that's no longer the case] */
687 Sprintf(buf
, "%s swallows", Monnam(magr
));
688 pline("%s %s.", buf
, mon_nam(mdef
));
690 for (obj
= mdef
->minvent
; obj
; obj
= obj
->nobj
)
691 (void) snuff_lit(obj
);
693 if (is_vampshifter(mdef
)
694 && newcham(mdef
, &mons
[mdef
->cham
], FALSE
, FALSE
)) {
696 /* 'it' -- previous form is no longer available and
697 using that would be excessively verbose */
698 pline("%s expels %s.", Monnam(magr
),
699 canspotmon(mdef
) ? "it" : something
);
700 if (canspotmon(mdef
))
701 pline("It turns into %s.", a_monnam(mdef
));
703 return MM_HIT
; /* bypass mdamagem() */
707 * All of this manipulation is needed to keep the display correct.
708 * There is a flush at the next pline().
715 * Leave the defender in the monster chain at it's current position,
716 * but don't leave it on the screen. Move the aggressor to the
717 * defender's position.
719 remove_monster(ax
, ay
);
720 place_monster(magr
, dx
, dy
);
721 newsym(ax
, ay
); /* erase old position */
722 newsym(dx
, dy
); /* update new position */
724 status
= mdamagem(magr
, mdef
, mattk
);
726 if ((status
& (MM_AGR_DIED
| MM_DEF_DIED
))
727 == (MM_AGR_DIED
| MM_DEF_DIED
)) {
728 ; /* both died -- do nothing */
729 } else if (status
& MM_DEF_DIED
) { /* defender died */
731 * Note: remove_monster() was called in relmon(), wiping out
732 * magr from level.monsters[mdef->mx][mdef->my]. We need to
733 * put it back and display it. -kd
735 place_monster(magr
, dx
, dy
);
737 /* aggressor moves to <dx,dy> and might encounter trouble there */
738 if (minliquid(magr
) || (t_at(dx
, dy
) && mintrap(magr
) == 2))
739 status
|= MM_AGR_DIED
;
740 } else if (status
& MM_AGR_DIED
) { /* aggressor died */
741 place_monster(mdef
, dx
, dy
);
743 } else { /* both alive, put them back */
745 pline("%s is regurgitated!", Monnam(mdef
));
747 remove_monster(dx
,dy
);
748 place_monster(magr
, ax
, ay
);
749 place_monster(mdef
, dx
, dy
);
758 explmm(magr
, mdef
, mattk
)
759 struct monst
*magr
, *mdef
;
760 struct attack
*mattk
;
767 if (cansee(magr
->mx
, magr
->my
))
768 pline("%s explodes!", Monnam(magr
));
772 result
= mdamagem(magr
, mdef
, mattk
);
774 /* Kill off aggressor if it didn't die. */
775 if (!(result
& MM_AGR_DIED
)) {
778 return result
; /* life saved */
779 result
|= MM_AGR_DIED
;
781 if (magr
->mtame
) /* give this one even if it was visible */
782 You(brief_feeling
, "melancholy");
788 * See comment at top of mattackm(), for return values.
791 mdamagem(magr
, mdef
, mattk
)
792 register struct monst
*magr
, *mdef
;
793 register struct attack
*mattk
;
797 struct permonst
*pa
= magr
->data
, *pd
= mdef
->data
;
798 int armpro
, num
, tmp
= d((int) mattk
->damn
, (int) mattk
->damd
),
802 if ((touch_petrifies(pd
) /* or flesh_petrifies() */
803 || (mattk
->adtyp
== AD_DGST
&& pd
== &mons
[PM_MEDUSA
]))
804 && !resists_ston(magr
)) {
805 long protector
= attk_protection((int) mattk
->aatyp
),
806 wornitems
= magr
->misc_worn_check
;
808 /* wielded weapon gives same protection as gloves here */
813 || (protector
!= ~0L && (wornitems
& protector
) != protector
)) {
814 if (poly_when_stoned(pa
)) {
816 return MM_HIT
; /* no damage during the polymorph */
818 if (vis
&& canspotmon(magr
))
819 pline("%s turns to stone!", Monnam(magr
));
822 return MM_HIT
; /* lifesaved */
823 else if (magr
->mtame
&& !vis
)
824 You(brief_feeling
, "peculiarly sad");
829 /* cancellation factor is the same as when attacking the hero */
830 armpro
= magic_negation(mdef
);
831 cancelled
= magr
->mcan
|| !(rn2(10) >= 3 * armpro
);
833 switch (mattk
->adtyp
) {
835 /* eating a Rider or its corpse is fatal */
837 if (vis
&& canseemon(magr
))
838 pline("%s %s!", Monnam(magr
),
839 (pd
== &mons
[PM_FAMINE
])
840 ? "belches feebly, shrivels up and dies"
841 : (pd
== &mons
[PM_PESTILENCE
])
842 ? "coughs spasmodically and collapses"
843 : "vomits violently and drops dead");
846 return 0; /* lifesaved */
847 else if (magr
->mtame
&& !vis
)
848 You(brief_feeling
, "queasy");
851 if (flags
.verbose
&& !Deaf
)
852 verbalize("Burrrrp!");
854 /* Use up amulet of life saving */
855 if (!!(obj
= mlifesaver(mdef
)))
858 /* Is a corpse for nutrition possible? It may kill magr */
859 if (!corpse_chance(mdef
, magr
, TRUE
) || magr
->mhp
< 1)
862 /* Pets get nutrition from swallowing monster whole.
863 * No nutrition from G_NOCORPSE monster, eg, undead.
864 * DGST monsters don't die from undead corpses
867 if (magr
->mtame
&& !magr
->isminion
868 && !(mvitals
[num
].mvflags
& G_NOCORPSE
)) {
869 struct obj
*virtualcorpse
= mksobj(CORPSE
, FALSE
, FALSE
);
872 set_corpsenm(virtualcorpse
, num
);
873 nutrit
= dog_nutrition(magr
, virtualcorpse
);
874 dealloc_obj(virtualcorpse
);
876 /* only 50% nutrition, 25% of normal eating time */
877 if (magr
->meating
> 1)
878 magr
->meating
= (magr
->meating
+ 3) / 4;
881 EDOG(magr
)->hungrytime
+= nutrit
;
888 pline("%s %s for a moment.", Monnam(mdef
),
889 makeplural(stagger(pd
, "stagger")));
902 if (mattk
->aatyp
== AT_KICK
&& thick_skinned(pd
)) {
904 } else if (mattk
->aatyp
== AT_WEAP
) {
906 if (otmp
->otyp
== CORPSE
907 && touch_petrifies(&mons
[otmp
->corpsenm
]))
909 tmp
+= dmgval(otmp
, mdef
);
910 if (otmp
->oartifact
) {
911 (void) artifact_hit(magr
, mdef
, otmp
, &tmp
, dieroll
);
914 | (grow_up(magr
, mdef
) ? 0 : MM_AGR_DIED
));
919 } else if (pa
== &mons
[PM_PURPLE_WORM
] && pd
== &mons
[PM_SHRIEKER
]) {
920 /* hack to enhance mm_aggression(); we don't want purple
921 worm's bite attack to kill a shrieker because then it
922 won't swallow the corpse; but if the target survives,
923 the subsequent engulf attack should accomplish that */
924 if (tmp
>= mdef
->mhp
&& mdef
->mhp
> 1)
933 if (vis
&& canseemon(mdef
))
934 pline("%s is %s!", Monnam(mdef
), on_fire(pd
, mattk
));
935 if (pd
== &mons
[PM_STRAW_GOLEM
] || pd
== &mons
[PM_PAPER_GOLEM
]) {
936 if (vis
&& canseemon(mdef
))
937 pline("%s burns completely!", Monnam(mdef
));
941 else if (mdef
->mtame
&& !vis
)
942 pline("May %s roast in peace.", mon_nam(mdef
));
943 return (MM_DEF_DIED
| (grow_up(magr
, mdef
) ? 0 : MM_AGR_DIED
));
945 tmp
+= destroy_mitem(mdef
, SCROLL_CLASS
, AD_FIRE
);
946 tmp
+= destroy_mitem(mdef
, SPBOOK_CLASS
, AD_FIRE
);
947 if (resists_fire(mdef
)) {
948 if (vis
&& canseemon(mdef
))
949 pline_The("fire doesn't seem to burn %s!", mon_nam(mdef
));
950 shieldeff(mdef
->mx
, mdef
->my
);
951 golemeffects(mdef
, AD_FIRE
, tmp
);
954 /* only potions damage resistant players in destroy_item */
955 tmp
+= destroy_mitem(mdef
, POTION_CLASS
, AD_FIRE
);
962 if (vis
&& canseemon(mdef
))
963 pline("%s is covered in frost!", Monnam(mdef
));
964 if (resists_cold(mdef
)) {
965 if (vis
&& canseemon(mdef
))
966 pline_The("frost doesn't seem to chill %s!", mon_nam(mdef
));
967 shieldeff(mdef
->mx
, mdef
->my
);
968 golemeffects(mdef
, AD_COLD
, tmp
);
971 tmp
+= destroy_mitem(mdef
, POTION_CLASS
, AD_COLD
);
978 if (vis
&& canseemon(mdef
))
979 pline("%s gets zapped!", Monnam(mdef
));
980 tmp
+= destroy_mitem(mdef
, WAND_CLASS
, AD_ELEC
);
981 if (resists_elec(mdef
)) {
982 if (vis
&& canseemon(mdef
))
983 pline_The("zap doesn't shock %s!", mon_nam(mdef
));
984 shieldeff(mdef
->mx
, mdef
->my
);
985 golemeffects(mdef
, AD_ELEC
, tmp
);
988 /* only rings damage resistant players in destroy_item */
989 tmp
+= destroy_mitem(mdef
, RING_CLASS
, AD_ELEC
);
996 if (resists_acid(mdef
)) {
997 if (vis
&& canseemon(mdef
))
998 pline("%s is covered in %s, but it seems harmless.",
999 Monnam(mdef
), hliquid("acid"));
1001 } else if (vis
&& canseemon(mdef
)) {
1002 pline("%s is covered in %s!", Monnam(mdef
), hliquid("acid"));
1003 pline("It burns %s!", mon_nam(mdef
));
1006 erode_armor(mdef
, ERODE_CORRODE
);
1008 acid_damage(MON_WEP(mdef
));
1013 if (pd
== &mons
[PM_IRON_GOLEM
]) {
1014 if (vis
&& canseemon(mdef
))
1015 pline("%s falls to pieces!", Monnam(mdef
));
1019 else if (mdef
->mtame
&& !vis
)
1020 pline("May %s rust in peace.", mon_nam(mdef
));
1021 return (MM_DEF_DIED
| (grow_up(magr
, mdef
) ? 0 : MM_AGR_DIED
));
1023 erode_armor(mdef
, ERODE_RUST
);
1024 mdef
->mstrategy
&= ~STRAT_WAITFORU
;
1030 erode_armor(mdef
, ERODE_CORRODE
);
1031 mdef
->mstrategy
&= ~STRAT_WAITFORU
;
1037 if (pd
== &mons
[PM_WOOD_GOLEM
] || pd
== &mons
[PM_LEATHER_GOLEM
]) {
1038 if (vis
&& canseemon(mdef
))
1039 pline("%s falls to pieces!", Monnam(mdef
));
1043 else if (mdef
->mtame
&& !vis
)
1044 pline("May %s rot in peace.", mon_nam(mdef
));
1045 return (MM_DEF_DIED
| (grow_up(magr
, mdef
) ? 0 : MM_AGR_DIED
));
1047 erode_armor(mdef
, ERODE_CORRODE
);
1048 mdef
->mstrategy
&= ~STRAT_WAITFORU
;
1055 /* may die from the acid if it eats a stone-curing corpse */
1056 if (munstone(mdef
, FALSE
))
1058 if (poly_when_stoned(pd
)) {
1063 if (!resists_ston(mdef
)) {
1064 if (vis
&& canseemon(mdef
))
1065 pline("%s turns to stone!", Monnam(mdef
));
1070 else if (mdef
->mtame
&& !vis
)
1071 You(brief_feeling
, "peculiarly sad");
1072 return (MM_DEF_DIED
| (grow_up(magr
, mdef
) ? 0 : MM_AGR_DIED
));
1074 tmp
= (mattk
->adtyp
== AD_STON
? 0 : 1);
1077 if (!cancelled
&& tmp
< mdef
->mhp
&& !tele_restrict(mdef
)) {
1078 char mdef_Monnam
[BUFSZ
];
1079 boolean wasseen
= canspotmon(mdef
);
1080 /* save the name before monster teleports, otherwise
1081 we'll get "it" in the suddenly disappears message */
1083 Strcpy(mdef_Monnam
, Monnam(mdef
));
1084 mdef
->mstrategy
&= ~STRAT_WAITFORU
;
1085 (void) rloc(mdef
, TRUE
);
1086 if (vis
&& wasseen
&& !canspotmon(mdef
) && mdef
!= u
.usteed
)
1087 pline("%s suddenly disappears!", mdef_Monnam
);
1091 if (!cancelled
&& !mdef
->msleeping
1092 && sleep_monst(mdef
, rnd(10), -1)) {
1093 if (vis
&& canspotmon(mdef
)) {
1094 Strcpy(buf
, Monnam(mdef
));
1095 pline("%s is put to sleep by %s.", buf
, mon_nam(magr
));
1097 mdef
->mstrategy
&= ~STRAT_WAITFORU
;
1102 if (!cancelled
&& mdef
->mcanmove
) {
1103 if (vis
&& canspotmon(mdef
)) {
1104 Strcpy(buf
, Monnam(mdef
));
1105 pline("%s is frozen by %s.", buf
, mon_nam(magr
));
1107 paralyze_monst(mdef
, rnd(10));
1111 if (!cancelled
&& mdef
->mspeed
!= MSLOW
) {
1112 unsigned int oldspeed
= mdef
->mspeed
;
1114 mon_adjust_speed(mdef
, -1, (struct obj
*) 0);
1115 mdef
->mstrategy
&= ~STRAT_WAITFORU
;
1116 if (mdef
->mspeed
!= oldspeed
&& vis
&& canspotmon(mdef
))
1117 pline("%s slows down.", Monnam(mdef
));
1121 /* Since confusing another monster doesn't have a real time
1122 * limit, setting spec_used would not really be right (though
1123 * we still should check for it).
1125 if (!magr
->mcan
&& !mdef
->mconf
&& !magr
->mspec_used
) {
1126 if (vis
&& canseemon(mdef
))
1127 pline("%s looks confused.", Monnam(mdef
));
1129 mdef
->mstrategy
&= ~STRAT_WAITFORU
;
1133 if (can_blnd(magr
, mdef
, mattk
->aatyp
, (struct obj
*) 0)) {
1134 register unsigned rnd_tmp
;
1136 if (vis
&& mdef
->mcansee
&& canspotmon(mdef
))
1137 pline("%s is blinded.", Monnam(mdef
));
1138 rnd_tmp
= d((int) mattk
->damn
, (int) mattk
->damd
);
1139 if ((rnd_tmp
+= mdef
->mblinded
) > 127)
1141 mdef
->mblinded
= rnd_tmp
;
1143 mdef
->mstrategy
&= ~STRAT_WAITFORU
;
1148 if (!magr
->mcan
&& haseyes(pd
) && mdef
->mcansee
) {
1149 if (vis
&& canseemon(mdef
))
1150 pline("%s looks %sconfused.", Monnam(mdef
),
1151 mdef
->mconf
? "more " : "");
1153 mdef
->mstrategy
&= ~STRAT_WAITFORU
;
1158 if (!night() && (pa
== &mons
[PM_GREMLIN
]))
1160 if (!magr
->mcan
&& !rn2(10)) {
1161 mdef
->mcan
= 1; /* cancelled regardless of lifesave */
1162 mdef
->mstrategy
&= ~STRAT_WAITFORU
;
1163 if (is_were(pd
) && pd
->mlet
!= S_HUMAN
)
1165 if (pd
== &mons
[PM_CLAY_GOLEM
]) {
1166 if (vis
&& canseemon(mdef
)) {
1167 pline("Some writing vanishes from %s head!",
1168 s_suffix(mon_nam(mdef
)));
1169 pline("%s is destroyed!", Monnam(mdef
));
1174 else if (mdef
->mtame
&& !vis
)
1175 You(brief_feeling
, "strangely sad");
1177 | (grow_up(magr
, mdef
) ? 0 : MM_AGR_DIED
));
1181 You_hear("laughter.");
1182 else if (canseemon(magr
))
1183 pline("%s chuckles.", Monnam(magr
));
1191 /* technically incorrect; no check for stealing gold from
1192 * between mdef's feet...
1195 struct obj
*gold
= findgold(mdef
->minvent
);
1199 obj_extract_self(gold
);
1200 add_to_minv(magr
, gold
);
1202 mdef
->mstrategy
&= ~STRAT_WAITFORU
;
1203 if (vis
&& canseemon(mdef
)) {
1204 Strcpy(buf
, Monnam(magr
));
1205 pline("%s steals some gold from %s.", buf
, mon_nam(mdef
));
1207 if (!tele_restrict(magr
)) {
1208 boolean couldspot
= canspotmon(magr
);
1209 (void) rloc(magr
, TRUE
);
1210 if (vis
&& couldspot
&& !canspotmon(magr
))
1211 pline("%s suddenly disappears!", buf
);
1215 if (!cancelled
&& !rn2(3) && !resists_drli(mdef
)) {
1217 if (vis
&& canspotmon(mdef
))
1218 pline("%s suddenly seems weaker!", Monnam(mdef
));
1219 mdef
->mhpmax
-= tmp
;
1220 if (mdef
->m_lev
== 0)
1224 /* Automatic kill if drained past level 0 */
1228 case AD_SITM
: /* for now these are the same */
1232 /* find an object to steal, non-cursed if magr is tame */
1233 for (obj
= mdef
->minvent
; obj
; obj
= obj
->nobj
)
1234 if (!magr
->mtame
|| !obj
->cursed
)
1238 char onambuf
[BUFSZ
], mdefnambuf
[BUFSZ
];
1240 /* make a special x_monnam() call that never omits
1241 the saddle, and save it for later messages */
1243 x_monnam(mdef
, ARTICLE_THE
, (char *) 0, 0, FALSE
));
1246 if (u
.usteed
== mdef
&& otmp
== which_armor(mdef
, W_SADDLE
))
1247 /* "You can no longer ride <steed>." */
1248 dismount_steed(DISMOUNT_POLY
);
1249 obj_extract_self(otmp
);
1250 if (otmp
->owornmask
) {
1251 mdef
->misc_worn_check
&= ~otmp
->owornmask
;
1252 if (otmp
->owornmask
& W_WEP
)
1254 otmp
->owornmask
= 0L;
1255 update_mon_intrinsics(mdef
, otmp
, FALSE
, FALSE
);
1257 /* add_to_minv() might free otmp [if it merges] */
1259 Strcpy(onambuf
, doname(otmp
));
1260 (void) add_to_minv(magr
, otmp
);
1261 if (vis
&& canseemon(mdef
)) {
1262 Strcpy(buf
, Monnam(magr
));
1263 pline("%s steals %s from %s!", buf
, onambuf
, mdefnambuf
);
1265 possibly_unwield(mdef
, FALSE
);
1266 mdef
->mstrategy
&= ~STRAT_WAITFORU
;
1267 mselftouch(mdef
, (const char *) 0, FALSE
);
1270 | (grow_up(magr
, mdef
) ? 0 : MM_AGR_DIED
));
1271 if (pa
->mlet
== S_NYMPH
&& !tele_restrict(magr
)) {
1272 boolean couldspot
= canspotmon(magr
);
1273 (void) rloc(magr
, TRUE
);
1274 if (vis
&& couldspot
&& !canspotmon(magr
))
1275 pline("%s suddenly disappears!", buf
);
1281 if (!cancelled
&& !rn2(4))
1282 xdrainenergym(mdef
, vis
&& canspotmon(mdef
) && mattk
->aatyp
!= AT_ENGL
);
1288 if (!cancelled
&& !rn2(8)) {
1289 if (vis
&& canspotmon(magr
))
1290 pline("%s %s was poisoned!", s_suffix(Monnam(magr
)),
1291 mpoisons_subj(magr
, mattk
));
1292 if (resists_poison(mdef
)) {
1293 if (vis
&& canspotmon(mdef
) && canspotmon(magr
))
1294 pline_The("poison doesn't seem to affect %s.",
1300 if (vis
&& canspotmon(mdef
))
1301 pline_The("poison was deadly...");
1308 if (notonhead
|| !has_head(pd
)) {
1309 if (vis
&& canspotmon(mdef
))
1310 pline("%s doesn't seem harmed.", Monnam(mdef
));
1311 /* Not clear what to do for green slimes */
1315 if ((mdef
->misc_worn_check
& W_ARMH
) && rn2(8)) {
1316 if (vis
&& canspotmon(magr
) && canseemon(mdef
)) {
1317 Strcpy(buf
, s_suffix(Monnam(mdef
)));
1318 pline("%s helmet blocks %s attack to %s head.", buf
,
1319 s_suffix(mon_nam(magr
)), mhis(mdef
));
1323 res
= eat_brains(magr
, mdef
, vis
, &tmp
);
1327 break; /* physical damage only */
1328 if (!rn2(4) && !slimeproof(pd
)) {
1329 if (!munslime(mdef
, FALSE
) && mdef
->mhp
> 0) {
1330 if (newcham(mdef
, &mons
[PM_GREEN_SLIME
], FALSE
, vis
&& canseemon(mdef
)))
1332 mdef
->mstrategy
&= ~STRAT_WAITFORU
;
1335 /* munslime attempt could have been fatal,
1336 potentially to multiple monsters (SCR_FIRE) */
1348 case AD_WRAP
: /* monsters cannot grab one another, it's too hard */
1353 /* there's no msomearmor() function, so just do damage */
1354 /* if (cancelled) break; */
1363 if ((mdef
->mhp
-= tmp
) < 1) {
1364 if (m_at(mdef
->mx
, mdef
->my
) == magr
) { /* see gulpmm() */
1365 remove_monster(mdef
->mx
, mdef
->my
);
1366 mdef
->mhp
= 1; /* otherwise place_monster will complain */
1367 place_monster(mdef
, mdef
->mx
, mdef
->my
);
1370 monkilled(mdef
, "", (int) mattk
->adtyp
);
1372 return res
; /* mdef lifesaved */
1373 else if (res
== MM_AGR_DIED
)
1374 return (MM_DEF_DIED
| MM_AGR_DIED
);
1376 if (mattk
->adtyp
== AD_DGST
) {
1377 /* various checks similar to dog_eat and meatobj.
1378 * after monkilled() to provide better message ordering */
1379 if (mdef
->cham
>= LOW_PM
) {
1380 (void) newcham(magr
, (struct permonst
*) 0, FALSE
, TRUE
);
1381 } else if (pd
== &mons
[PM_GREEN_SLIME
] && !slimeproof(pa
)) {
1382 (void) newcham(magr
, &mons
[PM_GREEN_SLIME
], FALSE
, TRUE
);
1383 } else if (pd
== &mons
[PM_WRAITH
]) {
1384 (void) grow_up(magr
, (struct monst
*) 0);
1385 /* don't grow up twice */
1386 return (MM_DEF_DIED
| (magr
->mhp
> 0 ? 0 : MM_AGR_DIED
));
1387 } else if (pd
== &mons
[PM_NURSE
]) {
1388 magr
->mhp
= magr
->mhpmax
;
1391 /* caveat: above digestion handling doesn't keep `pa' up to date */
1393 return (MM_DEF_DIED
| (grow_up(magr
, mdef
) ? 0 : MM_AGR_DIED
));
1395 return (res
== MM_AGR_DIED
) ? MM_AGR_DIED
: MM_HIT
;
1399 paralyze_monst(mon
, amt
)
1408 mon
->meating
= 0; /* terminate any meal-in-progress */
1409 mon
->mstrategy
&= ~STRAT_WAITFORU
;
1412 /* `mon' is hit by a sleep attack; return 1 if it's affected, 0 otherwise */
1414 sleep_monst(mon
, amt
, how
)
1418 if (resists_sleep(mon
)
1419 || (how
>= 0 && resist(mon
, (char) how
, 0, NOTELL
))) {
1420 shieldeff(mon
->mx
, mon
->my
);
1421 } else if (mon
->mcanmove
) {
1422 finish_meating(mon
); /* terminate any meal-in-progress */
1423 amt
+= (int) mon
->mfrozen
;
1424 if (amt
> 0) { /* sleep for N turns */
1426 mon
->mfrozen
= min(amt
, 127);
1427 } else { /* sleep until awakened */
1435 /* sleeping grabber releases, engulfer doesn't; don't use for paralysis! */
1440 if ((mon
->msleeping
|| !mon
->mcanmove
) && mon
== u
.ustuck
1441 && !sticks(youmonst
.data
) && !u
.uswallow
) {
1442 pline("%s grip relaxes.", s_suffix(Monnam(mon
)));
1452 int dmgtyp
= -1, chance
= 1;
1455 return; /* just in case */
1456 /* AD_ACID and AD_ENCH are handled in passivemm() and passiveum() */
1457 if (dmgtype(mdef
->data
, AD_CORR
)) {
1458 dmgtyp
= ERODE_CORRODE
;
1459 } else if (dmgtype(mdef
->data
, AD_RUST
)) {
1460 dmgtyp
= ERODE_RUST
;
1461 } else if (dmgtype(mdef
->data
, AD_FIRE
)
1462 /* steam vortex: fire resist applies, fire damage doesn't */
1463 && mdef
->data
!= &mons
[PM_STEAM_VORTEX
]) {
1464 dmgtyp
= ERODE_BURN
;
1468 if (dmgtyp
>= 0 && !rn2(chance
))
1469 (void) erode_obj(obj
, (char *) 0, dmgtyp
, EF_GREASE
| EF_VERBOSE
);
1473 mswingsm(magr
, mdef
, otemp
)
1474 struct monst
*magr
, *mdef
;
1477 if (flags
.verbose
&& !Blind
&& mon_visible(magr
)) {
1478 pline("%s %s %s%s %s at %s.", Monnam(magr
),
1479 (objects
[otemp
->otyp
].oc_dir
& PIERCE
) ? "thrusts" : "swings",
1480 (otemp
->quan
> 1L) ? "one of " : "", mhis(magr
), xname(otemp
),
1486 * Passive responses by defenders. Does not replicate responses already
1487 * handled above. Returns same values as mattackm.
1490 passivemm(magr
, mdef
, mhit
, mdead
)
1491 register struct monst
*magr
, *mdef
;
1495 register struct permonst
*mddat
= mdef
->data
;
1496 register struct permonst
*madat
= magr
->data
;
1502 return (mdead
| mhit
); /* no passive attacks */
1503 if (mddat
->mattk
[i
].aatyp
== AT_NONE
)
1506 if (mddat
->mattk
[i
].damn
)
1507 tmp
= d((int) mddat
->mattk
[i
].damn
, (int) mddat
->mattk
[i
].damd
);
1508 else if (mddat
->mattk
[i
].damd
)
1509 tmp
= d((int) mddat
->mlevel
+ 1, (int) mddat
->mattk
[i
].damd
);
1513 /* These affect the enemy even if defender killed */
1514 switch (mddat
->mattk
[i
].adtyp
) {
1516 if (mhit
&& !rn2(2)) {
1517 Strcpy(buf
, Monnam(magr
));
1518 if (canseemon(magr
))
1519 pline("%s is splashed by %s %s!", buf
,
1520 s_suffix(mon_nam(mdef
)), hliquid("acid"));
1521 if (resists_acid(magr
)) {
1522 if (canseemon(magr
))
1523 pline("%s is not affected.", Monnam(magr
));
1529 erode_armor(magr
, ERODE_CORRODE
);
1531 acid_damage(MON_WEP(magr
));
1533 case AD_ENCH
: /* KMH -- remove enchantment (disenchanter) */
1534 if (mhit
&& !mdef
->mcan
&& otmp
) {
1535 (void) drain_item(otmp
, FALSE
);
1542 if (mdead
|| mdef
->mcan
)
1543 return (mdead
| mhit
);
1545 /* These affect the enemy only if defender is still alive */
1547 switch (mddat
->mattk
[i
].adtyp
) {
1548 case AD_PLYS
: /* Floating eye */
1551 if (mddat
== &mons
[PM_FLOATING_EYE
]) {
1554 if (magr
->mcansee
&& haseyes(madat
) && mdef
->mcansee
1555 && (perceives(madat
) || !mdef
->minvis
)) {
1556 Sprintf(buf
, "%s gaze is reflected by %%s %%s.",
1557 s_suffix(Monnam(mdef
)));
1558 if (mon_reflects(magr
,
1559 canseemon(magr
) ? buf
: (char *) 0))
1560 return (mdead
| mhit
);
1561 Strcpy(buf
, Monnam(magr
));
1562 if (canseemon(magr
))
1563 pline("%s is frozen by %s gaze!", buf
,
1564 s_suffix(mon_nam(mdef
)));
1565 paralyze_monst(magr
, tmp
);
1566 return (mdead
| mhit
);
1568 } else { /* gelatinous cube */
1569 Strcpy(buf
, Monnam(magr
));
1570 if (canseemon(magr
))
1571 pline("%s is frozen by %s.", buf
, mon_nam(mdef
));
1572 paralyze_monst(magr
, tmp
);
1573 return (mdead
| mhit
);
1577 if (resists_cold(magr
)) {
1578 if (canseemon(magr
)) {
1579 pline("%s is mildly chilly.", Monnam(magr
));
1580 golemeffects(magr
, AD_COLD
, tmp
);
1585 if (canseemon(magr
))
1586 pline("%s is suddenly very cold!", Monnam(magr
));
1587 mdef
->mhp
+= tmp
/ 2;
1588 if (mdef
->mhpmax
< mdef
->mhp
)
1589 mdef
->mhpmax
= mdef
->mhp
;
1590 if (mdef
->mhpmax
> ((int) (mdef
->m_lev
+ 1) * 8))
1591 (void) split_mon(mdef
, magr
);
1596 if (canseemon(magr
))
1597 pline("%s %s...", Monnam(magr
),
1598 makeplural(stagger(magr
->data
, "stagger")));
1603 if (resists_fire(magr
)) {
1604 if (canseemon(magr
)) {
1605 pline("%s is mildly warmed.", Monnam(magr
));
1606 golemeffects(magr
, AD_FIRE
, tmp
);
1611 if (canseemon(magr
))
1612 pline("%s is suddenly very hot!", Monnam(magr
));
1615 if (resists_elec(magr
)) {
1616 if (canseemon(magr
)) {
1617 pline("%s is mildly tingled.", Monnam(magr
));
1618 golemeffects(magr
, AD_ELEC
, tmp
);
1623 if (canseemon(magr
))
1624 pline("%s is jolted with electricity!", Monnam(magr
));
1634 if ((magr
->mhp
-= tmp
) <= 0) {
1635 monkilled(magr
, "", (int) mddat
->mattk
[i
].adtyp
);
1636 return (mdead
| mhit
| MM_AGR_DIED
);
1638 return (mdead
| mhit
);
1641 /* hero or monster has successfully hit target mon with drain energy attack */
1643 xdrainenergym(mon
, givemsg
)
1647 if (mon
->mspec_used
< 20 /* limit draining */
1648 && (attacktype(mon
->data
, AT_MAGC
)
1649 || attacktype(mon
->data
, AT_BREA
))) {
1650 mon
->mspec_used
+= d(2, 2);
1652 pline("%s seems lethargic.", Monnam(mon
));
1656 /* "aggressive defense"; what type of armor prevents specified attack
1657 from touching its target? */
1659 attk_protection(aatyp
)
1672 w_mask
= ~0L; /* special case; no defense needed */
1677 w_mask
= W_ARMG
; /* caller needs to check for weapon */
1686 w_mask
= (W_ARMC
| W_ARMG
); /* attacker needs both to be protected */
1693 w_mask
= 0L; /* no defense available */