getpos moving to 'cmap' characters
While testing something I noticed that moving the cursor to visible '^' by typing '^' while getpos was asking me to pick a location, it didn't always cycle through all visible traps. The most straightforward culprit was after trap detection (via confused gold detection, not ^F) had found a trap door or level teleporter in a closet that itself was a secret corridor spot. But it turned out to be any location that hadn't been seen yet. This is a substantial overhaul of the relevant code and so far works for all the cases I've tried, but there are bound to be cases I haven't tried yet and those may or may not work correctly. There's also a bunch of formatting cleanup, and some simplification of the m/M/o/O/d/D/x/X handling.
This commit is contained in:
@@ -272,6 +272,8 @@ reviving one of a stack of N corpses in a shop charged a usage fee for all N;
|
||||
remaining N-1 were owned by hero if carried but by shop if on floor
|
||||
gremlin wailing in agony should wake up nearby monsters
|
||||
add more lighting variance to the second bigroom variant
|
||||
when getpost was picking a location, typing '^' to move to the next known trap
|
||||
skipped some detected traps if their location was unseen
|
||||
|
||||
|
||||
Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository
|
||||
|
||||
172
src/do_name.c
172
src/do_name.c
@@ -64,10 +64,15 @@ const char *goal;
|
||||
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.");
|
||||
putstr(tmpwin, 0, /* d,D are useful regardless of terrainmode */
|
||||
"Use d or D to move the cursor to next door or doorway.");
|
||||
if (!iflags.terrainmode || (iflags.terrainmode & TER_MAP) != 0) {
|
||||
/* both of these are primarily useful when choosing a travel
|
||||
destination for the '_' command */
|
||||
putstr(tmpwin, 0,
|
||||
"Use d or D to move the cursor to next door or doorway.");
|
||||
putstr(tmpwin, 0,
|
||||
"Use x or X to move the cursor to unexplored location.");
|
||||
}
|
||||
if (!iflags.terrainmode) {
|
||||
putstr(tmpwin, 0, "Use x or X to move the cursor to unexplored location.");
|
||||
if (getpos_hilitefunc)
|
||||
putstr(tmpwin, 0, "Use $ to display valid locations.");
|
||||
putstr(tmpwin, 0, "Use # to toggle automatic description.");
|
||||
@@ -134,10 +139,11 @@ enum gloctypes {
|
||||
};
|
||||
|
||||
|
||||
#define IS_UNEXPLORED_LOC(x,y) (isok((x), (y)) \
|
||||
&& glyph_is_cmap(levl[(x)][(y)].glyph) \
|
||||
&& glyph_to_cmap(levl[(x)][(y)].glyph) == S_stone \
|
||||
&& !levl[(x)][(y)].seenv)
|
||||
#define IS_UNEXPLORED_LOC(x,y) \
|
||||
(isok((x), (y)) \
|
||||
&& glyph_is_cmap(levl[(x)][(y)].glyph) \
|
||||
&& glyph_to_cmap(levl[(x)][(y)].glyph) == S_stone \
|
||||
&& !levl[(x)][(y)].seenv)
|
||||
|
||||
STATIC_OVL boolean
|
||||
gather_locs_interesting(x,y, gloc)
|
||||
@@ -150,28 +156,35 @@ int x,y, gloc;
|
||||
|
||||
switch (gloc) {
|
||||
default:
|
||||
case GLOC_MONS: return (glyph_is_monster(glyph)
|
||||
&& glyph != monnum_to_glyph(PM_LONG_WORM_TAIL));
|
||||
case GLOC_OBJS: return (glyph_is_object(glyph)
|
||||
&& glyph != objnum_to_glyph(BOULDER)
|
||||
&& glyph != objnum_to_glyph(ROCK));
|
||||
case GLOC_DOOR: return (glyph_is_cmap(glyph)
|
||||
&& (is_cmap_door(glyph_to_cmap(glyph))
|
||||
|| is_cmap_drawbridge(glyph_to_cmap(glyph))
|
||||
|| glyph_to_cmap(glyph) == S_ndoor));
|
||||
case GLOC_EXPLORE: return (glyph_is_cmap(glyph)
|
||||
&& (is_cmap_door(glyph_to_cmap(glyph))
|
||||
|| is_cmap_drawbridge(glyph_to_cmap(glyph))
|
||||
|| glyph_to_cmap(glyph) == S_ndoor
|
||||
|| glyph_to_cmap(glyph) == S_room
|
||||
|| glyph_to_cmap(glyph) == S_darkroom
|
||||
|| glyph_to_cmap(glyph) == S_corr
|
||||
|| glyph_to_cmap(glyph) == S_litcorr)
|
||||
&& (IS_UNEXPLORED_LOC(x+1,y)
|
||||
|| IS_UNEXPLORED_LOC(x-1,y)
|
||||
|| IS_UNEXPLORED_LOC(x,y+1)
|
||||
|| IS_UNEXPLORED_LOC(x,y-1)));
|
||||
case GLOC_MONS:
|
||||
/* unlike '/M', this skips monsters revealed by
|
||||
warning glyphs and remembered unseen ones */
|
||||
return (glyph_is_monster(glyph)
|
||||
&& glyph != monnum_to_glyph(PM_LONG_WORM_TAIL));
|
||||
case GLOC_OBJS:
|
||||
return (glyph_is_object(glyph)
|
||||
&& glyph != objnum_to_glyph(BOULDER)
|
||||
&& glyph != objnum_to_glyph(ROCK));
|
||||
case GLOC_DOOR:
|
||||
return (glyph_is_cmap(glyph)
|
||||
&& (is_cmap_door(glyph_to_cmap(glyph))
|
||||
|| is_cmap_drawbridge(glyph_to_cmap(glyph))
|
||||
|| glyph_to_cmap(glyph) == S_ndoor));
|
||||
case GLOC_EXPLORE:
|
||||
return (glyph_is_cmap(glyph)
|
||||
&& (is_cmap_door(glyph_to_cmap(glyph))
|
||||
|| is_cmap_drawbridge(glyph_to_cmap(glyph))
|
||||
|| glyph_to_cmap(glyph) == S_ndoor
|
||||
|| glyph_to_cmap(glyph) == S_room
|
||||
|| glyph_to_cmap(glyph) == S_darkroom
|
||||
|| glyph_to_cmap(glyph) == S_corr
|
||||
|| glyph_to_cmap(glyph) == S_litcorr)
|
||||
&& (IS_UNEXPLORED_LOC(x + 1, y)
|
||||
|| IS_UNEXPLORED_LOC(x - 1, y)
|
||||
|| IS_UNEXPLORED_LOC(x, y + 1)
|
||||
|| IS_UNEXPLORED_LOC(x, y - 1)));
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -199,10 +212,8 @@ int gloc;
|
||||
for (pass = 0; pass < 2; pass++) {
|
||||
for (x = 1; x < COLNO; x++)
|
||||
for (y = 0; y < ROWNO; y++) {
|
||||
/* unlike '/M', this skips monsters revealed by
|
||||
warning glyphs and remembered invisible ones */
|
||||
if ((x == u.ux && y == u.uy)
|
||||
|| gather_locs_interesting(x,y, gloc)) {
|
||||
|| gather_locs_interesting(x, y, gloc)) {
|
||||
if (!pass) {
|
||||
++*cnt_p;
|
||||
} else {
|
||||
@@ -317,13 +328,14 @@ coord *ccp;
|
||||
boolean force;
|
||||
const char *goal;
|
||||
{
|
||||
static const char pick_chars[] = ".,;:",
|
||||
mMoOdDxX[] = "mMoOdDxX";
|
||||
const char *cp;
|
||||
int result = 0;
|
||||
int cx, cy, i, c;
|
||||
int sidx, tx, ty;
|
||||
boolean msg_given = TRUE; /* clear message window by default */
|
||||
boolean show_goal_msg = FALSE;
|
||||
static const char pick_chars[] = ".,;:";
|
||||
const char *cp;
|
||||
boolean hilite_state = FALSE;
|
||||
coord *garr[NUM_GLOCS] = DUMMY;
|
||||
int gcount[NUM_GLOCS] = DUMMY;
|
||||
@@ -437,6 +449,10 @@ const char *goal;
|
||||
}
|
||||
goto nxtc;
|
||||
} else if (c == '#') {
|
||||
/* unfortunately, using '#' as a command means we can't move
|
||||
cursor to sinks, iron bars, and poison clouds; perhaps
|
||||
when autodescribe is already on, next '#' should try to
|
||||
move to '#' rather than to toggle off? (or ask; ick...) */
|
||||
iflags.autodescribe = !iflags.autodescribe;
|
||||
pline("Automatic description %sis %s.",
|
||||
flags.verbose ? "of features under cursor " : "",
|
||||
@@ -446,29 +462,25 @@ const char *goal;
|
||||
msg_given = TRUE;
|
||||
goto nxtc;
|
||||
} else if (c == '@') { /* return to hero's spot */
|
||||
/* reset 'm','M' and 'o','O'; otherwise, there's no way for player
|
||||
/* reset 'm&M', 'o&O', &c; otherwise, there's no way for player
|
||||
to achieve that except by manually cycling through all spots */
|
||||
for (i = 0; i < NUM_GLOCS; i++)
|
||||
gidx[i] = 0;
|
||||
cx = u.ux;
|
||||
cy = u.uy;
|
||||
goto nxtc;
|
||||
} else if (c == 'm' || c == 'M' /* nearest or farthest monster */
|
||||
|| c == 'o' || c == 'O' /* nearest or farthest object */
|
||||
|| c == 'x' || c == 'X' /* unexplored area */
|
||||
|| c == 'd' || c == 'D') { /* door/doorway */
|
||||
int gloc = (c == 'o' || c == 'O') ? GLOC_OBJS
|
||||
: (c == 'd' || c == 'D') ? GLOC_DOOR
|
||||
: (c == 'x' || c == 'X') ? GLOC_EXPLORE
|
||||
: GLOC_MONS;
|
||||
} else if ((cp = index(mMoOdDxX, c)) != 0) { /* 'm|M', 'o|O', &c */
|
||||
/* nearest or farthest monster or object or door or unexplored */
|
||||
int gtmp = (int) (cp - mMoOdDxX), /* 0..7 */
|
||||
gloc = gtmp >> 1; /* 0..3 */
|
||||
|
||||
if (!garr[gloc]) {
|
||||
gather_locs(&garr[gloc], &gcount[gloc], gloc);
|
||||
gidx[gloc] = 0; /* garr[][0] is hero's spot */
|
||||
}
|
||||
if (c == 'm' || c == 'o' || c == 'd' || c == 'x') {
|
||||
if (!(gtmp & 1)) { /* c=='m' || c=='o' || c=='d' || c=='x') */
|
||||
gidx[gloc] = (gidx[gloc] + 1) % gcount[gloc];
|
||||
} else {
|
||||
} else { /* c=='M' || c=='O' || c=='D' || c=='X') */
|
||||
if (--gidx[gloc] < 0)
|
||||
gidx[gloc] = gcount[gloc] - 1;
|
||||
}
|
||||
@@ -481,9 +493,17 @@ const char *goal;
|
||||
int pass, lo_x, lo_y, hi_x, hi_y, k = 0;
|
||||
|
||||
(void) memset((genericptr_t) matching, 0, sizeof matching);
|
||||
for (sidx = 1; sidx < MAXPCHARS; sidx++)
|
||||
for (sidx = 1; sidx < MAXPCHARS; sidx++) { /* [0] left as 0 */
|
||||
if (IS_DOOR(sidx) || IS_WALL(sidx)
|
||||
|| sidx == SDOOR || sidx == SCORR
|
||||
|| glyph_to_cmap(k) == S_room
|
||||
|| glyph_to_cmap(k) == S_darkroom
|
||||
|| glyph_to_cmap(k) == S_corr
|
||||
|| glyph_to_cmap(k) == S_litcorr)
|
||||
continue;
|
||||
if (c == defsyms[sidx].sym || c == (int) showsyms[sidx])
|
||||
matching[sidx] = (char) ++k;
|
||||
}
|
||||
if (k) {
|
||||
for (pass = 0; pass <= 1; pass++) {
|
||||
/* pass 0: just past current pos to lower right;
|
||||
@@ -494,35 +514,39 @@ const char *goal;
|
||||
lo_x = (pass == 0 && ty == lo_y) ? cx + 1 : 1;
|
||||
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 */
|
||||
k = back_to_glyph(tx, ty);
|
||||
/* uninteresting background glyph */
|
||||
/* first, look at what is currently visible
|
||||
(might be monster) */
|
||||
k = glyph_at(tx, ty);
|
||||
if (glyph_is_cmap(k)
|
||||
&& (IS_DOOR(levl[tx][ty].typ)
|
||||
|| glyph_to_cmap(k) == S_room
|
||||
|| glyph_to_cmap(k) == S_darkroom
|
||||
|| glyph_to_cmap(k) == S_corr
|
||||
|| glyph_to_cmap(k) == S_litcorr)) {
|
||||
/* what hero remembers to be at tx,ty */
|
||||
k = glyph_at(tx, ty);
|
||||
&& matching[glyph_to_cmap(k)])
|
||||
goto foundc;
|
||||
/* next, try glyph that's remembered here
|
||||
(might be trap or object) */
|
||||
if (level.flags.hero_memory
|
||||
/* !terrainmode: don't move to remembered
|
||||
trap or object if not currently shown */
|
||||
&& !iflags.terrainmode) {
|
||||
k = levl[tx][ty].glyph;
|
||||
if (glyph_is_cmap(k)
|
||||
&& matching[glyph_to_cmap(k)])
|
||||
goto foundc;
|
||||
}
|
||||
if (glyph_is_cmap(k)
|
||||
&& matching[glyph_to_cmap(k)]
|
||||
&& (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) {
|
||||
cx = tx, cy = ty;
|
||||
if (msg_given) {
|
||||
clear_nhwindow(WIN_MESSAGE);
|
||||
msg_given = FALSE;
|
||||
}
|
||||
goto nxtc;
|
||||
/* last, try actual terrain here (shouldn't
|
||||
we be using lastseentyp[][] instead?) */
|
||||
if (levl[tx][ty].seenv) {
|
||||
k = back_to_glyph(tx, ty);
|
||||
if (glyph_is_cmap(k)
|
||||
&& matching[glyph_to_cmap(k)])
|
||||
goto foundc;
|
||||
}
|
||||
continue;
|
||||
foundc:
|
||||
cx = tx, cy = ty;
|
||||
if (msg_given) {
|
||||
clear_nhwindow(WIN_MESSAGE);
|
||||
msg_given = FALSE;
|
||||
}
|
||||
goto nxtc;
|
||||
} /* column */
|
||||
} /* row */
|
||||
} /* pass */
|
||||
@@ -545,10 +569,8 @@ const char *goal;
|
||||
} /* !quitchars */
|
||||
if (force)
|
||||
goto nxtc;
|
||||
if (!iflags.terrainmode) {
|
||||
pline("Done.");
|
||||
msg_given = FALSE; /* suppress clear */
|
||||
}
|
||||
pline("Done.");
|
||||
msg_given = FALSE; /* suppress clear */
|
||||
cx = -1;
|
||||
cy = 0;
|
||||
result = 0; /* not -1 */
|
||||
|
||||
Reference in New Issue
Block a user