From 29b4c47bdf3a27312c4774c07a18d0d0d8c20c9a Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 16 Apr 2024 23:34:26 -0700 Subject: [PATCH] fix #K4142 - camera flash vs mimic When a camera flash hit a mimic which was posing as something, the feedback mentioned the mimic but didn't bring it out of hiding. Change to make light pass over a mimic impersonating an object but unhide one impersonating furniture. Ones impersonating some other monster are woken up but wakeup doesn't force it back to mimic shape. Trying to get the messages right brought on more code changes than antipated. I changed one of the arguments to mhidden_description() so had to change its callers; fortunately there aren't very many. --- doc/fixes3-7-0.txt | 4 +++- include/extern.h | 4 ++-- include/hack.h | 7 ++++++- src/insight.c | 5 +++-- src/makemon.c | 6 +++--- src/pager.c | 50 +++++++++++++++++++++++++++++++--------------- src/uhitm.c | 30 +++++++++++++++++++++++++--- src/zap.c | 30 ++++++++++++++++------------ 8 files changed, 95 insertions(+), 41 deletions(-) diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index ed271dfad..0f3a7a97f 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -1,4 +1,4 @@ -NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1416 $ $NHDT-Date: 1712453344 2024/04/07 01:29:04 $ +NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1427 $ $NHDT-Date: 1713334798 2024/04/17 06:19:58 $ General Fixes and Modified Features ----------------------------------- @@ -1929,6 +1929,8 @@ if a tame or peaceful monster was trapped and blind hero hadn't seen the trap yet, attempting to swap places would report "You stop. can't move out of that trap." and if the 'tips' option was On, #untrap would be suggested; but #untrap would fail due "you know of no traps there" +camera flash hitting a hidden mimic mentioned it as being a mimic but didn't + bring it out of hiding Fixes to 3.7.0-x Platform and/or Interface Problems Exposed Via git Repository diff --git a/include/extern.h b/include/extern.h index 113984202..28c8c8c8b 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 extern.h $NHDT-Date: 1711213872 2024/03/23 17:11:12 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1400 $ */ +/* NetHack 3.7 extern.h $NHDT-Date: 1713334799 2024/04/17 06:19:59 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1420 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2243,7 +2243,7 @@ extern void msgtype_free(void); extern char *self_lookat(char *) NONNULL NONNULLARG1; extern char *monhealthdescr(struct monst *mon, boolean, char *) NONNULL NONNULLARG3; -extern void mhidden_description(struct monst *, boolean, char *) NONNULLPTRS; +extern void mhidden_description(struct monst *, unsigned, char *) NONNULLPTRS; extern boolean object_from_map(int, coordxy, coordxy, struct obj **) NONNULLPTRS; extern const char *waterbody_name(coordxy, coordxy) NONNULL; diff --git a/include/hack.h b/include/hack.h index 7069141dc..5bf4fa9d3 100644 --- a/include/hack.h +++ b/include/hack.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 hack.h $NHDT-Date: 1701132211 2023/11/28 00:43:31 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.240 $ */ +/* NetHack 3.7 hack.h $NHDT-Date: 1713334806 2024/04/17 06:20:06 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.253 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Pasi Kallinen, 2017. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1102,6 +1102,11 @@ typedef uint32_t mmflags_nht; /* makemon MM_ flags */ #define GP_AVOID_MONPOS 0x01000000L /* don't accept existing mon location */ /* 25 bits used */ +/* flags for mhidden_description() (pager.c; used for mimics and hiders) */ +#define MHID_PREFIX 1 /* include ", mimicking " prefix */ +#define MHID_ARTICLE 2 /* include "a " or "an " after prefix */ +#define MHID_ALTMON 4 /* if mimicking a monster, include that */ + /* flags for make_corpse() and mkcorpstat(); 0..7 are recorded in obj->spe */ #define CORPSTAT_NONE 0x00 #define CORPSTAT_GENDER 0x03 /* 0x01 | 0x02 */ diff --git a/src/insight.c b/src/insight.c index 70f701046..8d44962d3 100644 --- a/src/insight.c +++ b/src/insight.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 insight.c $NHDT-Date: 1702023267 2023/12/08 08:14:27 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.104 $ */ +/* NetHack 3.7 insight.c $NHDT-Date: 1713334807 2024/04/17 06:20:07 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.112 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -3227,7 +3227,8 @@ mstatusline(struct monst *mtmp) /* a stethoscope exposes mimic before getting here so this won't be relevant for it, but wand of probing doesn't */ if (mtmp->mundetected || mtmp->m_ap_type) - mhidden_description(mtmp, TRUE, eos(info)); + mhidden_description(mtmp, MHID_PREFIX | MHID_ARTICLE | MHID_ALTMON, + eos(info)); if (mtmp->mcan) Strcat(info, ", cancelled"); if (mtmp->mconf) diff --git a/src/makemon.c b/src/makemon.c index d99649229..5027efcaa 100644 --- a/src/makemon.c +++ b/src/makemon.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 makemon.c $NHDT-Date: 1695327268 2023/09/21 20:14:28 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.227 $ */ +/* NetHack 3.7 makemon.c $NHDT-Date: 1713334814 2024/04/17 06:20:14 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.245 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1464,8 +1464,8 @@ makemon( exclaim = TRUE; } else if (canseemon(mtmp)) { /* mimic masquerading as furniture or object and not sensed */ - mhidden_description(mtmp, FALSE, mbuf); - what = upstart(strsubst(mbuf, ", mimicking ", "")); + mhidden_description(mtmp, MHID_ARTICLE | MHID_ALTMON, mbuf); + what = upstart(mbuf); } if (what) { set_msg_xy(mtmp->mx, mtmp->my); diff --git a/src/pager.c b/src/pager.c index 3b25511c9..c1536421e 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 pager.c $NHDT-Date: 1702349268 2023/12/12 02:47:48 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.266 $ */ +/* NetHack 3.7 pager.c $NHDT-Date: 1713334816 2024/04/17 06:20:16 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.274 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2018. */ /* NetHack may be freely redistributed. See license for details. */ @@ -119,7 +119,8 @@ self_lookat(char *outbuf) if (u.usteed) Sprintf(eos(outbuf), ", mounted on %s", y_monnam(u.usteed)); if (u.uundetected || (Upolyd && U_AP_TYPE)) - mhidden_description(&gy.youmonst, FALSE, eos(outbuf)); + mhidden_description(&gy.youmonst, MHID_PREFIX | MHID_ARTICLE, + eos(outbuf)); if (Punished) Sprintf(eos(outbuf), ", chained to %s", uball ? ansimpleoname(uball) : "nothing?"); @@ -177,34 +178,46 @@ trap_description(char *outbuf, int tnum, coordxy x, coordxy y) } /* describe a hidden monster; used for look_at during extended monster - detection and for probing; also when looking at self */ + detection and for probing; also when looking at self and camera feedback */ void mhidden_description( - struct monst *mon, - boolean altmon, /* for probing: if mimicking a monster, say so */ - char *outbuf) + struct monst *mon, /* hidden monster to describe */ + unsigned mhid_flags, /* controls optional aspects of description */ + char *outbuf) /* output buffer */ { struct obj *otmp; + const char *what; + boolean incl_prefix = (mhid_flags & MHID_PREFIX) != 0, + incl_article = (mhid_flags & MHID_ARTICLE) != 0, + show_altmon = (mhid_flags & MHID_ALTMON) != 0; boolean fakeobj, isyou = (mon == &gy.youmonst); coordxy x = isyou ? u.ux : mon->mx, y = isyou ? u.uy : mon->my; int glyph = (gl.level.flags.hero_memory && !isyou) ? levl[x][y].glyph - : glyph_at(x, y); + : glyph_at(x, y); *outbuf = '\0'; if (M_AP_TYPE(mon) == M_AP_FURNITURE || M_AP_TYPE(mon) == M_AP_OBJECT) { - Strcpy(outbuf, ", mimicking "); + if (incl_prefix) + Strcpy(outbuf, ", mimicking "); if (M_AP_TYPE(mon) == M_AP_FURNITURE) { - Strcat(outbuf, an(defsyms[mon->mappearance].explanation)); + what = defsyms[mon->mappearance].explanation; + if (incl_article) + what = an(what); + Strcat(outbuf, what); } else if (M_AP_TYPE(mon) == M_AP_OBJECT /* remembered glyph, not glyph_at() which is 'mon' */ && glyph_is_object(glyph)) { objfrommap: otmp = (struct obj *) 0; fakeobj = object_from_map(glyph, x, y, &otmp); - Strcat(outbuf, (otmp && otmp->otyp != STRANGE_OBJECT) - ? ansimpleoname(otmp) - : an(obj_descr[STRANGE_OBJECT].oc_name)); + what = (otmp && otmp->otyp != STRANGE_OBJECT) + ? simpleonames(otmp) + : obj_descr[STRANGE_OBJECT].oc_name; + if (incl_article) + what = an(what); + Strcat(outbuf, what); + if (fakeobj && otmp) { otmp->where = OBJ_FREE; /* object_from_map set to OBJ_FLOOR */ dealloc_obj(otmp); @@ -213,9 +226,14 @@ mhidden_description( Strcat(outbuf, something); } } else if (M_AP_TYPE(mon) == M_AP_MONSTER) { - if (altmon) - Sprintf(outbuf, ", masquerading as %s", - an(pmname(&mons[mon->mappearance], Mgender(mon)))); + if (show_altmon) { + if (incl_prefix) + Strcat(outbuf, ", masquerading as "); + what = pmname(&mons[mon->mappearance], Mgender(mon)); + if (incl_prefix) + what = an(what); + Strcat(outbuf, what); + } } else if (isyou ? u.uundetected : mon->mundetected) { Strcpy(outbuf, ", hiding"); if (hides_under(mon->data)) { @@ -407,7 +425,7 @@ look_at_monster( /* we know the hero sees a monster at this location, but if it's shown due to persistent monster detection he might remember something else */ if (mtmp->mundetected || M_AP_TYPE(mtmp)) - mhidden_description(mtmp, FALSE, eos(buf)); + mhidden_description(mtmp, MHID_PREFIX | MHID_ARTICLE, eos(buf)); if (monbuf) { unsigned how_seen = howmonseen(mtmp); diff --git a/src/uhitm.c b/src/uhitm.c index 8990cd70f..adf0cd0eb 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 uhitm.c $NHDT-Date: 1711484961 2024/03/26 20:29:21 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.443 $ */ +/* NetHack 3.7 uhitm.c $NHDT-Date: 1713334817 2024/04/17 06:20:17 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.444 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -6092,8 +6092,9 @@ nohandglow(struct monst *mon) /* returns 1 if light flash has noticeable effect on 'mtmp', 0 otherwise */ int -flash_hits_mon(struct monst *mtmp, - struct obj *otmp) /* source of flash */ +flash_hits_mon( + struct monst *mtmp, + struct obj *otmp) /* source of flash */ { struct rm *lev; int tmp, amt, useeit, res = 0; @@ -6103,6 +6104,29 @@ flash_hits_mon(struct monst *mtmp, lev = &levl[mtmp->mx][mtmp->my]; useeit = canseemon(mtmp); + if (M_AP_TYPE(mtmp) != M_AP_NOTHING) { + char whatbuf[BUFSZ]; + coordxy x = mtmp->mx, y = mtmp->my; + int oldglyph = glyph_at(x, y); + + /* 'altmon' probably doesn't matter here because 'whatbuf' will + only be shown if the glyph changes and wakeup() doesn't call + seemimic() for M_AP_MONSTER */ + mhidden_description(mtmp, MHID_ALTMON, whatbuf); + + wakeup(mtmp, FALSE); /* -> seemimic() -> newsym(); also calls + * finish_meating() to end quickmimic */ + + /* if glyph has changed then hero saw something happen */ + if (glyph_at(x, y) != oldglyph) + pline("That %s is really %s%c", whatbuf, + /* y_monnam()+a_monnam() */ + x_monnam(mtmp, mtmp->mtame ? ARTICLE_YOUR : ARTICLE_A, + (char *) 0, 0, FALSE), + mtmp->mtame ? '.' : '!'); + res = 1; /* mtmp is affected whether hero sees it or not */ + } + if (mtmp->msleeping && haseyes(mtmp->data)) { mtmp->msleeping = 0; if (useeit) { diff --git a/src/zap.c b/src/zap.c index bb15a6094..7e341c630 100644 --- a/src/zap.c +++ b/src/zap.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 zap.c $NHDT-Date: 1710344449 2024/03/13 15:40:49 $ $NHDT-Branch: keni-staticfn $:$NHDT-Revision: 1.525 $ */ +/* NetHack 3.7 zap.c $NHDT-Date: 1713334819 2024/04/17 06:20:19 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.532 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -423,7 +423,7 @@ bhitm(struct monst *mtmp, struct obj *otmp) mcureblindness(mtmp, canseemon(mtmp)); if (canseemon(mtmp)) { if (disguised_mimic) { - if (is_obj_mappear(mtmp,STRANGE_OBJECT)) { + if (is_obj_mappear(mtmp, STRANGE_OBJECT)) { /* it can do better now */ set_mimic_sym(mtmp); newsym(mtmp->mx, mtmp->my); @@ -3871,27 +3871,31 @@ bhit( } /* if mtmp is a shade and missile passes harmlessly through it, - give message and skip it in order to keep going */ - if (mtmp && (weapon == THROWN_WEAPON || weapon == KICKED_WEAPON) - && shade_miss(&gy.youmonst, mtmp, obj, TRUE, TRUE)) + give message and skip it in order to keep going; + if attack is light and mtmp is a mimic pretending to be an + object, behave as if there is no monster here (if pretending + to be furniture, it will be revealed by flash_hits_mon()) */ + if (mtmp && (((weapon == THROWN_WEAPON || weapon == KICKED_WEAPON) + && shade_miss(&gy.youmonst, mtmp, obj, TRUE, TRUE)) + || (weapon == FLASHED_LIGHT + && M_AP_TYPE(mtmp) == M_AP_OBJECT))) mtmp = (struct monst *) 0; if (mtmp) { gn.notonhead = (x != mtmp->mx || y != mtmp->my); if (weapon == FLASHED_LIGHT) { - /* FLASHED_LIGHT hitting invisible monster should - pass through instead of stop so we call - flash_hits_mon() directly rather than returning - mtmp back to caller. That allows the flash to - keep on going. Note that we use mtmp->minvis - not canspotmon() because it makes no difference - whether the hero can see the monster or not. */ + /* FLASHED_LIGHT hitting invisible monster should pass + through instead of stop so we call flash_hits_mon() + directly rather than returning mtmp back to caller. + That allows the flash to keep on going. Note that we + use mtmp->minvis not canspotmon() because it makes no + difference whether hero can see the monster or not. */ if (mtmp->minvis) { obj->ox = u.ux, obj->oy = u.uy; (void) flash_hits_mon(mtmp, obj); } else { tmp_at(DISP_END, 0); - result = mtmp; /* caller will call flash_hits_mon */ + result = mtmp; /* caller will call flash_hits_mon() */ goto bhit_done; } } else if (weapon == INVIS_BEAM) {