From 13012340393b6f57772b3838cb720d3fdd7425c1 Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 2 Dec 2024 11:37:04 -0800 Subject: [PATCH] mimic feedback tuning When a mimic in door form is hit by a wand of locking or wand of opening or corresponding spell, bring it out of concealment like was recently done for being zapped while in chest form. And give some feedback rather than just changing the mimic's form to 'm'. Give more detailed feedback when bumping into a mimic while moving. --- include/extern.h | 1 + src/uhitm.c | 50 +++++++++++++++++++++++++++++------------------- src/zap.c | 26 +++++++++++++++---------- 3 files changed, 47 insertions(+), 30 deletions(-) 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 */