From: nhmall Date: Sun, 14 Feb 2016 22:45:20 +0000 (-0500) Subject: Warning and adjacent hiders X-Git-Tag: NetHack-3.6.1_RC01~924 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=85582590abe7c34d86df03a4dbd4f1317b46bd76;p=nethack 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. --- diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 47f0e8f98..8ad6b90d6 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -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 diff --git a/include/extern.h b/include/extern.h index a15251e2c..9b88f9fa2 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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 ### */ diff --git a/src/allmain.c b/src/allmain.c index 737dcf0d5..4aef642c5 100644 --- a/src/allmain.c +++ b/src/allmain.c @@ -308,6 +308,8 @@ boolean resuming; if (Searching && multi >= 0) (void) dosearch0(1); + if (Warning) + warnreveal(); dosounds(); do_storms(); gethungry(); diff --git a/src/detect.c b/src/detect.c index c29ad83eb..e2214d20d 100644 --- a/src/detect.c +++ b/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() diff --git a/src/display.c b/src/display.c index 09fd943eb..b4970378f 100644 --- a/src/display.c +++ b/src/display.c @@ -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()