when engulfed, having swallower be killed by angry deity trying to zap hero
no longer violates pacifist conduct (other penalties--reduced luck or
alignment--still apply if target is something you shouldn't kill)
+likewise when a monster kills inself trying to prevent turning to stone or
+ into slime that's been caused by the player, pacifism is not affected
metabolism adjustments: hero poly'd into metallivore form still needs to eat;
being fainted or unconscious from other than sleep now consumes
nutrition at lower rate, like being asleep already did;
and "unreconnoitered" for non-adjacent anything, instead of "dark part
of a room" for the former and either dark-room or "unexplored" for the
latter depending upon whether the spot had previously been scouted
+monster who accidentally killed itself by zapping wand of fire or fire horn
+ at self to prevent turning into slime was not properly killed off;
+ it wouldn't benefit from an amulet of life saving and would trigger
+ impossible "dmonsfree: N removed doesn't match M pending"
Fixes to Post-3.6.0 Problems that Were Exposed Via git Respository
int idamres, idamnonres;
struct monst *mtmp, *mdef = 0;
uchar adtyp;
- int explmask[3][3];
- /* 0=normal explosion, 1=do shieldeff, 2=do nothing */
+ int explmask[3][3]; /* 0=normal explosion, 1=do shieldeff, 2=do nothing */
boolean shopdamage = FALSE, generic = FALSE, physical_dmg = FALSE,
do_hallu = FALSE, inside_engulfer;
char hallu_buf[BUFSZ];
mtmp->mhp -= (idamres + idamnonres);
}
if (mtmp->mhp <= 0) {
- if (mdef ? (mtmp == mdef) : !context.mon_moving)
+ if (!context.mon_moving) {
killed(mtmp);
- else
+ } else if (mdef && mtmp == mdef) {
+ /* 'mdef' killed self trying to cure being turned
+ * into slime due to some action by the player.
+ * Hero gets the credit (experience) and most of
+ * the blame (possible loss of alignment and/or
+ * luck and/or telepathy depending on mtmp) but
+ * doesn't break pacifism. xkilled()'s message
+ * would be "you killed <mdef>" so give our own.
+ */
+ if (cansee(mtmp->mx, mtmp->my) || canspotmon(mtmp))
+ pline("%s is %s!", Monnam(mtmp),
+ nonliving(mtmp->data) ? "destroyed"
+ : "killed");
+ xkilled(mtmp, XKILL_NOMSG | XKILL_NOCONDUCT);
+ } else
monkilled(mtmp, "", (int) adtyp);
} else if (!context.mon_moving) {
/* all affected monsters, even if mdef is set */
struct monst *mon;
struct obj *obj;
boolean by_you;
-boolean stoning;
+boolean stoning; /* True: stop petrification, False: cure stun && confusion */
{
boolean vis = canseemon(mon), tinned = obj->otyp == TIN,
food = obj->otyp == CORPSE || tinned,
if (mon->mhp <= 0) {
pline("%s dies!", Monnam(mon));
if (by_you)
- xkilled(mon, XKILL_NOMSG);
+ /* hero gets credit (experience) and blame (possible loss
+ of alignment and/or luck and/or telepathy depending on
+ mon) for the kill but does not break pacifism conduct */
+ xkilled(mon, XKILL_NOMSG | XKILL_NOCONDUCT);
else
mondead(mon);
return;
boolean by_you; /* true: if mon kills itself, hero gets credit/blame */
{ /* [by_you not honored if 'mon' triggers fire trap]. */
struct obj *odummyp;
- int otyp = obj->otyp, dmg;
+ int otyp = obj->otyp, dmg = 0;
boolean vis = canseemon(mon), res = TRUE;
if (vis)
if (!rn2(3))
mon->mspec_used = rn1(10, 5);
/* -21 => monster's fire breath; 1 => # of damage dice */
- (void) zhitm(mon, by_you ? 21 : -21, 1, &odummyp);
+ dmg = zhitm(mon, by_you ? 21 : -21, 1, &odummyp);
} else if (otyp == SCR_FIRE) {
mreadmsg(mon, obj);
if (mon->mconf) {
explode(mon->mx, mon->my, -11, dmg, SCROLL_CLASS,
/* by_you: override -11 for mon but not others */
by_you ? -EXPL_FIERY : EXPL_FIERY);
+ dmg = 0; /* damage has been applied by explode() */
}
} else { /* wand/horn of fire w/ positive charge count */
mzapmsg(mon, obj, TRUE);
obj->spe--;
/* -1 => monster's wand of fire; 2 => # of damage dice */
- (void) zhitm(mon, by_you ? 1 : -1, 2, &odummyp);
+ dmg = zhitm(mon, by_you ? 1 : -1, 2, &odummyp);
}
+ if (dmg) {
+ /* zhitm() applies damage but doesn't kill creature off;
+ for fire breath, dmg is going to be 0 (fire breathers are
+ immune to fire damage) but for wand of fire or fire horn,
+ 'mon' could have taken damage so might die */
+ if (mon->mhp <= 0) {
+ if (by_you) {
+ /* mon killed self but hero gets credit and blame (except
+ for pacifist conduct); xkilled()'s message would say
+ "You killed/destroyed <mon>" so give our own message */
+ if (vis)
+ pline("%s is %s by the fire!", Monnam(mon),
+ nonliving(mon->data) ? "destroyed" : "killed");
+ xkilled(mon, XKILL_NOMSG | XKILL_NOCONDUCT);
+ } else
+ monkilled(mon, "fire", AD_FIRE);
+ } else {
+ /* non-fatal damage occurred */
+ if (vis)
+ pline("%s is burned%s", Monnam(mon), exclam(dmg));
+ }
+ }
if (vis) {
if (res && mon->mhp > 0)
pline("%s slime is burned away!", s_suffix(Monnam(mon)));