From: nethack.rankin Date: Thu, 17 Feb 2011 03:51:04 +0000 (+0000) Subject: fix #H2225 - death by poison after life-saving (trunk only) X-Git-Tag: MOVE2GIT~266 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f23e87f2b43bba2c8fdf79c9ccacd784adcd63a9;p=nethack 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.] --- diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 776ec1947..1f93ea782 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -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 diff --git a/src/attrib.c b/src/attrib.c index b39e2b3f5..e43ea5103 100644 --- a/src/attrib.c +++ b/src/attrib.c @@ -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) { + } 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 { + /* 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, thrown_weapon ? -1 : -rn1(3,3), 1)) + if (adjattrib(typ, -loss, 1)) poisontell(typ, TRUE); - } else { - i = thrown_weapon ? rnd(6) : rn1(10,6); - losehp(i, pkiller, kprefix); /* poison damage */ } if (u.uhp < 1) { diff --git a/src/mthrowu.c b/src/mthrowu.c index 193582639..8ae801ca1 100644 --- a/src/mthrowu.c +++ b/src/mthrowu.c @@ -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, diff --git a/src/trap.c b/src/trap.c index 7f25e967d..51cf074d7 100644 --- a/src/trap.c +++ b/src/trap.c @@ -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)),