]> granicus.if.org Git - nethack/commitdiff
getpos moving to 'cmap' characters
authorPatR <rankin@nethack.org>
Tue, 31 May 2016 00:56:47 +0000 (17:56 -0700)
committerPatR <rankin@nethack.org>
Tue, 31 May 2016 00:56:47 +0000 (17:56 -0700)
While testing something I noticed that moving the cursor to visible '^'
by typing '^' while getpos was asking me to pick a location, it didn't
always cycle through all visible traps.  The most straightforward
culprit was after trap detection (via confused gold detection, not ^F)
had found a trap door or level teleporter in a closet that itself was
a secret corridor spot.  But it turned out to be any location that
hadn't been seen yet.  This is a substantial overhaul of the relevant
code and so far works for all the cases I've tried, but there are
bound to be cases I haven't tried yet and those may or may not work
correctly.

There's also a bunch of formatting cleanup, and some simplification of
the m/M/o/O/d/D/x/X handling.

doc/fixes36.1
src/do_name.c

index 313454491b4e2be4e204fca48f80d7c6e470c31b..fbb8b5a9b0832c0cbe4f7be90045ba4e5b1bfb2a 100644 (file)
@@ -272,6 +272,8 @@ reviving one of a stack of N corpses in a shop charged a usage fee for all N;
        remaining N-1 were owned by hero if carried but by shop if on floor
 gremlin wailing in agony should wake up nearby monsters
 add more lighting variance to the second bigroom variant
+when getpost was picking a location, typing '^' to move to the next known trap
+       skipped some detected traps if their location was unseen
 
 
 Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository
index 153002e76af10368019d0e94b9afcefc8de225f7..5d5c419c69f3a455fce54575ed14495d09b6335d 100644 (file)
@@ -64,10 +64,15 @@ const char *goal;
         putstr(tmpwin, 0, "Use m or M to move the cursor to next monster.");
     if (!iflags.terrainmode || (iflags.terrainmode & TER_OBJ) != 0)
         putstr(tmpwin, 0, "Use o or O to move the cursor to next object.");
-    putstr(tmpwin, 0, /* d,D are useful regardless of terrainmode */
-           "Use d or D to move the cursor to next door or doorway.");
+    if (!iflags.terrainmode || (iflags.terrainmode & TER_MAP) != 0) {
+        /* both of these are primarily useful when choosing a travel
+           destination for the '_' command */
+        putstr(tmpwin, 0,
+               "Use d or D to move the cursor to next door or doorway.");
+        putstr(tmpwin, 0,
+               "Use x or X to move the cursor to unexplored location.");
+    }
     if (!iflags.terrainmode) {
-        putstr(tmpwin, 0, "Use x or X to move the cursor to unexplored location.");
         if (getpos_hilitefunc)
             putstr(tmpwin, 0, "Use $ to display valid locations.");
         putstr(tmpwin, 0, "Use # to toggle automatic description.");
@@ -134,10 +139,11 @@ enum gloctypes {
 };
 
 
-#define IS_UNEXPLORED_LOC(x,y) (isok((x), (y))                          \
-                                && glyph_is_cmap(levl[(x)][(y)].glyph)  \
-                                && glyph_to_cmap(levl[(x)][(y)].glyph) == S_stone \
-                                && !levl[(x)][(y)].seenv)
+#define IS_UNEXPLORED_LOC(x,y) \
+    (isok((x), (y))                                     \
+     && glyph_is_cmap(levl[(x)][(y)].glyph)             \
+     && glyph_to_cmap(levl[(x)][(y)].glyph) == S_stone  \
+     && !levl[(x)][(y)].seenv)
 
 STATIC_OVL boolean
 gather_locs_interesting(x,y, gloc)
