]> granicus.if.org Git - nethack/commitdiff
fix #H2225 - death by poison after life-saving (trunk only)
authornethack.rankin <nethack.rankin>
Thu, 17 Feb 2011 03:51:04 +0000 (03:51 +0000)
committernethack.rankin <nethack.rankin>
Thu, 17 Feb 2011 03:51:04 +0000 (03:51 +0000)
     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.]

doc/fixes35.0
src/attrib.c
src/mthrowu.c
src/trap.c

index 776ec19470bb309058767b09de856184da61ae48..1f93ea78237106b4b355fb81dff6dcc41be75fd5 100644 (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
index b39e2b3f5ee0c2e13060a2b41a4c38effd686bd7..e43ea5103995c26fb659c2b4cbda31fdb3d8080b 100644 (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) {
+       } 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) {
index 1935826397806b99df05693d4a26841c581a5b24..8ae801ca1e095517b94d00e96e9a269cf21fbdad 100644 (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,
index 7f25e967d546cbaef44fe80be016d8ac70e71f7a..51cf074d7c18ceca2ac421be1378beb181e509e8 100644 (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)),