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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
27
src/cmd.c
27
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 */
|
||||
}
|
||||
|
||||
30
src/detect.c
30
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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
92
src/pager.c
92
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user