fix issue #339 - duplicate feature messages

while 'mention_decor' is enabled.  When stepping onto different
terrain and one or more objects remained on the new spot after
autopickup, describe_decor() was issuing its new-terrain message
right before look_here()'s similar under-the-objects message.  If
autopickup grabbed everything or there weren't any objects to begin
with, look_here() doesn't issue any dfeature (terrain) message.
describe_decor() isn't smart enought to know whether that is going
to happen.  Give look_here() a new flag argument so that its caller
can ask for the dfeature message to be skipped for the case where a
similar message has already been given.
This commit is contained in:
PatR
2020-04-27 04:25:26 -07:00
parent 42ffce0e5d
commit 09f9b3598f
6 changed files with 48 additions and 57 deletions

View File

@@ -211,6 +211,8 @@ fix crash in water_damage_chain
teleport feedback "you materialize at another location" was given too soon
'mention_decore' was repeatedly reporting "you are back on bottom" when
moving around underwater
revised 'mention_decor' was describing furniture or ice right before look-here
described the same thing when stepping onto object(s)
poison gas clouds located over known but unlit pools were visible as known
clouds but steam clouds in that situation were not
after the wish parsing change, wishing for "<something of monster>" or for

View File

@@ -1075,7 +1075,7 @@ E struct obj *FDECL(display_cinventory, (struct obj *));
E struct obj *FDECL(display_minventory, (struct monst *, int, char *));
E int NDECL(dotypeinv);
E const char *FDECL(dfeature_at, (int, int, char *));
E int FDECL(look_here, (int, BOOLEAN_P));
E int FDECL(look_here, (int, unsigned));
E int NDECL(dolook);
E boolean FDECL(will_feel_cockatrice, (struct obj *, BOOLEAN_P));
E void FDECL(feel_cockatrice, (struct obj *, BOOLEAN_P));

View File

