From 65b5f2cff17001199d0493c114ffaea0f6f7e2df Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 19 Aug 2024 13:10:28 -0700 Subject: [PATCH] farlook & probing feedback for monsters in regions When looking at a monster that's inside a gas cloud, include that fact in the output for farlook and for probing. When the monster being examined is sensed rather than seen, you'll sense the presense of the cloud as well as the monster even if the cloud can't be seen. Do likewise for self when using look-here (':'). Bonus fix: zapping wand of probing at self while engulfed reported that you were just held by the engulfer. Also fix an old comment typo/thinko. --- include/hack.h | 3 ++- src/insight.c | 34 ++++++++++++++++++++++++++-------- src/invent.c | 21 ++++++++++++++++++--- src/pager.c | 38 ++++++++++++++++++++++++++++++++------ 4 files changed, 78 insertions(+), 18 deletions(-) diff --git a/include/hack.h b/include/hack.h index fdd7740a4..1d6e457d5 100644 --- a/include/hack.h +++ b/include/hack.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 hack.h $NHDT-Date: 1717878594 2024/06/08 20:29:54 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.257 $ */ +/* NetHack 3.7 hack.h $NHDT-Date: 1724094288 2024/08/19 19:04:48 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.261 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Pasi Kallinen, 2017. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1139,6 +1139,7 @@ typedef uint32_t mmflags_nht; /* makemon MM_ flags */ #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 */ +#define MHID_REGION 8 /* include region when mon is in one */ /* flags for make_corpse() and mkcorpstat(); 0..7 are recorded in obj->spe */ #define CORPSTAT_NONE 0x00 diff --git a/src/insight.c b/src/insight.c index fbc9fcacb..542857501 100644 --- a/src/insight.c +++ b/src/insight.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 insight.c $NHDT-Date: 1713334807 2024/04/17 06:20:07 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.112 $ */ +/* NetHack 3.7 insight.c $NHDT-Date: 1724094296 2024/08/19 19:04:56 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.115 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -3205,7 +3205,7 @@ mstatusline(struct monst *mtmp) if (mtmp->data == &mons[PM_LONG_WORM]) { int segndx, nsegs = count_wsegs(mtmp); - /* the worm code internals don't consider the head of be one of + /* the worm code internals don't consider the head to be one of the worm's segments, but we count it as such when presenting worm feedback to the player */ if (!nsegs) { @@ -3226,8 +3226,10 @@ mstatusline(struct monst *mtmp) Strcat(info, ", eating"); /* 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, MHID_PREFIX | MHID_ARTICLE | MHID_ALTMON, + if (mtmp->mundetected || mtmp->m_ap_type + || visible_region_at(gb.bhitpos.x, gb.bhitpos.y)) + mhidden_description(mtmp, + MHID_PREFIX | MHID_ARTICLE | MHID_ALTMON | MHID_REGION, eos(info)); if (mtmp->mcan) Strcat(info, ", cancelled"); @@ -3311,7 +3313,9 @@ mstatusline(struct monst *mtmp) void ustatusline(void) { + NhRegion *reg; char info[BUFSZ]; + size_t ln; info[0] = '\0'; if (Sick) { @@ -3366,15 +3370,29 @@ ustatusline(void) Strcat(info, Very_fast ? ", very fast" : ", fast"); if (u.uundetected) Strcat(info, ", concealed"); + else if (U_AP_TYPE != M_AP_NOTHING) + Strcat(info, ", disguised"); if (Invis) Strcat(info, ", invisible"); if (u.ustuck) { - if (sticks(gy.youmonst.data)) - Strcat(info, ", holding "); - else + if (u.uswallow) + Strcat(info, digests(u.ustuck->data) ? ", being digested by " + : ", engulfed by "); + else if (!sticks(gy.youmonst.data)) Strcat(info, ", held by "); - Strcat(info, mon_nam(u.ustuck)); + else + Strcat(info, ", holding "); + /* FIXME? a_monnam() uses x_monnam() which has a special case that + forces "the" instead of "a" when formatting u.ustuck while hero + is swallowed; we don't really want that here but it isn't worth + fiddling with just for self-probing while engulfed */ + Strcat(info, a_monnam(u.ustuck)); } + if (!u.uswallow + && (reg = visible_region_at(u.ux, u.uy)) != 0 + && (ln = strlen(info)) < sizeof info) + Snprintf(eos(info), sizeof info - ln, ", in a cloud of %s", + reg_damg(reg) ? "poison gas" : "vapor"); pline("Status of %s (%s): Level %d HP %d(%d) AC %d%s.", svp.plname, piousness(FALSE, align_str(u.ualign.type)), diff --git a/src/invent.c b/src/invent.c index 76df37740..07ccd98c2 100644 --- a/src/invent.c +++ b/src/invent.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 invent.c $NHDT-Date: 1702023269 2023/12/08 08:14:29 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.485 $ */ +/* NetHack 3.7 invent.c $NHDT-Date: 1724094299 2024/08/19 19:04:59 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.516 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -4658,8 +4658,23 @@ look_here( } return (!!Blind ? ECMD_TIME : ECMD_OK); } - if (!skip_objects && (trap = t_at(u.ux, u.uy)) && trap->tseen) - There("is %s here.", an(trapname(trap->ttyp, FALSE))); + if (!skip_objects) { + NhRegion *reg; + char regbuf[QBUFSZ]; + + regbuf[0] = '\0'; + if ((reg = visible_region_at(u.ux, u.uy)) != 0) + Sprintf(regbuf, "a %s cloud", + reg_damg(reg) ? "poison gas" : "vapor"); + if ((trap = t_at(u.ux, u.uy)) != 0 && !trap->tseen) + trap = (struct trap *) NULL; + + if (reg || trap) + There("is %s%s%s here.", + reg ? regbuf : "", + (reg && trap) ? " and " : "", + trap ? an(trapname(trap->ttyp, FALSE)) : ""); + } otmp = svl.level.objects[u.ux][u.uy]; dfeature = dfeature_at(u.ux, u.uy, fbuf2); diff --git a/src/pager.c b/src/pager.c index 1c93d494e..eff6bfd6b 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 pager.c $NHDT-Date: 1720565361 2024/07/09 22:49:21 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.275 $ */ +/* NetHack 3.7 pager.c $NHDT-Date: 1724094301 2024/08/19 19:05:01 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.279 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2018. */ /* NetHack may be freely redistributed. See license for details. */ @@ -118,8 +118,10 @@ self_lookat(char *outbuf) pmname(&mons[u.umonnum], Ugender), svp.plname); if (u.usteed) Sprintf(eos(outbuf), ", mounted on %s", y_monnam(u.usteed)); - if (u.uundetected || (Upolyd && U_AP_TYPE)) - mhidden_description(&gy.youmonst, MHID_PREFIX | MHID_ARTICLE, + if (u.uundetected || (Upolyd && U_AP_TYPE) + || visible_region_at(u.ux, u.uy)) + mhidden_description(&gy.youmonst, + MHID_PREFIX | MHID_ARTICLE | MHID_REGION, eos(outbuf)); if (Punished) Sprintf(eos(outbuf), ", chained to %s", @@ -187,9 +189,12 @@ mhidden_description( { struct obj *otmp; const char *what; + NhRegion *reg; + size_t buflen; boolean incl_prefix = (mhid_flags & MHID_PREFIX) != 0, incl_article = (mhid_flags & MHID_ARTICLE) != 0, - show_altmon = (mhid_flags & MHID_ALTMON) != 0; + show_altmon = (mhid_flags & MHID_ALTMON) != 0, + force_region = (mhid_flags & MHID_REGION) != 0; boolean fakeobj, isyou = (mon == &gy.youmonst); coordxy x = isyou ? u.ux : mon->mx, y = isyou ? u.uy : mon->my; int glyph = (svl.level.flags.hero_memory && !isyou) ? levl[x][y].glyph @@ -251,6 +256,26 @@ mhidden_description( Strcat(outbuf, " in murky water"); } } + + /* FIXME: isn't right when looking at long worm tails */ + if ((reg = visible_region_at(x, y)) != 0 + && (buflen = strlen(outbuf)) < BUFSZ - 1) { + int r = (u.xray_range > 1) ? u.xray_range : 1; + + /* at present, hero must be next to the monster; being able to see + from the hero's spot to the monster's spot would be much better, + but a visible region marks all its spots as can't-be-seen, so + this monster's spot is !cansee and !couldsee [maybe we need an + additional vision bit for "hero's side of edge of gas cloud"?] */ + if (distu(x, y) <= r * (r + 1) || force_region) { + int rglyph = reg->glyph; + boolean poison_gas = (glyph_is_cmap(rglyph) + && glyph_to_cmap(rglyph) == S_poisoncloud); + + Snprintf(eos(outbuf), BUFSZ - buflen, ", in a cloud of %s", + poison_gas ? "poison gas" : "vapor"); + } + } } /* extracted from lookat(); also used by namefloorobj() */ @@ -424,8 +449,9 @@ 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, MHID_PREFIX | MHID_ARTICLE, eos(buf)); + if (mtmp->mundetected || M_AP_TYPE(mtmp) || visible_region_at(x, y)) + mhidden_description(mtmp, MHID_PREFIX | MHID_ARTICLE | MHID_REGION, + eos(buf)); if (monbuf) { unsigned how_seen = howmonseen(mtmp);