]> granicus.if.org Git - nethack/commitdiff
getpos improvements: automatic description
authorPasi Kallinen <paxed@alt.org>
Wed, 11 Mar 2015 15:16:05 +0000 (17:16 +0200)
committerPasi Kallinen <paxed@alt.org>
Wed, 11 Mar 2015 15:16:05 +0000 (17:16 +0200)
Pressing '@' will move the cursor on top of the hero.
Pressing '#' will toggle automatic description mode, where
the feature under the cursor is automatically described
when the cursor is moved.

doc/fixes35.0
src/do_name.c
src/pager.c

index f6519a6f7fafcc191577af542ed21d470810ca31..89646e389e1cea517f28d5e0d0ba0ddc04946ffd 100644 (file)
@@ -1080,6 +1080,9 @@ Add database entry for shuriken and make it match throwing star
 Add database entry for fedora
 Add database entry for land mine
 change command X to twoweapon toggle
+pressing @ when cursor positioning moves cursor on top of hero
+pressing # when cursor positioning toggles automatic description of features
+       under the cursor
 
 
 Platform- and/or Interface-Specific New Features
index 4face203e0de0e04826b8188751afbe3b04e3606..ce538adb4466b208bc2712c8ef8a0409a2811589 100644 (file)
@@ -40,6 +40,8 @@ const char *goal;
     putstr(tmpwin, 0, sbuf);
     putstr(tmpwin, 0, "Use [HJKL] to move the cursor 8 units at a time.");
     putstr(tmpwin, 0, "Or enter a background symbol (ex. <).");
+    putstr(tmpwin, 0, "Use @ to move the cursor on yourself.");
+    putstr(tmpwin, 0, "Use # to toggle automatic description.");
     /* disgusting hack; the alternate selection characters work for any
        getpos call, but they only matter for dowhatis (and doquickwhatis) */
     doing_what_is = (goal == what_is_an_unknown_object);
@@ -63,6 +65,8 @@ const char *goal;
     int cx, cy, i, c;
     int sidx, tx, ty;
     boolean msg_given = TRUE;  /* clear message window by default */
+    boolean auto_msg = FALSE;
+    boolean show_goal_msg = FALSE;
     static const char pick_chars[] = ".,;:";
     const char *cp;
 