@@ -150,28 +156,35 @@ int x,y, gloc;
 
     switch (gloc) {
     default:
-    case GLOC_MONS: return (glyph_is_monster(glyph)
-                            && glyph != monnum_to_glyph(PM_LONG_WORM_TAIL));
-    case GLOC_OBJS: return (glyph_is_object(glyph)
-                            && glyph != objnum_to_glyph(BOULDER)
-                            && glyph != objnum_to_glyph(ROCK));
-    case GLOC_DOOR: return (glyph_is_cmap(glyph)
-                            && (is_cmap_door(glyph_to_cmap(glyph))
-                                || is_cmap_drawbridge(glyph_to_cmap(glyph))
-                                || glyph_to_cmap(glyph) == S_ndoor));
-    case GLOC_EXPLORE: return (glyph_is_cmap(glyph)
-                               && (is_cmap_door(glyph_to_cmap(glyph))
-                                   || is_cmap_drawbridge(glyph_to_cmap(glyph))
-                                   || glyph_to_cmap(glyph) == S_ndoor
-                                   || glyph_to_cmap(glyph) == S_room
-                                   || glyph_to_cmap(glyph) == S_darkroom
-                                   || glyph_to_cmap(glyph) == S_corr
-                                   || glyph_to_cmap(glyph) == S_litcorr)
-                               && (IS_UNEXPLORED_LOC(x+1,y)
-                                   || IS_UNEXPLORED_LOC(x-1,y)
-                                   || IS_UNEXPLORED_LOC(x,y+1)
-                                   || IS_UNEXPLORED_LOC(x,y-1)));
+    case GLOC_MONS:
+        /* unlike '/M', this skips monsters revealed by
+           warning glyphs and remembered unseen ones */
+        return (glyph_is_monster(glyph)
+                && glyph != monnum_to_glyph(PM_LONG_WORM_TAIL));
+    case GLOC_OBJS:
+        return (glyph_is_object(glyph)
+                && glyph != objnum_to_glyph(BOULDER)
+                && glyph != objnum_to_glyph(ROCK));
+    case GLOC_DOOR:
+        return (glyph_is_cmap(glyph)
+                && (is_cmap_door(glyph_to_cmap(glyph))
+                    || is_cmap_drawbridge(glyph_to_cmap(glyph))
+                    || glyph_to_cmap(glyph) == S_ndoor));
+    case GLOC_EXPLORE:
+        return (glyph_is_cmap(glyph)
+                && (is_cmap_door(glyph_to_cmap(glyph))
+                    || is_cmap_drawbridge(glyph_to_cmap(glyph))
+                    || glyph_to_cmap(glyph) == S_ndoor
+                    || glyph_to_cmap(glyph) == S_room
+                    || glyph_to_cmap(glyph) == S_darkroom
+                    || glyph_to_cmap(glyph) == S_corr
+                    || glyph_to_cmap(glyph) == S_litcorr)
+                && (IS_UNEXPLORED_LOC(x + 1, y)
+                    || IS_UNEXPLORED_LOC(x - 1, y)
+                    || IS_UNEXPLORED_LOC(x, y + 1)
+                    || IS_UNEXPLORED_LOC(x, y - 1)));
     }
+    /*NOTREACHED*/
     return FALSE;
 }
 
