]> granicus.if.org Git - nethack/commitdiff
held artifacts evading your grasp (trunk only)
authornethack.rankin <nethack.rankin>
Sat, 10 Mar 2007 05:54:17 +0000 (05:54 +0000)
committernethack.rankin <nethack.rankin>
Sat, 10 Mar 2007 05:54:17 +0000 (05:54 +0000)
     From a bug report, trying
to invoke a wielded artifact after changing alignment resulted in "the
<artifact> evades your grasp" but it remained wielded, contradicting the
message.  This adjusts the message in touch_artifact() if the object is
already in inventory, and adds retouch_object() to handle cases where
failing to be able to touch ought to force unwearing/unwielding.

doc/fixes35.0
include/extern.h
src/apply.c
src/artifact.c
src/eat.c
src/mhitu.c
src/wield.c

index 835d4f18aae8db10bce63f68f80a0d27dfee0b35..ccb4a09c9aab075b155337a6ea9f6189a8908863 100644 (file)
@@ -194,6 +194,9 @@ if normal game save file is restored via `nethack -X', restore in normal
        mode--with save file deletion--and require confirmation ala 'X'
        command to make deferred switch into explore mode
 stethoscope applied to hiding mimic will bring it out of hiding
+rephrase "<artifact> evades your grasp" message if artifact is already held
+artifacts which subsequently evade your grasp/control after already being
+       worn or wielded become unworn/unwielded
 
 
 Platform- and/or Interface-Specific Fixes
index 6c196400250d9e96d63531cab07126c972867c32..99357a47de28abef2878ab0019f549a6968c7771 100644 (file)
@@ -84,6 +84,7 @@ E boolean FDECL(artifact_has_invprop, (struct obj *,UCHAR_P));
 E long FDECL(arti_cost, (struct obj *));
 E struct obj *FDECL(what_gives, (long *));
 E void FDECL(Sting_effects, (int));
+E int FDECL(retouch_object, (struct obj **,BOOLEAN_P));
 
 /* ### attrib.c ### */
 
index b899937f73dc1fcb8ed6f15e09856012428558d6..3bb57f08cdd6a02f3f740d214e775825c566743e 100644 (file)
@@ -2974,7 +2974,7 @@ doapply()
        obj = getobj(class_list, "use or apply");
        if(!obj) return 0;
 
-       if (obj->oartifact && !touch_artifact(obj, &youmonst))
+       if (!retouch_object(&obj, FALSE))
            return 1;   /* evading your grasp costs a turn; just be
                           grateful that you don't drop it as well */
 
index b0d3d610eb178a5884d18976eabec014eba31fea..c38098f802171e90bd9fc8816856acc52dc4ff15 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)artifact.c 3.5     2006/06/08      */
+/*     SCCS Id: @(#)artifact.c 3.5     2007/03/05      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -559,7 +559,12 @@ touch_artifact(obj,mon)
 
     /* can pick it up unless you're totally non-synch'd with the artifact */
     if (badclass && badalign && self_willed) {
-       if (yours) pline("%s your grasp!", Tobjnam(obj, "evade"));
+       if (yours) {
+           if (obj->where != OBJ_INVENT)
+               pline("%s your grasp!", Tobjnam(obj, "evade"));
+           else
+               pline("%s beyond your control!", Tobjnam(obj, "are"));
+       }
        return 0;
     }
 
@@ -1200,11 +1205,11 @@ static NEARDATA const char invoke_types[] = { ALL_CLASSES, 0 };
 int
 doinvoke()
 {
-    register struct obj *obj;
+    struct obj *obj;
 
     obj = getobj(invoke_types, "invoke");
     if (!obj) return 0;
-    if (obj->oartifact && !touch_artifact(obj, &youmonst)) return 1;
+    if (!retouch_object(&obj, FALSE)) return 1;
     return arti_invoke(obj);
 }
 
@@ -1596,4 +1601,52 @@ int orc_count;
       }
 }
 
+/* called when hero is wielding/applying/invoking a carried item, or
+   after undergoing a transformation (alignment change, lycanthropy)
+   which might affect item access */
+int
+retouch_object(objp, loseit)
+struct obj **objp;     /* might be destroyed or unintentionally dropped */
+boolean loseit;                /* whether to drop it if hero can longer touch it */
+{
+    struct obj *obj = *objp;
+
+    if (touch_artifact(obj, &youmonst)) {
+       /* nothing to do if hero can successfully handle this object */
+       if (!(objects[obj->otyp].oc_material == SILVER &&
+               (u.ulycn >= LOW_PM || hates_silver(youmonst.data))))
+           return 1;
+       /* we didn't get "<obj> evades your grasp" message; give alt message */
+       You_cant("handle %s anymore!", thesimpleoname(obj));
+    }
+
+    /* removing a worn item might result in loss of levitation,
+       dropping the hero onto a polymorph trap or into water or
+       lava and potentially dropping or destroying the item */
+    if (obj->owornmask) {
+       struct obj *otmp;
+
+       remove_worn_item(obj, FALSE);
+       for (otmp = invent; otmp; otmp = otmp->nobj)
+           if (otmp == obj) break;
+       if (!otmp) *objp = obj = 0;
+    }
+
+    /* if we still have it and caller wants us to drop it, do so now */
+    if (loseit && obj) {
+       if (Levitation) {
+           freeinv(obj);
+           hitfloor(obj);
+       } else {
+           /* dropx gives a message iff item lands on an altar */
+           if (!IS_ALTAR(levl[u.ux][u.uy].typ))
+               pline("%s to the %s.",
+                     Tobjnam(obj, "drop"), surface(u.ux, u.uy));
+           dropx(obj);
+       }
+       *objp = obj = 0;        /* no longer in inventory */
+    }
+    return 0;
+}
+
 /*artifact.c*/
index 781f028dc1926f2b6c9b9d69364d20b0116fed25..d67cf1da82f21c0d7881d8d4e38493f65c868b7c 100644 (file)
--- a/src/eat.c
+++ b/src/eat.c
@@ -1152,11 +1152,9 @@ register int pm;
            break;
        }
 
-       if (catch_lycanthropy && defends(AD_WERE, uwep)) {
-           if (!touch_artifact(uwep, &youmonst)) {
-               dropx(uwep);
-               uwepgone();
-           }
+       if (catch_lycanthropy) {
+           if (u.twoweap) (void)retouch_object(&uswapwep, TRUE);
+           if (uwep) (void)retouch_object(&uwep, TRUE);
        }
 
        return;
@@ -2250,7 +2248,7 @@ struct obj *otmp;
 int
 doeat()                /* generic "eat" command funtion (see cmd.c) */
 {
-       register struct obj *otmp;
+       struct obj *otmp;
        int basenutrit;                 /* nutrition of full item */
        boolean dont_start = FALSE, nodelicious = FALSE;
        
@@ -2276,7 +2274,8 @@ doeat()           /* generic "eat" command funtion (see cmd.c) */
         * mails, players who polymorph back to human in the middle of their
         * metallic meal, etc....
         */
-       if (otmp->oartifact && !touch_artifact(otmp, &youmonst)) {
+       if (!(carried(otmp) ? retouch_object(&otmp, FALSE) :
+                             touch_artifact(otmp, &youmonst))) {
            return 1;
        } else if (!is_edible(otmp)) {
            You("cannot eat that!");
index 29dc2b101eb15ccd5e1922f4cd2f130ba175641b..96eed6609660550da60fa5ee4695b3675833837f 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)mhitu.c    3.5     2006/08/07      */
+/*     SCCS Id: @(#)mhitu.c    3.5     2007/03/09      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1230,6 +1230,8 @@ dopois:
                    You_feel("feverish.");
                    exercise(A_CON, FALSE);
                    u.ulycn = monsndx(mdat);
+                   if (u.twoweap) (void)retouch_object(&uswapwep, TRUE);
+                   if (uwep) (void)retouch_object(&uwep, TRUE);
                }
                break;
            case AD_SGLD:
index c0ac0319225db8b21ed5eaf2adc8de8e37169dc1..0c5f9708f8e9ed722a113fea1e04a279a738759c 100644 (file)
@@ -150,11 +150,11 @@ struct obj *wep;
        } else if (wep->otyp == CORPSE && cant_wield_corpse(wep)) {
            /* hero must have been life-saved to get here; use a turn */
            res++;      /* corpse won't be wielded */
-       } else if (uarms && bimanual(wep))
+       } else if (uarms && bimanual(wep)) {
            You("cannot wield a two-handed %s while wearing a shield.",
                is_sword(wep) ? "sword" :
                    wep->otyp == BATTLE_AXE ? "axe" : "weapon");
-       else if (wep->oartifact && !touch_artifact(wep, &youmonst)) {
+       } else if (!retouch_object(&wep, FALSE)) {
            res++;      /* takes a turn even though it doesn't get wielded */
        } else {
            /* Weapon WILL be wielded after this point */