From: PatR Date: Fri, 13 May 2016 01:57:10 +0000 (-0700) Subject: autodescribe for #terrain X-Git-Tag: NetHack-3.6.1_RC01~778 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dccc8188014e7337fcbd39a9cd11dbd555ad1d01;p=nethack autodescribe for #terrain Requested during beta-testing however long ago: want a way to look at specific map locations while #terrain is showing them without monsters and/or objects and/or traps being displayed in the way. The post-3.6.0 autodescribe feature for getpos() made this pretty easy to achieve, although the lookat() aspect felt more like trail-and-error than careful design. Instead of putting up a --More-- prompt, ask the player to pick a location with the cursor. Moving the cursor gives the terse description for every location traversed. Actually picking a spot just ends #terrain and goes back to normal play. --- diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 37f1d1064..a71fd3756 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -349,6 +349,8 @@ extend wizard-mode '#stats' command quivered, provided the stack isn't already in the quiver slot during end of game disclosure, the vanquished monsters list can be sorted in one of several ways by answering 'a' to "disclose vanquished monsters?" +when #terrain is displaying a censored version of the map (no monsters, &c), + moving the cursor will display farlook's brief autodescribe feedback Platform- and/or Interface-Specific New Features diff --git a/include/flag.h b/include/flag.h index 9f611bfe9..4136070ab 100644 --- a/include/flag.h +++ b/include/flag.h @@ -3,8 +3,8 @@ /* NetHack may be freely redistributed. See license for details. */ /* If you change the flag structure make sure you increment EDITLEVEL in */ -/* patchlevel.h if needed. Changing the instance_flags structure does */ -/* not require incrementing EDITLEVEL. */ +/* patchlevel.h if needed. Changing the instance_flags structure does */ +/* not require incrementing EDITLEVEL. */ #ifndef FLAG_H #define FLAG_H @@ -97,7 +97,7 @@ struct flag { * characters or letters, because that limits us to 26 roles. * They are not booleans, because someday someone may need a neuter * gender. Negative values are used to indicate that the user - * hasn't yet specified that particular value. If you determine + * hasn't yet specified that particular value. If you determine * that the user wants a random choice, then you should set an * appropriate random value; if you just left the negative value, * the user would be asked again! @@ -186,17 +186,24 @@ struct instance_flags { int purge_monsters; /* # of dead monsters still on fmon list */ int override_ID; /* true to force full identification of objects */ int suppress_price; /* controls doname() for unpaid objects */ + int terrainmode; /* for getpos()'s autodescribe when #terrain is active */ +#define TER_MAP 0x01 +#define TER_TRP 0x02 +#define TER_OBJ 0x04 +#define TER_MON 0x08 coord travelcc; /* coordinates for travel_cache */ boolean window_inited; /* true if init_nhwindows() completed */ boolean vision_inited; /* true if vision is ready */ boolean sanity_check; /* run sanity checks */ boolean mon_polycontrol; /* debug: control monster polymorphs */ - /* stuff that is related to options and/or user or platform preferences */ + + /* stuff that is related to options and/or user or platform preferences + */ unsigned msg_history; /* hint: # of top lines to save */ int getpos_coords; /* show coordinates when getting cursor position */ int menu_headings; /* ATR for menu headings */ int *opt_booldup; /* for duplication of boolean opts in config file */ - int *opt_compdup; /* for duplication of compound opts in config file */ + int *opt_compdup; /* for duplication of compound opts in conf file */ #ifdef ALTMETA boolean altmeta; /* Alt-c sends ESC c rather than M-c */ #endif @@ -224,11 +231,11 @@ struct instance_flags { boolean hilite_pile; /* mark piles of objects with a hilite */ boolean autodescribe; /* autodescribe mode in getpos() */ #if 0 - boolean DECgraphics; /* use DEC VT-xxx extended character set */ - boolean IBMgraphics; /* use IBM extended character set */ + boolean DECgraphics; /* use DEC VT-xxx extended character set */ + boolean IBMgraphics; /* use IBM extended character set */ #ifdef MAC_GRAPHICS_ENV - boolean MACgraphics; /* use Macintosh extended character set, as - as defined in the special font HackFont */ + boolean MACgraphics; /* use Macintosh extended character set, as + as defined in the special font HackFont */ #endif #endif uchar bouldersym; /* symbol for boulder display */ @@ -275,6 +282,7 @@ struct instance_flags { boolean vt_tiledata; /* output console codes for tile support in TTY */ #endif boolean wizweight; /* display weight of everything in wizard mode */ + /* * Window capability support. */ diff --git a/src/cmd.c b/src/cmd.c index f8f779fc5..80dbcd0f4 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -1226,13 +1226,26 @@ doterrain(VOID_ARGS) free((genericptr_t) sel); switch (which) { - case 1: reveal_terrain(0, 0); break; /* known map */ - case 2: reveal_terrain(0, 1); break; /* known map with traps */ - case 3: reveal_terrain(0, 1|2); break; /* known map w/ traps & objs */ - case 4: reveal_terrain(1, 0); break; /* full map */ - case 5: wiz_map_levltyp(); break; /* map internals */ - case 6: wiz_levltyp_legend(); break; /* internal details */ - default: break; + case 1: /* known map */ + reveal_terrain(0, TER_MAP); + break; + case 2: /* known map with known traps */ + reveal_terrain(0, TER_MAP | TER_TRP); + break; + case 3: /* known map with known traps and objects */ + reveal_terrain(0, TER_MAP | TER_TRP | TER_OBJ); + break; + case 4: /* full map */ + reveal_terrain(1, TER_MAP); + break; + case 5: /* map internals */ + wiz_map_levltyp(); + break; + case 6: /* internal details */ + wiz_levltyp_legend(); + break; + default: + break; } return 0; /* no time elapses */ } diff --git a/src/detect.c b/src/detect.c index 526c81c6b..08773c20d 100644 --- a/src/detect.c +++ b/src/detect.c @@ -1524,10 +1524,12 @@ int which_subset; /* when not full, whether to suppress objs and/or traps */ unsigned save_swallowed; struct monst *mtmp; struct trap *t; + coord pos; char buf[BUFSZ]; - boolean keep_traps = (which_subset & 1) !=0, - keep_objs = (which_subset & 2) != 0, - keep_mons = (which_subset & 4) != 0; /* actually always 0 */ + /* there is a TER_MAP bit too; we always show map regardless of it */ + boolean keep_traps = (which_subset & TER_TRP) !=0, + keep_objs = (which_subset & TER_OBJ) != 0, + keep_mons = (which_subset & TER_MON) != 0; /* not used */ save_swallowed = u.uswallow; iflags.save_uinwater = u.uinwater, iflags.save_uburied = u.uburied; @@ -1605,11 +1607,8 @@ int which_subset; /* when not full, whether to suppress objs and/or traps */ show_glyph(x, y, glyph); } - /* [TODO: highlight hero's location somehow] */ - u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied; - iflags.save_uinwater = iflags.save_uburied = 0; - if (save_swallowed) - u.uswallow = 1; + /* hero's location is not highlighted, but getpos() starts with + cursor there, and after moving it anywhere '@' moves it back */ flush_screen(1); if (full) { Strcpy(buf, "underlying terrain"); @@ -1627,7 +1626,20 @@ int which_subset; /* when not full, whether to suppress objs and/or traps */ (keep_traps || keep_objs) ? "," : ""); } pline("Showing %s only...", buf); - display_nhwindow(WIN_MAP, TRUE); /* give "--More--" prompt */ + + /* allow player to move cursor around and get autodescribe feedback + based on what is visible now rather than what is on 'real' map */ + pos.x = u.ux, pos.y = u.uy; + iflags.autodescribe = TRUE; + iflags.terrainmode = which_subset | TER_MAP; /* guaranteed non-zero */ + getpos(&pos, FALSE, "anything of interest"); + iflags.terrainmode = 0; + /* leave iflags.autodescribe 'on' even if it was previously 'off' */ + + u.uinwater = iflags.save_uinwater, u.uburied = iflags.save_uburied; + iflags.save_uinwater = iflags.save_uburied = 0; + if (save_swallowed) + u.uswallow = 1; docrt(); /* redraw the screen, restoring regular map */ if (Underwater) under_water(2); diff --git a/src/do_name.c b/src/do_name.c index de2c00952..1570e41bf 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -59,30 +59,37 @@ const char *goal; 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 m or M to move the cursor to next monster."); - putstr(tmpwin, 0, "Use o or O to move the cursor to next object."); - if (getpos_hilitefunc) - putstr(tmpwin, 0, "Use $ to display valid locations."); - putstr(tmpwin, 0, "Use # to toggle automatic description."); - if (iflags.cmdassist) /* assisting the '/' command, I suppose... */ - putstr(tmpwin, 0, (iflags.getpos_coords == GPCOORDS_NONE) - ? "(Set 'whatis_coord' option to include coordinates with '#' text.)" + if (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0) + 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."); + if (!iflags.terrainmode) { + if (getpos_hilitefunc) + putstr(tmpwin, 0, "Use $ to display valid locations."); + putstr(tmpwin, 0, "Use # to toggle automatic description."); + if (iflags.cmdassist) /* assisting the '/' command, I suppose... */ + putstr(tmpwin, 0, + (iflags.getpos_coords == GPCOORDS_NONE) + ? "(Set 'whatis_coord' option to include coordinates with '#' text.)" : "(Reset 'whatis_coord' option to omit coordinates from '#' text.)"); - /* 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); - Sprintf(sbuf, "Type a .%s when you are at the right place.", - doing_what_is ? " or , or ; or :" : ""); - putstr(tmpwin, 0, sbuf); - if (doing_what_is) { - putstr(tmpwin, 0, - " : describe current spot, show 'more info', move to another spot."); - Sprintf(sbuf, " . describe current spot,%s move to another spot;", - flags.help ? " prompt if 'more info'," : ""); + /* disgusting hack; the alternate selection characters work for any + getpos call, but only matter for dowhatis (and doquickwhatis) */ + doing_what_is = (goal == what_is_an_unknown_object); + Sprintf(sbuf, "Type a .%s when you are at the right place.", + doing_what_is ? " or , or ; or :" : ""); putstr(tmpwin, 0, sbuf); - putstr(tmpwin, 0, " , describe current spot, move to another spot;"); - putstr(tmpwin, 0, - " ; describe current spot, stop looking at things;"); + if (doing_what_is) { + putstr(tmpwin, 0, + " : describe current spot, show 'more info', move to another spot."); + Sprintf(sbuf, + " . describe current spot,%s move to another spot;", + flags.help ? " prompt if 'more info'," : ""); + putstr(tmpwin, 0, sbuf); + putstr(tmpwin, 0, + " , describe current spot, move to another spot;"); + putstr(tmpwin, 0, + " ; describe current spot, stop looking at things;"); + } } if (!force) putstr(tmpwin, 0, "Type Space or Escape when you're done."); @@ -446,7 +453,7 @@ const char *goal; 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 */ + user-visible glyph */ k = back_to_glyph(tx, ty); /* uninteresting background glyph */ if (glyph_is_cmap(k) @@ -460,9 +467,10 @@ const char *goal; } if (glyph_is_cmap(k) && matching[glyph_to_cmap(k)] - && levl[tx][ty].seenv - && (!IS_WALL(levl[tx][ty].typ)) - && (levl[tx][ty].typ != SDOOR) + && (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) { @@ -495,8 +503,10 @@ const char *goal; } /* !quitchars */ if (force) goto nxtc; - pline("Done."); - msg_given = FALSE; /* suppress clear */ + if (!iflags.terrainmode) { + pline("Done."); + msg_given = FALSE; /* suppress clear */ + } cx = -1; cy = 0; result = 0; /* not -1 */ diff --git a/src/pager.c b/src/pager.c index 3e95336b0..f1ed5d485 100644 --- a/src/pager.c +++ b/src/pager.c @@ -166,7 +166,8 @@ struct obj **obj_p; otmp->corpsenm = MCORPSENM(mtmp); } /* if located at adjacent spot, mark it as having been seen up close */ - if (otmp && distu(x, y) <= 2 && !Blind && !Hallucination) + if (otmp && distu(x, y) <= 2 && !Blind && !Hallucination + && !iflags.terrainmode) otmp->dknown = 1; *obj_p = otmp; @@ -323,7 +324,8 @@ char *buf, *monbuf; buf[0] = monbuf[0] = '\0'; glyph = glyph_at(x, y); - if (u.ux == x && u.uy == y && canspotself()) { + if (u.ux == x && u.uy == y && canspotself() + && (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0)) { /* fill in buf[] */ (void) self_lookat(buf); @@ -348,14 +350,14 @@ char *buf, *monbuf; how |= 4; if (how) - Sprintf( - eos(buf), " [seen: %s%s%s%s%s]", - (how & 1) ? "infravision" : "", - /* add comma if telep and infrav */ - ((how & 3) > 2) ? ", " : "", (how & 2) ? "telepathy" : "", - /* add comma if detect and (infrav or telep or both) */ - ((how & 7) > 4) ? ", " : "", - (how & 4) ? "monster detection" : ""); + Sprintf(eos(buf), " [seen: %s%s%s%s%s]", + (how & 1) ? "infravision" : "", + /* add comma if telep and infrav */ + ((how & 3) > 2) ? ", " : "", + (how & 2) ? "telepathy" : "", + /* add comma if detect and (infrav or telep or both) */ + ((how & 7) > 4) ? ", " : "", + (how & 4) ? "monster detection" : ""); } } else if (u.uswallow) { /* all locations when swallowed other than the hero are the monster */ @@ -682,42 +684,50 @@ const char **firstmatch; } /* 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)); + if (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0) { + 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" */ } - /* 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" */ /* 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 (!iflags.terrainmode || (iflags.terrainmode & TER_OBJ) != 0) { + for (i = 1; i < MAXOCLASSES; i++) { + if (sym == (looked ? showsyms[i + SYM_OFF_O] + : def_oc_syms[i].sym) + || (looked && i == ROCK_CLASS && glyph_is_statue(glyph))) { + 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)); + } } } }