@@ -199,10 +212,8 @@ int gloc;
     for (pass = 0; pass < 2; pass++) {
         for (x = 1; x < COLNO; x++)
             for (y = 0; y < ROWNO; y++) {
-                /* unlike '/M', this skips monsters revealed by
-                   warning glyphs and remembered invisible ones */
                 if ((x == u.ux && y == u.uy)
-                    || gather_locs_interesting(x,y, gloc)) {
+                    || gather_locs_interesting(x, y, gloc)) {
                     if (!pass) {
                         ++*cnt_p;
                     } else {
@@ -317,13 +328,14 @@ coord *ccp;
 boolean force;
 const char *goal;
 {
+    static const char pick_chars[] = ".,;:",
+                      mMoOdDxX[] = "mMoOdDxX";
+    const char *cp;
     int result = 0;
     int cx, cy, i, c;
     int sidx, tx, ty;
     boolean msg_given = TRUE; /* clear message window by default */
     boolean show_goal_msg = FALSE;
-    static const char pick_chars[] = ".,;:";
-    const char *cp;
     boolean hilite_state = FALSE;
     coord *garr[NUM_GLOCS] = DUMMY;
     int gcount[NUM_GLOCS] = DUMMY;
@@ -437,6 +449,10 @@ const char *goal;
             }
             goto nxtc;
         } else if (c == '#') {
+            /* unfortunately, using '#' as a command means we can't move
+               cursor to sinks, iron bars, and poison clouds; perhaps
+               when autodescribe is already on, next '#' should try to
+               move to '#' rather than to toggle off? (or ask; ick...) */
             iflags.autodescribe = !iflags.autodescribe;
             pline("Automatic description %sis %s.",
                   flags.verbose ? "of features under cursor " : "",
@@ -446,29 +462,25 @@ const char *goal;
             msg_given = TRUE;
             goto nxtc;
         } else if (c == '@') { /* return to hero's spot */
-            /* reset 'm','M' and 'o','O'; otherwise, there's no way for player
+            /* reset 'm&M', 'o&O', &c; otherwise, there's no way for player
                to achieve that except by manually cycling through all spots */
             for (i = 0; i < NUM_GLOCS; i++)
                 gidx[i] = 0;
             cx = u.ux;
             cy = u.uy;
             goto nxtc;
-        } else if (c == 'm' || c == 'M' /* nearest or farthest monster */
-                   || c == 'o' || c == 'O'  /* nearest or farthest object */
-                   || c == 'x' || c == 'X' /* unexplored area */
-                   || c == 'd' || c == 'D') { /* door/doorway */
-            int gloc = (c == 'o' || c == 'O') ? GLOC_OBJS
-                : (c == 'd' || c == 'D') ? GLOC_DOOR
-                : (c == 'x' || c == 'X') ? GLOC_EXPLORE
-                : GLOC_MONS;
+        } else if ((cp = index(mMoOdDxX, c)) != 0) { /* 'm|M', 'o|O', &c */
+            /* nearest or farthest monster or object or door or unexplored */
+            int gtmp = (int) (cp - mMoOdDxX), /* 0..7 */
+                gloc = gtmp >> 1;             /* 0..3 */
 
             if (!garr[gloc]) {
                 gather_locs(&garr[gloc], &gcount[gloc], gloc);
                 gidx[gloc] = 0; /* garr[][0] is hero's spot */
             }
-            if (c == 'm' || c == 'o' || c == 'd' || c == 'x') {
+            if (!(gtmp & 1)) {  /* c=='m' || c=='o' || c=='d' || c=='x') */
                 gidx[gloc] = (gidx[gloc] + 1) % gcount[gloc];
-            } else {
+            } else {            /* c=='M' || c=='O' || c=='D' || c=='X') */
                 if (--gidx[gloc] < 0)
                     gidx[gloc] = gcount[gloc] - 1;
             }
@@ -481,9 +493,17 @@ const char *goal;
                 int pass, lo_x, lo_y, hi_x, hi_y, k = 0;
 
                 (void) memset((genericptr_t) matching, 0, sizeof matching);
-                for (sidx = 1; sidx < MAXPCHARS; sidx++)
+                for (sidx = 1; sidx < MAXPCHARS; sidx++) { /* [0] left as 0 */
+                    if (IS_DOOR(sidx) || IS_WALL(sidx)
+                        || sidx == SDOOR || sidx == SCORR
+                        || glyph_to_cmap(k) == S_room
+                        || glyph_to_cmap(k) == S_darkroom
+                        || glyph_to_cmap(k) == S_corr
+                        || glyph_to_cmap(k) == S_litcorr)
+                        continue;
                     if (c == defsyms[sidx].sym || c == (int) showsyms[sidx])
                         matching[sidx] = (char) ++k;
+                }
                 if (k) {
                     for (pass = 0; pass <= 1; pass++) {
                         /* pass 0: just past current pos to lower right;
@@ -494,35 +514,39 @@ const char *goal;
                             lo_x = (pass == 0 && ty == lo_y) ? cx + 1 : 1;
                             hi_x = (pass == 1 && ty == hi_y) ? cx : COLNO - 1;
                             for (tx = lo_x; tx <= hi_x; tx++) {
-                                /* look at dungeon feature, not at
-                                   user-visible glyph */
-                                k = back_to_glyph(tx, ty);
-                                /* uninteresting background glyph */
+                                /* first, look at what is currently visible
+                                   (might be monster) */
+                                k = glyph_at(tx, ty);
                                 if (glyph_is_cmap(k)
-                                    && (IS_DOOR(levl[tx][ty].typ)
-                                        || glyph_to_cmap(k) == S_room
-                                        || glyph_to_cmap(k) == S_darkroom
-                                        || glyph_to_cmap(k) == S_corr
-                                        || glyph_to_cmap(k) == S_litcorr)) {
-                                    /* what hero remembers to be at tx,ty */
-                                    k = glyph_at(tx, ty);
+                                    && matching[glyph_to_cmap(k)])
+                                    goto foundc;
+                                /* next, try glyph that's remembered here
+                                   (might be trap or object) */
+                                if (level.flags.hero_memory
+                                    /* !terrainmode: don't move to remembered
+                                       trap or object if not currently shown */
+                                    && !iflags.terrainmode) {
+                                    k = levl[tx][ty].glyph;
+                                    if (glyph_is_cmap(k)
+                                        && matching[glyph_to_cmap(k)])
+                                        goto foundc;
                                 }
-                                if (glyph_is_cmap(k)
-                                    && matching[glyph_to_cmap(k)]
-                                    && (levl[tx][ty].seenv
-                                        || iflags.terrainmode)
-                                    && !IS_WALL(levl[tx][ty].typ)
-                                    && levl[tx][ty].typ != SDOOR
-                                    && glyph_to_cmap(k) != S_room
-                                    && glyph_to_cmap(k) != S_corr
-                                    && glyph_to_cmap(k) != S_litcorr) {
-                                    cx = tx, cy = ty;
-                                    if (msg_given) {
-                                        clear_nhwindow(WIN_MESSAGE);
-                                        msg_given = FALSE;
-                                    }
-                                    goto nxtc;
+                                /* last, try actual terrain here (shouldn't
+                                   we be using lastseentyp[][] instead?) */
+                                if (levl[tx][ty].seenv) {
+                                    k = back_to_glyph(tx, ty);
+                                    if (glyph_is_cmap(k)
+                                        && matching[glyph_to_cmap(k)])
+                                        goto foundc;
                                 }
+                                continue;
+                            foundc:
+                                cx = tx, cy = ty;
+                                if (msg_given) {
+                                    clear_nhwindow(WIN_MESSAGE);
+                                    msg_given = FALSE;
+                                }
+                                goto nxtc;
                             } /* column */
                         }     /* row */
                     }         /* pass */
@@ -545,10 +569,8 @@ const char *goal;
             }     /* !quitchars */
             if (force)
                 goto nxtc;
-            if (!iflags.terrainmode) {
-                pline("Done.");
-                msg_given = FALSE; /* suppress clear */
-            }
+            pline("Done.");
+            msg_given = FALSE; /* suppress clear */
             cx = -1;
             cy = 0;
             result = 0; /* not -1 */