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.
This commit is contained in:
PatR
2024-04-16 23:34:26 -07:00
parent e20774e16f
commit 29b4c47bdf
8 changed files with 95 additions and 41 deletions

View File

@@ -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)

View File

@@ -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);

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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) {