]> granicus.if.org Git - nethack/commitdiff
mimic-as-door stealing key (trunk only)
authornethack.rankin <nethack.rankin>
Thu, 3 Feb 2011 21:49:36 +0000 (21:49 +0000)
committernethack.rankin <nethack.rankin>
Thu, 3 Feb 2011 21:49:36 +0000 (21:49 +0000)
     Suggested by <email deleted> a month ago when he
reported that attempting to unlock a door which was actually a mimic
simply told the player that the door was not locked or that there was
no door.  He thought that mimic should take the key/pick/card away from
the hero.  This gives a 50% chance for the unlocking tool to be stolen
and become part of the mimic's inventory; it will be dropped when mimic
is killed.

     The theft routine has groundwork to be able to be used to take the
hero's wielded or thrown weapon when hitting, but the attack code doesn't
call it so that won't happen (and the theft code hasn't been tested under
that circumstance).  I'm not sure whether mimics should be able to grab
weapons, but g.cubes perhaps should, and if puddings could then "pudding
farming" [using a low damage iron weapon to split puddings, yielding tons
of experience, death drops, and #offer fodder when they're killed and
repeatable for as long as at least one pudding is kept healthy enough to
be split again] would become tougher to accomplish.  [The item drop and
corpse aspects have been toned down quite a bit since 3.4.3, but with
sufficient patience it is still possible to abuse.]

doc/fixes35.0
include/extern.h
src/lock.c
src/steal.c

index f4fdb603a10a9590f2900fab60e7a3549395f414..776ec19470bb309058767b09de856184da61ae48 100644 (file)
@@ -467,6 +467,7 @@ Add M-C and M-R meta-key shortcuts for #conduct and #ride, respectively
 can now use ESC to cancel out of prompts for playing musical instruments
 being crowned gives an additional benefit:  one extra skill slot/credit
 chatting to a gecko or shopkeeper while hallucinating gives alternate message
+mimic posing as door might steal hero's key when [un]locking is attempted
 
 
 Platform- and/or Interface-Specific New Features
index 2e599816be88ff4e8bcd0c9d1044c0081f0d9e3c..4b36a5a6e9b22daeb7e2f9d20ef46873eb55d51b 100644 (file)
@@ -2171,6 +2171,7 @@ E void FDECL(remove_worn_item, (struct obj *,BOOLEAN_P));
 E int FDECL(steal, (struct monst *, char *));
 E int FDECL(mpickobj, (struct monst *,struct obj *));
 E void FDECL(stealamulet, (struct monst *));
+E void FDECL(maybe_absorb_item, (struct monst *,struct obj *,int,int));
 E void FDECL(mdrop_obj, (struct monst *,struct obj *,BOOLEAN_P));
 E void FDECL(mdrop_special_objs, (struct monst *));
 E void FDECL(relobj, (struct monst *,int,BOOLEAN_P));
index 0fce4639c200f2c1237e2f44d23e7837093e64be..c90793cdc63ce6a5c3a2f2220cc8ba0857791dc1 100644 (file)
@@ -406,6 +406,8 @@ pick_lock(pick)
                         mtmp->mappearance == S_hcdoor)) {
                /* "The door actually was a <mimic>!" */
                stumble_onto_mimic(mtmp);
+               /* mimic might keep the key (50% chance, 10% for PYEC) */
+               maybe_absorb_item(mtmp, pick, 50, 10);
                return PICKLOCK_LEARNED_SOMETHING;
            }
            if(!IS_DOOR(door->typ)) {
index fa1f49a326d04eb11d09f9441cd6a3441e7e1cda..bfe773572d9294010786a2a66cb8a6070cb1ebc3 100644 (file)
@@ -509,6 +509,10 @@ register struct obj *otmp;
            pline("%s out.", Tobjnam(otmp, "go"));
        snuff_otmp = TRUE;
     }
+    /* if monster is acquiring a thrown or kicked object, the throwing
+       or kicking code shouldn't continue to track and place it */
+    if (otmp == thrownobj) thrownobj = 0;
+    else if (otmp == kickedobj) kickedobj = 0;
     /* for hero owned object on shop floor, mtmp is taking possession
        and if it's eventually dropped in a shop, shk will claim it */
     if (!mtmp->mtame) otmp->no_charge = 0;
@@ -571,6 +575,46 @@ struct monst *mtmp;
     }
 }
 
+/* when a mimic gets poked with something, it might take that thing
+   (at present, only implemented for when the hero does the poking) */
+void
+maybe_absorb_item(mon, obj, ochance, achance)
+struct monst *mon;
+struct obj *obj;
+int ochance, achance;  /* percent chance for ordinary item, artifact */
+{
+    if (obj == uball || obj == uchain || obj->oclass == ROCK_CLASS ||
+           obj_resists(obj, 100 - ochance, 100 - achance) ||
+           !touch_artifact(obj, mon))
+       return;
+
+    if (carried(obj)) {
+       if (obj->owornmask) remove_worn_item(obj, TRUE);
+       if (obj->unpaid) subfrombill(obj, shop_keeper(*u.ushops));
+       if (cansee(mon->mx, mon->my)) {
+           const char *MonName = Monnam(mon);
+
+           /* mon might be invisible; avoid "It pulls ... and absorbs it!" */
+           if (!strcmp(MonName, "It")) MonName = "Something";
+           pline("%s pulls %s away from you and absorbs %s!",
+                 MonName, yname(obj), (obj->quan > 1L) ? "them" : "it");
+       } else {
+           const char *hand_s = body_part(HAND);
+
+           if (bimanual(obj)) hand_s = makeplural(hand_s);
+           pline("%s %s pulled from your %s!",
+                 upstart(yname(obj)), otense(obj, "are"), hand_s);
+       }
+       freeinv(obj);
+    } else {
+       /* not carried; presumeably thrown or kicked */
+       if (canspotmon(mon))
+           pline("%s absorbs %s!", Monnam(mon), yname(obj));
+    }
+    /* add to mon's inventory */
+    (void) mpickobj(mon, obj);
+}
+
 /* drop one object taken from a (possibly dead) monster's inventory */
 void
 mdrop_obj(mon, obj, verbosely)