Warning and adjacent hiders
Changes to be committed:
modified: include/extern.h
modified: src/allmain.c
modified: src/detect.c
modified: src/display.c
Bug bz22 (no corresponding web id) reported quite some time ago.
Reported:
Warning stays on when a "lurker above" is co-located with a
boulder, even when you are adjacent to the spot. Even though
you see the warning symbol and not the boulder, an attempt
to move in that direction tries to move the boulder, rather
than attack the creature you know to be there. What's more,
you can get the
"You hear a monster on the other side of the boulder..."
preventing anything from happening if there is a monster on
the other side of the spot. The player doesn't necessarily
even know there is a boulder there at the time (because
warning trumps the boulder display) so it can all be somewhat
confusing.
Change:
- Split off a section of the search0() code for monsters into
a separately callable function, arbitrarily named mfind0(),
which takes a special arg for this particular scenario.
- If you have Warning and you get adjacent to an unseen hider
such as a lurker above with the Warning glyph still displayed,
a specific search is carried out for the obviously present monster.
- The boulder concerns in the original report should become moot
after this.
This commit is contained in:
@@ -153,6 +153,8 @@ barbarian and samurai can achieve basic in their special spell's skill
|
||||
scalpel and tsurugi can now split puddings; bashing with darts or arrows can't
|
||||
jumping while punished could leave ball and chain in the wrong place
|
||||
improve Deaf message handling for the minetown watch and shops
|
||||
issues with Warning when you're adjacent to an undetected hider; clearly you
|
||||
are aware a monster is present so this causes you to search it out
|
||||
|
||||
|
||||
Platform- and/or Interface-Specific Fixes
|
||||
|
||||
@@ -256,6 +256,7 @@ E int NDECL(findit);
|
||||
E int NDECL(openit);
|
||||
E boolean FDECL(detecting, (void (*)(int, int, genericptr)));
|
||||
E void FDECL(find_trap, (struct trap *));
|
||||
E void NDECL(warnreveal);
|
||||
E int FDECL(dosearch0, (int));
|
||||
E int NDECL(dosearch);
|
||||
E void NDECL(sokoban_detect);
|
||||
@@ -333,6 +334,7 @@ E int FDECL(zapdir_to_glyph, (int, int, int));
|
||||
E int FDECL(glyph_at, (XCHAR_P, XCHAR_P));
|
||||
E void NDECL(set_wall_state);
|
||||
E void FDECL(unset_seenv, (struct rm *, int, int, int, int));
|
||||
E int FDECL(warning_of, (struct monst *));
|
||||
|
||||
/* ### do.c ### */
|
||||
|
||||
|
||||
@@ -308,6 +308,8 @@ boolean resuming;
|
||||
|
||||
if (Searching && multi >= 0)
|
||||
(void) dosearch0(1);
|
||||
if (Warning)
|
||||
warnreveal();
|
||||
dosounds();
|
||||
do_storms();
|
||||
gethungry();
|
||||
|
||||
109
src/detect.c
109
src/detect.c
@@ -20,6 +20,7 @@ STATIC_DCL int FDECL(detect_obj_traps, (struct obj *, BOOLEAN_P, int));
|
||||
STATIC_DCL void FDECL(show_map_spot, (int, int));
|
||||
STATIC_PTR void FDECL(findone, (int, int, genericptr_t));
|
||||
STATIC_PTR void FDECL(openone, (int, int, genericptr_t));
|
||||
STATIC_DCL int FDECL(mfind0, (struct monst *, BOOLEAN_P));
|
||||
|
||||
/* Recursively search obj for an object in class oclass and return 1st found
|
||||
*/
|
||||
@@ -1311,6 +1312,57 @@ struct trap *trap;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC_OVL int
|
||||
mfind0(mtmp, via_warning)
|
||||
struct monst *mtmp;
|
||||
boolean via_warning;
|
||||
{
|
||||
xchar x = mtmp->mx,
|
||||
y = mtmp->my;
|
||||
|
||||
if (via_warning && !warning_of(mtmp))
|
||||
return -1;
|
||||
|
||||
if (mtmp->m_ap_type) {
|
||||
seemimic(mtmp);
|
||||
find:
|
||||
exercise(A_WIS, TRUE);
|
||||
if (!canspotmon(mtmp)) {
|
||||
if (glyph_is_invisible(levl[x][y].glyph)) {
|
||||
/* found invisible monster in a square
|
||||
* which already has an 'I' in it.
|
||||
* Logically, this should still take
|
||||
* time and lead to a return(1), but
|
||||
* if we did that the player would keep
|
||||
* finding the same monster every turn.
|
||||
*/
|
||||
return -1;
|
||||
} else {
|
||||
You_feel("an unseen monster!");
|
||||
map_invisible(x, y);
|
||||
}
|
||||
} else if (!sensemon(mtmp))
|
||||
You("find %s.", mtmp->mtame
|
||||
? y_monnam(mtmp)
|
||||
: a_monnam(mtmp));
|
||||
return 1;
|
||||
}
|
||||
if (!canspotmon(mtmp)) {
|
||||
if (mtmp->mundetected
|
||||
&& (is_hider(mtmp->data)
|
||||
|| mtmp->data->mlet == S_EEL))
|
||||
if (via_warning) {
|
||||
Your("warning senses cause you to take a second %s.",
|
||||
Blind ? "to check nearby" : "look close by");
|
||||
display_nhwindow(WIN_MESSAGE, FALSE); /* flush messages */
|
||||
}
|
||||
mtmp->mundetected = 0;
|
||||
newsym(x, y);
|
||||
goto find;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dosearch0(aflag)
|
||||
register int aflag; /* intrinsic autosearch vs explicit searching */
|
||||
@@ -1368,38 +1420,12 @@ register int aflag; /* intrinsic autosearch vs explicit searching */
|
||||
} else {
|
||||
/* Be careful not to find anything in an SCORR or SDOOR */
|
||||
if ((mtmp = m_at(x, y)) != 0 && !aflag) {
|
||||
if (mtmp->m_ap_type) {
|
||||
seemimic(mtmp);
|
||||
find:
|
||||
exercise(A_WIS, TRUE);
|
||||
if (!canspotmon(mtmp)) {
|
||||
if (glyph_is_invisible(levl[x][y].glyph)) {
|
||||
/* found invisible monster in a square
|
||||
* which already has an 'I' in it.
|
||||
* Logically, this should still take
|
||||
* time and lead to a return(1), but
|
||||
* if we did that the player would keep
|
||||
* finding the same monster every turn.
|
||||
*/
|
||||
continue;
|
||||
} else {
|
||||
You_feel("an unseen monster!");
|
||||
map_invisible(x, y);
|
||||
}
|
||||
} else if (!sensemon(mtmp))
|
||||
You("find %s.", mtmp->mtame
|
||||
? y_monnam(mtmp)
|
||||
: a_monnam(mtmp));
|
||||
return 1;
|
||||
}
|
||||
if (!canspotmon(mtmp)) {
|
||||
if (mtmp->mundetected
|
||||
&& (is_hider(mtmp->data)
|
||||
|| mtmp->data->mlet == S_EEL))
|
||||
mtmp->mundetected = 0;
|
||||
newsym(x, y);
|
||||
goto find;
|
||||
}
|
||||
int mfres = mfind0(mtmp, 0);
|
||||
|
||||
if (mfres == -1)
|
||||
continue;
|
||||
else if (mfres > 0)
|
||||
return mfres;
|
||||
}
|
||||
|
||||
/* see if an invisible monster has moved--if Blind,
|
||||
@@ -1434,6 +1460,25 @@ dosearch()
|
||||
return dosearch0(0);
|
||||
}
|
||||
|
||||
void
|
||||
warnreveal()
|
||||
{
|
||||
xchar x, y;
|
||||
struct monst *mtmp;
|
||||
|
||||
for (x = u.ux - 1; x < u.ux + 2; x++)
|
||||
for (y = u.uy - 1; y < u.uy + 2; y++) {
|
||||
if (!isok(x, y))
|
||||
continue;
|
||||
if (x == u.ux && y == u.uy)
|
||||
continue;
|
||||
|
||||
if ((mtmp = m_at(x, y)) != 0
|
||||
&& warning_of(mtmp) && mtmp->mundetected)
|
||||
(void) mfind0(mtmp, 1); /* via_warning */
|
||||
}
|
||||
}
|
||||
|
||||
/* Pre-map the sokoban levels */
|
||||
void
|
||||
sokoban_detect()
|
||||
|
||||
@@ -466,16 +466,10 @@ display_warning(mon)
|
||||
register struct monst *mon;
|
||||
{
|
||||
int x = mon->mx, y = mon->my;
|
||||
int wl = (int) (mon->m_lev / 4);
|
||||
int glyph;
|
||||
|
||||
if (mon_warning(mon)) {
|
||||
if (wl > WARNCOUNT - 1)
|
||||
wl = WARNCOUNT - 1;
|
||||
/* 3.4.1: this really ought to be rn2(WARNCOUNT), but value "0"
|
||||
isn't handled correctly by the what_is routine so avoid it */
|
||||
if (Hallucination)
|
||||
wl = rn1(WARNCOUNT - 1, 1);
|
||||
int wl = Hallucination ? rn1(WARNCOUNT - 1, 1) : warning_of(mon);
|
||||
glyph = warning_to_glyph(wl);
|
||||
} else if (MATCH_WARN_OF_MON(mon)) {
|
||||
glyph = mon_to_glyph(mon);
|
||||
@@ -486,6 +480,18 @@ register struct monst *mon;
|
||||
show_glyph(x, y, glyph);
|
||||
}
|
||||
|
||||
int
|
||||
warning_of(mon)
|
||||
struct monst *mon;
|
||||
{
|
||||
int wl = 0, tmp = 0;
|
||||
if (mon_warning(mon)) {
|
||||
tmp = (int) (mon->m_lev / 4); /* match display.h */
|
||||
wl = (tmp > WARNCOUNT - 1) ? WARNCOUNT - 1 : tmp;
|
||||
}
|
||||
return wl;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* feel_newsym()
|
||||
|
||||
Reference in New Issue
Block a user