]> granicus.if.org Git - nethack/commitdiff
Warning and adjacent hiders
authornhmall <mjnh@persona.ca>
Sun, 14 Feb 2016 22:45:20 +0000 (17:45 -0500)
committernhmall <mjnh@persona.ca>
Sun, 14 Feb 2016 22:45:20 +0000 (17:45 -0500)
 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.

doc/fixes36.1
include/extern.h
src/allmain.c
src/detect.c
src/display.c

index 47f0e8f9882b0329b187ac5653a8e6096140a9b2..8ad6b90d66eee6fa5a6916573fb5cae0cc76be21 100644 (file)
@@ -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
index a15251e2c59a19705c41a6f1840c0756dd75d79e..9b88f9fa296b1eecbc269005773b27a812d0ab37 100644 (file)
@@ -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 ### */
 
index 737dcf0d500ad6b61d154e00cb3f67e609bfd508..4aef642c54168a7463df27dac07efbdedd5941de 100644 (file)
@@ -308,6 +308,8 @@ boolean resuming;
 
                     if (Searching && multi >= 0)
                         (void) dosearch0(1);
+                    if (Warning)
+                        warnreveal();
                     dosounds();
                     do_storms();
                     gethungry();
index c29ad83eb69aa2c28b4374651b551b7edf731b0a..e2214d20d50bd2078bf5c297a739fd961ba90a2a 100644 (file)
@@ -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()
index 09fd943eb410a8627fbd3b79a15506b9883f1de7..b4970378f41d2feb5bc63440ee19d44a6cb5621b 100644 (file)
@@ -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()