diff --git a/src/exper.c b/src/exper.c index d55f9abab..1fe07dcd1 100644 --- a/src/exper.c +++ b/src/exper.c @@ -321,8 +321,8 @@ pluslvl( u.mh += hpinc; } hpinc = newhp(); - setuhpmax(u.uhpmax + hpinc); u.uhp += hpinc; + setuhpmax(u.uhpmax + hpinc); /* will lower u.uhp if it exceeds uhpmax */ /* increase spell power/energy points */ eninc = newpw(); diff --git a/src/hack.c b/src/hack.c index 2b9ca664c..1e249a68c 100644 --- a/src/hack.c +++ b/src/hack.c @@ -4039,10 +4039,15 @@ maybe_wail(void) int saving_grace(int dmg) { - if (!u.usaving_grace && (u.uhp <= dmg) - && (u.uhp * 100 / u.uhpmax) > 90) { + if (dmg < 0) { + impossible("saving_grace check for negative damage? (%d)", dmg); + return 0; + } + + if (!u.usaving_grace && dmg >= u.uhp && (u.uhp * 100 / u.uhpmax) > 90) { + /* note: this could reduce dmg to 0 if u.uhpmax==1 */ dmg = u.uhp - 1; - u.usaving_grace = TRUE; /* used up */ + u.usaving_grace = 1; /* used up */ end_running(TRUE); if (u.usleep) unmul("Suddenly you wake up!"); diff --git a/src/mcastu.c b/src/mcastu.c index 68a8a8119..90f9bd9c3 100644 --- a/src/mcastu.c +++ b/src/mcastu.c @@ -342,14 +342,12 @@ castmu( break; case AD_SPEL: /* wizard spell */ case AD_CLRC: /* clerical spell */ - { if (mattk->adtyp == AD_SPEL) cast_wizard_spell(mtmp, dmg, spellnum); else cast_cleric_spell(mtmp, dmg, spellnum); dmg = 0; /* done by the spell casting functions */ break; - } } /* switch */ if (dmg) mdamageu(mtmp, dmg); @@ -441,6 +439,11 @@ death_inflicted_by( staticfn void cast_wizard_spell(struct monst *mtmp, int dmg, int spellnum) { + if (dmg < 0) { + impossible("monster cast wizard spell (%d) with negative dmg (%d)?", + spellnum, dmg); + return; + } if (dmg == 0 && !is_undirected_spell(AD_SPEL, spellnum)) { impossible("cast directed wizard spell (%d) with dmg=0?", spellnum); return; @@ -620,6 +623,12 @@ staticfn void cast_cleric_spell(struct monst *mtmp, int dmg, int spellnum) { int orig_dmg = 0; + + if (dmg < 0) { + impossible("monster cast cleric spell (%d) with negative dmg (%d)?", + spellnum, dmg); + return; + } if (dmg == 0 && !is_undirected_spell(AD_CLRC, spellnum)) { impossible("cast directed cleric spell (%d) with dmg=0?", spellnum); return; diff --git a/src/mhitu.c b/src/mhitu.c index b7f338294..33e738189 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -1211,7 +1211,7 @@ hitmu(struct monst *mtmp, struct attack *mattk) else if (*hpmax_p > lowerlimit) *hpmax_p = lowerlimit; /* else unlikely... - * already at or below minimum threshold; do nothing */ + * already at or below minimum threshold, do nothing to hpmax */ disp.botl = TRUE; } @@ -1846,16 +1846,27 @@ gazemu(struct monst *mtmp, struct attack *mattk) void mdamageu(struct monst *mtmp, int n) { + if (n < 0) { + impossible("mdamageu for negative damage? (%d)", n); + n = 0; + } + disp.botl = TRUE; if (Upolyd) { u.mh -= n; showdamage(n); + /* caller might have reduced mhmax before calling mdamageu() */ + if (u.mh > u.mhmax) + u.mh = u.mhmax; if (u.mh < 1) rehumanize(); } else { n = saving_grace(n); u.uhp -= n; showdamage(n); + /* caller might have reduced uhpmax before calling mdamageu() */ + if (u.uhp > u.uhpmax) + u.uhp = u.uhpmax; if (u.uhp < 1) done_in_by(mtmp, DIED); } @@ -2422,10 +2433,10 @@ passiveum( break; } pline("%s is suddenly very cold!", Monnam(mtmp)); - u.mh += tmp / 2; + u.mh += (tmp + rn2(2)) / 2; if (u.mhmax < u.mh) u.mhmax = u.mh; - if (u.mhmax > ((gy.youmonst.data->mlevel + 1) * 8)) + if (u.mhmax > (((int) gy.youmonst.data->mlevel + 1) * 8)) (void) split_mon(&gy.youmonst, mtmp); break; case AD_STUN: /* Yellow mold */ diff --git a/src/uhitm.c b/src/uhitm.c index 307883235..bda3557f0 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -5906,11 +5906,11 @@ passive( You("are suddenly very cold!"); mdamageu(mon, tmp); /* monster gets stronger with your heat! */ - mon->mhp += tmp / 2; + mon->mhp += (tmp + rn2(2)) / 2; if (mon->mhpmax < mon->mhp) mon->mhpmax = mon->mhp; /* at a certain point, the monster will reproduce! */ - if (mon->mhpmax > ((int) (mon->m_lev + 1) * 8)) + if (mon->mhpmax > (((int) mon->m_lev) + 1) * 8) (void) split_mon(mon, &gy.youmonst); } break;