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:
PatR
2016-05-30 17:56:47 -07:00
parent 5addbf88dd
commit 7404597ac5
2 changed files with 99 additions and 75 deletions

View File

@@ -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

View File

@@ -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 */