fix #H2225 - death by poison after life-saving (trunk only)

From a bug report,
when falling into a spiked pit and being killed and then life-saved, you
could immediately die from fatal poison.  It isn't necessarily a bug and
there are other ways to be killed, life-saved, and re-killed (such as
zaps that bounce off walls or reflecting targets), but it does seem to be
somewhat unfair.  This patch makes life-saving be more effective:  in a
damage-plus-poison situation, if the damage triggers life-saving then the
poison won't deal out any further damage (including its nasty chance for
instant death).  The poison still matters, but it will always target an
attribute stat--which is already one possible random outcome--instead of
maybe doing damage.  [It is actually possible to get damage if stat loss
tries to take hero's strength below 3, but now there's no chance of that
being fatal immediately after savelife() has restored full hit points.]
This commit is contained in:
nethack.rankin
2011-02-17 03:51:04 +00:00
parent 38cea51d15
commit f23e87f2b4
4 changed files with 34 additions and 17 deletions

View File

@@ -343,6 +343,8 @@ when reading an unknown scroll and learning it, discovery of teleporation was
using an unlocking tool on a closed door which was actually a mimic reported
that there was no door to unlock instead of exposing the mimic
purple worm could end up in wall or solid rock when swallowing ghost or xorn
enhance life-saving by preventing subsequent poison from being fatal upon
rescue from death due to spiked pit, dart trap, or poisoned missile
Platform- and/or Interface-Specific Fixes

View File

@@ -1,5 +1,4 @@
/* NetHack 3.5 attrib.c $Date$ $Revision$ */
/* SCCS Id: @(#)attrib.c 3.5 2008/02/02 */
/* Copyright 1988, 1989, 1990, 1992, M. Stephenson */
/* NetHack may be freely redistributed. See license for details. */
@@ -225,10 +224,10 @@ void
poisoned(reason, typ, pkiller, fatal, thrown_weapon)
const char *reason, /* controls what messages we display */
*pkiller; /* for score+log file if fatal */
int typ, fatal;
int typ, fatal; /* if fatal is 0, limit damage to adjattrib */
boolean thrown_weapon; /* thrown weapons are less deadly */
{
int i, kprefix = KILLED_BY_AN;
int i, loss, kprefix = KILLED_BY_AN;
/* inform player about being poisoned unless that's already been done;
"blast" has given a "blast of poison gas" message; "poison arrow",
@@ -259,17 +258,22 @@ boolean thrown_weapon; /* thrown weapons are less deadly */
kprefix = KILLED_BY;
}
i = rn2(fatal + (thrown_weapon ? 20 : 0));
i = !fatal ? 1 : rn2(fatal + (thrown_weapon ? 20 : 0));
if (i == 0 && typ != A_CHA) {
/* instant kill */
u.uhp = -1;
pline_The("poison was deadly...");
} else if (i <= 5) {
/* check that a stat change was made */
if (adjattrib(typ, thrown_weapon ? -1 : -rn1(3,3), 1))
poisontell(typ, TRUE);
} else if (i > 5) {
/* HP damage; more likely--but less severe--with missiles */
loss = thrown_weapon ? rnd(6) : rn1(10,6);
losehp(loss, pkiller, kprefix); /* poison damage */
} else {
i = thrown_weapon ? rnd(6) : rn1(10,6);
losehp(i, pkiller, kprefix); /* poison damage */
/* attribute loss; if typ is A_STR, reduction in current and
maximum HP will occur once strength has dropped down to 3 */
loss = (thrown_weapon || !fatal) ? 1 : d(2, 2); /* was rn1(3,3) */
/* check that a stat change was made */
if (adjattrib(typ, -loss, 1))
poisontell(typ, TRUE);
}
if (u.uhp < 1) {

View File

@@ -1,5 +1,4 @@
/* NetHack 3.5 mthrowu.c $Date$ $Revision$ */
/* SCCS Id: @(#)mthrowu.c 3.5 2009/02/17 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -245,7 +244,7 @@ struct obj *obj; /* missile (or stack providing it) */
struct monst *mtmp;
struct obj *singleobj;
char sym = obj->oclass;
int hitu, blindinc = 0;
int hitu, oldumort, blindinc = 0;
bhitpos.x = x;
bhitpos.y = y;
@@ -346,6 +345,7 @@ struct obj *obj; /* missile (or stack providing it) */
potionhit(&youmonst, singleobj, FALSE);
break;
}
oldumort = u.umortality;
switch(singleobj->otyp) {
int dam, hitv;
case EGG:
@@ -383,7 +383,10 @@ struct obj *obj; /* missile (or stack providing it) */
Strcpy(onmbuf, xname(singleobj));
Strcpy(knmbuf, killer_xname(singleobj));
poisoned(onmbuf, A_STR, knmbuf, 10, TRUE);
poisoned(onmbuf, A_STR, knmbuf,
/* if damage triggered life-saving,
poison is limited to attrib loss */
(u.umortality > oldumort) ? 0 : 10, TRUE);
}
if(hitu &&
can_blnd((struct monst*)0, &youmonst,

View File

@@ -686,6 +686,7 @@ unsigned trflags;
forcebungle = (trflags & FORCEBUNGLE) != 0,
plunged = (trflags & TOOKPLUNGE) != 0,
adj_pit = conjoined_pits(trap, t_at(u.ux0,u.uy0), TRUE);
int oldumort;
#ifdef STEED
int steed_article = ARTICLE_THE;
#endif
@@ -779,13 +780,17 @@ unsigned trflags;
otmp->quan = 1L;
otmp->owt = weight(otmp);
if (!rn2(6)) otmp->opoisoned = 1;
oldumort = u.umortality;
#ifdef STEED
if (u.usteed && !rn2(2) && steedintrap(trap, otmp)) /* nothing */;
else
#endif
if (thitu(7, dmgval(otmp, &youmonst), otmp, "little dart")) {
if (otmp->opoisoned)
poisoned("dart", A_CON, "little dart", 10, TRUE);
poisoned("dart", A_CON, "little dart",
/* if damage triggered life-saving,
poison is limited to attrib loss */
(u.umortality > oldumort) ? 0 : 10, TRUE);
obfree(otmp, (struct obj *)0);
} else {
place_object(otmp, u.ux, u.uy);
@@ -1041,6 +1046,7 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst);
if (!steedintrap(trap, (struct obj *)0)) {
#endif
if (ttype == SPIKED_PIT) {
oldumort = u.umortality;
losehp(Maybe_Half_Phys(rnd(adj_pit ? 6 : 10)),
plunged ? "deliberately plunged into a pit of iron spikes" :
adj_pit ? "stepped into a pit of iron spikes" :
@@ -1048,9 +1054,11 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst);
NO_KILLER_PREFIX);
if (!rn2(6))
poisoned("spikes", A_STR,
adj_pit ? "stepping on poison spikes" :
"fall onto poison spikes",
8, FALSE);
adj_pit ? "stepping on poison spikes" :
"fall onto poison spikes",
/* if damage triggered life-saving,
poison is limited to attrib loss */
(u.umortality > oldumort) ? 0 : 8, FALSE);
} else {
if (!adj_pit)
losehp(Maybe_Half_Phys(rnd(6)),