diff --git a/doc/fixes35.0 b/doc/fixes35.0 index f4fdb603a..776ec1947 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -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 diff --git a/include/extern.h b/include/extern.h index 2e599816b..4b36a5a6e 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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)); diff --git a/src/lock.c b/src/lock.c index 0fce4639c..c90793cdc 100644 --- a/src/lock.c +++ b/src/lock.c @@ -406,6 +406,8 @@ pick_lock(pick) mtmp->mappearance == S_hcdoor)) { /* "The door actually was a !" */ 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)) { diff --git a/src/steal.c b/src/steal.c index fa1f49a32..bfe773572 100644 --- a/src/steal.c +++ b/src/steal.c @@ -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)