From f7853be3dc9732b595d46d2c3b514c06a8534eba Mon Sep 17 00:00:00 2001 From: nhmall Date: Thu, 19 Dec 2024 17:53:43 -0500 Subject: [PATCH] fix GitHub issue 1303 related to engravings GitHub issue reported by ars3niy: https://github.com/NetHack/NetHack/issues/1303 @ars3niy commented on Oct 27: Stepping on a square with a dust or "graffiti" engraving while blind produces no message because presumably you can't read them by swiping the floor with your hands, however the engraving glyph still shows up on the map afterwards. While this helps zen players, it looks like a bug. @ville-v commented 3 days ago: Searching while blind also reveals the engravings. Here is a save file demonstrating the issue. [...] This adds an erevealed bit to engravings, to accompany the the eread bit that is already there. eread: refers to the text of the engraving erevealed: refers to the engraving map symbol Hopefully, this resolves issue 1303 without creating additional bugs. This invalidates existing save files and bones. Fixes #1303 --- include/engrave.h | 5 ++-- include/extern.h | 1 + src/display.c | 59 +++++++++++++++++++++++++++++------------------ src/engrave.c | 36 +++++++++++++++++++++++++++-- 4 files changed, 74 insertions(+), 27 deletions(-) diff --git a/include/engrave.h b/include/engrave.h index c0a53a6df..00fd586e1 100644 --- a/include/engrave.h +++ b/include/engrave.h @@ -33,8 +33,9 @@ struct engr { * even when hero isn't (so behaves similarly * to how Elbereth did in 3.4.3) */ Bitfield(nowipeout, 1); /* this engraving will not degrade */ - Bitfield(eread, 1); /* the engraving text has been read or felt */ - /* 5 free bits */ + Bitfield(eread, 1); /* refers to the engaving text: read or felt */ + Bitfield(erevealed, 1); /* refers to engraving map symbol: revealed */ + /* 4 free bits */ }; #define newengr(lth) \ diff --git a/include/extern.h b/include/extern.h index 84d61a8e1..932e95514 100644 --- a/include/extern.h +++ b/include/extern.h @@ -969,6 +969,7 @@ extern void make_grave(coordxy, coordxy, const char *); extern void disturb_grave(coordxy, coordxy); extern void see_engraving(struct engr *) NONNULLARG1; extern void feel_engraving(struct engr *) NONNULLARG1; +extern boolean engr_can_be_felt(struct engr *) NONNULLARG1; /* ### exper.c ### */ diff --git a/src/display.c b/src/display.c index 0e9cca612..f47e63062 100644 --- a/src/display.c +++ b/src/display.c @@ -420,10 +420,12 @@ unmap_object(coordxy x, coordxy y) struct rm *lev = &levl[x][y]; if (spot_shows_engravings(x, y) - && (ep = engr_at(x, y)) != 0 && !covers_traps(x, y)) + && (ep = engr_at(x, y)) != 0 && !covers_traps(x, y)) { + ep->erevealed = 0; map_engraving(ep, 0); - else + } else { map_background(x, y, 0); + } /* turn remembered dark room squares dark */ if (!lev->waslit && lev->glyph == cmap_to_glyph(S_room) @@ -443,26 +445,29 @@ unmap_object(coordxy x, coordxy y) * Internal to display.c, this is a #define for speed. */ #define _map_location(x, y, show) \ - do { \ - struct obj *obj; \ - struct trap *trap; \ - struct engr *ep; \ - NhRegion *_ml_reg; \ - \ - if ((obj = vobj_at(x, y)) && !covers_objects(x, y)) \ - map_object(obj, show); \ - else if ((trap = t_at(x, y)) && trap->tseen && !covers_traps(x, y)) \ - map_trap(trap, show); \ - else if (spot_shows_engravings(x, y) \ - && (ep = engr_at(x, y)) != 0 \ - && !covers_traps(x, y)) \ - map_engraving(ep, show); \ - else \ - map_background(x, y, show); \ - \ - update_lastseentyp(x, y); \ - if (show && !Blind && (_ml_reg = visible_region_at(x, y)) != 0) \ - show_region(_ml_reg, x, y); \ + do { \ + struct obj *obj; \ + struct trap *trap; \ + struct engr *ml_ep; \ + NhRegion *_ml_reg; \ + \ + if ((obj = vobj_at(x, y)) && !covers_objects(x, y)) { \ + map_object(obj, show); \ + } else if ((trap = t_at(x, y)) \ + && trap->tseen && !covers_traps(x, y)) { \ + map_trap(trap, show); \ + } else if (spot_shows_engravings(x, y) \ + && (ml_ep = engr_at(x, y)) != 0 \ + && ml_ep->erevealed != 0 \ + && !covers_traps(x, y)) { \ + map_engraving(ml_ep, show); \ + } else { \ + map_background(x, y, show); \ + } \ + \ + update_lastseentyp(x, y); \ + if (show && !Blind && (_ml_reg = visible_region_at(x, y)) != 0) \ + show_region(_ml_reg, x, y); \ } while (0) void @@ -742,6 +747,7 @@ feel_location(coordxy x, coordxy y) struct rm *lev; struct obj *boulder; struct monst *mon; + struct engr *ep; /* replicate safeguards used by newsym(); might not be required here */ if (_suppress_map_output()) @@ -851,6 +857,9 @@ feel_location(coordxy x, coordxy y) show_glyph(x, y, lev->glyph = cmap_to_glyph(S_darkroom)); } } else { + if ((ep = engr_at(x, y)) && !ep->erevealed && engr_can_be_felt(ep)) + ep->erevealed = 1; + _map_location(x, y, 1); if (Punished) { @@ -911,6 +920,7 @@ newsym(coordxy x, coordxy y) int see_it; boolean worm_tail; struct rm *lev = &(levl[x][y]); + struct engr *ep; /* don't try to produce map output when level is in a state of flux */ if (_suppress_map_output()) @@ -1009,8 +1019,11 @@ newsym(coordxy x, coordxy y) display_warning(mon); } else if (glyph_is_invisible(lev->glyph)) { map_invisible(x, y); - } else + } else { + if ((ep = engr_at(x, y)) && !ep->erevealed) + ep->erevealed = 1; _map_location(x, y, 1); /* map the location */ + } } /* Can't see the location. */ diff --git a/src/engrave.c b/src/engrave.c index 88ac6b29e..07f30bea5 100644 --- a/src/engrave.c +++ b/src/engrave.c @@ -285,6 +285,31 @@ wipe_engr_at(coordxy x, coordxy y, xint16 cnt, boolean magical) } } +/* + * Returns: + * non-zero if it can be felt + */ +boolean +engr_can_be_felt(struct engr *ep) +{ + boolean canfeel = FALSE; + + switch (ep->engr_type) { + case ENGRAVE: + case HEADSTONE: + case BURN: + canfeel = TRUE; + break; + case DUST: + case MARK: + case ENGR_BLOOD: + default: + canfeel = FALSE; + break; + } + return canfeel; +} + void read_engr_at(coordxy x, coordxy y) { @@ -355,6 +380,7 @@ read_engr_at(coordxy x, coordxy y) You("%s: \"%s\".", (Blind) ? "feel the words" : "read", et); Strcpy(ep->engr_txt[remembered_text], ep->engr_txt[actual_text]); ep->eread = 1; + ep->erevealed = 1; if (svc.context.run > 0) nomul(0); } @@ -399,7 +425,8 @@ make_engr_at( ep->engr_type = (xint8) ((e_type > 0) ? e_type : rnd(N_ENGRAVE - 1)); ep->engr_szeach = smem; ep->engr_alloc = smem * 3; - /* we do not set ep->eread; the caller will need to if required */ + /* we do not set ep->eread or ep->erevealed; + * the caller will need to if required */ } /* delete any engraving at location */ @@ -996,6 +1023,7 @@ doengrave(void) if (de->teleengr) { rloc_engr(de->oep); de->oep->eread = 0; + de->oep->erevealed = 0; de->disprefresh = TRUE; de->oep = (struct engr *) 0; } @@ -1014,6 +1042,7 @@ doengrave(void) if (tmp_ep != 0) { pline_The("engraving now reads: \"%s\".", de->buf); tmp_ep->eread = 1; + tmp_ep->erevealed = 1; de->disprefresh = TRUE; } } @@ -1395,8 +1424,10 @@ engrave(void) make_engr_at(u.ux, u.uy, buf, svm.moves - gm.multi, svc.context.engraving.type); oep = engr_at(u.ux, u.uy); - if (oep) + if (oep) { oep->eread = 1; + oep->erevealed = 1; + } if (*endc) { svc.context.engraving.nextc = endc; @@ -1640,6 +1671,7 @@ void feel_engraving(struct engr *ep) { ep->eread = 1; + ep->erevealed = 1; map_engraving(ep, 1); /* in case it's beneath something, redisplay the something */ newsym(ep->engr_x, ep->engr_y);