]> granicus.if.org Git - nethack/commitdiff
add ^ and " choices to / command
authorPatR <rankin@nethack.org>
Mon, 31 May 2021 00:31:47 +0000 (17:31 -0700)
committerPatR <rankin@nethack.org>
Mon, 31 May 2021 00:31:47 +0000 (17:31 -0700)
Like /m for nearby monsters and /O for all objects, implement /^
and /" to view a list of nearby traps or all known traps.  Only
lists discovered traps (or mimics immitating traps, or detected
door or chest traps iff still shown as such on map), but lists
map traps even when an object or monster at the same location is
blocking view of them.

For traps on the Water and Air levels that have been mapped, they
will only be listed when within line of sight so that this feature
can't be used to track portal location as it moves around.  However,
when within line of sight it does allow the portal to be recognized
if that has become covered.

doc/fixes37.0
src/pager.c

index 3a8d41c2649b9d84f018bd0d2d8f89a2b503cd53..7d6ca7349e5b48b16fe1aae10006ce416eee5a6a 100644 (file)
@@ -1,4 +1,4 @@
-NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.554 $ $NHDT-Date: 1622363511 2021/05/30 08:31:51 $
+NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.555 $ $NHDT-Date: 1622421099 2021/05/31 00:31:39 $
 
 General Fixes and Modified Features
 -----------------------------------
@@ -1015,6 +1015,8 @@ using 'f' while quiver is empty and 'autoquiver' is Off when wielding a
        to Maskerade
 monsters can see and remember hero resistances
 monsters can gain resistances by eating corpses
+menu for what-is command supports /^ and /" to view a list of nearby or whole
+       level visible and remembered traps
 
 
 Platform- and/or Interface-Specific New Features
index 0597b223d51ea373a90ccaae979b09bd3e2f3eef..9f8cf059a7b13346811bccf90aa98818c458c678 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.7 pager.c $NHDT-Date: 1620590081 2021/05/09 19:54:41 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.201 $ */
+/* NetHack 3.7 pager.c $NHDT-Date: 1622421100 2021/05/31 00:31:40 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.202 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2018. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 static boolean is_swallow_sym(int);
 static int append_str(char *, const char *);
+static void trap_description(char *, int, int, int);
 static void look_at_object(char *, int, int, int);
 static void look_at_monster(char *, char *, struct monst *, int, int);
 static struct permonst *lookat(int, int, char *, char *);
 static void checkfile(char *, struct permonst *, boolean, boolean,
                       char *);
-static void look_all(boolean,boolean);
+static void look_all(boolean, boolean);
+static void look_traps(boolean);
 static void do_supplemental_info(char *, struct permonst *, boolean);
 static void whatdoes_help(void);
 static void docontact(void);
@@ -127,6 +129,25 @@ monhealthdescr(struct monst *mon, boolean addspace, char *outbuf)
     return outbuf;
 }
 
+/* copy a trap's description into outbuf[] */
+static void
+trap_description(char *outbuf, int tnum, int x, int y)
+{
+    /* Trap detection displays a bear trap at locations having
+     * a trapped door or trapped container or both.
+     *
+     * TODO: we should create actual trap types for doors and
+     * chests so that they can have their own glyphs and tiles.
+     */
+    if (trapped_chest_at(tnum, x, y))
+        Strcpy(outbuf, "trapped chest"); /* might actually be a large box */
+    else if (trapped_door_at(tnum, x, y))
+        Strcpy(outbuf, "trapped door"); /* not "trap door"... */
+    else
+        Strcpy(outbuf, trapname(tnum, FALSE));
+    return;
+}
+
 /* describe a hidden monster; used for look_at during extended monster
    detection and for probing; also when looking at self */
 void
@@ -399,7 +420,8 @@ look_at_monster(char *buf,
                                         : (mW & M2_ELF & m2) ? "elf"
                                           : (mW & M2_ORC & m2) ? "orc"
                                             : (mW & M2_DEMON & m2) ? "demon"
-                                              : pmname(mtmp->data, Mgender(mtmp)));
+                                              : pmname(mtmp->data,
+                                                       Mgender(mtmp)));
 
                     Sprintf(eos(monbuf), "warned of %s", makeplural(whom));
                 }
