1 /* NetHack 3.6 mhitm.c $NHDT-Date: 1583606861 2020/03/07 18:47:41 $ $NHDT-Branch: NetHack-3.6-Mar2020 $:$NHDT-Revision: 1.119 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2011. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020 */
9 /* JNetHack may be freely redistributed. See license for details. */
14 extern boolean notonhead;
16 static NEARDATA boolean vis, far_noise;
17 static NEARDATA long noisetime;
18 static NEARDATA struct obj *otmp;
20 static const char brief_feeling[] =
22 "have a %s feeling for a moment, then it passes.";
24 "%s
\8bC
\8e\9d\82É
\82¨
\82»
\82í
\82ê
\82½
\82ª
\81C
\82·
\82®
\82É
\89ß
\82¬
\82³
\82Á
\82½
\81D";
26 STATIC_DCL int FDECL(hitmm, (struct monst *, struct monst *,
28 STATIC_DCL int FDECL(gazemm, (struct monst *, struct monst *,
30 STATIC_DCL int FDECL(gulpmm, (struct monst *, struct monst *,
32 STATIC_DCL int FDECL(explmm, (struct monst *, struct monst *,
34 STATIC_DCL int FDECL(mdamagem, (struct monst *, struct monst *,
36 STATIC_DCL void FDECL(mswingsm, (struct monst *, struct monst *,
38 STATIC_DCL void FDECL(noises, (struct monst *, struct attack *));
39 STATIC_DCL void FDECL(missmm, (struct monst *, struct monst *,
41 STATIC_DCL int FDECL(passivemm, (struct monst *, struct monst *,
44 /* Needed for the special case of monsters wielding vorpal blades (rare).
45 * If we use this a lot it should probably be a parameter to mdamagem()
46 * instead of a global variable.
52 register struct monst *magr;
53 register struct attack *mattk;
55 boolean farq = (distu(magr->mx, magr->my) > 15);
57 if (!Deaf && (farq != far_noise || moves - noisetime > 10)) {
62 (mattk->aatyp == AT_EXPL) ? "an explosion" : "some noises",
63 farq ? " in the distance" : "");
65 You_hear("%s%s
\82ð
\95·
\82¢
\82½
\81D",
66 farq ? "
\89\93\82
\82Å" : "",
67 (mattk->aatyp == AT_EXPL) ? "
\94\9a\94
\89¹" : "
\89½
\82©
\82ª
\90í
\82¤
\89¹"
75 missmm(magr, mdef, mattk)
76 register struct monst *magr, *mdef;
81 boolean showit = FALSE;
83 /* unhiding or unmimicking happens even if hero can't see it
84 because the formerly concealed monster is now in action */
85 if (M_AP_TYPE(mdef)) {
88 } else if (mdef->mundetected) {
89 mdef->mundetected = 0;
92 if (M_AP_TYPE(magr)) {
95 } else if (magr->mundetected) {
96 magr->mundetected = 0;
101 if (!canspotmon(magr))
102 map_invisible(magr->mx, magr->my);
104 newsym(magr->mx, magr->my);
105 if (!canspotmon(mdef))
106 map_invisible(mdef->mx, mdef->my);
108 newsym(mdef->mx, mdef->my);
111 fmt = (could_seduce(magr, mdef, mattk) && !magr->mcan)
112 ? "%s pretends to be friendly to"
114 #else /*JP:
\89p
\8cê
\82Æ
\95Ï
\90\94\93W
\8aJ
\82Ì
\83^
\83C
\83~
\83\93\83O
\82ª
\88Ù
\82È
\82é
\82Ì
\82Å
\92\8d\88Ó*/
115 fmt = (could_seduce(magr,mdef,mattk) && !magr->mcan)
116 ? "%s
\82Í%%s
\82É
\97F
\8dD
\93I
\82È
\82Ó
\82è
\82ð
\82µ
\82½
\81D"
117 : "%s
\82Ì%%s
\82Ö
\82Ì
\8dU
\8c\82\82Í
\8aO
\82ê
\82½
\81D";
119 Sprintf(buf, fmt, Monnam(magr));
121 pline("%s %s.", buf, mon_nam_too(mdef, magr));
123 pline(buf, mon_nam_too(mdef, magr));
130 * fightm() -- fight some other monster
133 * 0 - Monster did nothing.
134 * 1 - If the monster made an attack. The monster might have died.
136 * There is an exception to the above. If mtmp has the hero swallowed,
137 * then we report that the monster did nothing so it will continue to
140 /* have monsters fight each other */
143 register struct monst *mtmp;
145 register struct monst *mon, *nmon;
146 int result, has_u_swallowed;
150 /* perhaps the monster will resist Conflict */
151 if (resist(mtmp, RING_CLASS, 0, 0))
154 if (u.ustuck == mtmp) {
155 /* perhaps we're holding it... */
159 has_u_swallowed = (u.uswallow && (mtmp == u.ustuck));
161 for (mon = fmon; mon; mon = nmon) {
165 /* Be careful to ignore monsters that are already dead, since we
166 * might be calling this before we've cleaned them up. This can
167 * happen if the monster attacked a cockatrice bare-handedly, for
170 if (mon != mtmp && !DEADMONSTER(mon)) {
171 if (monnear(mtmp, mon->mx, mon->my)) {
172 if (!u.uswallow && (mtmp == u.ustuck)) {
175 pline("%s releases you!", Monnam(mtmp));
177 pline("%s
\82Í
\82 \82È
\82½
\82ð
\89ð
\95ú
\82µ
\82½
\81I", Monnam(mtmp));
183 /* mtmp can be killed */
187 result = mattackm(mtmp, mon);
189 if (result & MM_AGR_DIED)
190 return 1; /* mtmp died */
192 * If mtmp has the hero swallowed, lie and say there
193 * was no attack (this allows mtmp to digest the hero).
198 /* Allow attacked monsters a chance to hit back. Primarily
199 * to allow monsters that resist conflict to respond.
201 if ((result & MM_HIT) && !(result & MM_DEF_DIED) && rn2(4)
202 && mon->movement >= NORMAL_SPEED) {
203 mon->movement -= NORMAL_SPEED;
205 (void) mattackm(mon, mtmp); /* return attack */
208 return (result & MM_HIT) ? 1 : 0;
216 * mdisplacem() -- attacker moves defender out of the way;
217 * returns same results as mattackm().
220 mdisplacem(magr, mdef, quietly)
221 register struct monst *magr, *mdef;
224 struct permonst *pa, *pd;
227 /* sanity checks; could matter if we unexpectedly get a long worm */
228 if (!magr || !mdef || magr == mdef)
230 pa = magr->data, pd = mdef->data;
231 tx = mdef->mx, ty = mdef->my; /* destination */
232 fx = magr->mx, fy = magr->my; /* current location */
233 if (m_at(fx, fy) != magr || m_at(tx, ty) != mdef)
236 /* The 1 in 7 failure below matches the chance in attack()
237 * for pet displacement.
242 /* Grid bugs cannot displace at an angle. */
243 if (pa == &mons[PM_GRID_BUG] && magr->mx != mdef->mx
244 && magr->my != mdef->my)
247 /* undetected monster becomes un-hidden if it is displaced */
248 if (mdef->mundetected)
249 mdef->mundetected = 0;
250 if (M_AP_TYPE(mdef) && M_AP_TYPE(mdef) != M_AP_MONSTER)
252 /* wake up the displaced defender */
254 mdef->mstrategy &= ~STRAT_WAITMASK;
255 finish_meating(mdef);
258 * Set up the visibility of action.
259 * You can observe monster displacement if you can see both of
260 * the monsters involved.
262 vis = (canspotmon(magr) && canspotmon(mdef));
264 if (touch_petrifies(pd) && !resists_ston(magr)) {
265 if (which_armor(magr, W_ARMG) != 0) {
266 if (poly_when_stoned(pa)) {
268 return MM_HIT; /* no damage during the polymorph */
270 if (!quietly && canspotmon(magr))
272 pline("%s turns to stone!", Monnam(magr));
274 pline("%s
\82Í
\90Î
\82É
\82È
\82Á
\82½
\81I", Monnam(magr));
276 if (!DEADMONSTER(magr))
277 return MM_HIT; /* lifesaved */
278 else if (magr->mtame && !vis)
280 You(brief_feeling, "peculiarly sad");
282 You(brief_feeling, "
\82à
\82Ì
\94ß
\82µ
\82¢");
287 remove_monster(fx, fy); /* pick up from orig position */
288 remove_monster(tx, ty);
289 place_monster(magr, tx, ty); /* put down at target spot */
290 place_monster(mdef, fx, fy);
293 pline("%s moves %s out of %s way!", Monnam(magr), mon_nam(mdef),
294 is_rider(pa) ? "the" : mhis(magr));
296 pline("%s
\82Í%s
\82ð
\89\9f\82µ
\82Ì
\82¯
\82½
\81I", Monnam(magr), mon_nam(mdef));
298 newsym(fx, fy); /* see it */
299 newsym(tx, ty); /* all happen */
300 flush_screen(0); /* make sure it shows up */
306 * mattackm() -- a monster attacks another monster.
308 * --------- aggressor died
309 * / ------- defender died
310 * / / ----- defender was hit
319 * Each successive attack has a lower probability of hitting. Some rely on
320 * success of previous attacks. ** this doen't seem to be implemented -dl **
322 * In the case of exploding monsters, the monster dies as well.
326 register struct monst *magr, *mdef;
328 int i, /* loop counter */
329 tmp, /* amour class difference */
330 strike = 0, /* hit this attack */
331 attk, /* attack attempted this time */
332 struck = 0, /* hit at least once */
333 res[NATTK]; /* results of all attacks */
334 struct attack *mattk, alt_attk;
335 struct permonst *pa, *pd;
338 return MM_MISS; /* mike@genat */
339 if (!magr->mcanmove || magr->msleeping)
344 /* Grid bugs cannot attack at an angle. */
345 if (pa == &mons[PM_GRID_BUG] && magr->mx != mdef->mx
346 && magr->my != mdef->my)
349 /* Calculate the armour class differential. */
350 tmp = find_mac(mdef) + magr->m_lev;
351 if (mdef->mconf || !mdef->mcanmove || mdef->msleeping) {
356 /* undetect monsters become un-hidden if they are attacked */
357 if (mdef->mundetected) {
358 mdef->mundetected = 0;
359 newsym(mdef->mx, mdef->my);
360 if (canseemon(mdef) && !sensemon(mdef)) {
363 boolean justone = (mdef->data->geno & G_UNIQ) != 0L;
366 montype = noname_monnam(mdef, justone ? ARTICLE_THE
369 montype = makeplural(montype);
370 You("dream of %s.", montype);
372 You("%s
\82Ì
\96²
\82ð
\8c©
\82½
\81D", a_monnam(mdef));
376 pline("Suddenly, you notice %s.", a_monnam(mdef));
378 pline("
\93Ë
\91R
\81C
\82 \82È
\82½
\82Í%s
\82É
\8bC
\82ª
\82Â
\82¢
\82½
\81D", a_monnam(mdef));
382 /* Elves hate orcs. */
383 if (is_elf(pa) && is_orc(pd))
386 /* Set up the visibility of action */
387 vis = (cansee(magr->mx, magr->my) && cansee(mdef->mx, mdef->my)
388 && (canspotmon(magr) || canspotmon(mdef)));
390 /* Set flag indicating monster has moved this turn. Necessary since a
391 * monster might get an attack out of sequence (i.e. before its move) in
392 * some cases, in which case this still counts as its move for the round
393 * and it shouldn't move again.
395 magr->mlstmv = monstermoves;
397 /* Now perform all attacks for the monster. */
398 for (i = 0; i < NATTK; i++) {
400 mattk = getmattk(magr, mdef, i, res, &alt_attk);
401 otmp = (struct obj *) 0;
403 switch (mattk->aatyp) {
404 case AT_WEAP: /* "hand to hand" attacks */
405 if (distmin(magr->mx, magr->my, mdef->mx, mdef->my) > 1) {
406 /* D: Do a ranged attack here! */
407 strike = thrwmm(magr, mdef);
408 if (DEADMONSTER(mdef))
409 res[i] = MM_DEF_DIED;
410 if (DEADMONSTER(magr))
411 res[i] |= MM_AGR_DIED;
414 if (magr->weapon_check == NEED_WEAPON || !MON_WEP(magr)) {
415 magr->weapon_check = NEED_HTH_WEAPON;
416 if (mon_wield_item(magr) != 0)
419 possibly_unwield(magr, FALSE);
420 otmp = MON_WEP(magr);
424 mswingsm(magr, mdef, otmp);
425 tmp += hitval(otmp, mdef);
435 /* Nymph that teleported away on first attack? */
436 if (distmin(magr->mx, magr->my, mdef->mx, mdef->my) > 1)
437 /* Continue because the monster may have a ranged attack. */
439 /* Monsters won't attack cockatrices physically if they
440 * have a weapon instead. This instinct doesn't work for
441 * players, or under conflict or confusion.
443 if (!magr->mconf && !Conflict && otmp && mattk->aatyp != AT_WEAP
444 && touch_petrifies(mdef->data)) {
448 dieroll = rnd(20 + i);
449 strike = (tmp > dieroll);
450 /* KMH -- don't accumulate to-hit bonuses */
452 tmp -= hitval(otmp, mdef);
454 res[i] = hitmm(magr, mdef, mattk);
455 if ((mdef->data == &mons[PM_BLACK_PUDDING]
456 || mdef->data == &mons[PM_BROWN_PUDDING])
457 && (otmp && (objects[otmp->otyp].oc_material == IRON
458 || objects[otmp->otyp].oc_material == METAL))
459 && mdef->mhp > 1 && !mdef->mcan) {
460 struct monst *mclone;
462 if ((mclone = clone_mon(mdef, 0, 0)) != 0) {
463 if (vis && canspotmon(mdef)) {
466 Strcpy(buf, Monnam(mdef));
468 pline("%s divides as %s hits it!", buf,
471 pline("%s
\82Ì
\8dU
\8c\82\82Å%s
\82ª
\95ª
\97ô
\82µ
\82½
\81I",
479 missmm(magr, mdef, mattk);
482 case AT_HUGS: /* automatic if prev two attacks succeed */
483 strike = (i >= 2 && res[i - 1] == MM_HIT && res[i - 2] == MM_HIT);
485 res[i] = hitmm(magr, mdef, mattk);
491 res[i] = gazemm(magr, mdef, mattk);
495 /* D: Prevent explosions from a distance */
496 if (distmin(magr->mx,magr->my,mdef->mx,mdef->my) > 1)
499 res[i] = explmm(magr, mdef, mattk);
500 if (res[i] == MM_MISS) { /* cancelled--no attack */
504 strike = 1; /* automatic hit */
508 if (mdef->data == &mons[PM_SHADE]) { /* no silver teeth... */
511 pline("%s attempt to engulf %s is futile.",
512 s_suffix(Monnam(magr)), mon_nam(mdef));
514 pline("%s
\82Í%s
\82ð
\88ù
\82Ý
\8d\9e\82à
\82¤
\82Æ
\82µ
\82½
\82ª
\82Þ
\82¾
\82¾
\82Á
\82½
\81D",
515 Monnam(magr), mon_nam(mdef));
520 if (u.usteed && mdef == u.usteed) {
524 /* D: Prevent engulf from a distance */
525 if (distmin(magr->mx, magr->my, mdef->mx, mdef->my) > 1)
527 /* Engulfing attacks are directed at the hero if possible. -dlc */
528 if (u.uswallow && magr == u.ustuck)
530 else if ((strike = (tmp > rnd(20 + i))) != 0)
531 res[i] = gulpmm(magr, mdef, mattk);
533 missmm(magr, mdef, mattk);
537 if (!monnear(magr, mdef->mx, mdef->my)) {
538 strike = breamm(magr, mattk, mdef);
540 /* We don't really know if we hit or not; pretend we did. */
543 if (DEADMONSTER(mdef))
544 res[i] = MM_DEF_DIED;
545 if (DEADMONSTER(magr))
546 res[i] |= MM_AGR_DIED;
553 if (!monnear(magr, mdef->mx, mdef->my)) {
554 strike = spitmm(magr, mattk, mdef);
556 /* We don't really know if we hit or not; pretend we did. */
559 if (DEADMONSTER(mdef))
560 res[i] = MM_DEF_DIED;
561 if (DEADMONSTER(magr))
562 res[i] |= MM_AGR_DIED;
566 default: /* no attack */
572 if (attk && !(res[i] & MM_AGR_DIED)
573 && distmin(magr->mx, magr->my, mdef->mx, mdef->my) <= 1)
574 res[i] = passivemm(magr, mdef, strike, res[i] & MM_DEF_DIED);
576 if (res[i] & MM_DEF_DIED)
578 if (res[i] & MM_AGR_DIED)
580 /* return if aggressor can no longer attack */
581 if (!magr->mcanmove || magr->msleeping)
584 struck = 1; /* at least one hit */
587 return (struck ? MM_HIT : MM_MISS);
590 /* Returns the result of mdamagem(). */
592 hitmm(magr, mdef, mattk)
593 register struct monst *magr, *mdef;
594 struct attack *mattk;
596 boolean weaponhit = ((mattk->aatyp == AT_WEAP
597 || (mattk->aatyp == AT_CLAW && otmp))),
598 silverhit = (weaponhit && otmp
599 && objects[otmp->otyp].oc_material == SILVER),
602 /* unhiding or unmimicking happens even if hero can't see it
603 because the formerly concealed monster is now in action */
604 if (M_AP_TYPE(mdef)) {
607 } else if (mdef->mundetected) {
608 mdef->mundetected = 0;
611 if (M_AP_TYPE(magr)) {
614 } else if (magr->mundetected) {
615 magr->mundetected = 0;
623 if (!canspotmon(magr))
624 map_invisible(magr->mx, magr->my);
626 newsym(magr->mx, magr->my);
627 if (!canspotmon(mdef))
628 map_invisible(mdef->mx, mdef->my);
630 newsym(mdef->mx, mdef->my);
632 if ((compat = could_seduce(magr, mdef, mattk)) && !magr->mcan) {
634 Sprintf(buf, "%s %s", Monnam(magr),
635 mdef->mcansee ? "smiles at" : "talks to");
636 pline("%s %s %s.", buf, mon_nam(mdef),
637 compat == 2 ? "engagingly" : "seductively");
639 Sprintf(buf, "%s
\82Í%%s
\82É%%s%s
\81D", Monnam(magr),
640 mdef->mcansee ? "
\94÷
\8fÎ
\82Ý
\82©
\82¯
\82½" : "
\98b
\82µ
\82©
\82¯
\82½");
641 pline(buf, mon_nam(mdef),
642 compat == 2 ? "
\96£
\97Í
\93I
\82É" : "
\97U
\98f
\93I
\82É");
644 } else if (shade_miss(magr, mdef, otmp, FALSE, TRUE)) {
645 return MM_MISS; /* bypass mdamagem() */
647 char magr_name[BUFSZ];
649 Strcpy(magr_name, Monnam(magr));
650 switch (mattk->aatyp) {
653 Sprintf(buf, "%s bites", magr_name);
655 Sprintf(buf,"%s
\82Í%%s
\82É
\8a\9a\82Ý
\82Â
\82¢
\82½
\81D", magr_name);
659 Sprintf(buf, "%s stings", magr_name);
661 Sprintf(buf,"%s
\82Í%%s
\82ð
\93Ë
\82«
\82³
\82µ
\82½
\81D", magr_name);
665 Sprintf(buf, "%s butts", magr_name);
667 Sprintf(buf,"%s
\82Í%%s
\82É
\93ª
\93Ë
\82«
\82ð
\82
\82ç
\82í
\82µ
\82½
\81D", magr_name);
671 Sprintf(buf, "%s touches", magr_name);
673 Sprintf(buf,"%s
\82Í%%s
\82É
\90G
\82ê
\82½
\81D", magr_name);
677 Sprintf(buf, "%s tentacles suck", s_suffix(magr_name));
679 Sprintf(buf, "%s
\82Ì
\90G
\8eè
\82ª%%s
\82Ì
\91Ì
\89t
\82ð
\8bz
\82¢
\82Æ
\82Á
\82½
\81D", magr_name);
682 if (magr != u.ustuck) {
684 Sprintf(buf, "%s squeezes", magr_name);
686 Sprintf(buf,"%s
\82Í%%s
\82ð
\8di
\82ß
\82½
\81D", magr_name);
692 Sprintf(buf, "%s hits", magr_name);
694 Sprintf(buf, "%s
\82Ì%%s
\82Ö
\82Ì
\8dU
\8c\82\82Í
\96½
\92\86\82µ
\82½
\81D", magr_name);
697 pline("%s %s.", buf, mon_nam_too(mdef, magr));
699 pline(buf, mon_nam_too(mdef, magr));
702 if (mon_hates_silver(mdef) && silverhit) {
703 char *mdef_name = mon_nam_too(mdef, magr);
705 /* note: mon_nam_too returns a modifiable buffer; so
706 does s_suffix, but it returns a single static buffer
707 and we might be calling it twice for this message */
708 Strcpy(magr_name, s_suffix(magr_name));
709 if (!noncorporeal(mdef->data) && !amorphous(mdef->data)) {
711 mdef_name = s_suffix(mdef_name);
713 (void) strsubst(mdef_name, "himself", "his own");
714 (void) strsubst(mdef_name, "herself", "her own");
715 (void) strsubst(mdef_name, "itself", "its own");
718 Strcat(mdef_name, " flesh");
720 Strcat(mdef_name, "
\82Ì
\93÷");
724 pline("%s %s sears %s!", magr_name, /*s_suffix(magr_name), */
725 simpleonames(otmp), mdef_name);
727 pline("%s
\82Ì%s
\82ª%s
\82ð
\8fÄ
\82¢
\82½
\81I", magr_name, /*s_suffix(magr_name), */
728 simpleonames(otmp), mdef_name);
735 return mdamagem(magr, mdef, mattk);
738 /* Returns the same values as mdamagem(). */
740 gazemm(magr, mdef, mattk)
741 register struct monst *magr, *mdef;
742 struct attack *mattk;
747 if (mdef->data->mlet == S_MIMIC
748 && M_AP_TYPE(mdef) != M_AP_NOTHING)
751 Sprintf(buf, "%s gazes at", Monnam(magr));
752 pline("%s %s...", buf,
753 canspotmon(mdef) ? mon_nam(mdef) : "something");
755 Sprintf(buf, "%s
\82Í%%s
\82ð
\82É
\82ç
\82Ý
\82Â
\82¯
\82½
\81D
\81D
\81D", Monnam(magr));
756 pline(buf, canspotmon(mdef) ? mon_nam(mdef) : "
\89½
\82©");
760 if (magr->mcan || !magr->mcansee || !mdef->mcansee
761 || (magr->minvis && !perceives(mdef->data)) || mdef->msleeping) {
762 if (vis && canspotmon(mdef))
764 pline("but nothing happens.");
766 pline("
\82µ
\82©
\82µ
\89½
\82à
\82¨
\82±
\82ç
\82È
\82©
\82Á
\82½
\81D");
769 /* call mon_reflects 2x, first test, then, if visible, print message */
770 if (magr->data == &mons[PM_MEDUSA] && mon_reflects(mdef, (char *) 0)) {
773 (void) mon_reflects(mdef, "The gaze is reflected away by %s %s.");
775 (void) mon_reflects(mdef, "
\82É
\82ç
\82Ý
\82Í%s
\82Ì%s
\82Å
\94½
\8eË
\82µ
\82½
\81D");
777 if (mon_reflects(magr, (char *) 0)) {
780 (void) mon_reflects(magr,
781 "The gaze is reflected away by %s %s.");
783 (void) mon_reflects(magr,
784 "
\82É
\82ç
\82Ý
\82Í%s
\82Ì%s
\82Å
\94½
\8eË
\82µ
\82½
\81D");
788 if (mdef->minvis && !perceives(magr->data)) {
789 if (canseemon(magr)) {
792 "%s doesn't seem to notice that %s gaze was reflected.",
793 Monnam(magr), mhis(magr));
795 pline("
\82É
\82ç
\82Ý
\82ª
\94½
\8eË
\82µ
\82Ä
\82¢
\82é
\82±
\82Æ
\82É%s
\82Í
\8bC
\95t
\82¢
\82Ä
\82¢
\82È
\82¢
\82æ
\82¤
\82¾
\81D",
803 pline("%s is turned to stone!", Monnam(magr));
805 pline("%s
\82Í
\90Î
\82É
\82È
\82Á
\82½
\81I", Monnam(magr));
807 if (!DEADMONSTER(magr))
813 return mdamagem(magr, mdef, mattk);
816 /* return True if magr is allowed to swallow mdef, False otherwise */
818 engulf_target(magr, mdef)
819 struct monst *magr, *mdef;
824 /* can't swallow something that's too big */
825 if (mdef->data->msize >= MZ_HUGE)
828 /* (hypothetical) engulfers who can pass through walls aren't
829 limited by rock|trees|bars */
830 if ((magr == &youmonst) ? Passes_walls : passes_walls(magr->data))
833 /* don't swallow something in a spot where attacker wouldn't
834 otherwise be able to move onto; we don't want to engulf
835 a wall-phaser and end up with a non-phaser inside a wall */
836 dx = mdef->mx, dy = mdef->my;
837 if (mdef == &youmonst)
838 dx = u.ux, dy = u.uy;
840 if (IS_ROCK(lev->typ) || closed_door(dx, dy) || IS_TREE(lev->typ)
841 /* not passes_bars(); engulfer isn't squeezing through */
842 || (lev->typ == IRONBARS && !is_whirly(magr->data)))
848 /* Returns the same values as mattackm(). */
850 gulpmm(magr, mdef, mattk)
851 register struct monst *magr, *mdef;
852 register struct attack *mattk;
854 xchar ax, ay, dx, dy;
859 if (!engulf_target(magr, mdef))
863 /* [this two-part formatting dates back to when only one x_monnam
864 result could be included in an expression because the next one
865 would overwrite first's result -- that's no longer the case] */
867 Sprintf(buf, "%s swallows", Monnam(magr));
868 pline("%s %s.", buf, mon_nam(mdef));
870 Sprintf(buf, "%s
\82Í%%s
\82ð
\82®
\82Á
\82Æ
\88ù
\82Ý
\82±
\82ñ
\82¾
\81D", Monnam(magr));
871 pline(buf, mon_nam(mdef));
874 for (obj = mdef->minvent; obj; obj = obj->nobj)
875 (void) snuff_lit(obj);
877 if (is_vampshifter(mdef)
878 && newcham(mdef, &mons[mdef->cham], FALSE, FALSE)) {
880 /* 'it' -- previous form is no longer available and
881 using that would be excessively verbose */
883 pline("%s expels %s.", Monnam(magr),
884 canspotmon(mdef) ? "it" : something);
886 pline("%s
\82Í%s
\82ð
\93f
\82«
\8fo
\82µ
\82½
\81D", Monnam(magr),
887 canspotmon(mdef) ? "
\89½
\82©" : something);
889 if (canspotmon(mdef))
891 pline("It turns into %s.", a_monnam(mdef));
893 pline("
\82»
\82ê
\82Í%s
\82É
\82È
\82Á
\82½
\81D", a_monnam(mdef));
895 return MM_HIT; /* bypass mdamagem() */
899 * All of this manipulation is needed to keep the display correct.
900 * There is a flush at the next pline().
907 * Leave the defender in the monster chain at it's current position,
908 * but don't leave it on the screen. Move the aggressor to the
909 * defender's position.
911 remove_monster(dx, dy);
912 remove_monster(ax, ay);
913 place_monster(magr, dx, dy);
914 newsym(ax, ay); /* erase old position */
915 newsym(dx, dy); /* update new position */
917 status = mdamagem(magr, mdef, mattk);
919 if ((status & (MM_AGR_DIED | MM_DEF_DIED))
920 == (MM_AGR_DIED | MM_DEF_DIED)) {
921 ; /* both died -- do nothing */
922 } else if (status & MM_DEF_DIED) { /* defender died */
924 * Note: remove_monster() was called in relmon(), wiping out
925 * magr from level.monsters[mdef->mx][mdef->my]. We need to
926 * put it back and display it. -kd
928 place_monster(magr, dx, dy);
930 /* aggressor moves to <dx,dy> and might encounter trouble there */
931 if (minliquid(magr) || (t_at(dx, dy) && mintrap(magr) == 2))
932 status |= MM_AGR_DIED;
933 } else if (status & MM_AGR_DIED) { /* aggressor died */
934 place_monster(mdef, dx, dy);
936 } else { /* both alive, put them back */
939 pline("%s is regurgitated!", Monnam(mdef));
941 pline("%s
\82Í
\93f
\82«
\96ß
\82³
\82ê
\82½
\81I", Monnam(mdef));
943 remove_monster(dx,dy);
944 place_monster(magr, ax, ay);
945 place_monster(mdef, dx, dy);
954 explmm(magr, mdef, mattk)
955 struct monst *magr, *mdef;
956 struct attack *mattk;
963 if (cansee(magr->mx, magr->my))
965 pline("%s explodes!", Monnam(magr));
967 pline("%s
\82Í
\94\9a\94
\82µ
\82½
\81I", Monnam(magr));
971 result = mdamagem(magr, mdef, mattk);
973 /* Kill off aggressor if it didn't die. */
974 if (!(result & MM_AGR_DIED)) {
975 boolean was_leashed = (magr->mleashed != 0);
978 if (!DEADMONSTER(magr))
979 return result; /* life saved */
980 result |= MM_AGR_DIED;
982 /* mondead() -> m_detach() -> m_unleash() always suppresses
983 the m_unleash() slack message, so deliver it here instead */
986 Your("leash falls slack.");
988 Your("
\95R
\82ª
\82½
\82é
\82ñ
\82Å
\97\8e\82¿
\82½
\81D");
990 if (magr->mtame) /* give this one even if it was visible */
992 You(brief_feeling, "melancholy");
994 You(brief_feeling, "
\97J
\82¤
\82Â
\82È");
1000 * See comment at top of mattackm(), for return values.
1003 mdamagem(magr, mdef, mattk)
1004 register struct monst *magr, *mdef;
1005 register struct attack *mattk;
1009 struct permonst *pa = magr->data, *pd = mdef->data;
1011 tmp = d((int) mattk->damn, (int) mattk->damd),
1015 if ((touch_petrifies(pd) /* or flesh_petrifies() */
1016 || (mattk->adtyp == AD_DGST && pd == &mons[PM_MEDUSA]))
1017 && !resists_ston(magr)) {
1018 long protector = attk_protection((int) mattk->aatyp),
1019 wornitems = magr->misc_worn_check;
1021 /* wielded weapon gives same protection as gloves here */
1023 wornitems |= W_ARMG;
1026 || (protector != ~0L && (wornitems & protector) != protector)) {
1027 if (poly_when_stoned(pa)) {
1029 return MM_HIT; /* no damage during the polymorph */
1031 if (vis && canspotmon(magr))
1033 pline("%s turns to stone!", Monnam(magr));
1035 pline("%s
\82Í
\90Î
\82É
\82È
\82Á
\82½
\81I", Monnam(magr));
1037 if (!DEADMONSTER(magr))
1038 return MM_HIT; /* lifesaved */
1039 else if (magr->mtame && !vis)
1041 You(brief_feeling, "peculiarly sad");
1043 You(brief_feeling, "
\82à
\82Ì
\94ß
\82µ
\82¢");
1048 /* cancellation factor is the same as when attacking the hero */
1049 armpro = magic_negation(mdef);
1050 cancelled = magr->mcan || !(rn2(10) >= 3 * armpro);
1052 switch (mattk->adtyp) {
1054 /* eating a Rider or its corpse is fatal */
1056 if (vis && canseemon(magr))
1058 pline("%s %s!", Monnam(magr),
1059 (pd == &mons[PM_FAMINE])
1060 ? "belches feebly, shrivels up and dies"
1061 : (pd == &mons[PM_PESTILENCE])
1062 ? "coughs spasmodically and collapses"
1063 : "vomits violently and drops dead");
1065 pline("%s%s
\81I", Monnam(magr),
1066 (pd == &mons[PM_FAMINE])
1067 ? "
\8eã
\81X
\82µ
\82
\93f
\82«
\82à
\82Ç
\82µ
\82½
\82©
\82Æ
\8ev
\82¤
\82Æ
\81C
\91Ì
\82ª
\82µ
\82Ú
\82Ý
\8e\80\82ñ
\82Å
\82µ
\82Ü
\82Á
\82½"
1068 : (pd == &mons[PM_PESTILENCE])
1069 ? "áz
\9d¹
\82µ
\82½
\82æ
\82¤
\82É
\82¹
\82«
\82±
\82Ý
\93|
\82ê
\82½"
1070 : "
\8c\83\82µ
\82
\9aq
\93f
\82µ
\8e\80\82ñ
\82¾");
1073 if (!DEADMONSTER(magr))
1074 return 0; /* lifesaved */
1075 else if (magr->mtame && !vis)
1077 You(brief_feeling, "queasy");
1079 You(brief_feeling, "
\95s
\88À
\82È");
1082 if (flags.verbose && !Deaf)
1084 verbalize("Burrrrp!");
1086 verbalize("
\82°
\82Á
\82Õ
\81I");
1088 /* Use up amulet of life saving */
1089 if (!!(obj = mlifesaver(mdef)))
1092 /* Is a corpse for nutrition possible? It may kill magr */
1093 if (!corpse_chance(mdef, magr, TRUE) || DEADMONSTER(magr))
1096 /* Pets get nutrition from swallowing monster whole.
1097 * No nutrition from G_NOCORPSE monster, eg, undead.
1098 * DGST monsters don't die from undead corpses
1101 if (magr->mtame && !magr->isminion
1102 && !(mvitals[num].mvflags & G_NOCORPSE)) {
1103 struct obj *virtualcorpse = mksobj(CORPSE, FALSE, FALSE);
1106 set_corpsenm(virtualcorpse, num);
1107 nutrit = dog_nutrition(magr, virtualcorpse);
1108 dealloc_obj(virtualcorpse);
1110 /* only 50% nutrition, 25% of normal eating time */
1111 if (magr->meating > 1)
1112 magr->meating = (magr->meating + 3) / 4;
1115 EDOG(magr)->hungrytime += nutrit;
1121 if (canseemon(mdef))
1123 pline("%s %s for a moment.", Monnam(mdef),
1124 makeplural(stagger(pd, "stagger")));
1126 pline("%s
\82Í
\82·
\82±
\82µ%s
\81D", Monnam(mdef),
1127 jpast(stagger(pd, "
\82æ
\82ë
\82ß
\82")));
1141 obj = (mattk->aatyp == AT_WEAP || mattk->aatyp == AT_CLAW) ? otmp : 0;
1142 if (shade_miss(magr, mdef, obj, FALSE, TRUE)) {
1144 } else if (mattk->aatyp == AT_KICK && thick_skinned(pd)) {
1146 } else if (mattk->aatyp == AT_WEAP
1147 || (mattk->aatyp == AT_CLAW && otmp)) {
1151 if (otmp->otyp == CORPSE
1152 && touch_petrifies(&mons[otmp->corpsenm]))
1155 tmp += dmgval(otmp, mdef);
1156 if ((marmg = which_armor(magr, W_ARMG)) != 0
1157 && marmg->otyp == GAUNTLETS_OF_POWER)
1158 tmp += rn1(4, 3); /* 3..6 */
1159 if (tmp < 1) /* is this necessary? mhitu.c has it... */
1161 if (otmp->oartifact) {
1162 (void) artifact_hit(magr, mdef, otmp, &tmp, dieroll);
1163 if (DEADMONSTER(mdef))
1165 | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
1170 } else if (pa == &mons[PM_PURPLE_WORM] && pd == &mons[PM_SHRIEKER]) {
1171 /* hack to enhance mm_aggression(); we don't want purple
1172 worm's bite attack to kill a shrieker because then it
1173 won't swallow the corpse; but if the target survives,
1174 the subsequent engulf attack should accomplish that */
1175 if (tmp >= mdef->mhp && mdef->mhp > 1)
1176 tmp = mdef->mhp - 1;
1184 if (vis && canseemon(mdef))
1186 pline("%s is %s!", Monnam(mdef), on_fire(pd, mattk));
1188 pline("%s
\82Í%s
\81I", Monnam(mdef), on_fire(pd, mattk));
1189 if (completelyburns(pd)) { /* paper golem or straw golem */
1190 if (vis && canseemon(mdef))
1192 pline("%s burns completely!", Monnam(mdef));
1194 pline("%s
\82Í
\8aD
\82É
\82È
\82Á
\82½
\81I", Monnam(mdef));
1195 mondead(mdef); /* was mondied() but that dropped paper scrolls */
1196 if (!DEADMONSTER(mdef))
1198 else if (mdef->mtame && !vis)
1200 pline("May %s roast in peace.", mon_nam(mdef));
1202 pline("%s
\82æ
\81C
\88À
\82ç
\82©
\82É
\94R
\82¦
\82ñ
\8e\96\82ð
\81D", mon_nam(mdef));
1203 return (MM_DEF_DIED | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
1205 tmp += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
1206 tmp += destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
1207 if (resists_fire(mdef)) {
1208 if (vis && canseemon(mdef))
1210 pline_The("fire doesn't seem to burn %s!", mon_nam(mdef));
1212 pline("%s
\82Í
\89\8a\82Å
\94R
\82¦
\82È
\82¢
\82æ
\82¤
\82¾
\81I", mon_nam(mdef));
1213 shieldeff(mdef->mx, mdef->my);
1214 golemeffects(mdef, AD_FIRE, tmp);
1217 /* only potions damage resistant players in destroy_item */
1218 tmp += destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
1225 if (vis && canseemon(mdef))
1227 pline("%s is covered in frost!", Monnam(mdef));
1229 pline("%s
\82Í
\95X
\82Å
\95¢
\82í
\82ê
\82½
\81I", Monnam(mdef));
1230 if (resists_cold(mdef)) {
1231 if (vis && canseemon(mdef))
1233 pline_The("frost doesn't seem to chill %s!", mon_nam(mdef));
1235 pline("
\95X
\82Í%s
\82ð
\93\80\82ç
\82¹
\82é
\82±
\82Æ
\82ª
\82Å
\82«
\82È
\82¢
\82æ
\82¤
\82¾
\81I", mon_nam(mdef));
1236 shieldeff(mdef->mx, mdef->my);
1237 golemeffects(mdef, AD_COLD, tmp);
1240 tmp += destroy_mitem(mdef, POTION_CLASS, AD_COLD);
1247 if (vis && canseemon(mdef))
1249 pline("%s gets zapped!", Monnam(mdef));
1251 pline("%s
\82Í
\8fÕ
\8c\82\82ð
\82
\82ç
\82Á
\82½
\81I", Monnam(mdef));
1252 tmp += destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
1253 if (resists_elec(mdef)) {
1254 if (vis && canseemon(mdef))
1256 pline_The("zap doesn't shock %s!", mon_nam(mdef));
1258 pline("
\8fÕ
\8c\82\82Í%s
\82É
\89e
\8b¿
\82ð
\97^
\82¦
\82È
\82¢
\81I", mon_nam(mdef));
1259 shieldeff(mdef->mx, mdef->my);
1260 golemeffects(mdef, AD_ELEC, tmp);
1263 /* only rings damage resistant players in destroy_item */
1264 tmp += destroy_mitem(mdef, RING_CLASS, AD_ELEC);
1271 if (resists_acid(mdef)) {
1272 if (vis && canseemon(mdef))
1274 pline("%s is covered in %s, but it seems harmless.",
1275 Monnam(mdef), hliquid("acid"));
1277 pline("%s
\82Í%s
\82É
\82Â
\82Â
\82Ü
\82ê
\82½
\81D
\82µ
\82©
\82µ
\82È
\82ñ
\82Æ
\82à
\82È
\82¢
\82æ
\82¤
\82¾
\81D",
1278 Monnam(mdef), hliquid("
\8e_"));
1281 } else if (vis && canseemon(mdef)) {
1283 pline("%s is covered in %s!", Monnam(mdef), hliquid("acid"));
1285 pline("%s
\82Í%s
\82É
\82Â
\82Â
\82Ü
\82ê
\82½
\81I", Monnam(mdef), hliquid("
\8e_"));
1287 pline("It burns %s!", mon_nam(mdef));
1289 pline("%s
\82Í
\8fÄ
\82©
\82ê
\82½
\81I", mon_nam(mdef));
1292 erode_armor(mdef, ERODE_CORRODE);
1294 acid_damage(MON_WEP(mdef));
1299 if (pd == &mons[PM_IRON_GOLEM]) {
1300 if (vis && canseemon(mdef))
1302 pline("%s falls to pieces!", Monnam(mdef));
1304 pline("%s
\82Í
\83o
\83\89\83o
\83\89\82É
\82È
\82Á
\82½
\81I", Monnam(mdef));
1306 if (!DEADMONSTER(mdef))
1308 else if (mdef->mtame && !vis)
1310 pline("May %s rust in peace.", mon_nam(mdef));
1312 pline("%s
\82æ
\81C
\88À
\82ç
\82©
\82É
\8eK
\82Ñ
\82ñ
\8e\96\82ð
\81D", mon_nam(mdef));
1313 return (MM_DEF_DIED | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
1315 erode_armor(mdef, ERODE_RUST);
1316 mdef->mstrategy &= ~STRAT_WAITFORU;
1322 erode_armor(mdef, ERODE_CORRODE);
1323 mdef->mstrategy &= ~STRAT_WAITFORU;
1329 if (pd == &mons[PM_WOOD_GOLEM] || pd == &mons[PM_LEATHER_GOLEM]) {
1330 if (vis && canseemon(mdef))
1332 pline("%s falls to pieces!", Monnam(mdef));
1334 pline("%s
\82Í
\83o
\83\89\83o
\83\89\82É
\82È
\82Á
\82½
\81I", Monnam(mdef));
1336 if (!DEADMONSTER(mdef))
1338 else if (mdef->mtame && !vis)
1340 pline("May %s rot in peace.", mon_nam(mdef));
1342 pline("%s
\82æ
\81C
\88À
\82ç
\82©
\82É
\95\85\82ç
\82ñ
\8e\96\82ð
\81D", mon_nam(mdef));
1343 return (MM_DEF_DIED | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
1345 erode_armor(mdef, ERODE_CORRODE);
1346 mdef->mstrategy &= ~STRAT_WAITFORU;
1353 /* may die from the acid if it eats a stone-curing corpse */
1354 if (munstone(mdef, FALSE))
1356 if (poly_when_stoned(pd)) {
1361 if (!resists_ston(mdef)) {
1362 if (vis && canseemon(mdef))
1364 pline("%s turns to stone!", Monnam(mdef));
1366 pline("%s
\82Í
\90Î
\82É
\82È
\82Á
\82½
\81I", Monnam(mdef));
1369 if (!DEADMONSTER(mdef))
1371 else if (mdef->mtame && !vis)
1373 You(brief_feeling, "peculiarly sad");
1375 You(brief_feeling, "
\82à
\82Ì
\94ß
\82µ
\82¢");
1376 return (MM_DEF_DIED | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
1378 tmp = (mattk->adtyp == AD_STON ? 0 : 1);
1381 if (!cancelled && tmp < mdef->mhp && !tele_restrict(mdef)) {
1382 char mdef_Monnam[BUFSZ];
1383 boolean wasseen = canspotmon(mdef);
1385 /* save the name before monster teleports, otherwise
1386 we'll get "it" in the suddenly disappears message */
1388 Strcpy(mdef_Monnam, Monnam(mdef));
1389 mdef->mstrategy &= ~STRAT_WAITFORU;
1390 (void) rloc(mdef, TRUE);
1391 if (vis && wasseen && !canspotmon(mdef) && mdef != u.usteed)
1393 pline("%s suddenly disappears!", mdef_Monnam);
1395 pline("%s
\82Í
\93Ë
\91R
\8fÁ
\82¦
\82½
\81I", mdef_Monnam);
1396 if (tmp >= mdef->mhp) { /* see hitmu(mhitu.c) */
1399 tmp = mdef->mhp - 1;
1404 if (!cancelled && !mdef->msleeping
1405 && sleep_monst(mdef, rnd(10), -1)) {
1406 if (vis && canspotmon(mdef)) {
1407 Strcpy(buf, Monnam(mdef));
1409 pline("%s is put to sleep by %s.", buf, mon_nam(magr));
1411 pline("%s
\82Í%s
\82É
\82æ
\82Á
\82Ä
\96°
\82ç
\82³
\82ê
\82½
\81D", buf, mon_nam(magr));
1413 mdef->mstrategy &= ~STRAT_WAITFORU;
1418 if (!cancelled && mdef->mcanmove) {
1419 if (vis && canspotmon(mdef)) {
1420 Strcpy(buf, Monnam(mdef));
1422 pline("%s is frozen by %s.", buf, mon_nam(magr));
1424 pline("%s
\82Í%s
\82É
\82æ
\82Á
\82Ä
\93®
\82¯
\82È
\82
\82È
\82Á
\82½
\81D", buf, mon_nam(magr));
1426 paralyze_monst(mdef, rnd(10));
1430 if (!cancelled && mdef->mspeed != MSLOW) {
1431 unsigned int oldspeed = mdef->mspeed;
1433 mon_adjust_speed(mdef, -1, (struct obj *) 0);
1434 mdef->mstrategy &= ~STRAT_WAITFORU;
1435 if (mdef->mspeed != oldspeed && vis && canspotmon(mdef))
1437 pline("%s slows down.", Monnam(mdef));
1439 pline("%s
\82Í
\93®
\8dì
\82ª
\82Ì
\82ë
\82
\82È
\82Á
\82½
\81D", Monnam(mdef));
1443 /* Since confusing another monster doesn't have a real time
1444 * limit, setting spec_used would not really be right (though
1445 * we still should check for it).
1447 if (!magr->mcan && !mdef->mconf && !magr->mspec_used) {
1448 if (vis && canseemon(mdef))
1450 pline("%s looks confused.", Monnam(mdef));
1452 pline("%s
\82Í
\8d¬
\97\90\82µ
\82Ä
\82¢
\82é
\82æ
\82¤
\82É
\8c©
\82¦
\82é
\81D", Monnam(mdef));
1454 mdef->mstrategy &= ~STRAT_WAITFORU;
1458 if (can_blnd(magr, mdef, mattk->aatyp, (struct obj *) 0)) {
1459 register unsigned rnd_tmp;
1461 if (vis && mdef->mcansee && canspotmon(mdef))
1463 pline("%s is blinded.", Monnam(mdef));
1465 pline("%s
\82Í
\96Ú
\82ª
\8c©
\82¦
\82È
\82
\82È
\82Á
\82½
\81D", Monnam(mdef));
1466 rnd_tmp = d((int) mattk->damn, (int) mattk->damd);
1467 if ((rnd_tmp += mdef->mblinded) > 127)
1469 mdef->mblinded = rnd_tmp;
1471 mdef->mstrategy &= ~STRAT_WAITFORU;
1476 if (!magr->mcan && haseyes(pd) && mdef->mcansee) {
1477 if (vis && canseemon(mdef))
1479 pline("%s looks %sconfused.", Monnam(mdef),
1480 mdef->mconf ? "more " : "");
1482 pline("%s
\82Í%s
\8d¬
\97\90\82µ
\82Ä
\82¢
\82é
\82æ
\82¤
\82É
\8c©
\82¦
\82é
\81D", Monnam(mdef),
1483 mdef->mconf ? "
\82Ü
\82·
\82Ü
\82·" : "");
1486 mdef->mstrategy &= ~STRAT_WAITFORU;
1491 if (!night() && (pa == &mons[PM_GREMLIN]))
1493 if (!magr->mcan && !rn2(10)) {
1494 mdef->mcan = 1; /* cancelled regardless of lifesave */
1495 mdef->mstrategy &= ~STRAT_WAITFORU;
1496 if (is_were(pd) && pd->mlet != S_HUMAN)
1498 if (pd == &mons[PM_CLAY_GOLEM]) {
1499 if (vis && canseemon(mdef)) {
1501 pline("Some writing vanishes from %s head!",
1502 s_suffix(mon_nam(mdef)));
1504 pline("
\82¢
\82
\82Â
\82©
\82Ì
\95¶
\8e\9a\82ª%s
\82Ì
\93ª
\82©
\82ç
\8fÁ
\82¦
\82½
\81I",
1508 pline("%s is destroyed!", Monnam(mdef));
1510 pline("%s
\82Í
\94j
\89ó
\82³
\82ê
\82½
\81I", Monnam(mdef));
1513 if (!DEADMONSTER(mdef))
1515 else if (mdef->mtame && !vis)
1517 You(brief_feeling, "strangely sad");
1519 You(brief_feeling, "
\96
\82É
\94ß
\82µ
\82¢");
1521 | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
1526 You_hear("laughter.");
1528 You_hear("
\8fÎ
\82¢
\90º
\82ð
\95·
\82¢
\82½
\81D");
1529 else if (canseemon(magr))
1531 pline("%s chuckles.", Monnam(magr));
1533 pline("%s
\82Í
\82
\82·
\82
\82·
\8fÎ
\82Á
\82½
\81D", Monnam(magr));
1541 /* technically incorrect; no check for stealing gold from
1542 * between mdef's feet...
1545 struct obj *gold = findgold(mdef->minvent);
1549 obj_extract_self(gold);
1550 add_to_minv(magr, gold);
1552 mdef->mstrategy &= ~STRAT_WAITFORU;
1553 if (vis && canseemon(mdef)) {
1554 Strcpy(buf, Monnam(magr));
1556 pline("%s steals some gold from %s.", buf, mon_nam(mdef));
1558 pline("%s
\82Í%s
\82©
\82ç
\8bà
\82ð
\93\90\82ñ
\82¾
\81D", buf, mon_nam(mdef));
1560 if (!tele_restrict(magr)) {
1561 boolean couldspot = canspotmon(magr);
1562 (void) rloc(magr, TRUE);
1563 if (vis && couldspot && !canspotmon(magr))
1565 pline("%s suddenly disappears!", buf);
1567 pline("%s
\82Í
\93Ë
\91R
\8fÁ
\82¦
\82½
\81I", buf);
1571 if (!cancelled && !rn2(3) && !resists_drli(mdef)) {
1573 if (vis && canspotmon(mdef))
1575 pline("%s suddenly seems weaker!", Monnam(mdef));
1577 pline("%s
\82Í
\93Ë
\91R
\8eã
\82
\82È
\82Á
\82½
\82æ
\82¤
\82É
\8c©
\82¦
\82½
\81I", Monnam(mdef));
1578 mdef->mhpmax -= tmp;
1579 if (mdef->m_lev == 0)
1583 /* Automatic kill if drained past level 0 */
1587 case AD_SITM: /* for now these are the same */
1591 /* find an object to steal, non-cursed if magr is tame */
1592 for (obj = mdef->minvent; obj; obj = obj->nobj)
1593 if (!magr->mtame || !obj->cursed)
1597 char onambuf[BUFSZ], mdefnambuf[BUFSZ];
1599 /* make a special x_monnam() call that never omits
1600 the saddle, and save it for later messages */
1602 x_monnam(mdef, ARTICLE_THE, (char *) 0, 0, FALSE));
1605 if (u.usteed == mdef && otmp == which_armor(mdef, W_SADDLE))
1606 /* "You can no longer ride <steed>." */
1607 dismount_steed(DISMOUNT_POLY);
1608 obj_extract_self(otmp);
1609 if (otmp->owornmask) {
1610 mdef->misc_worn_check &= ~otmp->owornmask;
1611 if (otmp->owornmask & W_WEP)
1613 otmp->owornmask = 0L;
1614 update_mon_intrinsics(mdef, otmp, FALSE, FALSE);
1615 /* give monster a chance to wear other equipment on its next
1616 move instead of waiting until it picks something up */
1617 mdef->misc_worn_check |= I_SPECIAL;
1619 /* add_to_minv() might free otmp [if it merges] */
1621 Strcpy(onambuf, doname(otmp));
1622 (void) add_to_minv(magr, otmp);
1623 if (vis && canseemon(mdef)) {
1624 Strcpy(buf, Monnam(magr));
1626 pline("%s steals %s from %s!", buf, onambuf, mdefnambuf);
1628 pline("%s
\82Í%s
\82©
\82ç%s
\82ð
\93\90\82ñ
\82¾
\81I", buf, mdefnambuf, onambuf);
1630 possibly_unwield(mdef, FALSE);
1631 mdef->mstrategy &= ~STRAT_WAITFORU;
1632 mselftouch(mdef, (const char *) 0, FALSE);
1633 if (DEADMONSTER(mdef))
1635 | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
1636 if (pa->mlet == S_NYMPH && !tele_restrict(magr)) {
1637 boolean couldspot = canspotmon(magr);
1639 (void) rloc(magr, TRUE);
1640 if (vis && couldspot && !canspotmon(magr))
1642 pline("%s suddenly disappears!", buf);
1644 pline("%s
\82Í
\93Ë
\91R
\8fÁ
\82¦
\82½
\81I", buf);
1650 if (!cancelled && !rn2(4))
1651 xdrainenergym(mdef, (boolean) (vis && canspotmon(mdef)
1652 && mattk->aatyp != AT_ENGL));
1658 if (!cancelled && !rn2(8)) {
1659 if (vis && canspotmon(magr))
1661 pline("%s %s was poisoned!", s_suffix(Monnam(magr)),
1662 mpoisons_subj(magr, mattk));
1664 pline("%s
\82Ì%s
\82Í
\93Å
\82³
\82ê
\82Ä
\82¢
\82é
\81I", Monnam(magr),
1665 mpoisons_subj(magr, mattk));
1667 if (resists_poison(mdef)) {
1668 if (vis && canspotmon(mdef) && canspotmon(magr))
1670 pline_The("poison doesn't seem to affect %s.",
1672 pline("%s
\82Í
\93Å
\82Ì
\89e
\8b¿
\82ð
\8eó
\82¯
\82È
\82¢
\81D",
1678 if (vis && canspotmon(mdef))
1680 pline_The("poison was deadly...");
1682 pline("
\93Å
\82Í
\92v
\8e\80\97Ê
\82¾
\82Á
\82½
\81D
\81D
\81D");
1689 if (notonhead || !has_head(pd)) {
1690 if (vis && canspotmon(mdef))
1692 pline("%s doesn't seem harmed.", Monnam(mdef));
1694 pline("%s
\82Í
\8f\9d\82Â
\82¢
\82½
\82æ
\82¤
\82É
\82Í
\8c©
\82¦
\82È
\82¢
\81D", Monnam(mdef));
1695 /* Not clear what to do for green slimes */
1699 if ((mdef->misc_worn_check & W_ARMH) && rn2(8)) {
1700 if (vis && canspotmon(magr) && canseemon(mdef)) {
1701 Strcpy(buf, s_suffix(Monnam(mdef)));
1703 pline("%s helmet blocks %s attack to %s head.", buf,
1704 s_suffix(mon_nam(magr)), mhis(mdef));
1706 pline("%s
\82Ì
\8a\95\82Í%s
\82Ì
\93ª
\82Ö
\82Ì
\8dU
\8c\82\82ð
\96h
\82¢
\82¾
\81D", buf,
1712 res = eat_brains(magr, mdef, vis, &tmp);
1716 break; /* physical damage only */
1717 if (!rn2(4) && !slimeproof(pd)) {
1718 if (!munslime(mdef, FALSE) && !DEADMONSTER(mdef)) {
1719 if (newcham(mdef, &mons[PM_GREEN_SLIME], FALSE,
1720 (boolean) (vis && canseemon(mdef))))
1722 mdef->mstrategy &= ~STRAT_WAITFORU;
1725 /* munslime attempt could have been fatal,
1726 potentially to multiple monsters (SCR_FIRE) */
1727 if (DEADMONSTER(magr))
1729 if (DEADMONSTER(mdef))
1738 case AD_WRAP: /* monsters cannot grab one another, it's too hard */
1743 /* there's no msomearmor() function, so just do damage */
1744 /* if (cancelled) break; */
1753 if ((mdef->mhp -= tmp) < 1) {
1754 if (m_at(mdef->mx, mdef->my) == magr) { /* see gulpmm() */
1755 remove_monster(mdef->mx, mdef->my);
1756 mdef->mhp = 1; /* otherwise place_monster will complain */
1757 place_monster(mdef, mdef->mx, mdef->my);
1760 monkilled(mdef, "", (int) mattk->adtyp);
1761 if (!DEADMONSTER(mdef))
1762 return res; /* mdef lifesaved */
1763 else if (res == MM_AGR_DIED)
1764 return (MM_DEF_DIED | MM_AGR_DIED);
1766 if (mattk->adtyp == AD_DGST) {
1767 /* various checks similar to dog_eat and meatobj.
1768 * after monkilled() to provide better message ordering */
1769 if (mdef->cham >= LOW_PM) {
1770 (void) newcham(magr, (struct permonst *) 0, FALSE, TRUE);
1771 } else if (pd == &mons[PM_GREEN_SLIME] && !slimeproof(pa)) {
1772 (void) newcham(magr, &mons[PM_GREEN_SLIME], FALSE, TRUE);
1773 } else if (pd == &mons[PM_WRAITH]) {
1774 (void) grow_up(magr, (struct monst *) 0);
1775 /* don't grow up twice */
1776 return (MM_DEF_DIED | (!DEADMONSTER(magr) ? 0 : MM_AGR_DIED));
1777 } else if (pd == &mons[PM_NURSE]) {
1778 magr->mhp = magr->mhpmax;
1781 /* caveat: above digestion handling doesn't keep `pa' up to date */
1783 return (MM_DEF_DIED | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
1785 return (res == MM_AGR_DIED) ? MM_AGR_DIED : MM_HIT;
1789 paralyze_monst(mon, amt)
1798 mon->meating = 0; /* terminate any meal-in-progress */
1799 mon->mstrategy &= ~STRAT_WAITFORU;
1802 /* `mon' is hit by a sleep attack; return 1 if it's affected, 0 otherwise */
1804 sleep_monst(mon, amt, how)
1808 if (resists_sleep(mon)
1809 || (how >= 0 && resist(mon, (char) how, 0, NOTELL))) {
1810 shieldeff(mon->mx, mon->my);
1811 } else if (mon->mcanmove) {
1812 finish_meating(mon); /* terminate any meal-in-progress */
1813 amt += (int) mon->mfrozen;
1814 if (amt > 0) { /* sleep for N turns */
1816 mon->mfrozen = min(amt, 127);
1817 } else { /* sleep until awakened */
1825 /* sleeping grabber releases, engulfer doesn't; don't use for paralysis! */
1830 if ((mon->msleeping || !mon->mcanmove) && mon == u.ustuck
1831 && !sticks(youmonst.data) && !u.uswallow) {
1833 pline("%s grip relaxes.", s_suffix(Monnam(mon)));
1835 pline("%s
\82Ì
\88¬
\82é
\97Í
\82ª
\8eã
\82
\82È
\82Á
\82½
\81D", Monnam(mon));
1845 int dmgtyp = -1, chance = 1;
1848 return; /* just in case */
1849 /* AD_ACID and AD_ENCH are handled in passivemm() and passiveum() */
1850 if (dmgtype(mdef->data, AD_CORR)) {
1851 dmgtyp = ERODE_CORRODE;
1852 } else if (dmgtype(mdef->data, AD_RUST)) {
1853 dmgtyp = ERODE_RUST;
1854 } else if (dmgtype(mdef->data, AD_FIRE)
1855 /* steam vortex: fire resist applies, fire damage doesn't */
1856 && mdef->data != &mons[PM_STEAM_VORTEX]) {
1857 dmgtyp = ERODE_BURN;
1861 if (dmgtyp >= 0 && !rn2(chance))
1862 (void) erode_obj(obj, (char *) 0, dmgtyp, EF_GREASE | EF_VERBOSE);
1866 mswingsm(magr, mdef, otemp)
1867 struct monst *magr, *mdef;
1870 if (flags.verbose && !Blind && mon_visible(magr)) {
1872 pline("%s %s %s%s %s at %s.", Monnam(magr),
1873 (objects[otemp->otyp].oc_dir & PIERCE) ? "thrusts" : "swings",
1874 (otemp->quan > 1L) ? "one of " : "", mhis(magr), xname(otemp),
1877 pline((objects[otemp->otyp].oc_dir & PIERCE) ?
1878 "%s
\82Í%s
\82Å%s
\82ð
\93Ë
\82¢
\82½
\81D" :
1879 "%s
\82Í%s
\82ð
\90U
\82è
\82Ü
\82í
\82µ%s
\82ð
\8dU
\8c\82\82µ
\82½
\81D", Monnam(magr),
1880 xname(otemp), mon_nam(mdef));
1886 * Passive responses by defenders. Does not replicate responses already
1887 * handled above. Returns same values as mattackm.
1890 passivemm(magr, mdef, mhit, mdead)
1891 register struct monst *magr, *mdef;
1895 register struct permonst *mddat = mdef->data;
1896 register struct permonst *madat = magr->data;
1902 return (mdead | mhit); /* no passive attacks */
1903 if (mddat->mattk[i].aatyp == AT_NONE)
1906 if (mddat->mattk[i].damn)
1907 tmp = d((int) mddat->mattk[i].damn, (int) mddat->mattk[i].damd);
1908 else if (mddat->mattk[i].damd)
1909 tmp = d((int) mddat->mlevel + 1, (int) mddat->mattk[i].damd);
1913 /* These affect the enemy even if defender killed */
1914 switch (mddat->mattk[i].adtyp) {
1916 if (mhit && !rn2(2)) {
1917 Strcpy(buf, Monnam(magr));
1918 if (canseemon(magr))
1920 pline("%s is splashed by %s %s!", buf,
1921 s_suffix(mon_nam(mdef)), hliquid("acid"));
1923 pline("%s
\82Í%s
\82Ì%s
\82ð
\97\81\82Ñ
\82½
\81I", buf,
1924 mon_nam(mdef), hliquid("
\8e_"));
1926 if (resists_acid(magr)) {
1927 if (canseemon(magr))
1929 pline("%s is not affected.", Monnam(magr));
1931 pline("%s
\82Í
\89e
\8b¿
\82ð
\8eó
\82¯
\82È
\82¢
\81D", Monnam(magr));
1937 erode_armor(magr, ERODE_CORRODE);
1939 acid_damage(MON_WEP(magr));
1941 case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */
1942 if (mhit && !mdef->mcan && otmp) {
1943 (void) drain_item(otmp, FALSE);
1950 if (mdead || mdef->mcan)
1951 return (mdead | mhit);
1953 /* These affect the enemy only if defender is still alive */
1955 switch (mddat->mattk[i].adtyp) {
1956 case AD_PLYS: /* Floating eye */
1959 if (mddat == &mons[PM_FLOATING_EYE]) {
1962 if (magr->mcansee && haseyes(madat) && mdef->mcansee
1963 && (perceives(madat) || !mdef->minvis)) {
1964 /* construct format string; guard against '%' in Monnam */
1966 Strcpy(buf, s_suffix(Monnam(mdef)));
1968 Strcpy(buf, Monnam(mdef));
1970 (void) strNsubst(buf, "%", "%%", 0);
1972 Strcat(buf, " gaze is reflected by %s %s.");
1974 Strcat(buf, "
\82Ì
\82É
\82ç
\82Ý
\82Í%s
\82É
\82æ
\82Á
\82Ä%s
\81D");
1975 if (mon_reflects(magr,
1976 canseemon(magr) ? buf : (char *) 0))
1977 return (mdead | mhit);
1978 Strcpy(buf, Monnam(magr));
1979 if (canseemon(magr))
1981 pline("%s is frozen by %s gaze!", buf,
1982 s_suffix(mon_nam(mdef)));
1984 pline("%s
\82Í%s
\82Ì
\82É
\82ç
\82Ý
\82Å
\93®
\82¯
\82È
\82
\82È
\82Á
\82½
\81I", buf,
1987 paralyze_monst(magr, tmp);
1988 return (mdead | mhit);
1990 } else { /* gelatinous cube */
1991 Strcpy(buf, Monnam(magr));
1992 if (canseemon(magr))
1994 pline("%s is frozen by %s.", buf, mon_nam(mdef));
1996 pline("%s
\82Í%s
\82É
\82æ
\82Á
\82Ä
\93®
\82¯
\82È
\82
\82È
\82Á
\82½
\81D", buf, mon_nam(mdef));
1997 paralyze_monst(magr, tmp);
1998 return (mdead | mhit);
2002 if (resists_cold(magr)) {
2003 if (canseemon(magr)) {
2005 pline("%s is mildly chilly.", Monnam(magr));
2007 pline("%s
\82Í
\97â
\82¦
\82½
\81D", Monnam(magr));
2008 golemeffects(magr, AD_COLD, tmp);
2013 if (canseemon(magr))
2015 pline("%s is suddenly very cold!", Monnam(magr));
2017 pline("%s
\82Í
\93Ë
\91R
\93\80\82è
\82Ã
\82¯
\82É
\82È
\82Á
\82½
\81I", Monnam(magr));
2018 mdef->mhp += tmp / 2;
2019 if (mdef->mhpmax < mdef->mhp)
2020 mdef->mhpmax = mdef->mhp;
2021 if (mdef->mhpmax > ((int) (mdef->m_lev + 1) * 8))
2022 (void) split_mon(mdef, magr);
2027 if (canseemon(magr))
2029 pline("%s %s...", Monnam(magr),
2030 makeplural(stagger(magr->data, "stagger")));
2032 pline("%s
\82Í%s
\81D
\81D
\81D", Monnam(magr),
2033 jpast(stagger(magr->data, "
\82æ
\82ë
\82ß
\82")));
2039 if (resists_fire(magr)) {
2040 if (canseemon(magr)) {
2042 pline("%s is mildly warmed.", Monnam(magr));
2044 pline("%s
\82Í
\92g
\82©
\82
\82È
\82Á
\82½
\81D", Monnam(magr));
2045 golemeffects(magr, AD_FIRE, tmp);
2050 if (canseemon(magr))
2052 pline("%s is suddenly very hot!", Monnam(magr));
2054 pline("%s
\82Í
\93Ë
\91R
\82Æ
\82Ä
\82à
\94M
\82
\82È
\82Á
\82½
\81I", Monnam(magr));
2057 if (resists_elec(magr)) {
2058 if (canseemon(magr)) {
2060 pline("%s is mildly tingled.", Monnam(magr));
2062 pline("%s
\82Í
\83s
\83\8a\83s
\83\8a\82µ
\82Ä
\82¢
\82é
\81D", Monnam(magr));
2063 golemeffects(magr, AD_ELEC, tmp);
2068 if (canseemon(magr))
2070 pline("%s is jolted with electricity!", Monnam(magr));
2072 pline("%s
\82Í
\93d
\8bC
\83V
\83\87\83b
\83N
\82ð
\82¤
\82¯
\82½
\81I", Monnam(magr));
2082 if ((magr->mhp -= tmp) <= 0) {
2083 monkilled(magr, "", (int) mddat->mattk[i].adtyp);
2084 return (mdead | mhit | MM_AGR_DIED);
2086 return (mdead | mhit);
2089 /* hero or monster has successfully hit target mon with drain energy attack */
2091 xdrainenergym(mon, givemsg)
2095 if (mon->mspec_used < 20 /* limit draining */
2096 && (attacktype(mon->data, AT_MAGC)
2097 || attacktype(mon->data, AT_BREA))) {
2098 mon->mspec_used += d(2, 2);
2101 pline("%s seems lethargic.", Monnam(mon));
2103 pline("%s
\82Í
\96³
\8bC
\97Í
\82É
\82È
\82Á
\82½
\82æ
\82¤
\82¾
\81D", Monnam(mon));
2107 /* "aggressive defense"; what type of armor prevents specified attack
2108 from touching its target? */
2110 attk_protection(aatyp)
2123 w_mask = ~0L; /* special case; no defense needed */
2128 w_mask = W_ARMG; /* caller needs to check for weapon */
2137 w_mask = (W_ARMC | W_ARMG); /* attacker needs both to be protected */
2144 w_mask = 0L; /* no defense available */