From: PatR Date: Mon, 31 May 2021 00:31:47 +0000 (-0700) Subject: add ^ and " choices to / command X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=53888a713cae2d0fcc81afe5bc0d0e5a2f1d68bf;p=nethack add ^ and " choices to / command 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. --- diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 3a8d41c26..7d6ca7349 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -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 diff --git a/src/pager.c b/src/pager.c index 0597b223d..9f8cf059a 100644 --- a/src/pager.c +++ b/src/pager.c @@ -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. */ @@ -11,12 +11,14 @@ 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",