From 22685763d1a7f2a4d645d61e35028e56c36e8cfe Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 6 Jan 2016 16:47:30 -0800 Subject: [PATCH] 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?) --- doc/fixes36.1 | 15 ++++--- src/do_name.c | 117 +++++++++++++++++++++++++++++++++++++------------- 2 files changed, 96 insertions(+), 36 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 97fc2b360..2602460c0 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -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 (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 diff --git a/src/do_name.c b/src/do_name.c index 2341adb0e..da48c07dc 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -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; } -- 2.40.0