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

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