1 /* SCCS Id: @(#)uhitm.c 3.4 2003/02/18 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
7 STATIC_DCL boolean FDECL(known_hitum, (struct monst *,int *,struct attack *));
8 STATIC_DCL void FDECL(steal_it, (struct monst *, struct attack *));
9 STATIC_DCL boolean FDECL(hitum, (struct monst *,int,struct attack *));
10 STATIC_DCL boolean FDECL(hmon_hitmon, (struct monst *,struct obj *,int));
12 STATIC_DCL int FDECL(joust, (struct monst *,struct obj *));
14 STATIC_DCL void NDECL(demonpet);
15 STATIC_DCL boolean FDECL(m_slips_free, (struct monst *mtmp,struct attack *mattk));
16 STATIC_DCL int FDECL(explum, (struct monst *,struct attack *));
17 STATIC_DCL void FDECL(start_engulf, (struct monst *));
18 STATIC_DCL void NDECL(end_engulf);
19 STATIC_DCL int FDECL(gulpum, (struct monst *,struct attack *));
20 STATIC_DCL boolean FDECL(hmonas, (struct monst *,int));
21 STATIC_DCL void FDECL(nohandglow, (struct monst *));
22 STATIC_DCL boolean FDECL(shade_aware, (struct obj *));
24 extern boolean notonhead; /* for long worms */
25 /* The below might become a parameter instead if we use it a lot */
27 /* Used to flag attacks caused by Stormbringer's maliciousness. */
28 static boolean override_confirmation = FALSE;
30 #define PROJECTILE(obj) ((obj) && is_ammo(obj))
32 /* modified from hurtarmor() in mhitu.c */
33 /* This is not static because it is also used for monsters rusting monsters */
35 hurtmarmor(mdef, attk)
43 /* 0 is burning, which we should never be called with */
44 case AD_RUST: hurt = 1; break;
45 case AD_CORR: hurt = 3; break;
46 default: hurt = 2; break;
48 /* What the following code does: it keeps looping until it
49 * finds a target for the rust monster.
50 * Head, feet, etc... not covered by metal, or covered by
51 * rusty metal, are not targets. However, your body always
52 * is, no matter what covers it.
57 target = which_armor(mdef, W_ARMH);
58 if (!target || !rust_dmg(target, xname(target), hurt, FALSE, mdef))
62 target = which_armor(mdef, W_ARMC);
64 (void)rust_dmg(target, xname(target), hurt, TRUE, mdef);
67 if ((target = which_armor(mdef, W_ARM)) != (struct obj *)0) {
68 (void)rust_dmg(target, xname(target), hurt, TRUE, mdef);
70 } else if ((target = which_armor(mdef, W_ARMU)) != (struct obj *)0) {
71 (void)rust_dmg(target, xname(target), hurt, TRUE, mdef);
76 target = which_armor(mdef, W_ARMS);
77 if (!target || !rust_dmg(target, xname(target), hurt, FALSE, mdef))
81 target = which_armor(mdef, W_ARMG);
82 if (!target || !rust_dmg(target, xname(target), hurt, FALSE, mdef))
86 target = which_armor(mdef, W_ARMF);
87 if (!target || !rust_dmg(target, xname(target), hurt, FALSE, mdef))
91 break; /* Out of while loop */
95 /* FALSE means it's OK to attack */
97 attack_checks(mtmp, wep)
98 register struct monst *mtmp;
99 struct obj *wep; /* uwep for attack(), null for kick_monster() */
103 /* if you're close enough to attack, alert any waiting monster */
104 mtmp->mstrategy &= ~STRAT_WAITMASK;
106 if (u.uswallow && mtmp == u.ustuck) return FALSE;
108 if (flags.forcefight) {
109 /* Do this in the caller, after we checked that the monster
110 * didn't die from the blow. Reason: putting the 'I' there
111 * causes the hero to forget the square's contents since
112 * both 'I' and remembered contents are stored in .glyph.
113 * If the monster dies immediately from the blow, the 'I' will
114 * not stay there, so the player will have suddenly forgotten
115 * the square's contents for no apparent reason.
116 if (!canspotmon(mtmp) &&
117 !glyph_is_invisible(levl[u.ux+u.dx][u.uy+u.dy].glyph))
118 map_invisible(u.ux+u.dx, u.uy+u.dy);
123 /* Put up an invisible monster marker, but with exceptions for
124 * monsters that hide and monsters you've been warned about.
125 * The former already prints a warning message and
126 * prevents you from hitting the monster just via the hidden monster
127 * code below; if we also did that here, similar behavior would be
128 * happening two turns in a row. The latter shows a glyph on
129 * the screen, so you know something is there.
131 if (!canspotmon(mtmp) &&
132 !glyph_is_warning(glyph_at(u.ux+u.dx,u.uy+u.dy)) &&
133 !glyph_is_invisible(levl[u.ux+u.dx][u.uy+u.dy].glyph) &&
134 !(!Blind && mtmp->mundetected && hides_under(mtmp->data))) {
135 pline("Wait! There's %s there you can't see!",
137 map_invisible(u.ux+u.dx, u.uy+u.dy);
138 /* if it was an invisible mimic, treat it as if we stumbled
139 * onto a visible mimic
141 if(mtmp->m_ap_type && !Protection_from_shape_changers) {
142 if(!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data,AD_STCK))
145 wakeup(mtmp); /* always necessary; also un-mimics mimics */
149 if (mtmp->m_ap_type && !Protection_from_shape_changers &&
151 !glyph_is_warning(glyph_at(u.ux+u.dx,u.uy+u.dy))) {
152 /* If a hidden mimic was in a square where a player remembers
153 * some (probably different) unseen monster, the player is in
154 * luck--he attacks it even though it's hidden.
156 if (glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph)) {
160 stumble_onto_mimic(mtmp);
164 if (mtmp->mundetected && !canseemon(mtmp) &&
165 !glyph_is_warning(glyph_at(u.ux+u.dx,u.uy+u.dy)) &&
166 (hides_under(mtmp->data) || mtmp->data->mlet == S_EEL)) {
167 mtmp->mundetected = mtmp->msleeping = 0;
168 newsym(mtmp->mx, mtmp->my);
169 if (glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph)) {
173 if (!(Blind ? Blind_telepat : Unblind_telepat)) {
176 if (Blind || (is_pool(mtmp->mx,mtmp->my) && !Underwater))
177 pline("Wait! There's a hidden monster there!");
178 else if ((obj = level.objects[mtmp->mx][mtmp->my]) != 0)
179 pline("Wait! There's %s hiding under %s!",
180 an(l_monnam(mtmp)), doname(obj));
186 * make sure to wake up a monster from the above cases if the
187 * hero can sense that the monster is there.
189 if ((mtmp->mundetected || mtmp->m_ap_type) && sensemon(mtmp)) {
190 mtmp->mundetected = 0;
194 if (flags.confirm && mtmp->mpeaceful
195 && !Confusion && !Hallucination && !Stunned) {
196 /* Intelligent chaotic weapons (Stormbringer) want blood */
197 if (wep && wep->oartifact == ART_STORMBRINGER) {
198 override_confirmation = TRUE;
201 if (canspotmon(mtmp)) {
202 Sprintf(qbuf, "Really attack %s?", mon_nam(mtmp));
203 if (yn(qbuf) != 'y') {
214 * It is unchivalrous for a knight to attack the defenseless or from behind.
220 if (Role_if(PM_KNIGHT) && u.ualign.type == A_LAWFUL &&
221 (!mtmp->mcanmove || mtmp->msleeping ||
222 (mtmp->mflee && !mtmp->mavenge)) &&
223 u.ualign.record > -10) {
230 find_roll_to_hit(mtmp)
231 register struct monst *mtmp;
236 tmp = 1 + Luck + abon() + find_mac(mtmp) + u.uhitinc +
237 maybe_polyd(youmonst.data->mlevel, u.ulevel);
241 /* attacking peaceful creatures is bad for the samurai's giri */
242 if (Role_if(PM_SAMURAI) && mtmp->mpeaceful &&
243 u.ualign.record > -10) {
244 You("dishonorably attack the innocent!");
248 /* Adjust vs. (and possibly modify) monster state. */
250 if(mtmp->mstun) tmp += 2;
251 if(mtmp->mflee) tmp += 2;
253 if (mtmp->msleeping) {
257 if(!mtmp->mcanmove) {
264 if (is_orc(mtmp->data) && maybe_polyd(is_elf(youmonst.data),
267 if(Role_if(PM_MONK) && !Upolyd) {
269 Your("armor is rather cumbersome...");
270 tmp -= urole.spelarmr;
271 } else if (!uwep && !uarms) {
272 tmp += (u.ulevel / 3) + 2;
276 /* with a lot of luggage, your agility diminishes */
277 if ((tmp2 = near_capacity()) != 0) tmp -= (tmp2*2) - 1;
278 if (u.utrap) tmp -= 3;
279 /* Some monsters have a combination of weapon attacks and non-weapon
280 * attacks. It is therefore wrong to add hitval to tmp; we must add
281 * it only for the specific attack (in hmonas()).
283 if (uwep && !Upolyd) {
284 tmp += hitval(uwep, mtmp);
285 tmp += weapon_hit_bonus(uwep);
290 /* try to attack; return FALSE if monster evaded */
291 /* u.dx and u.dy must be set */
294 register struct monst *mtmp;
297 register struct permonst *mdat = mtmp->data;
299 /* This section of code provides protection against accidentally
300 * hitting peaceful (like '@') and tame (like 'd') monsters.
301 * Protection is provided as long as player is not: blind, confused,
302 * hallucinating or stunned.
303 * changes by wwp 5/16/85
304 * More changes 12/90, -dkh-. if its tame and safepet, (and protected
305 * 07/92) then we assume that you're not trying to attack. Instead,
306 * you'll usually just swap places if this is a movement command
308 /* Intelligent chaotic weapons (Stormbringer) want blood */
309 if (is_safepet(mtmp) && !flags.forcefight) {
310 if (!uwep || uwep->oartifact != ART_STORMBRINGER) {
311 /* there are some additional considerations: this won't work
312 * if in a shop or Punished or you miss a random roll or
313 * if you can walk thru walls and your pet cannot (KAA) or
314 * if your pet is a long worm (unless someone does better).
315 * there's also a chance of displacing a "frozen" monster.
316 * sleeping monsters might magically walk in their sleep.
318 boolean foo = (Punished || !rn2(7) || is_longworm(mtmp->data)),
322 for (p = in_rooms(mtmp->mx, mtmp->my, SHOPBASE); *p; p++)
323 if (tended_shop(&rooms[*p - ROOMOFFSET])) {
329 (IS_ROCK(levl[u.ux][u.uy].typ) &&
330 !passes_walls(mtmp->data))) {
333 monflee(mtmp, rnd(6), FALSE, FALSE);
334 Strcpy(buf, y_monnam(mtmp));
335 buf[0] = highc(buf[0]);
336 You("stop. %s is in the way!", buf);
338 } else if ((mtmp->mfrozen || (! mtmp->mcanmove)
339 || (mtmp->data->mmove == 0)) && rn2(6)) {
340 pline("%s doesn't seem to move!", Monnam(mtmp));
342 } else return(FALSE);
346 /* possibly set in attack_checks;
347 examined in known_hitum, called via hitum or hmonas below */
348 override_confirmation = FALSE;
349 if (attack_checks(mtmp, uwep)) return(TRUE);
352 /* certain "pacifist" monsters don't attack */
353 if(noattacks(youmonst.data)) {
354 You("have no way to attack monsters physically.");
355 mtmp->mstrategy &= ~STRAT_WAITMASK;
360 if(check_capacity("You cannot fight while so heavily loaded."))
363 if (u.twoweap && !can_twoweapon())
370 You("begin bashing monsters with your %s.",
371 aobjnam(uwep, (char *)0));
372 else if (!cantwield(youmonst.data))
373 You("begin %sing monsters with your %s %s.",
374 Role_if(PM_MONK) ? "strik" : "bash",
375 uarmg ? "gloved" : "bare", /* Del Lamb */
376 makeplural(body_part(HAND)));
379 exercise(A_STR, TRUE); /* you're exercising muscles */
380 /* andrew@orca: prevent unlimited pick-axe attacks */
383 /* Is the "it died" check actually correct? */
384 if(mdat->mlet == S_LEPRECHAUN && !mtmp->mfrozen && !mtmp->msleeping &&
385 !mtmp->mconf && mtmp->mcansee && !rn2(7) &&
386 (m_move(mtmp, 0) == 2 || /* it died */
387 mtmp->mx != u.ux+u.dx || mtmp->my != u.uy+u.dy)) /* it moved */
390 tmp = find_roll_to_hit(mtmp);
392 (void) hmonas(mtmp, tmp);
394 (void) hitum(mtmp, tmp, youmonst.data->mattk);
395 mtmp->mstrategy &= ~STRAT_WAITMASK;
398 /* see comment in attack_checks() */
399 /* we only need to check for this if we did an attack_checks()
400 * and it returned 0 (it's okay to attack), and the monster didn't
403 if (flags.forcefight && mtmp->mhp > 0 && !canspotmon(mtmp) &&
404 !glyph_is_invisible(levl[u.ux+u.dx][u.uy+u.dy].glyph) &&
405 !(u.uswallow && mtmp == u.ustuck))
406 map_invisible(u.ux+u.dx, u.uy+u.dy);
412 known_hitum(mon, mhit, uattk) /* returns TRUE if monster still lives */
413 register struct monst *mon;
415 struct attack *uattk;
417 register boolean malive = TRUE;
419 if (override_confirmation) {
420 /* this may need to be generalized if weapons other than
421 Stormbringer acquire similar anti-social behavior... */
422 if (flags.verbose) Your("bloodthirsty blade attacks!");
428 int oldhp = mon->mhp,
429 x = u.ux + u.dx, y = u.uy + u.dy;
432 if (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep)))
433 u.uconduct.weaphit++;
435 /* we hit the monster; be careful: it might die or
436 be knocked into a different location */
437 notonhead = (mon->mx != x || mon->my != y);
438 malive = hmon(mon, uwep, 0);
439 /* this assumes that Stormbringer was uwep not uswapwep */
440 if (malive && u.twoweap && !override_confirmation &&
442 malive = hmon(mon, uswapwep, 0);
444 /* monster still alive */
445 if(!rn2(25) && mon->mhp < mon->mhpmax/2
446 && !(u.uswallow && mon == u.ustuck)) {
447 /* maybe should regurgitate if swallowed? */
449 monflee(mon, rnd(100), FALSE, TRUE);
450 } else monflee(mon, 0, FALSE, TRUE);
452 if(u.ustuck == mon && !u.uswallow && !sticks(youmonst.data))
455 /* Vorpal Blade hit converted to miss */
456 /* could be headless monster or worm tail */
457 if (mon->mhp == oldhp) {
459 /* a miss does not break conduct */
461 (uwep->oclass == WEAPON_CLASS || is_weptool(uwep)))
462 --u.uconduct.weaphit;
464 if (mon->wormno && *mhit)
465 cutworm(mon, x, y, uwep);
472 hitum(mon, tmp, uattk) /* returns TRUE if monster still lives */
475 struct attack *uattk;
478 int mhit = (tmp > (dieroll = rnd(20)) || u.uswallow);
480 if(tmp > dieroll) exercise(A_DEX, TRUE);
481 malive = known_hitum(mon, &mhit, uattk);
482 (void) passive(mon, mhit, malive, AT_WEAP);
486 boolean /* general "damage monster" routine */
487 hmon(mon, obj, thrown) /* return TRUE if mon still alive */
492 boolean result, anger_guards;
494 anger_guards = (mon->mpeaceful &&
495 (mon->ispriest || mon->isshk ||
496 mon->data == &mons[PM_WATCHMAN] ||
497 mon->data == &mons[PM_WATCH_CAPTAIN]));
498 result = hmon_hitmon(mon, obj, thrown);
499 if (mon->ispriest && !rn2(2)) ghod_hitsu(mon);
500 if (anger_guards) (void)angry_guards(!flags.soundok);
506 hmon_hitmon(mon, obj, thrown)
512 struct permonst *mdat = mon->data;
513 int barehand_silver_rings = 0;
514 /* The basic reason we need all these booleans is that we don't want
515 * a "hit" message when a monster dies, so we have to know how much
516 * damage it did _before_ outputting a hit message, but any messages
517 * associated with the damage don't come out until _after_ outputting
520 boolean hittxt = FALSE, destroyed = FALSE, already_killed = FALSE;
521 boolean get_dmg_bonus = TRUE;
522 boolean ispoisoned = FALSE, needpoismsg = FALSE, poiskilled = FALSE;
523 boolean silvermsg = FALSE, silverobj = FALSE;
524 boolean valid_weapon_attack = FALSE;
525 boolean unarmed = !uwep && !uarm && !uarms;
532 char unconventional[BUFSZ]; /* substituted for word "attack" in msg */
533 char saved_oname[BUFSZ];
535 unconventional[0] = '\0';
536 saved_oname[0] = '\0';
539 if(!obj) { /* attack with bare hands */
540 if (mdat == &mons[PM_SHADE])
542 else if (martial_bonus())
543 tmp = rnd(4); /* bonus for martial arts */
546 valid_weapon_attack = (tmp > 1);
547 /* blessed gloves give bonuses when fighting 'bare-handed' */
548 if (uarmg && uarmg->blessed && (is_undead(mdat) || is_demon(mdat)))
550 /* So do silver rings. Note: rings are worn under gloves, so you
551 * don't get both bonuses.
554 if (uleft && objects[uleft->otyp].oc_material == SILVER)
555 barehand_silver_rings++;
556 if (uright && objects[uright->otyp].oc_material == SILVER)
557 barehand_silver_rings++;
558 if (barehand_silver_rings && hates_silver(mdat)) {
564 Strcpy(saved_oname, cxname(obj));
565 if(obj->oclass == WEAPON_CLASS || is_weptool(obj) ||
566 obj->oclass == GEM_CLASS) {
568 /* is it not a melee weapon? */
569 if (/* if you strike with a bow... */
571 /* or strike with a missile in your hand... */
572 (!thrown && (is_missile(obj) || is_ammo(obj))) ||
573 /* or use a pole at short range and not mounted... */
579 /* or throw a missile without the proper bow... */
580 (is_ammo(obj) && !ammo_and_launcher(obj, uwep))) {
581 /* then do only 1-2 points of damage */
582 if (mdat == &mons[PM_SHADE] && obj->otyp != SILVER_ARROW)
586 if (!thrown && obj == uwep && obj->otyp == BOOMERANG &&
588 boolean more_than_1 = (obj->quan > 1L);
590 pline("As you hit %s, %s%s %s breaks into splinters.",
591 mon_nam(mon), more_than_1 ? "one of " : "",
592 shk_your(yourbuf, obj), xname(obj));
593 if (!more_than_1) uwepgone(); /* set unweapon */
595 if (!more_than_1) obj = (struct obj *) 0;
597 if (mdat != &mons[PM_SHADE])
601 tmp = dmgval(obj, mon);
602 /* a minimal hit doesn't exercise proficiency */
603 valid_weapon_attack = (tmp > 1);
604 if (!valid_weapon_attack || mon == u.ustuck || u.twoweap) {
605 ; /* no special bonuses */
606 } else if (mon->mflee && Role_if(PM_ROGUE) && !Upolyd) {
607 You("strike %s from behind!", mon_nam(mon));
608 tmp += rnd(u.ulevel);
610 } else if (dieroll == 2 && obj == uwep &&
611 obj->oclass == WEAPON_CLASS &&
613 (Role_if(PM_SAMURAI) && obj->otyp == KATANA && !uarms)) &&
614 ((wtype = uwep_skill_type()) != P_NONE &&
615 P_SKILL(wtype) >= P_SKILLED) &&
616 ((monwep = MON_WEP(mon)) != 0 &&
617 !is_flimsy(monwep) &&
619 50 + 15 * greatest_erosion(obj), 100))) {
621 * 2.5% chance of shattering defender's weapon when
622 * using a two-handed weapon; less if uwep is rusted.
623 * [dieroll == 2 is most successful non-beheading or
624 * -bisecting hit, in case of special artifact damage;
625 * the percentage chance is (1/20)*(50/100).]
627 setmnotwielded(mon,monwep);
629 mon->weapon_check = NEED_WEAPON;
630 pline("%s %s %s from the force of your blow!",
631 s_suffix(Monnam(mon)), xname(monwep),
632 otense(monwep, "shatter"));
633 m_useup(mon, monwep);
634 /* If someone just shattered MY weapon, I'd flee! */
636 monflee(mon, d(2,3), TRUE, TRUE);
641 if (obj->oartifact &&
642 artifact_hit(&youmonst, mon, obj, &tmp, dieroll)) {
643 if(mon->mhp <= 0) /* artifact killed monster */
645 if (tmp == 0) return TRUE;
648 if (objects[obj->otyp].oc_material == SILVER
649 && hates_silver(mdat)) {
650 silvermsg = TRUE; silverobj = TRUE;
653 if (u.usteed && !thrown && tmp > 0 &&
654 weapon_type(obj) == P_LANCE && mon != u.ustuck) {
655 jousting = joust(mon, obj);
656 /* exercise skill even for minimal damage hits */
657 if (jousting) valid_weapon_attack = TRUE;
660 if (thrown && (is_ammo(obj) || is_missile(obj))) {
661 if (ammo_and_launcher(obj, uwep)) {
662 /* Elves and Samurai do extra damage using
663 * their bows&arrows; they're highly trained.
665 if (Role_if(PM_SAMURAI) &&
666 obj->otyp == YA && uwep->otyp == YUMI)
668 else if (Race_if(PM_ELF) &&
669 obj->otyp == ELVEN_ARROW &&
670 uwep->otyp == ELVEN_BOW)
673 if(obj->opoisoned && is_poisonable(obj))
677 } else if(obj->oclass == POTION_CLASS) {
679 obj = splitobj(obj, 1L);
681 setuwep((struct obj *)0);
683 potionhit(mon, obj, TRUE);
684 if (mon->mhp <= 0) return FALSE; /* killed */
686 /* in case potion effect causes transformation */
688 tmp = (mdat == &mons[PM_SHADE]) ? 0 : 1;
690 if (mdat == &mons[PM_SHADE] && !shade_aware(obj)) {
692 Strcpy(unconventional, cxname(obj));
695 case BOULDER: /* 1d20 */
696 case HEAVY_IRON_BALL: /* 1d25 */
697 case IRON_CHAIN: /* 1d4+1 */
698 tmp = dmgval(obj, mon);
701 if (breaktest(obj)) {
702 You("break %s mirror. That's bad luck!",
703 shk_your(yourbuf, obj));
706 obj = (struct obj *) 0;
707 unarmed = FALSE; /* avoid obj==0 confusion */
708 get_dmg_bonus = FALSE;
714 case EXPENSIVE_CAMERA:
715 You("succeed in destroying %s camera. Congratulations!",
716 shk_your(yourbuf, obj));
722 case CORPSE: /* fixed by polder@cs.vu.nl */
723 if (touch_petrifies(&mons[obj->corpsenm])) {
724 static const char withwhat[] = "corpse";
727 You("hit %s with %s %s.", mon_nam(mon),
728 obj->dknown ? the(mons[obj->corpsenm].mname) :
729 an(mons[obj->corpsenm].mname),
730 (obj->quan > 1) ? makeplural(withwhat) : withwhat);
731 if (!munstone(mon, TRUE))
732 minstapetrify(mon, TRUE);
733 if (resists_ston(mon)) break;
734 /* note: hp may be <= 0 even if munstoned==TRUE */
735 return (boolean) (mon->mhp > 0);
737 } else if (touch_petrifies(mdat)) {
738 /* maybe turn the corpse into a statue? */
741 tmp = (obj->corpsenm >= LOW_PM ?
742 mons[obj->corpsenm].msize : 0) + 1;
746 #define useup_eggs(o) { if (thrown) obfree(o,(struct obj *)0); \
748 o = (struct obj *)0; } /* now gone */
749 long cnt = obj->quan;
751 tmp = 1; /* nominal physical damage */
752 get_dmg_bonus = FALSE;
753 hittxt = TRUE; /* message always given */
754 /* egg is always either used up or transformed, so next
755 hand-to-hand attack should yield a "bashing" mesg */
756 if (obj == uwep) unweapon = TRUE;
757 if (obj->spe && obj->corpsenm >= LOW_PM) {
759 change_luck((schar) -(obj->quan));
764 if (touch_petrifies(&mons[obj->corpsenm])) {
765 /*learn_egg_type(obj->corpsenm);*/
766 pline("Splat! You hit %s with %s %s egg%s!",
768 obj->known ? "the" : cnt > 1L ? "some" : "a",
769 obj->known ? mons[obj->corpsenm].mname : "petrifying",
771 obj->known = 1; /* (not much point...) */
773 if (!munstone(mon, TRUE))
774 minstapetrify(mon, TRUE);
775 if (resists_ston(mon)) break;
776 return (boolean) (mon->mhp > 0);
777 } else { /* ordinary egg(s) */
779 (obj->corpsenm != NON_PM && obj->known) ?
780 the(mons[obj->corpsenm].mname) :
781 (cnt > 1L) ? "some" : "an";
782 You("hit %s with %s egg%s.",
783 mon_nam(mon), eggp, plur(cnt));
784 if (touch_petrifies(mdat) && !stale_egg(obj)) {
785 pline_The("egg%s %s alive any more...",
787 (cnt == 1L) ? "isn't" : "aren't");
788 if (obj->timed) obj_stop_timers(obj);
790 obj->oclass = GEM_CLASS;
793 obj->known = obj->dknown = obj->bknown = 0;
794 obj->owt = weight(obj);
795 if (thrown) place_object(obj, mon->mx, mon->my);
799 exercise(A_WIS, FALSE);
805 case CLOVE_OF_GARLIC: /* no effect against demons */
806 if (is_undead(mdat)) {
807 monflee(mon, d(2, 4), FALSE, TRUE);
814 if (can_blnd(&youmonst, mon, (uchar)
815 (obj->otyp == BLINDING_VENOM
816 ? AT_SPIT : AT_WEAP), obj)) {
818 pline(obj->otyp == CREAM_PIE ?
819 "Splat!" : "Splash!");
820 } else if (obj->otyp == BLINDING_VENOM) {
821 pline_The("venom blinds %s%s!", mon_nam(mon),
822 mon->mcansee ? "" : " further");
824 char *whom = mon_nam(mon);
825 char *what = The(xname(obj));
826 if (!thrown && obj->quan > 1)
827 what = An(singular(obj, xname));
828 /* note: s_suffix returns a modifiable buffer */
830 && mdat != &mons[PM_FLOATING_EYE])
831 whom = strcat(strcat(s_suffix(whom), " "),
832 mbodypart(mon, FACE));
833 pline("%s %s over %s!",
834 what, vtense(what, "splash"), whom);
839 if(((int) mon->mblinded + tmp) > 127)
841 else mon->mblinded += tmp;
843 pline(obj->otyp==CREAM_PIE ? "Splat!" : "Splash!");
846 if (thrown) obfree(obj, (struct obj *)0);
849 get_dmg_bonus = FALSE;
852 case ACID_VENOM: /* thrown (or spit) */
853 if (resists_acid(mon)) {
854 Your("venom hits %s harmlessly.",
858 Your("venom burns %s!", mon_nam(mon));
859 tmp = dmgval(obj, mon);
861 if (thrown) obfree(obj, (struct obj *)0);
864 get_dmg_bonus = FALSE;
867 /* non-weapons can damage because of their weight */
868 /* (but not too much) */
874 * Things like silver wands can arrive here so
875 * so we need another silver check.
877 if (objects[obj->otyp].oc_material == SILVER
878 && hates_silver(mdat)) {
880 silvermsg = TRUE; silverobj = TRUE;
887 /****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG)
888 * *OR* if attacking bare-handed!! */
890 if (get_dmg_bonus && tmp > 0) {
892 /* If you throw using a propellor, you don't get a strength
893 * bonus but you do get an increase-damage bonus.
895 if(!thrown || !obj || !uwep || !ammo_and_launcher(obj, uwep))
899 if (valid_weapon_attack) {
902 /* to be valid a projectile must have had the correct projector */
903 wep = PROJECTILE(obj) ? uwep : obj;
904 tmp += weapon_dam_bonus(wep);
905 /* [this assumes that `!thrown' implies wielded...] */
906 wtype = thrown ? weapon_type(wep) : uwep_skill_type();
911 int nopoison = (10 - (obj->owt/10));
912 if(nopoison < 2) nopoison = 2;
913 if Role_if(PM_SAMURAI) {
914 You("dishonorably use a poisoned weapon!");
915 adjalign(-sgn(u.ualign.type));
916 } else if ((u.ualign.type == A_LAWFUL) && (u.ualign.record > -10)) {
917 You_feel("like an evil coward for using a poisoned weapon.");
920 if (obj && !rn2(nopoison)) {
921 obj->opoisoned = FALSE;
922 Your("%s %s no longer poisoned.", xname(obj),
925 if (resists_poison(mon))
929 else poiskilled = TRUE;
932 /* make sure that negative damage adjustment can't result
933 in inadvertently boosting the victim's hit points */
935 if (mdat == &mons[PM_SHADE]) {
937 const char *what = unconventional[0] ? unconventional : "attack";
938 Your("%s %s harmlessly through %s.",
939 what, vtense(what, "pass"),
944 if (get_dmg_bonus) tmp = 1;
950 tmp += d(2, (obj == uwep) ? 10 : 2); /* [was in dmgval()] */
952 mon_nam(mon), canseemon(mon) ? exclam(tmp) : ".");
954 Your("%s shatters on impact!", xname(obj));
955 /* (must be either primary or secondary weapon to get here) */
956 u.twoweap = FALSE; /* untwoweapon() is too verbose here */
957 if (obj == uwep) uwepgone(); /* set unweapon */
958 /* minor side-effect: broken lance won't split puddings */
962 /* avoid migrating a dead monster */
963 if (mon->mhp > tmp) {
964 mhurtle(mon, u.dx, u.dy, 1);
965 mdat = mon->data; /* in case of a polymorph trap */
966 if (DEADMONSTER(mon)) already_killed = TRUE;
972 /* VERY small chance of stunning opponent if unarmed. */
973 if (unarmed && tmp > 1 && !thrown && !obj && !Upolyd) {
974 if (rnd(100) < P_SKILL(P_BARE_HANDED_COMBAT) &&
975 !bigmonst(mdat) && !thick_skinned(mdat)) {
977 pline("%s %s from your powerful strike!", Monnam(mon),
978 makeplural(stagger(mon->data, "stagger")));
979 /* avoid migrating a dead monster */
980 if (mon->mhp > tmp) {
981 mhurtle(mon, u.dx, u.dy, 1);
982 mdat = mon->data; /* in case of a polymorph trap */
983 if (DEADMONSTER(mon)) already_killed = TRUE;
989 if (!already_killed) mon->mhp -= tmp;
990 /* adjustments might have made tmp become less than what
991 a level draining artifact has already done to max HP */
992 if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
995 if (mon->mtame && (!mon->mflee || mon->mfleetim) && tmp > 0) {
997 monflee(mon, 10 * rnd(tmp), FALSE, FALSE);
999 if((mdat == &mons[PM_BLACK_PUDDING] || mdat == &mons[PM_BROWN_PUDDING])
1000 && obj && obj == uwep
1001 && objects[obj->otyp].oc_material == IRON
1002 && mon->mhp > 1 && !thrown && !mon->mcan
1003 /* && !destroyed -- guaranteed by mhp > 1 */ ) {
1004 if (clone_mon(mon, 0, 0)) {
1005 pline("%s divides as you hit it!", Monnam(mon));
1010 if (!hittxt && /*( thrown => obj exists )*/
1011 (!destroyed || (thrown && m_shot.n > 1 && m_shot.o == obj->otyp))) {
1012 if (thrown) hit(mshot_xname(obj), mon, exclam(tmp));
1013 else if (!flags.verbose) You("hit it.");
1014 else You("%s %s%s", Role_if(PM_BARBARIAN) ? "smite" : "hit",
1015 mon_nam(mon), canseemon(mon) ? exclam(tmp) : ".");
1020 char *whom = mon_nam(mon);
1021 char silverobjbuf[BUFSZ];
1023 if (canspotmon(mon)) {
1024 if (barehand_silver_rings == 1)
1025 fmt = "Your silver ring sears %s!";
1026 else if (barehand_silver_rings == 2)
1027 fmt = "Your silver rings sear %s!";
1028 else if (silverobj && saved_oname[0]) {
1029 Sprintf(silverobjbuf, "Your %s%s %s %%s!",
1030 strstri(saved_oname, "silver") ?
1032 saved_oname, vtense(saved_oname, "sear"));
1035 fmt = "The silver sears %s!";
1037 *whom = highc(*whom); /* "it" -> "It" */
1038 fmt = "%s is seared!";
1040 /* note: s_suffix returns a modifiable buffer */
1041 if (!noncorporeal(mdat))
1042 whom = strcat(s_suffix(whom), " flesh");
1047 pline_The("poison doesn't seem to affect %s.", mon_nam(mon));
1049 pline_The("poison was deadly...");
1050 if (!already_killed) xkilled(mon, 0);
1052 } else if (destroyed) {
1053 if (!already_killed)
1054 killed(mon); /* takes care of most messages */
1055 } else if(u.umconf && !thrown) {
1057 if (!mon->mconf && !resist(mon, SPBOOK_CLASS, 0, NOTELL)) {
1059 if (!mon->mstun && mon->mcanmove && !mon->msleeping &&
1061 pline("%s appears confused.", Monnam(mon));
1065 return((boolean)(destroyed ? FALSE : TRUE));
1072 if (!obj) return FALSE;
1074 * The things in this list either
1077 * 2) are dealt with properly by other routines
1078 * when it comes to shades.
1080 if (obj->otyp == BOULDER || obj->otyp == HEAVY_IRON_BALL
1081 || obj->otyp == IRON_CHAIN /* dmgval handles those first three */
1082 || obj->otyp == MIRROR /* silver in the reflective surface */
1083 || obj->otyp == CLOVE_OF_GARLIC /* causes shades to flee */
1084 || objects[obj->otyp].oc_material == SILVER)
1089 /* check whether slippery clothing protects from hug or wrap attack */
1090 /* [currently assumes that you are the attacker] */
1092 m_slips_free(mdef, mattk)
1094 struct attack *mattk;
1098 if (mattk->adtyp == AD_DRIN) {
1099 /* intelligence drain attacks the head */
1100 obj = which_armor(mdef, W_ARMH);
1102 /* grabbing attacks the body */
1103 obj = which_armor(mdef, W_ARMC); /* cloak */
1104 if (!obj) obj = which_armor(mdef, W_ARM); /* suit */
1106 if (!obj) obj = which_armor(mdef, W_ARMU); /* shirt */
1110 /* if your cloak/armor is greased, monster slips off; this
1111 protection might fail (33% chance) when the armor is cursed */
1112 if (obj && (obj->greased || obj->otyp == OILSKIN_CLOAK) &&
1113 (!obj->cursed || rn2(3))) {
1115 mattk->adtyp == AD_WRAP ?
1116 "slip off of" : "grab, but cannot hold onto",
1117 s_suffix(mon_nam(mdef)),
1118 obj->greased ? "greased" : "slippery",
1119 /* avoid "slippery slippery cloak"
1120 for undiscovered oilskin cloak */
1121 (obj->greased || objects[obj->otyp].oc_name_known) ?
1122 xname(obj) : cloak_simple_name(obj));
1124 if (obj->greased && !rn2(2)) {
1125 pline_The("grease wears off.");
1133 /* used when hitting a monster with a lance while mounted */
1134 STATIC_OVL int /* 1: joust hit; 0: ordinary hit; -1: joust but break lance */
1136 struct monst *mon; /* target */
1137 struct obj *obj; /* weapon */
1139 int skill_rating, joust_dieroll;
1141 if (Fumbling || Stunned) return 0;
1142 /* sanity check; lance must be wielded in order to joust */
1143 if (obj != uwep && (obj != uswapwep || !u.twoweap)) return 0;
1145 /* if using two weapons, use worse of lance and two-weapon skills */
1146 skill_rating = P_SKILL(weapon_type(obj)); /* lance skill */
1147 if (u.twoweap && P_SKILL(P_TWO_WEAPON_COMBAT) < skill_rating)
1148 skill_rating = P_SKILL(P_TWO_WEAPON_COMBAT);
1149 if (skill_rating == P_ISRESTRICTED) skill_rating = P_UNSKILLED; /* 0=>1 */
1151 /* odds to joust are expert:80%, skilled:60%, basic:40%, unskilled:20% */
1152 if ((joust_dieroll = rn2(5)) < skill_rating) {
1153 if (joust_dieroll == 0 && rnl(50) == (50-1) &&
1154 !unsolid(mon->data) && !obj_resists(obj, 0, 100))
1155 return -1; /* hit that breaks lance */
1156 return 1; /* successful joust */
1158 return 0; /* no joust bonus; revert to ordinary attack */
1162 * Send in a demon pet for the hero. Exercise wisdom.
1164 * This function used to be inline to damageum(), but the Metrowerks compiler
1165 * (DR4 and DR4.5) screws up with an internal error 5 "Expression Too Complex."
1166 * Pulling it out makes it work.
1172 struct permonst *pm;
1175 pline("Some hell-p has arrived!");
1176 i = !rn2(6) ? ndemon(u.ualign.type) : NON_PM;
1177 pm = i != NON_PM ? &mons[i] : youmonst.data;
1178 if ((dtmp = makemon(pm, u.ux, u.uy, NO_MM_FLAGS)) != 0)
1179 (void)tamedog(dtmp, (struct obj *)0);
1180 exercise(A_WIS, TRUE);
1184 * Player uses theft attack against monster.
1186 * If the target is wearing body armor, take all of its possesions;
1187 * otherwise, take one object. [Is this really the behavior we want?]
1189 * This routine implicitly assumes that there is no way to be able to
1190 * resist petfication (ie, be polymorphed into a xorn or golem) at the
1191 * same time as being able to steal (poly'd into nymph or succubus).
1192 * If that ever changes, the check for touching a cockatrice corpse
1193 * will need to be smarter about whether to break out of the theft loop.
1196 steal_it(mdef, mattk)
1198 struct attack *mattk;
1200 struct obj *otmp, *stealoid, **minvent_ptr;
1203 if (!mdef->minvent) return; /* nothing to take */
1205 /* look for worn body armor */
1206 stealoid = (struct obj *)0;
1207 if (could_seduce(&youmonst, mdef, mattk)) {
1208 /* find armor, and move it to end of inventory in the process */
1209 minvent_ptr = &mdef->minvent;
1210 while ((otmp = *minvent_ptr) != 0)
1211 if (otmp->owornmask & W_ARM) {
1212 if (stealoid) panic("steal_it: multiple worn suits");
1213 *minvent_ptr = otmp->nobj; /* take armor out of minvent */
1215 stealoid->nobj = (struct obj *)0;
1217 minvent_ptr = &otmp->nobj;
1219 *minvent_ptr = stealoid; /* put armor back into minvent */
1222 if (stealoid) { /* we will be taking everything */
1223 if (gender(mdef) == (int) u.mfemale &&
1224 youmonst.data->mlet == S_NYMPH)
1225 You("charm %s. She gladly hands over her possessions.",
1228 You("seduce %s and %s starts to take off %s clothes.",
1229 mon_nam(mdef), mhe(mdef), mhis(mdef));
1232 while ((otmp = mdef->minvent) != 0) {
1233 if (!Upolyd) break; /* no longer have ability to steal */
1234 /* take the object away from the monster */
1235 obj_extract_self(otmp);
1236 if ((unwornmask = otmp->owornmask) != 0L) {
1237 mdef->misc_worn_check &= ~unwornmask;
1238 if (otmp->owornmask & W_WEP) {
1239 setmnotwielded(mdef,otmp);
1242 otmp->owornmask = 0L;
1243 update_mon_intrinsics(mdef, otmp, FALSE, FALSE);
1245 if (otmp == stealoid) /* special message for final item */
1246 pline("%s finishes taking off %s suit.",
1247 Monnam(mdef), mhis(mdef));
1249 /* give the object to the character */
1250 otmp = hold_another_object(otmp, "You snatched but dropped %s.",
1251 doname(otmp), "You steal: ");
1252 if (otmp->where != OBJ_INVENT) continue;
1253 if (otmp->otyp == CORPSE &&
1254 touch_petrifies(&mons[otmp->corpsenm]) && !uarmg) {
1257 Sprintf(kbuf, "stolen %s corpse", mons[otmp->corpsenm].mname);
1259 break; /* stop the theft even if hero survives */
1261 /* more take-away handling, after theft message */
1262 if (unwornmask & W_WEP) { /* stole wielded weapon */
1263 possibly_unwield(mdef, FALSE);
1264 } else if (unwornmask & W_ARMG) { /* stole worn gloves */
1265 mselftouch(mdef, (const char *)0, TRUE);
1266 if (mdef->mhp <= 0) /* it's now a statue */
1267 return; /* can't continue stealing */
1270 if (!stealoid) break; /* only taking one item */
1275 damageum(mdef, mattk)
1276 register struct monst *mdef;
1277 register struct attack *mattk;
1279 register struct permonst *pd = mdef->data;
1280 register int tmp = d((int)mattk->damn, (int)mattk->damd);
1284 armpro = magic_negation(mdef);
1285 /* since hero can't be cancelled, only defender's armor applies */
1286 negated = !((rn2(3) >= armpro) || !rn2(50));
1288 if (is_demon(youmonst.data) && !rn2(13) && !uwep
1289 && u.umonnum != PM_SUCCUBUS && u.umonnum != PM_INCUBUS
1290 && u.umonnum != PM_BALROG) {
1294 switch(mattk->adtyp) {
1297 pline("%s %s for a moment.", Monnam(mdef),
1298 makeplural(stagger(mdef->data, "stagger")));
1302 /* if (u.ucancelled) { */
1307 case AD_WERE: /* no special effect on monsters */
1308 case AD_HEAL: /* likewise */
1311 if(mattk->aatyp == AT_WEAP) {
1313 } else if(mattk->aatyp == AT_KICK) {
1314 if(thick_skinned(mdef->data)) tmp = 0;
1315 if(mdef->data == &mons[PM_SHADE]) {
1316 if (!(uarmf && uarmf->blessed)) {
1317 impossible("bad shade attack function flow?");
1320 tmp = rnd(4); /* bless damage */
1330 pline("%s is %s!", Monnam(mdef),
1331 on_fire(mdef->data, mattk));
1332 if (pd == &mons[PM_STRAW_GOLEM] ||
1333 pd == &mons[PM_PAPER_GOLEM]) {
1335 pline("%s burns completely!", Monnam(mdef));
1339 /* Don't return yet; keep hp<1 and tmp=0 for pet msg */
1341 tmp += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
1342 tmp += destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
1343 if (resists_fire(mdef)) {
1345 pline_The("fire doesn't heat %s!", mon_nam(mdef));
1346 golemeffects(mdef, AD_FIRE, tmp);
1347 shieldeff(mdef->mx, mdef->my);
1350 /* only potions damage resistant players in destroy_item */
1351 tmp += destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
1358 if (!Blind) pline("%s is covered in frost!", Monnam(mdef));
1359 if (resists_cold(mdef)) {
1360 shieldeff(mdef->mx, mdef->my);
1362 pline_The("frost doesn't chill %s!", mon_nam(mdef));
1363 golemeffects(mdef, AD_COLD, tmp);
1366 tmp += destroy_mitem(mdef, POTION_CLASS, AD_COLD);
1373 if (!Blind) pline("%s is zapped!", Monnam(mdef));
1374 tmp += destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
1375 if (resists_elec(mdef)) {
1377 pline_The("zap doesn't shock %s!", mon_nam(mdef));
1378 golemeffects(mdef, AD_ELEC, tmp);
1379 shieldeff(mdef->mx, mdef->my);
1382 /* only rings damage resistant players in destroy_item */
1383 tmp += destroy_mitem(mdef, RING_CLASS, AD_ELEC);
1386 if (resists_acid(mdef)) tmp = 0;
1389 if (!munstone(mdef, TRUE))
1390 minstapetrify(mdef, TRUE);
1398 steal_it(mdef, mattk);
1404 u.ugold += mdef->mgold;
1406 Your("purse feels heavier.");
1409 /* This you as a leprechaun, so steal
1410 real gold only, no lesser coins */
1412 struct obj *mongold = findgold(mdef->minvent);
1414 obj_extract_self(mongold);
1415 if (merge_choice(invent, mongold) || inv_cnt() < 52) {
1417 Your("purse feels heavier.");
1419 You("grab %s's gold, but find no room in your knapsack.", mon_nam(mdef));
1425 exercise(A_DEX, TRUE);
1429 if (tmp <= 0) tmp = 1;
1430 if (!negated && tmp < mdef->mhp) {
1432 boolean u_saw_mon = canseemon(mdef) ||
1433 (u.uswallow && u.ustuck == mdef);
1434 /* record the name before losing sight of monster */
1435 Strcpy(nambuf, Monnam(mdef));
1436 if (u_teleport_mon(mdef, FALSE) &&
1437 u_saw_mon && !canseemon(mdef))
1438 pline("%s suddenly disappears!", nambuf);
1442 if (can_blnd(&youmonst, mdef, mattk->aatyp, (struct obj*)0)) {
1443 if(!Blind && mdef->mcansee)
1444 pline("%s is blinded.", Monnam(mdef));
1446 tmp += mdef->mblinded;
1447 if (tmp > 127) tmp = 127;
1448 mdef->mblinded = tmp;
1453 if (night() && !rn2(10) && !mdef->mcan) {
1454 if (mdef->data == &mons[PM_CLAY_GOLEM]) {
1456 pline("Some writing vanishes from %s head!",
1457 s_suffix(mon_nam(mdef)));
1459 /* Don't return yet; keep hp<1 and tmp=0 for pet msg */
1468 if (!negated && !rn2(3) && !resists_drli(mdef)) {
1470 pline("%s suddenly seems weaker!", Monnam(mdef));
1471 mdef->mhpmax -= xtmp;
1472 if ((mdef->mhp -= xtmp) <= 0 || !mdef->m_lev) {
1473 pline("%s dies!", Monnam(mdef));
1481 if (pd == &mons[PM_IRON_GOLEM]) {
1482 pline("%s falls to pieces!", Monnam(mdef));
1485 hurtmarmor(mdef, AD_RUST);
1489 hurtmarmor(mdef, AD_CORR);
1493 if (pd == &mons[PM_WOOD_GOLEM] ||
1494 pd == &mons[PM_LEATHER_GOLEM]) {
1495 pline("%s falls to pieces!", Monnam(mdef));
1498 hurtmarmor(mdef, AD_DCAY);
1504 if (!negated && !rn2(8)) {
1505 Your("%s was poisoned!", mpoisons_subj(&youmonst, mattk));
1506 if (resists_poison(mdef))
1507 pline_The("poison doesn't seem to affect %s.",
1511 Your("poison was deadly...");
1513 } else tmp += rn1(10,6);
1518 if (notonhead || !has_head(mdef->data)) {
1519 pline("%s doesn't seem harmed.", Monnam(mdef));
1521 if (!Unchanging && mdef->data == &mons[PM_GREEN_SLIME]) {
1523 You("suck in some slime and don't feel very well.");
1529 if (m_slips_free(mdef, mattk)) break;
1531 if ((mdef->misc_worn_check & W_ARMH) && rn2(8)) {
1532 pline("%s helmet blocks your attack to %s head.",
1533 s_suffix(Monnam(mdef)), mhis(mdef));
1537 You("eat %s brain!", s_suffix(mon_nam(mdef)));
1539 if (touch_petrifies(mdef->data) && !Stone_resistance && !Stoned) {
1541 killer_format = KILLED_BY_AN;
1542 delayed_killer = mdef->data->mname;
1544 if (!vegan(mdef->data))
1545 u.uconduct.unvegan++;
1546 if (!vegetarian(mdef->data))
1547 violated_vegetarian();
1548 if (mindless(mdef->data)) {
1549 pline("%s doesn't notice.", Monnam(mdef));
1553 morehungry(-rnd(30)); /* cannot choke */
1554 if (ABASE(A_INT) < AMAX(A_INT)) {
1555 ABASE(A_INT) += rnd(4);
1556 if (ABASE(A_INT) > AMAX(A_INT))
1557 ABASE(A_INT) = AMAX(A_INT);
1560 exercise(A_WIS, TRUE);
1563 if (!negated && !sticks(mdef->data))
1564 u.ustuck = mdef; /* it's now stuck to you */
1567 if (!sticks(mdef->data)) {
1568 if (!u.ustuck && !rn2(10)) {
1569 if (m_slips_free(mdef, mattk)) {
1572 You("swing yourself around %s!",
1576 } else if(u.ustuck == mdef) {
1577 /* Monsters don't wear amulets of magical breathing */
1578 if (is_pool(u.ux,u.uy) && !is_swimmer(mdef->data) &&
1579 !amphibious(mdef->data)) {
1580 You("drown %s...", mon_nam(mdef));
1582 } else if(mattk->aatyp == AT_HUGS)
1583 pline("%s is being crushed.", Monnam(mdef));
1587 You("brush against %s %s.",
1588 s_suffix(mon_nam(mdef)),
1589 mbodypart(mdef, LEG));
1594 if (!negated && mdef->mcanmove && !rn2(3) && tmp < mdef->mhp) {
1595 if (!Blind) pline("%s is frozen by you!", Monnam(mdef));
1597 mdef->mfrozen = rnd(10);
1601 if (!negated && !mdef->msleeping &&
1602 sleep_monst(mdef, rnd(10), -1)) {
1604 pline("%s is put to sleep by you!", Monnam(mdef));
1609 if (negated) break; /* physical damage only */
1610 if (!rn2(4) && !flaming(mdef->data) &&
1611 mdef->data != &mons[PM_GREEN_SLIME]) {
1612 You("turn %s into slime.", mon_nam(mdef));
1613 (void) newcham(mdef, &mons[PM_GREEN_SLIME], FALSE, FALSE);
1617 case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */
1618 /* there's no msomearmor() function, so just do damage */
1619 /* if (negated) break; */
1622 if (!negated && mdef->mspeed != MSLOW) {
1623 unsigned int oldspeed = mdef->mspeed;
1625 mon_adjust_speed(mdef, -1, (struct obj *)0);
1626 if (mdef->mspeed != oldspeed && canseemon(mdef))
1627 pline("%s slows down.", Monnam(mdef));
1632 if (canseemon(mdef))
1633 pline("%s looks confused.", Monnam(mdef));
1641 mdef->mstrategy &= ~STRAT_WAITFORU; /* in case player is very fast */
1642 if((mdef->mhp -= tmp) < 1) {
1643 if (mdef->mtame && !cansee(mdef->mx,mdef->my)) {
1644 You_feel("embarrassed for a moment.");
1645 if (tmp) xkilled(mdef, 0); /* !tmp but hp<1: already killed */
1646 } else if (!flags.verbose) {
1648 if (tmp) xkilled(mdef, 0);
1650 if (tmp) killed(mdef);
1658 register struct monst *mdef;
1659 register struct attack *mattk;
1661 register int tmp = d((int)mattk->damn, (int)mattk->damd);
1664 switch(mattk->adtyp) {
1665 boolean resistance; /* only for cold/fire/elec */
1668 if (!resists_blnd(mdef)) {
1669 pline("%s is blinded by your flash of light!", Monnam(mdef));
1670 mdef->mblinded = min((int)mdef->mblinded + tmp, 127);
1675 if (haseyes(mdef->data) && mdef->mcansee) {
1676 pline("%s is affected by your flash of light!",
1682 resistance = resists_cold(mdef);
1685 resistance = resists_fire(mdef);
1688 resistance = resists_elec(mdef);
1691 pline("%s gets blasted!", Monnam(mdef));
1693 if (mdef->mhp <= 0) {
1698 shieldeff(mdef->mx, mdef->my);
1699 if (is_golem(mdef->data))
1700 golemeffects(mdef, (int)mattk->adtyp, tmp);
1702 pline_The("blast doesn't seem to affect %s.",
1717 map_location(u.ux, u.uy, TRUE);
1718 tmp_at(DISP_ALWAYS, mon_to_glyph(&youmonst));
1719 tmp_at(mdef->mx, mdef->my);
1721 You("engulf %s!", mon_nam(mdef));
1730 tmp_at(DISP_END, 0);
1737 register struct monst *mdef;
1738 register struct attack *mattk;
1741 register int dam = d((int)mattk->damn, (int)mattk->damd);
1743 /* Not totally the same as for real monsters. Specifically, these
1744 * don't take multiple moves. (It's just too hard, for too little
1745 * result, to program monsters which attack from inside you, which
1746 * would be necessary if done accurately.) Instead, we arbitrarily
1747 * kill the monster immediately for AD_DGST and we regurgitate them
1748 * after exactly 1 round of attack otherwise. -KAA
1751 if(mdef->data->msize >= MZ_HUGE) return 0;
1753 if(u.uhunger < 1500 && !u.uswallow) {
1754 for (otmp = mdef->minvent; otmp; otmp = otmp->nobj)
1755 (void) snuff_lit(otmp);
1757 if(!touch_petrifies(mdef->data) || Stone_resistance) {
1758 #ifdef LINT /* static char msgbuf[BUFSZ]; */
1761 static char msgbuf[BUFSZ];
1764 switch(mattk->adtyp) {
1766 /* eating a Rider or its corpse is fatal */
1767 if (is_rider(mdef->data)) {
1768 pline("Unfortunately, digesting any of it is fatal.");
1770 Sprintf(msgbuf, "unwisely tried to eat %s",
1773 killer_format = NO_KILLER_PREFIX;
1775 return 0; /* lifesaved */
1778 if (Slow_digestion) {
1785 if (!vegan(mdef->data))
1786 u.uconduct.unvegan++;
1787 if (!vegetarian(mdef->data))
1788 violated_vegetarian();
1790 /* Use up amulet of life saving */
1791 if (!!(otmp = mlifesaver(mdef))) m_useup(mdef, otmp);
1795 if (mdef->mhp > 0) { /* monster lifesaved */
1796 You("hurriedly regurgitate the sizzling in your %s.",
1797 body_part(STOMACH));
1799 tmp = 1 + (mdef->data->cwt >> 8);
1800 if (corpse_chance(mdef, &youmonst, TRUE) &&
1801 !(mvitals[monsndx(mdef->data)].mvflags &
1803 /* nutrition only if there can be a corpse */
1804 u.uhunger += (mdef->data->cnutrit+1) / 2;
1806 Sprintf(msgbuf, "You totally digest %s.",
1809 /* setting afternmv = end_engulf is tempting,
1810 * but will cause problems if the player is
1811 * attacked (which uses his real location) or
1812 * if his See_invisible wears off
1814 You("digest %s.", mon_nam(mdef));
1815 if (Slow_digestion) tmp *= 2;
1818 } else pline("%s", msgbuf);
1819 if (mdef->data == &mons[PM_GREEN_SLIME]) {
1820 Sprintf(msgbuf, "%s isn't sitting well with you.",
1821 The(mdef->data->mname));
1827 exercise(A_CON, TRUE);
1832 if (youmonst.data == &mons[PM_FOG_CLOUD]) {
1833 pline("%s is laden with your moisture.",
1835 if (amphibious(mdef->data) &&
1836 !flaming(mdef->data)) {
1838 pline("%s seems unharmed.", Monnam(mdef));
1841 pline("%s is pummeled with your debris!",
1845 pline("%s is covered with your goo!", Monnam(mdef));
1846 if (resists_acid(mdef)) {
1847 pline("It seems harmless to %s.", mon_nam(mdef));
1852 if (can_blnd(&youmonst, mdef, mattk->aatyp, (struct obj *)0)) {
1854 pline("%s can't see in there!", Monnam(mdef));
1856 dam += mdef->mblinded;
1857 if (dam > 127) dam = 127;
1858 mdef->mblinded = dam;
1864 pline_The("air around %s crackles with electricity.", mon_nam(mdef));
1865 if (resists_elec(mdef)) {
1866 pline("%s seems unhurt.", Monnam(mdef));
1869 golemeffects(mdef,(int)mattk->adtyp,dam);
1874 if (resists_cold(mdef)) {
1875 pline("%s seems mildly chilly.", Monnam(mdef));
1878 pline("%s is freezing to death!",Monnam(mdef));
1879 golemeffects(mdef,(int)mattk->adtyp,dam);
1884 if (resists_fire(mdef)) {
1885 pline("%s seems mildly hot.", Monnam(mdef));
1888 pline("%s is burning to a crisp!",Monnam(mdef));
1889 golemeffects(mdef,(int)mattk->adtyp,dam);
1894 if ((mdef->mhp -= dam) <= 0) {
1896 if (mdef->mhp <= 0) /* not lifesaved */
1899 You("%s %s!", is_animal(youmonst.data) ? "regurgitate"
1900 : "expel", mon_nam(mdef));
1901 if (Slow_digestion || is_animal(youmonst.data)) {
1902 pline("Obviously, you didn't like %s taste.",
1903 s_suffix(mon_nam(mdef)));
1908 You("bite into %s.", mon_nam(mdef));
1909 Sprintf(kbuf, "swallowing %s whole", an(mdef->data->mname));
1918 register struct monst *mdef;
1919 register struct attack *mattk;
1921 if (could_seduce(&youmonst, mdef, mattk))
1922 You("pretend to be friendly to %s.", mon_nam(mdef));
1923 else if(canspotmon(mdef) && flags.verbose)
1924 You("miss %s.", mon_nam(mdef));
1927 if (!mdef->msleeping && mdef->mcanmove)
1932 hmonas(mon, tmp) /* attack monster as a monster. */
1933 register struct monst *mon;
1936 struct attack *mattk, alt_attk;
1937 int i, sum[NATTK], hittmp = 0;
1941 for(i = 0; i < NATTK; i++) {
1944 mattk = getmattk(youmonst.data, i, sum, &alt_attk);
1945 switch(mattk->aatyp) {
1948 /* Certain monsters don't use weapons when encountered as enemies,
1949 * but players who polymorph into them have hands or claws and thus
1950 * should be able to use weapons. This shouldn't prohibit the use
1951 * of most special abilities, either.
1953 /* Potential problem: if the monster gets multiple weapon attacks,
1954 * we currently allow the player to get each of these as a weapon
1955 * attack. Is this really desirable?
1958 hittmp = hitval(uwep, mon);
1959 hittmp += weapon_hit_bonus(uwep);
1962 dhit = (tmp > (dieroll = rnd(20)) || u.uswallow);
1963 /* KMH -- Don't accumulate to-hit bonuses */
1964 if (uwep) tmp -= hittmp;
1965 /* Enemy dead, before any special abilities used */
1966 if (!known_hitum(mon,&dhit,mattk)) {
1969 } else sum[i] = dhit;
1970 /* might be a worm that gets cut in half */
1971 if (m_at(u.ux+u.dx, u.uy+u.dy) != mon) return((boolean)(nsum != 0));
1972 /* Do not print "You hit" message, since known_hitum
1975 if (dhit && mattk->adtyp != AD_SPEL
1976 && mattk->adtyp != AD_PHYS)
1977 sum[i] = damageum(mon,mattk);
1980 if (i==0 && uwep && !cantwield(youmonst.data)) goto use_weapon;
1982 /* succubi/incubi are humanoid, but their _second_
1983 * attack is AT_CLAW, not their first...
1985 if (i==1 && uwep && (u.umonnum == PM_SUCCUBUS ||
1986 u.umonnum == PM_INCUBUS)) goto use_weapon;
1994 if (i==0 && uwep && (youmonst.data->mlet==S_LICH)) goto use_weapon;
1995 if ((dhit = (tmp > rnd(20) || u.uswallow)) != 0) {
1999 (compat=could_seduce(&youmonst, mon, mattk))) {
2001 mon->mcansee && haseyes(mon->data)
2002 ? "smile at" : "talk to",
2004 compat == 2 ? "engagingly":"seductively");
2005 /* doesn't anger it; no wakeup() */
2006 sum[i] = damageum(mon, mattk);
2010 /* maybe this check should be in damageum()? */
2011 if (mon->data == &mons[PM_SHADE] &&
2012 !(mattk->aatyp == AT_KICK &&
2013 uarmf && uarmf->blessed)) {
2014 Your("attack passes harmlessly through %s.",
2018 if (mattk->aatyp == AT_KICK)
2019 You("kick %s.", mon_nam(mon));
2020 else if (mattk->aatyp == AT_BITE)
2021 You("bite %s.", mon_nam(mon));
2022 else if (mattk->aatyp == AT_STNG)
2023 You("sting %s.", mon_nam(mon));
2024 else if (mattk->aatyp == AT_BUTT)
2025 You("butt %s.", mon_nam(mon));
2026 else if (mattk->aatyp == AT_TUCH)
2027 You("touch %s.", mon_nam(mon));
2028 else if (mattk->aatyp == AT_TENT)
2029 Your("tentacles suck %s.", mon_nam(mon));
2030 else You("hit %s.", mon_nam(mon));
2031 sum[i] = damageum(mon, mattk);
2037 /* automatic if prev two attacks succeed, or if
2038 * already grabbed in a previous attack
2042 if (mon->data == &mons[PM_SHADE])
2043 Your("hug passes harmlessly through %s.",
2045 else if (!sticks(mon->data) && !u.uswallow) {
2046 if (mon==u.ustuck) {
2047 pline("%s is being %s.", Monnam(mon),
2048 u.umonnum==PM_ROPE_GOLEM ? "choked":
2050 sum[i] = damageum(mon, mattk);
2051 } else if(i >= 2 && sum[i-1] && sum[i-2]) {
2052 You("grab %s!", mon_nam(mon));
2054 sum[i] = damageum(mon, mattk);
2059 case AT_EXPL: /* automatic hit if next to */
2062 sum[i] = explum(mon, mattk);
2066 if((dhit = (tmp > rnd(20+i)))) {
2068 if (mon->data == &mons[PM_SHADE])
2069 Your("attempt to surround %s is harmless.",
2072 sum[i]= gulpum(mon,mattk);
2074 (mon->data->mlet == S_ZOMBIE ||
2075 mon->data->mlet == S_MUMMY) &&
2079 (Sick) ? "very " : "");
2080 mdamageu(mon, rnd(8));
2088 /* No check for uwep; if wielding nothing we want to
2089 * do the normal 1-2 points bare hand damage...
2091 if (i==0 && (youmonst.data->mlet==S_KOBOLD
2092 || youmonst.data->mlet==S_ORC
2093 || youmonst.data->mlet==S_GNOME
2099 /* Not break--avoid passive attacks from enemy */
2103 case AT_GAZE: /* all done using #monster command */
2107 default: /* Strange... */
2108 impossible("strange attack of yours (%d)",
2112 u.mh = -1; /* dead in the current form */
2116 return((boolean)passive(mon, 1, 0, mattk->aatyp));
2119 (void) passive(mon, sum[i], 1, mattk->aatyp);
2123 break; /* No extra attacks if no longer a monster */
2125 break; /* If paralyzed while attacking, i.e. floating eye */
2127 return((boolean)(nsum != 0));
2130 /* Special (passive) attacks on you by monsters done here. */
2133 passive(mon, mhit, malive, aatyp)
2134 register struct monst *mon;
2135 register boolean mhit;
2136 register int malive;
2139 register struct permonst *ptr = mon->data;
2140 register int i, tmp;
2143 if(i >= NATTK) return(malive | mhit); /* no passive attacks */
2144 if(ptr->mattk[i].aatyp == AT_NONE) break; /* try this one */
2146 /* Note: tmp not always used */
2147 if (ptr->mattk[i].damn)
2148 tmp = d((int)ptr->mattk[i].damn, (int)ptr->mattk[i].damd);
2149 else if(ptr->mattk[i].damd)
2150 tmp = d((int)mon->m_lev+1, (int)ptr->mattk[i].damd);
2154 /* These affect you even if they just died */
2156 switch(ptr->mattk[i].adtyp) {
2159 if(mhit && rn2(2)) {
2160 if (Blind || !flags.verbose) You("are splashed!");
2161 else You("are splashed by %s acid!",
2162 s_suffix(mon_nam(mon)));
2164 if (!Acid_resistance)
2166 if(!rn2(30)) erode_armor(&youmonst, TRUE);
2169 if (aatyp == AT_KICK) {
2170 if (uarmf && !rn2(6))
2171 (void)rust_dmg(uarmf, xname(uarmf), 3, TRUE, &youmonst);
2172 } else if (aatyp == AT_WEAP || aatyp == AT_CLAW ||
2173 aatyp == AT_MAGC || aatyp == AT_TUCH)
2174 passive_obj(mon, (struct obj*)0, &(ptr->mattk[i]));
2176 exercise(A_STR, FALSE);
2179 if (mhit) { /* successful attack */
2180 long protector = attk_protection((int)aatyp);
2182 /* hero using monsters' AT_MAGC attack is hitting hand to
2183 hand rather than casting a spell */
2184 if (aatyp == AT_MAGC) protector = W_ARMG;
2186 if (protector == 0L || /* no protection */
2187 (protector == W_ARMG && !uarmg && !uwep) ||
2188 (protector == W_ARMF && !uarmf) ||
2189 (protector == W_ARMH && !uarmh) ||
2190 (protector == (W_ARMC|W_ARMG) && (!uarmc || !uarmg))) {
2191 if (!Stone_resistance &&
2192 !(poly_when_stoned(youmonst.data) &&
2193 polymon(PM_STONE_GOLEM))) {
2194 You("turn to stone...");
2202 if(mhit && !mon->mcan) {
2203 if (aatyp == AT_KICK) {
2205 (void)rust_dmg(uarmf, xname(uarmf), 1, TRUE, &youmonst);
2206 } else if (aatyp == AT_WEAP || aatyp == AT_CLAW ||
2207 aatyp == AT_MAGC || aatyp == AT_TUCH)
2208 passive_obj(mon, (struct obj*)0, &(ptr->mattk[i]));
2212 if(mhit && !mon->mcan) {
2213 if (aatyp == AT_KICK) {
2215 (void)rust_dmg(uarmf, xname(uarmf), 3, TRUE, &youmonst);
2216 } else if (aatyp == AT_WEAP || aatyp == AT_CLAW ||
2217 aatyp == AT_MAGC || aatyp == AT_TUCH)
2218 passive_obj(mon, (struct obj*)0, &(ptr->mattk[i]));
2222 /* wrath of gods for attacking Oracle */
2224 shieldeff(u.ux, u.uy);
2225 pline("A hail of magic missiles narrowly misses you!");
2227 You("are hit by magic missiles appearing from thin air!");
2231 case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */
2233 struct obj *obj = (struct obj *)0;
2235 if (aatyp == AT_KICK) {
2238 } else if (aatyp == AT_BITE || aatyp == AT_BUTT ||
2239 (aatyp >= AT_STNG && aatyp < AT_WEAP)) {
2240 break; /* no object involved */
2242 passive_obj(mon, obj, &(ptr->mattk[i]));
2249 /* These only affect you if they still live */
2251 if(malive && !mon->mcan && rn2(3)) {
2253 switch(ptr->mattk[i].adtyp) {
2256 if(ptr == &mons[PM_FLOATING_EYE]) {
2257 if (!canseemon(mon)) {
2261 if (ureflects("%s gaze is reflected by your %s.",
2262 s_suffix(Monnam(mon))))
2264 else if (Free_action)
2265 You("momentarily stiffen under %s gaze!",
2266 s_suffix(mon_nam(mon)));
2268 You("are frozen by %s gaze!",
2269 s_suffix(mon_nam(mon)));
2270 nomul((ACURR(A_WIS) > 12 || rn2(4)) ? -tmp : -127);
2273 pline("%s cannot defend itself.",
2274 Adjmonnam(mon,"blind"));
2275 if(!rn2(500)) change_luck(-1);
2277 } else if (Free_action) {
2278 You("momentarily stiffen.");
2279 } else { /* gelatinous cube */
2280 You("are frozen by %s!", mon_nam(mon));
2281 nomovemsg = 0; /* default: "you can move again" */
2283 exercise(A_DEX, FALSE);
2286 case AD_COLD: /* brown mold or blue jelly */
2287 if(monnear(mon, u.ux, u.uy)) {
2288 if(Cold_resistance) {
2289 shieldeff(u.ux, u.uy);
2290 You_feel("a mild chill.");
2291 ugolemeffects(AD_COLD, tmp);
2294 You("are suddenly very cold!");
2296 /* monster gets stronger with your heat! */
2297 mon->mhp += tmp / 2;
2298 if (mon->mhpmax < mon->mhp) mon->mhpmax = mon->mhp;
2299 /* at a certain point, the monster will reproduce! */
2300 if(mon->mhpmax > ((int) (mon->m_lev+1) * 8))
2301 (void)split_mon(mon, &youmonst);
2304 case AD_STUN: /* specifically yellow mold */
2306 make_stunned((long)tmp, TRUE);
2309 if(monnear(mon, u.ux, u.uy)) {
2310 if(Fire_resistance) {
2311 shieldeff(u.ux, u.uy);
2312 You_feel("mildly warm.");
2313 ugolemeffects(AD_FIRE, tmp);
2316 You("are suddenly very hot!");
2321 if(Shock_resistance) {
2322 shieldeff(u.ux, u.uy);
2323 You_feel("a mild tingle.");
2324 ugolemeffects(AD_ELEC, tmp);
2327 You("are jolted with electricity!");
2334 return(malive | mhit);
2338 * Special (passive) attacks on an attacking object by monsters done here.
2339 * Assumes the attack was successful.
2342 passive_obj(mon, obj, mattk)
2343 register struct monst *mon;
2344 register struct obj *obj; /* null means pick uwep, uswapwep or uarmg */
2345 struct attack *mattk; /* null means we find one internally */
2347 register struct permonst *ptr = mon->data;
2350 /* if caller hasn't specified an object, use uwep, uswapwep or uarmg */
2352 obj = (u.twoweap && uswapwep && !rn2(2)) ? uswapwep : uwep;
2353 if (!obj && mattk->adtyp == AD_ENCH)
2354 obj = uarmg; /* no weapon? then must be gloves */
2355 if (!obj) return; /* no object to affect */
2358 /* if caller hasn't specified an attack, find one */
2361 if(i >= NATTK) return; /* no passive attacks */
2362 if(ptr->mattk[i].aatyp == AT_NONE) break; /* try this one */
2364 mattk = &(ptr->mattk[i]);
2367 switch(mattk->adtyp) {
2371 erode_obj(obj, TRUE, FALSE);
2376 erode_obj(obj, FALSE, FALSE);
2381 erode_obj(obj, TRUE, FALSE);
2386 if (drain_item(obj) && carried(obj) &&
2387 (obj->known || obj->oclass == ARMOR_CLASS)) {
2388 Your("%s less effective.", aobjnam(obj, "seem"));
2396 if (carried(obj)) update_inventory();
2399 /* Note: caller must ascertain mtmp is mimicking... */
2401 stumble_onto_mimic(mtmp)
2404 const char *fmt = "Wait! That's %s!",
2405 *generic = "a monster",
2408 if(!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data,AD_STCK))
2413 what = generic; /* with default fmt */
2414 else if (mtmp->m_ap_type == M_AP_MONSTER)
2415 what = a_monnam(mtmp); /* differs from what was sensed */
2417 int glyph = levl[u.ux+u.dx][u.uy+u.dy].glyph;
2419 if (glyph_is_cmap(glyph) &&
2420 (glyph_to_cmap(glyph) == S_hcdoor ||
2421 glyph_to_cmap(glyph) == S_vcdoor))
2422 fmt = "The door actually was %s!";
2423 else if (glyph_is_object(glyph) &&
2424 glyph_to_obj(glyph) == GOLD_PIECE)
2425 fmt = "That gold was %s!";
2427 /* cloned Wiz starts out mimicking some other monster and
2428 might make himself invisible before being revealed */
2429 if (mtmp->minvis && !See_invisible)
2432 what = a_monnam(mtmp);
2434 if (what) pline(fmt, what);
2436 wakeup(mtmp); /* clears mimicking */
2443 char *hands=makeplural(body_part(HAND));
2445 if (!u.umconf || mon->mconf) return;
2446 if (u.umconf == 1) {
2448 Your("%s stop tingling.", hands);
2450 Your("%s stop glowing %s.", hands, hcolor(NH_RED));
2453 pline_The("tingling in your %s lessens.", hands);
2455 Your("%s no longer glow so brightly %s.", hands,
2462 flash_hits_mon(mtmp, otmp)
2464 struct obj *otmp; /* source of flash */
2466 int tmp, amt, res = 0, useeit = canseemon(mtmp);
2468 if (mtmp->msleeping) {
2469 mtmp->msleeping = 0;
2471 pline_The("flash awakens %s.", mon_nam(mtmp));
2474 } else if (mtmp->data->mlet != S_LIGHT) {
2475 if (!resists_blnd(mtmp)) {
2476 tmp = dist2(otmp->ox, otmp->oy, mtmp->mx, mtmp->my);
2478 pline("%s is blinded by the flash!", Monnam(mtmp));
2481 if (mtmp->data == &mons[PM_GREMLIN]) {
2482 /* Rule #1: Keep them out of the light. */
2483 amt = otmp->otyp == WAN_LIGHT ? d(1 + otmp->spe, 4) :
2484 rn2(min(mtmp->mhp,4));
2485 pline("%s %s!", Monnam(mtmp), amt > mtmp->mhp / 2 ?
2486 "wails in agony" : "cries out in pain");
2487 if ((mtmp->mhp -= amt) <= 0) {
2488 if (flags.mon_moving)
2489 monkilled(mtmp, (char *)0, AD_BLND);
2492 } else if (cansee(mtmp->mx,mtmp->my) && !canspotmon(mtmp)){
2493 map_invisible(mtmp->mx, mtmp->my);
2496 if (mtmp->mhp > 0) {
2497 if (!flags.mon_moving) setmangry(mtmp);
2498 if (tmp < 9 && !mtmp->isshk && rn2(4)) {
2500 monflee(mtmp, rnd(100), FALSE, TRUE);
2502 monflee(mtmp, 0, FALSE, TRUE);
2505 mtmp->mblinded = (tmp < 3) ? 0 : rnd(1 + 50/tmp);