@@ -487,17 +509,7 @@ lookat(int x, int y, char *buf, char *monbuf)
     } else if (glyph_is_trap(glyph)) {
         int tnum = glyph_to_trap(glyph);
 
-        /* Trap detection displays a bear trap at locations having
-         * a trapped door or trapped container or both.
-         * TODO: we should create actual trap types for doors and
-         * chests so that they can have their own glyphs and tiles.
-         */
-        if (trapped_chest_at(tnum, x, y))
-            Strcpy(buf, "trapped chest"); /* might actually be a large box */
-        else if (trapped_door_at(tnum, x, y))
-            Strcpy(buf, "trapped door"); /* not "trap door"... */
-        else
-            Strcpy(buf, trapname(tnum, FALSE));
+        trap_description(buf, tnum, x, y);
     } else if (glyph_is_warning(glyph)) {
         int warnindx = glyph_to_warning(glyph);
 
@@ -1140,7 +1152,8 @@ do_screen_description(coord cc, boolean looked, int sym, char *out_str,
             case SYM_PET_OVERRIDE + SYM_OFF_X:
                 if (looked) {
                     /* convert to symbol without override in effect */
-                    map_glyphinfo(cc.x, cc.y, glyph, MG_FLAG_NOOVERRIDE, &glyphinfo);
+                    map_glyphinfo(cc.x, cc.y, glyph, MG_FLAG_NOOVERRIDE,
+                                  &glyphinfo);
                     sym = glyphinfo.ttychar;
                     goto check_monsters;
                 }
@@ -1285,6 +1298,14 @@ do_look(int mode, coord *click_cc)
                 add_menu(win, &nul_glyphinfo, &any,
                          flags.lootabc ? 0 : any.a_char, 0, ATR_NONE,
                          "all objects shown on map", MENU_ITEMFLAGS_NONE);
+                any.a_char = '^';
+                add_menu(win, &nul_glyphinfo, &any,
+                         flags.lootabc ? 0 : any.a_char, 0, ATR_NONE,
+                         "nearby traps", MENU_ITEMFLAGS_NONE);
+                any.a_char = '\"';
+                add_menu(win, &nul_glyphinfo, &any,
+                         flags.lootabc ? 0 : any.a_char, 0, ATR_NONE,
+                         "all seen or remembered traps", MENU_ITEMFLAGS_NONE);
             }
             end_menu(win, "What do you want to look at:");
             if (select_menu(win, PICK_ONE, &pick_list) > 0) {
@@ -1351,6 +1372,12 @@ do_look(int mode, coord *click_cc)
         case 'O':
             look_all(FALSE, FALSE); /* list all objects */
             return 0;
+        case '^':
+            look_traps(TRUE); /* list nearby traps */
+            return 0;
+        case '\"':
+            look_traps(FALSE); /* list all traps (visible or remembered) */
+            return 0;
         }
     } else { /* clicklook */
         cc.x = click_cc->x;
@@ -1524,6 +1551,73 @@ look_all(boolean nearby,  /* True => within BOLTLIM, False => entire map */
     destroy_nhwindow(win);
 }
 
+/* give a /M style display of discovered traps, even when they're covered */
+static void
+look_traps(boolean nearby)
+{
+    winid win;
+    struct trap *t;
+    int x, y, lo_x, lo_y, hi_x, hi_y, glyph, tnum, count = 0;
+    char lookbuf[BUFSZ], outbuf[BUFSZ];
+
+    win = create_nhwindow(NHW_TEXT);
+    lo_y = nearby ? max(u.uy - BOLT_LIM, 0) : 0;
+    lo_x = nearby ? max(u.ux - BOLT_LIM, 1) : 1;
+    hi_y = nearby ? min(u.uy + BOLT_LIM, ROWNO - 1) : ROWNO - 1;
+    hi_x = nearby ? min(u.ux + BOLT_LIM, COLNO - 1) : COLNO - 1;
+    for (y = lo_y; y <= hi_y; y++) {
+        for (x = lo_x; x <= hi_x; x++) {
+            lookbuf[0] = '\0';
+            glyph = glyph_at(x, y);
+            if (glyph_is_trap(glyph)) {
+                tnum = glyph_to_trap(glyph);
+                trap_description(lookbuf, tnum, x, y);
+                ++count;
+            } else if ((t = t_at(x, y)) != 0 && t->tseen
+                       /* can't use /" to track traps moved by bubbles or
+                          clouds except when hero has direct line of sight */
+                       && ((!Is_waterlevel(&u.uz) && !Is_airlevel(&u.uz))
+                           || couldsee(x, y))) {
+                Strcpy(lookbuf, trapname(t->ttyp, FALSE));
+                Sprintf(eos(lookbuf), ", obscured by %s", encglyph(glyph));
+                glyph = trap_to_glyph(t);
+                ++count;
+            }
+            if (*lookbuf) {
+                char coordbuf[20], cmode;
+
+                cmode = (iflags.getpos_coords != GPCOORDS_NONE)
+                           ? iflags.getpos_coords : GPCOORDS_MAP;
+                if (count == 1) {
+                    Sprintf(outbuf, "%sseen or remembered traps%s:",
+                            nearby ? "nearby " : "",
+                            nearby ? "" : " on this level");
+                    putstr(win, 0, upstart(outbuf));
+                    /* hack alert! Qt watches a text window for any line
+                       with 4 consecutive spaces and renders the window
+                       in a fixed-width font it if finds at least one */
+                    putstr(win, 0, "    "); /* separator */
+                }
+                /* prefix: "coords  C  " where 'C' is trap symbol */
+                Sprintf(outbuf, (cmode == GPCOORDS_SCREEN) ? "%s  "
+                                  : (cmode == GPCOORDS_MAP) ? "%8s  "
+                                      : "%12s  ",
+                        coord_desc(x, y, coordbuf, cmode));
+                Sprintf(eos(outbuf), "%s  ", encglyph(glyph));
+                /* guard against potential overflow */
+                lookbuf[sizeof lookbuf - 1 - strlen(outbuf)] = '\0';
+                Strcat(outbuf, lookbuf);
+                putmixed(win, 0, outbuf);
+            }
+        }
+    }
+    if (count)
+        display_nhwindow(win, TRUE);
+    else
+        pline("No traps seen or remembered%s.", nearby ? " nearby" : "");
+    destroy_nhwindow(win);
+    }
+
 static const char *suptext1[] = {
     "%s is a member of a marauding horde of orcs",
     "rumored to have brutally attacked and plundered",