diff --git a/include/extern.h b/include/extern.h index c3f64a34b..7de27aee2 100644 --- a/include/extern.h +++ b/include/extern.h @@ -3350,6 +3350,7 @@ extern boolean mhitm_knockback(struct monst *, struct monst *,struct attack *, extern int passive(struct monst *, struct obj *, boolean, boolean, uchar, boolean) NONNULLARG1; extern void passive_obj(struct monst *, struct obj *, struct attack *) NONNULLARG1; +extern void that_is_a_mimic(struct monst *, boolean) NONNULLARG1; extern void stumble_onto_mimic(struct monst *) NONNULLARG1; extern int flash_hits_mon(struct monst *, struct obj *) NONNULLARG12; extern void light_hits_gremlin(struct monst *, int) NONNULLARG1; diff --git a/src/uhitm.c b/src/uhitm.c index 6cc8af687..2d1715bf6 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -6032,20 +6032,17 @@ passive_obj( DISABLE_WARNING_FORMAT_NONLITERAL -/* Note: caller must ascertain mtmp is mimicking... */ +/* used by stuble_onto_mimic() and bhitm() cases WAN_LOCKING, WAN_OPENING */ void -stumble_onto_mimic(struct monst *mtmp) +that_is_a_mimic( + struct monst *mtmp, /* a hidden mimic (nonnull) */ + boolean reveal_it) /* True: remove its disguise */ { static char generic[] = "a monster"; - char fmt[QBUFSZ]; + char fmtbuf[BUFSZ]; const char *what = NULL; - Strcpy(fmt, "Wait! That's %s!"); - if (!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data, AD_STCK) - /* must be adjacent; attack via polearm could be from farther away */ - && m_next2u(mtmp)) - set_ustuck(mtmp); - + Strcpy(fmtbuf, "Wait! That's %s!"); if (Blind) { if (!Blind_telepat) what = generic; /* with default fmt */ @@ -6055,11 +6052,9 @@ stumble_onto_mimic(struct monst *mtmp) int glyph = levl[u.ux + u.dx][u.uy + u.dy].glyph; if (glyph_is_cmap(glyph)) { - Sprintf(fmt, "%s %s actually is %%s!", - is_cmap_stairs(glyph) ? "Those" : "That", - defsyms[mtmp->mappearance].explanation); - /* BUG: this will misclassify a paralyzed mimic as sleeping */ - what = x_monnam(mtmp, ARTICLE_A, "sleeping", 0, FALSE); + /* note: defsyms[stairs] yields singular "staircase {up|down}" */ + Snprintf(fmtbuf, sizeof fmtbuf, "That %s actually is %%s!", + defsyms[mtmp->mappearance].explanation); } else if (glyph_is_object(glyph)) { boolean fakeobj; const char *otmp_name; @@ -6068,9 +6063,9 @@ stumble_onto_mimic(struct monst *mtmp) fakeobj = object_from_map(glyph, mtmp->mx, mtmp->my, &otmp); otmp_name = (otmp && otmp->otyp != STRANGE_OBJECT) ? simpleonames(otmp) : "strange object"; - Sprintf(fmt, "%s %s %s %%s!", - otmp && is_plural(otmp) ? "Those" : "That", - otmp_name, otmp ? otense(otmp, "are") : "is"); + Snprintf(fmtbuf, sizeof fmtbuf, "%s %s %s %%s!", + (otmp && is_plural(otmp)) ? "Those" : "That", + otmp_name, otmp ? otense(otmp, "are") : "is"); if (fakeobj && otmp) { otmp->where = OBJ_FREE; /* object_from_map set to OBJ_FLOOR */ dealloc_obj(otmp); @@ -6090,8 +6085,25 @@ stumble_onto_mimic(struct monst *mtmp) else what = a_monnam(mtmp); } + if (what) - pline(fmt, what); + pline(fmtbuf, what); + if (reveal_it) + seemimic(mtmp); +} + +RESTORE_WARNING_FORMAT_NONLITERAL + +/* Note: caller must ascertain mtmp is mimicking... */ +void +stumble_onto_mimic(struct monst *mtmp) +{ + that_is_a_mimic(mtmp, TRUE); + + if (!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data, AD_STCK) + /* must be adjacent; attack via polearm could be from farther away */ + && m_next2u(mtmp)) + set_ustuck(mtmp); wakeup(mtmp, FALSE); /* clears mimicking */ /* if hero is blind, wakeup() won't display the monster even though @@ -6101,8 +6113,6 @@ stumble_onto_mimic(struct monst *mtmp) map_invisible(mtmp->mx, mtmp->my); } -RESTORE_WARNING_FORMAT_NONLITERAL - staticfn void nohandglow(struct monst *mon) { diff --git a/src/zap.c b/src/zap.c index 59c871edc..84cc79561 100644 --- a/src/zap.c +++ b/src/zap.c @@ -167,6 +167,15 @@ bhitm(struct monst *mtmp, struct obj *otmp) struct obj *obj; boolean disguised_mimic = (mtmp->data->mlet == S_MIMIC && M_AP_TYPE(mtmp) != M_AP_NOTHING); + /* box_or_door(): mimic appearances that have locks */ +#define box_or_door(monst) \ + ((M_AP_TYPE(monst) == M_AP_OBJECT \ + && ((monst)->mappearance == CHEST \ + || (monst)->mappearance == LARGE_BOX)) \ + || (M_AP_TYPE(monst) == M_AP_FURNITURE \ + /* is_cmap_door() tests S_symbol values, and */ \ + /* mon->mappearance for furniture contains one of those */ \ + && is_cmap_door((monst)->mappearance))) if (engulfing_u(mtmp)) reveal_invis = FALSE; @@ -355,10 +364,8 @@ bhitm(struct monst *mtmp, struct obj *otmp) } case WAN_LOCKING: case SPE_WIZARD_LOCK: - /* can't use Is_box() here */ - if (disguised_mimic && (is_obj_mappear(mtmp, CHEST) - || is_obj_mappear(mtmp, LARGE_BOX))) - seemimic(mtmp); + if (disguised_mimic && box_or_door(mtmp)) + that_is_a_mimic(mtmp, TRUE); /*seemimic()*/ wake = closeholdingtrap(mtmp, &learn_it); break; case WAN_PROBING: @@ -369,9 +376,8 @@ bhitm(struct monst *mtmp, struct obj *otmp) break; case WAN_OPENING: case SPE_KNOCK: - if (disguised_mimic && (is_obj_mappear(mtmp, CHEST) - || is_obj_mappear(mtmp, LARGE_BOX))) - seemimic(mtmp); + if (disguised_mimic && box_or_door(mtmp)) + that_is_a_mimic(mtmp, TRUE); /*seemimic()*/ wake = FALSE; /* don't want immediate counterattack */ if (mtmp == u.ustuck) { /* zapping either holder/holdee or self [zapyourself()] will @@ -541,6 +547,7 @@ bhitm(struct monst *mtmp, struct obj *otmp) if (learn_it) learnwand(otmp); return ret; +#undef box_or_door } /* hero is held by a monster or engulfed or holding a monster and has zapped @@ -1768,10 +1775,9 @@ poly_obj(struct obj *obj, int id) /* Keep chest/box traps and poisoned ammo if we may */ if (obj->otrapped && Is_box(otmp)) - otmp->otrapped = TRUE; - + otmp->otrapped = 1; if (obj->opoisoned && is_poisonable(otmp)) - otmp->opoisoned = TRUE; + otmp->opoisoned = 1; if (id == STRANGE_OBJECT && obj->otyp == CORPSE) { /* turn crocodile corpses into shoes */