@@ -134,6 +134,10 @@ enum cost_alteration_types {
#define CXN_ARTICLE 8 /* include a/an/the prefix */
#define CXN_NOCORPSE 16 /* suppress " corpse" suffix */
/* flags for look_here() */
#define LOOKHERE_PICKED_SOME 1
#define LOOKHERE_SKIP_DFEATURE 2
/* getpos() return values */
enum getpos_retval {
LOOK_TRADITIONAL = 0, /* '.' -- ask about "more info?" */
@@ -255,13 +259,12 @@ struct sortloot_item {
};
typedef struct sortloot_item Loot;
#define MATCH_WARN_OF_MON(mon) \
(Warn_of_mon && ((g.context.warntype.obj \
&& (g.context.warntype.obj & (mon)->data->mflags2)) \
|| (g.context.warntype.polyd \
&& (g.context.warntype.polyd & (mon)->data->mflags2)) \
|| (g.context.warntype.species \
&& (g.context.warntype.species == (mon)->data))))
#define MATCH_WARN_OF_MON(mon) \
(Warn_of_mon \
&& ((g.context.warntype.obj & (mon)->data->mflags2) != 0 \
|| (g.context.warntype.polyd & (mon)->data->mflags2) != 0 \
|| (g.context.warntype.species \
&& (g.context.warntype.species == (mon)->data))))
#include "trap.h"
#include "flag.h"

View File

@@ -3414,9 +3414,9 @@ char *buf;
/* look at what is here; if there are many objects (pile_limit or more),
don't show them unless obj_cnt is 0 */
int
look_here(obj_cnt, picked_some)
look_here(obj_cnt, lookhere_flags)
int obj_cnt; /* obj_cnt > 0 implies that autopickup is in progress */
boolean picked_some;
unsigned lookhere_flags;
{
struct obj *otmp;
struct trap *trap;
@@ -3424,12 +3424,15 @@ boolean picked_some;
const char *dfeature = (char *) 0;
char fbuf[BUFSZ], fbuf2[BUFSZ];
winid tmpwin;
boolean skip_objects, felt_cockatrice = FALSE;
boolean skip_objects, felt_cockatrice = FALSE,
picked_some = (lookhere_flags & LOOKHERE_PICKED_SOME) != 0,
/* skip 'dfeature' if caller used describe_decor() to show it */
skip_dfeature = (lookhere_flags & LOOKHERE_SKIP_DFEATURE) != 0;
/* default pile_limit is 5; a value of 0 means "never skip"
(and 1 effectively forces "always skip") */
skip_objects = (flags.pile_limit > 0 && obj_cnt >= flags.pile_limit);
if (u.uswallow && u.ustuck) {
if (u.uswallow) {
struct monst *mtmp = u.ustuck;
/*
@@ -3502,12 +3505,12 @@ boolean picked_some;
}
}
if (dfeature)
if (dfeature && !skip_dfeature)
Sprintf(fbuf, "There is %s here.", an(dfeature));
if (!otmp || is_lava(u.ux, u.uy)
|| (is_pool(u.ux, u.uy) && !Underwater)) {
if (dfeature)
if (dfeature && !skip_dfeature)
pline1(fbuf);
read_engr_at(u.ux, u.uy); /* Eric Backus */
if (!skip_objects && (Blind || !dfeature))
@@ -3517,7 +3520,7 @@ boolean picked_some;
/* we know there is something here */
if (skip_objects) {
if (dfeature)
if (dfeature && !skip_dfeature)
pline1(fbuf);
read_engr_at(u.ux, u.uy); /* Eric Backus */
if (obj_cnt == 1 && otmp->quan == 1L)
@@ -3547,7 +3550,7 @@ boolean picked_some;
}
} else if (!otmp->nexthere) {
/* only one object */
if (dfeature)
if (dfeature && !skip_dfeature)
pline1(fbuf);
read_engr_at(u.ux, u.uy); /* Eric Backus */
You("%s here %s.", verb, doname_with_price(otmp));
@@ -3559,7 +3562,7 @@ boolean picked_some;
display_nhwindow(WIN_MESSAGE, FALSE);
tmpwin = create_nhwindow(NHW_MENU);
if (dfeature) {
if (dfeature && !skip_dfeature) {
putstr(tmpwin, 0, fbuf);
putstr(tmpwin, 0, "");
}

View File

@@ -16,7 +16,7 @@ static boolean FDECL(query_classes, (char *, boolean *, boolean *,
const char *, struct obj *,
BOOLEAN_P, int *));
static boolean FDECL(fatal_corpse_mistake, (struct obj *, BOOLEAN_P));
static void NDECL(describe_decor);
static boolean NDECL(describe_decor);
static void FDECL(check_here, (BOOLEAN_P));
static boolean FDECL(n_or_more, (struct obj *));
static boolean FDECL(all_but_uchain, (struct obj *));
@@ -295,32 +295,31 @@ boolean setup; /* True: deferring, False: catching up */
if (setup) {
iflags.defer_decor = TRUE;
} else {
describe_decor();
(void) describe_decor();
iflags.defer_decor = FALSE;
}
}
/* handle 'mention_decor' (when walking onto a dungeon feature such as
stairs or altar, describe it even if it isn't covered up by an object) */
static void
static boolean
describe_decor()
{
char outbuf[BUFSZ], fbuf[QBUFSZ];
boolean doorhere, waterhere, do_norep;
boolean doorhere, waterhere, res = TRUE;
const char *dfeature;
int ltyp;
if (Fumbling && !iflags.defer_decor) {
if ((HFumbling & TIMEOUT) == 1L && !iflags.defer_decor) {
/*
* In case Fumbling is due to walking on ice.
* Work around a message sequencing issue: avoid
* |You are back on floor.
* |You trip over <object>.
* |You trip over <object>. or You flounder.
* when the trip is being caused by moving on ice as hero
* steps off ice onto non-ice.
*/
deferred_decor(TRUE);
return;
return FALSE;
}
ltyp = levl[u.ux][u.uy].typ;
@@ -328,7 +327,8 @@ describe_decor()
ltyp = db_under_typ(levl[u.ux][u.uy].drawbridgemask);
dfeature = dfeature_at(u.ux, u.uy, fbuf);
/* we don't mention "ordinary" doors but do mention broken ones */
/* we don't mention "ordinary" doors but do mention broken ones (and
closed ones, which will only happen for Passes_walls) */
doorhere = dfeature && (!strcmp(dfeature, "open door")
|| !strcmp(dfeature, "doorway"));
waterhere = dfeature && !strcmp(dfeature, "pool of water");
@@ -337,7 +337,7 @@ describe_decor()
dfeature = 0;
if (ltyp == iflags.prev_decor && !IS_FURNITURE(ltyp)) {
;
res = FALSE;
} else if (dfeature) {
if (waterhere)
dfeature = strcpy(fbuf, waterbody_name(u.ux, u.uy));
@@ -351,14 +351,7 @@ describe_decor()
Strcpy(fbuf, dfeature);
Sprintf(outbuf, "%s.", upstart(fbuf));
}
do_norep = (ltyp == iflags.prev_decor
&& (waterhere
|| !strcmp(dfeature, "molten lava")
|| !strcmp(dfeature, "ice")));
if (!do_norep)
pline("%s", outbuf);
else
Norep("%s", outbuf);
pline("%s", outbuf);
} else if (!Underwater) {
if (IS_POOL(iflags.prev_decor)
|| iflags.prev_decor == LAVAPOOL
@@ -373,6 +366,7 @@ describe_decor()
}
}
iflags.prev_decor = ltyp;
return res;
}
/* look at the objects at our location, unless there are too many of them */
@@ -382,9 +376,12 @@ boolean picked_some;
{
register struct obj *obj;
register int ct = 0;
unsigned lhflags = picked_some ? LOOKHERE_PICKED_SOME : 0;
if (flags.mention_decor)
describe_decor();
if (flags.mention_decor) {
if (describe_decor())
lhflags |= LOOKHERE_SKIP_DFEATURE;
}
/* count the objects here */
for (obj = g.level.objects[u.ux][u.uy]; obj; obj = obj->nexthere) {
@@ -397,9 +394,7 @@ boolean picked_some;
if (g.context.run)
nomul(0);
flush_screen(1);
(void) look_here(ct, picked_some);
iflags.prev_decor = STONE;
(void) look_here(ct, lhflags);
} else {
read_engr_at(u.ux, u.uy);
}
@@ -599,13 +594,13 @@ int what; /* should be a long */
|| (is_pool(u.ux, u.uy) && !Underwater)
|| is_lava(u.ux, u.uy))) {
if (flags.mention_decor)
describe_decor();
(void) describe_decor();
read_engr_at(u.ux, u.uy);
return 0;
}
/* no pickup if levitating & not on air or water level */
if (!can_reach_floor(TRUE)) {
describe_decor(); /* even when !flags.mention_decor */
(void) describe_decor(); /* even when !flags.mention_decor */
if ((g.multi && !g.context.run) || (autopickup && !flags.pickup)
|| ((t = t_at(u.ux, u.uy)) != 0
&& (uteetering_at_seen_pit(t) || uescaped_shaft(t))))
@@ -631,8 +626,6 @@ int what; /* should be a long */
&& !g.context.nopick)
nomul(0);
}
/* for describe_decor()'s Norep handling */
iflags.prev_decor = STONE;
add_valid_menu_class(0); /* reset */
if (!u.uswallow) {
@@ -988,7 +981,7 @@ boolean FDECL((*allow), (OBJ_P)); /* allow function */
if ((qflags & FEEL_COCKATRICE) && curr->otyp == CORPSE
&& will_feel_cockatrice(curr, FALSE)) {
destroy_nhwindow(win); /* stop the menu and revert */
(void) look_here(0, FALSE);
(void) look_here(0, 0);
unsortloot(&sortedolist);
return 0;
}

View File

@@ -737,18 +737,8 @@ nh_timeout()
incr_itimeout(&HFumbling, rnd(20));
if (iflags.defer_decor) {
/*
* describe_decor() is attempting to work around a
* message sequencing issue: avoid
* |You are back on floor.
* |You trip over <object>.
* if the trip is being caused by moving on ice
* that the hero just left. A trip message has
* just been given, now give change-in-terrain one.
* Operate this way even for non-ice Fumbling so
* that describe_decor() doesn't need to know any
* details about that.
*/
/* 'mention_decor' was deferred for message sequencing
reasons; catch up now */
deferred_decor(FALSE);
}
break;