getpos() for objects

Extend the 'm' and 'M' functionality (move cursor to nearest monster
or farthest monster, respectively, then to next nearest/next farthest
when used successively) to 'o' and 'O' for objects.

'M' was picking the wrong monster (nearest) on first use; now fixed.
Hero is now included in the monster list, and will be the last one
reached if you cycle all the way through in either direction.  (Makes
it easier to tell that you have actually been all the way through.
Unfortunately, objects don't have any seen-'em-all indicator.  Perhaps
the hero's coordinates should go on that list too?)
This commit is contained in:
PatR
2016-01-06 16:47:30 -08:00
parent c8cd550a5a
commit 22685763d1
2 changed files with 96 additions and 36 deletions

View File

@@ -87,20 +87,14 @@ requiver pickup_thrown objects if quiver is empty
make mimics mimicing walls or trees also block light
stepping onto lava destroyed non-fireproof water walking boots but left other
vulnerable boot types intact
allow moving cursor to monsters with 'm' and 'M' when asked for map location
fix death reason when eating tainted glob of <monster> (not corpse)
use appropriate place name for drum of earthquake shakes
fix unmapped branch stairs on sokoban level
redraw map when hilite_pile is toggled to display the highlighting
make commands that accept a count prefix for item selection
show "Count:" like command repeating does
allow picking a used inventory letter from menu when #adjusting
zapping wand of opening at yourself, unlock carried boxes
dissolve iron bars by force-fighting with wielded potion of acid
poison breath leaves a trail of poison gas
make vault guard accept names starting with number
fix weight of containers in special levels
allow knife and stiletto as possible tin opening tools
make the raven medusa level shortsighted
fix possible segfault in lev_comp when map was too tall
@@ -134,10 +128,17 @@ General New Features
--------------------
naming Sting or Orcrist now breaks illiterate conduct
different feedback for reading a scroll of mail created by writing with marker
wizard mode #wizintrinsic
reading non-cursed scroll of enchant weapon uncurses welded tin opener
if hero has no jumping ability but knows the jumping spell, the #jump command
will attempt to cast the spell
allow moving cursor to monsters with 'm' (nearest first) and 'M' (furthest
first) when asked for map location, or to objects with 'o' and 'O'
allow picking a used inventory letter from menu when #adjusting
zapping wand of opening at yourself, unlock carried boxes
dissolve iron bars by force-fighting with wielded potion of acid
poison breath leaves a trail of poison gas
allow knife and stiletto as possible tin opening tools
wizard mode #wizintrinsic command
additional tribute passages for The Colour of Magic, The Light Fantastic,
Equal Rites, Snuff, and Raising Steam
compile-time options SIMPLE_MAIL and SERVER_ADMIN_MSG for public server use

View File

@@ -8,6 +8,7 @@ STATIC_DCL char *NDECL(nextmbuf);
STATIC_DCL void FDECL(getpos_help, (BOOLEAN_P, const char *));
STATIC_DCL int FDECL(CFDECLSPEC cmp_coord_distu, (const void *,
const void *));
STATIC_OVL void FDECL(gather_locs, (coord **, int *, BOOLEAN_P));
STATIC_DCL void NDECL(do_mname);
STATIC_DCL boolean FDECL(alreadynamed, (struct monst *, char *, char *));
STATIC_DCL void FDECL(do_oname, (struct obj *));
@@ -58,6 +59,7 @@ const char *goal;
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.");
@@ -93,6 +95,61 @@ const void *b;
return dist_1 - dist_2;
}
/* gather locations for monsters or objects shown on the map */
STATIC_OVL void
gather_locs(arr_p, cnt_p, do_mons)
coord **arr_p;
int *cnt_p;
boolean do_mons;
{
int x, y, pass, glyph, idx;
*cnt_p = idx = 0;
for (pass = 0; pass < 2; pass++) {
if (pass) {
/* *cnt_p + 1: always allocate a non-zero amount */
*arr_p = (coord *) alloc(sizeof (coord) * (*cnt_p + 1));
if (!*cnt_p) {
/* needed for caller's mon[0].x,.y==u.ux,.uy check */
(*arr_p)[0].x = (*arr_p)[0].y = 0;
break;
}
}
for (x = 1; x < COLNO; x++)
for (y = 0; y < ROWNO; y++) {
glyph = glyph_at(x, y);
if (do_mons) {
/* unlike '/M', this skips monsters revealed by
* warning glyphs and remembered invisible ones;
* TODO: skip worm tails
*/
if (glyph_is_monster(glyph)) {
if (!pass) {
++*cnt_p;
} else {
(*arr_p)[idx].x = x;
(*arr_p)[idx].y = y;
++idx;
}
}
} else { /* objects */
/* TODO: skip boulders and rocks */
if (glyph_is_object(glyph)) {
if (!pass) {
++*cnt_p;
} else {
(*arr_p)[idx].x = x;
(*arr_p)[idx].y = y;
++idx;
}
}
}
}
} /* pass */
if (*cnt_p)
qsort(*arr_p, *cnt_p, sizeof (coord), cmp_coord_distu);
}
int
getpos(ccp, force, goal)
coord *ccp;
@@ -107,9 +164,8 @@ const char *goal;
static const char pick_chars[] = ".,;:";
const char *cp;
boolean hilite_state = FALSE;
coord *monarr = NULL;
int moncount = 0;
int monidx = 0;
coord *monarr = (coord *) 0, *objarr = (coord *) 0;
int moncount = 0, monidx = 0, objcount = 0, objidx = 0;
if (!goal)
goal = "desired location";
@@ -244,32 +300,15 @@ const char *goal;
goto nxtc;
} else if (c == 'm' || c == 'M') {
if (!monarr) {
int x,y,s;
moncount = 0;
for (s = 0; s < 2; s++) {
if (s) {
/* moncount + 1: always allocate a non-zero amount */
monarr = (coord *) alloc(sizeof (coord) * (moncount + 1));
monidx = 0;
}
if (!s || s && moncount)
for (x = 0; x < COLNO; x++)
for (y = 0; y < ROWNO; y++)
if (glyph_is_monster(glyph_at(x,y))
&& !(x == u.ux && y == u.uy)) {
if (!s)
moncount++;
else {
monarr[monidx].x = x;
monarr[monidx].y = y;
monidx++;
}
}
}
qsort(monarr, moncount, sizeof (coord), cmp_coord_distu);
/* ready for first increment/decrement to change to zero */
monidx = (c == 'm') ? -1 : 1;
gather_locs(&monarr, &moncount, TRUE);
/* when hero is first element (always, unless unseen),
we want first increment to reach 1 (nearest aside
from hero) or first decrement to reach moncount-1
(farthest); if hero is not first element, we want
first increment to end up with 0 (nearest monster),
first decrement should still choose moncount-1 */
monidx = (monarr[0].x == u.ux && monarr[0].y == u.uy) ? 0
: (c == 'm') ? -1 : 0;
}
if (moncount) {
if (c == 'm') {
@@ -282,6 +321,24 @@ const char *goal;
cy = monarr[monidx].y;
goto nxtc;
}
} else if (c == 'o' || c == 'O') {
if (!objarr) {
gather_locs(&objarr, &objcount, FALSE);
/* ready for first increment to change to zero
or first decrement to change to objcount-1 */
objidx = (c == 'o') ? -1 : 0;
}
if (objcount) {
if (c == 'o') {
objidx = (objidx + 1) % objcount;
} else {
if (--objidx < 0)
objidx = objcount - 1;
}
cx = objarr[objidx].x;
cy = objarr[objidx].y;
goto nxtc;
}
} else {
if (!index(quitchars, c)) {
char matching[MAXPCHARS];
@@ -375,6 +432,8 @@ const char *goal;
ccp->y = cy;
if (monarr)
free((genericptr_t) monarr);
if (objarr)
free((genericptr_t) objarr);
getpos_hilitefunc = (void FDECL((*), (int))) 0;
return result;
}