@@ -82,7 +86,32 @@ const char *goal;
     lock_mouse_cursor(TRUE);
 #endif
     for (;;) {
+
+       if (show_goal_msg) {
+           pline("Move cursor to %s:", goal);
+           curs(WIN_MAP, cx, cy);
+           flush_screen(0);
+           show_goal_msg = FALSE;
+       } else if (auto_msg && !msg_given) {
+           coord cc;
+           int sym = 0;
+           char tmpbuf[BUFSZ];
+           char *firstmatch = NULL;
+           cc.x = cx;
+           cc.y = cy;
+           if (do_screen_description(cc, TRUE, sym, tmpbuf, &firstmatch)) {
+               /* there may be an encoded glyph */
+               putmixed(WIN_MESSAGE, 0, tmpbuf);
+               curs(WIN_MAP, cx, cy);
+               flush_screen(0);
+           }
+       }
+
        c = nh_poskey(&tx, &ty, &sidx);
+
+       if (auto_msg)
+           msg_given = FALSE;
+
        if (c == '\033') {
            cx = cy = -10;
            msg_given = TRUE;   /* force clear */
@@ -142,8 +171,20 @@ const char *goal;
            else                /* ^R */
                docrt();        /* redraw */
            /* update message window to reflect that we're still targetting */
-           pline("Move cursor to %s:", goal);
+           show_goal_msg = TRUE;
+           msg_given = TRUE;
+       } else if (c == '#') {
+           auto_msg = !auto_msg;
+           pline("Automatic description %sis %s.",
+                 flags.verbose ? "of features under cursor " : "",
+                 auto_msg ? "on" : "off");
+           if (!auto_msg) show_goal_msg = TRUE;
            msg_given = TRUE;
+           goto nxtc;
+       } else if (c == '@') {
+           cx = u.ux;
+           cy = u.uy;
+           goto nxtc;
        } else {
            if (!index(quitchars, c)) {
                char matching[MAXPCHARS];
index 459a6daf4def0c12b35a043941fd5f027343c889..af36ba6e0f59e06959e5a77ece790a3e5201d8df 100644 (file)
@@ -437,6 +437,229 @@ bad_data_file:    impossible("'data' file in wrong format");
     (void) dlb_fclose(fp);
 }
 
+int
+do_screen_description(cc, looked, sym, out_str, firstmatch)
+coord cc;
+boolean looked;
+int sym;
+char *out_str;
+const char **firstmatch;
+{
+    boolean need_to_look = FALSE;
+    int glyph;
+    char    look_buf[BUFSZ], prefix[BUFSZ];
+    int            found = 0;          /* count of matching syms found */
+    int i;
+    int skipped_venom = 0;
+    boolean hit_trap;
+    const char *x_str;
+    static const char *mon_interior = "the interior of a monster";
+    struct permonst *pm = NULL;
+
+    if (looked) {
+       int oc, so;
+       unsigned os;
+
+       glyph = glyph_at(cc.x,cc.y);
+
+       /* Convert the glyph at the selected position to a symbol. */
+       so = mapglyph(glyph, &sym, &oc, &os, cc.x, cc.y);
+    }
+
+    if (looked)
+       Sprintf(prefix, "%s        ", encglyph(glyph));
+    else
+       Sprintf(prefix, "%c        ", sym);
+
+    /*
+     * Check all the possibilities, saving all explanations in a buffer.
+     * When all have been checked then the string is printed.
+     */
+
+    /* Check for monsters */
+    for (i = 0; i < MAXMCLASSES; i++) {
+       if (sym == ((looked) ?
+                   showsyms[i + SYM_OFF_M] : def_monsyms[i].sym) &&
+           def_monsyms[i].explain) {
+           need_to_look = TRUE;
+           if (!found) {
+               Sprintf(out_str, "%s%s",
+                       prefix, an(def_monsyms[i].explain));
+               *firstmatch = def_monsyms[i].explain;
+               found++;
+           } else {
+               found += append_str(out_str, an(def_monsyms[i].explain));
+           }
+       }
+    }
+    /* handle '@' as a special case if it refers to you and you're
+       playing a character which isn't normally displayed by that
+       symbol; firstmatch is assumed to already be set for '@' */
+    if (((looked) ?
+        (sym == showsyms[S_HUMAN + SYM_OFF_M] && cc.x == u.ux && cc.y == u.uy) :
+        (sym == def_monsyms[S_HUMAN].sym && !flags.showrace)) &&
+       !(Race_if(PM_HUMAN) || Race_if(PM_ELF)) && !Upolyd)
+       found += append_str(out_str, "you");    /* tack on "or you" */
+
+    /*
+     * Special case: if identifying from the screen, and we're swallowed,
+     * and looking at something other than our own symbol, then just say
+     * "the interior of a monster".
+     */
+    if (u.uswallow && (looked) && is_swallow_sym(sym)) {
+       if (!found) {
+           Sprintf(out_str, "%s%s",
+                   prefix, mon_interior);
+           *firstmatch = mon_interior;
+       } else {
+           found += append_str(out_str, mon_interior);
+       }
+       need_to_look = TRUE;
+    }
+
+    /* Now check for objects */
+    for (i = 1; i < MAXOCLASSES; i++) {
+       if (sym == ((looked) ?
+                   showsyms[i + SYM_OFF_O] : def_oc_syms[i].sym)) {
+           need_to_look = TRUE;
+           if ((looked) && i == VENOM_CLASS) {
+               skipped_venom++;
+               continue;
+           }
+           if (!found) {
+               Sprintf(out_str, "%s%s",
+                       prefix, an(def_oc_syms[i].explain));
+               *firstmatch = def_oc_syms[i].explain;
+               found++;
+           } else {
+               found += append_str(out_str, an(def_oc_syms[i].explain));
+           }
+       }
+    }
+
+    if (sym == DEF_INVISIBLE) {
+       if (!found) {
+           Sprintf(out_str, "%s%s",
+                   prefix,
+                   an(invisexplain));
+           *firstmatch = invisexplain;
+           found++;
+       } else {
+           found += append_str(out_str, an(invisexplain));
+       }
+    }
+
+#define is_cmap_trap(i) ((i) >= S_arrow_trap && (i) <= S_polymorph_trap)
+#define is_cmap_drawbridge(i) ((i) >= S_vodbridge && (i) <= S_hcdbridge)
+
+    /* Now check for graphics symbols */
+    for (hit_trap = FALSE, i = 0; i < MAXPCHARS; i++) {
+       x_str = defsyms[i].explanation;
+       if (sym == ((looked) ?
+                   showsyms[i] : defsyms[i].sym) && *x_str) {
+           /* avoid "an air", "a water", or "a floor of a room" */
+           int article = (i == S_room) ? 2 :           /* 2=>"the" */
+               !(strcmp(x_str, "air") == 0 ||  /* 1=>"an"  */
+                 strcmp(x_str, "water") == 0); /* 0=>(none)*/
+
+           if (!found) {
+               if (is_cmap_trap(i)) {
+                   Sprintf(out_str, "%sa trap", prefix);
+                   hit_trap = TRUE;
+               } else {
+                   Sprintf(out_str, "%s%s",
+                           prefix,
+                           article == 2 ? the(x_str) :
+                           article == 1 ? an(x_str) : x_str);
+               }
+               *firstmatch = x_str;
+               found++;
+           } else if (!u.uswallow && !(hit_trap && is_cmap_trap(i)) &&
+                      !(found >= 3 && is_cmap_drawbridge(i))) {
+               found += append_str(out_str,
+                                   article == 2 ? the(x_str) :
+                                   article == 1 ? an(x_str) : x_str);
+               if (is_cmap_trap(i)) hit_trap = TRUE;
+           }
+
+           if (i == S_altar || is_cmap_trap(i))
+               need_to_look = TRUE;
+       }
+    }
+
+    /* Now check for warning symbols */
+    for (i = 1; i < WARNCOUNT; i++) {
+       x_str = def_warnsyms[i].explanation;
+       if (sym == ((looked) ?
+                   warnsyms[i] : def_warnsyms[i].sym)) {
+           if (!found) {
+               Sprintf(out_str, "%s%s",
+                       prefix, def_warnsyms[i].explanation);
+               *firstmatch = def_warnsyms[i].explanation;
+               found++;
+           } else {
+               found += append_str(out_str, def_warnsyms[i].explanation);
+           }
+           /* Kludge: warning trumps boulders on the display.
+              Reveal the boulder too or player can get confused */
+           if ((looked) && sobj_at(BOULDER, cc.x, cc.y))
+               Strcat(out_str, " co-located with a boulder");
+           break;      /* out of for loop*/
+       }
+    }
+
+    /* if we ignored venom and list turned out to be short, put it back */
+    if (skipped_venom && found < 2) {
+       x_str = def_oc_syms[VENOM_CLASS].explain;
+       if (!found) {
+           Sprintf(out_str, "%s%s",
+                   prefix, an(x_str));
+           *firstmatch = x_str;
+           found++;
+       } else {
+           found += append_str(out_str, an(x_str));
+       }
+    }
+
+    /* handle optional boulder symbol as a special case */
+    if (iflags.bouldersym && sym == iflags.bouldersym) {
+       if (!found) {
+           *firstmatch = "boulder";
+           Sprintf(out_str, "%s%s",
+                   prefix, an(*firstmatch));
+           found++;
+       } else {
+           found += append_str(out_str, "boulder");
+       }
+    }
+
+    /*
+     * If we are looking at the screen, follow multiple possibilities or
+     * an ambiguous explanation by something more detailed.
+     */
+    if (looked) {
+       if (found > 1 || need_to_look) {
+           char monbuf[BUFSZ];
+           char temp_buf[BUFSZ];
+
+           pm = lookat(cc.x, cc.y, look_buf, monbuf);
+           *firstmatch = look_buf;
+           if (*(*firstmatch)) {
+               Sprintf(temp_buf, " (%s)", *firstmatch);
+               (void)strncat(out_str, temp_buf, BUFSZ-strlen(out_str)-1);
+               found = 1;      /* we have something to look up */
+           }
+           if (monbuf[0]) {
+               Sprintf(temp_buf, " [seen: %s]", monbuf);
+               (void)strncat(out_str, temp_buf, BUFSZ-strlen(out_str)-1);
+           }
+       }
+    }
+
+    return found;
+}
+
+
 /* getpos() return values */
 #define LOOK_TRADITIONAL       0       /* '.' -- ask about "more info?" */
 #define LOOK_QUICK             1       /* ',' -- skip "more info?" */
@@ -453,19 +676,15 @@ do_look(mode, click_cc)
 {
     boolean quick = (mode == 1); /* use cursor && don't search for "more info" */
     boolean clicklook = (mode == 2); /* right mouse-click method */
-    char    out_str[BUFSZ], look_buf[BUFSZ], prefix[BUFSZ];
-    const char *x_str, *firstmatch = 0;
+    char    out_str[BUFSZ];
+    const char *firstmatch = 0;
     struct permonst *pm = 0;
-    int glyph;                 /* glyph at selected position */
     int     i, ans = 0;
     int     sym;               /* typed symbol or converted glyph */
     int            found;              /* count of matching syms found */
     coord   cc;                        /* screen pos of unknown glyph */
     boolean save_verbose;      /* saved value of flags.verbose */
     boolean from_screen;       /* question from the screen */
-    boolean need_to_look;      /* need to get explan. from glyph */
-    boolean hit_trap;          /* true if found trap explanation */
-    int skipped_venom;         /* non-zero if we ignored "splash of venom" */
     static const char *mon_interior = "the interior of a monster";
 
     if (!clicklook) {
@@ -506,9 +725,7 @@ do_look(mode, click_cc)
      */
     do {
        /* Reset some variables. */
-       need_to_look = FALSE;
        pm = (struct permonst *)0;
-       skipped_venom = 0;
        found = 0;
        out_str[0] = '\0';
 
@@ -529,201 +746,9 @@ do_look(mode, click_cc)
                }
                flags.verbose = FALSE;  /* only print long question once */
            }
-           glyph = glyph_at(cc.x,cc.y);
-
-           /* Convert the glyph at the selected position to a symbol. */
-           so = mapglyph(glyph, &sym, &oc, &os, cc.x, cc.y);
-       }
-
-       if (from_screen || clicklook)
-           Sprintf(prefix, "%s        ", encglyph(glyph));
-       else
-           Sprintf(prefix, "%c        ", sym); 
-
-       /*
-        * Check all the possibilities, saving all explanations in a buffer.
-        * When all have been checked then the string is printed.
-        */
-
-       /* Check for monsters */
-       for (i = 0; i < MAXMCLASSES; i++) {
-           if (sym == ((from_screen || clicklook) ?
-                       showsyms[i + SYM_OFF_M] : def_monsyms[i].sym) &&
-               def_monsyms[i].explain) {
-               need_to_look = TRUE;
-               if (!found) {
-                   Sprintf(out_str, "%s%s",
-                               prefix, an(def_monsyms[i].explain));
-                   firstmatch = def_monsyms[i].explain;
-                   found++;
-               } else {
-                   found += append_str(out_str, an(def_monsyms[i].explain));
-               }
-           }
-       }
-       /* handle '@' as a special case if it refers to you and you're
-          playing a character which isn't normally displayed by that
-          symbol; firstmatch is assumed to already be set for '@' */
-       if (((from_screen || clicklook) ?
-               (sym == showsyms[S_HUMAN + SYM_OFF_M] && cc.x == u.ux && cc.y == u.uy) :
-               (sym == def_monsyms[S_HUMAN].sym && !flags.showrace)) &&
-           !(Race_if(PM_HUMAN) || Race_if(PM_ELF)) && !Upolyd)
-           found += append_str(out_str, "you");        /* tack on "or you" */
-
-       /*
-        * Special case: if identifying from the screen, and we're swallowed,
-        * and looking at something other than our own symbol, then just say
-        * "the interior of a monster".
-        */
-       if (u.uswallow && (from_screen || clicklook) && is_swallow_sym(sym)) {
-           if (!found) {
-               Sprintf(out_str, "%s%s",
-                       prefix, mon_interior);
-               firstmatch = mon_interior;
-           } else {
-               found += append_str(out_str, mon_interior);
-           }
-           need_to_look = TRUE;
-       }
-
-       /* Now check for objects */
-       for (i = 1; i < MAXOCLASSES; i++) {
-           if (sym == ((from_screen || clicklook) ?
-                       showsyms[i + SYM_OFF_O] : def_oc_syms[i].sym)) {
-               need_to_look = TRUE;
-               if ((from_screen || clicklook) && i == VENOM_CLASS) {
-                   skipped_venom++;
-                   continue;
-               }
-               if (!found) {
-                   Sprintf(out_str, "%s%s",
-                               prefix, an(def_oc_syms[i].explain));
-                   firstmatch = def_oc_syms[i].explain;
-                   found++;
-               } else {
-                   found += append_str(out_str, an(def_oc_syms[i].explain));
-               }
-           }
-       }
-
-       if (sym == DEF_INVISIBLE) {
-           if (!found) {
-               Sprintf(out_str, "%s%s",
-                       prefix,
-                       an(invisexplain));
-               firstmatch = invisexplain;
-               found++;
-           } else {
-               found += append_str(out_str, an(invisexplain));
-           }
-       }
-
-#define is_cmap_trap(i) ((i) >= S_arrow_trap && (i) <= S_polymorph_trap)
-#define is_cmap_drawbridge(i) ((i) >= S_vodbridge && (i) <= S_hcdbridge)
-
-       /* Now check for graphics symbols */
-       for (hit_trap = FALSE, i = 0; i < MAXPCHARS; i++) {
-           x_str = defsyms[i].explanation;
-           if (sym == ((from_screen || clicklook) ?
-               showsyms[i] : defsyms[i].sym) && *x_str) {
-               /* avoid "an air", "a water", or "a floor of a room" */
-               int article = (i == S_room) ? 2 :               /* 2=>"the" */
-                             !(strcmp(x_str, "air") == 0 ||    /* 1=>"an"  */
-                               strcmp(x_str, "water") == 0);   /* 0=>(none)*/
-
-               if (!found) {
-                   if (is_cmap_trap(i)) {
-                       Sprintf(out_str, "%sa trap", prefix);
-                       hit_trap = TRUE;
-                   } else {
-                       Sprintf(out_str, "%s%s",
-                               prefix,
-                               article == 2 ? the(x_str) :
-                               article == 1 ? an(x_str) : x_str);
-                   }
-                   firstmatch = x_str;
-                   found++;
-               } else if (!u.uswallow && !(hit_trap && is_cmap_trap(i)) &&
-                          !(found >= 3 && is_cmap_drawbridge(i))) {
-                   found += append_str(out_str,
-                                       article == 2 ? the(x_str) :
-                                       article == 1 ? an(x_str) : x_str);
-                   if (is_cmap_trap(i)) hit_trap = TRUE;
-               }
-
-               if (i == S_altar || is_cmap_trap(i))
-                   need_to_look = TRUE;
-           }
        }
 
-       /* Now check for warning symbols */
-       for (i = 1; i < WARNCOUNT; i++) {
-           x_str = def_warnsyms[i].explanation;
-           if (sym == ((from_screen || clicklook) ?
-               warnsyms[i] : def_warnsyms[i].sym)) {
-               if (!found) {
-                       Sprintf(out_str, "%s%s",
-                               prefix, def_warnsyms[i].explanation);
-                       firstmatch = def_warnsyms[i].explanation;
-                       found++;
-               } else {
-                       found += append_str(out_str, def_warnsyms[i].explanation);
-               }
-               /* Kludge: warning trumps boulders on the display.
-                  Reveal the boulder too or player can get confused */
-               if ((from_screen || clicklook) && sobj_at(BOULDER, cc.x, cc.y))
-                       Strcat(out_str, " co-located with a boulder");
-               break;  /* out of for loop*/
-           }
-       }
-    
-       /* if we ignored venom and list turned out to be short, put it back */
-       if (skipped_venom && found < 2) {
-           x_str = def_oc_syms[VENOM_CLASS].explain;
-           if (!found) {
-               Sprintf(out_str, "%s%s",
-                       prefix, an(x_str));
-               firstmatch = x_str;
-               found++;
-           } else {
-               found += append_str(out_str, an(x_str));
-           }
-       }
-
-       /* handle optional boulder symbol as a special case */ 
-       if (iflags.bouldersym && sym == iflags.bouldersym) {
-           if (!found) {
-               firstmatch = "boulder";
-               Sprintf(out_str, "%s%s",
-                       prefix, an(firstmatch));
-               found++;
-           } else {
-               found += append_str(out_str, "boulder");
-           }
-       }
-       
-       /*
-        * If we are looking at the screen, follow multiple possibilities or
-        * an ambiguous explanation by something more detailed.
-        */
-       if (from_screen || clicklook) {
-           if (found > 1 || need_to_look) {
-               char monbuf[BUFSZ];
-               char temp_buf[BUFSZ];
-
-               pm = lookat(cc.x, cc.y, look_buf, monbuf);
-               firstmatch = look_buf;
-               if (*firstmatch) {
-                   Sprintf(temp_buf, " (%s)", firstmatch);
-                   (void)strncat(out_str, temp_buf, BUFSZ-strlen(out_str)-1);
-                   found = 1;  /* we have something to look up */
-               }
-               if (monbuf[0]) {
-                   Sprintf(temp_buf, " [seen: %s]", monbuf);
-                   (void)strncat(out_str, temp_buf, BUFSZ-strlen(out_str)-1);
-               }
-           }
-       }
+       found = do_screen_description(cc, (from_screen||clicklook), sym, out_str, &firstmatch);
 
        /* Finally, print out our explanation. */
        if (found) {