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
|
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
|
jumping while punished could leave ball and chain in the wrong place
|
||||||
improve Deaf message handling for the minetown watch and shops
|
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
|
Platform- and/or Interface-Specific Fixes
|
||||||
|
|||||||
@@ -256,6 +256,7 @@ E int NDECL(findit);
|
|||||||
E int NDECL(openit);
|
E int NDECL(openit);
|
||||||
E boolean FDECL(detecting, (void (*)(int, int, genericptr)));
|
E boolean FDECL(detecting, (void (*)(int, int, genericptr)));
|
||||||
E void FDECL(find_trap, (struct trap *));
|
E void FDECL(find_trap, (struct trap *));
|
||||||
|
E void NDECL(warnreveal);
|
||||||
E int FDECL(dosearch0, (int));
|
E int FDECL(dosearch0, (int));
|
||||||
E int NDECL(dosearch);
|
E int NDECL(dosearch);
|
||||||
E void NDECL(sokoban_detect);
|
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 int FDECL(glyph_at, (XCHAR_P, XCHAR_P));
|
||||||
E void NDECL(set_wall_state);
|
E void NDECL(set_wall_state);
|
||||||
E void FDECL(unset_seenv, (struct rm *, int, int, int, int));
|
E void FDECL(unset_seenv, (struct rm *, int, int, int, int));
|
||||||
|
E int FDECL(warning_of, (struct monst *));
|
||||||
|
|
||||||
/* ### do.c ### */
|
/* ### do.c ### */
|
||||||
|
|
||||||
|
|||||||
@@ -308,6 +308,8 @@ boolean resuming;
|
|||||||
|
|
||||||
if (Searching && multi >= 0)
|
if (Searching && multi >= 0)
|
||||||
(void) dosearch0(1);
|
(void) dosearch0(1);
|
||||||
|
if (Warning)
|
||||||
|
warnreveal();
|
||||||
dosounds();
|
dosounds();
|
||||||
do_storms();
|
do_storms();
|
||||||
gethungry();
|
gethungry();
|
||||||
|
|||||||
+77
-32
@@ -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_DCL void FDECL(show_map_spot, (int, int));
|
||||||
STATIC_PTR void FDECL(findone, (int, int, genericptr_t));
|
STATIC_PTR void FDECL(findone, (int, int, genericptr_t));
|
||||||
STATIC_PTR void FDECL(openone, (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
|
/* 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
|
int
|
||||||
dosearch0(aflag)
|
dosearch0(aflag)
|
||||||
register int aflag; /* intrinsic autosearch vs explicit searching */
|
register int aflag; /* intrinsic autosearch vs explicit searching */
|
||||||
@@ -1368,38 +1420,12 @@ register int aflag; /* intrinsic autosearch vs explicit searching */
|
|||||||
} else {
|
} else {
|
||||||
/* Be careful not to find anything in an SCORR or SDOOR */
|
/* Be careful not to find anything in an SCORR or SDOOR */
|
||||||
if ((mtmp = m_at(x, y)) != 0 && !aflag) {
|
if ((mtmp = m_at(x, y)) != 0 && !aflag) {
|
||||||
if (mtmp->m_ap_type) {
|
int mfres = mfind0(mtmp, 0);
|
||||||
seemimic(mtmp);
|
|
||||||
find:
|
if (mfres == -1)
|
||||||
exercise(A_WIS, TRUE);
|
continue;
|
||||||
if (!canspotmon(mtmp)) {
|
else if (mfres > 0)
|
||||||
if (glyph_is_invisible(levl[x][y].glyph)) {
|
return mfres;
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* see if an invisible monster has moved--if Blind,
|
/* see if an invisible monster has moved--if Blind,
|
||||||
@@ -1434,6 +1460,25 @@ dosearch()
|
|||||||
return dosearch0(0);
|
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 */
|
/* Pre-map the sokoban levels */
|
||||||
void
|
void
|
||||||
sokoban_detect()
|
sokoban_detect()
|
||||||
|
|||||||
+13
-7
@@ -466,16 +466,10 @@ display_warning(mon)
|
|||||||
register struct monst *mon;
|
register struct monst *mon;
|
||||||
{
|
{
|
||||||
int x = mon->mx, y = mon->my;
|
int x = mon->mx, y = mon->my;
|
||||||
int wl = (int) (mon->m_lev / 4);
|
|
||||||
int glyph;
|
int glyph;
|
||||||
|
|
||||||
if (mon_warning(mon)) {
|
if (mon_warning(mon)) {
|
||||||
if (wl > WARNCOUNT - 1)
|
int wl = Hallucination ? rn1(WARNCOUNT - 1, 1) : warning_of(mon);
|
||||||
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);
|
|
||||||
glyph = warning_to_glyph(wl);
|
glyph = warning_to_glyph(wl);
|
||||||
} else if (MATCH_WARN_OF_MON(mon)) {
|
} else if (MATCH_WARN_OF_MON(mon)) {
|
||||||
glyph = mon_to_glyph(mon);
|
glyph = mon_to_glyph(mon);
|
||||||
@@ -486,6 +480,18 @@ register struct monst *mon;
|
|||||||
show_glyph(x, y, glyph);
|
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()
|
* feel_newsym()
|
||||||
|
|||||||
Reference in New Issue
Block a user