From b8f8b170a87685c03fff79b2763dd2e62a65c726 Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 24 Aug 2022 15:33:35 -0700 Subject: [PATCH] sort #migratemons list of migrating monsters If there are any migrating monsters, #migratemons offers a chance to view them; display the list in arrival destination order rather than the arbitrary migrating_mons order. Doesn't change the list's order and doesn't apply to viewing 'c' (mons aimed at current level) or 'n' (mons aimed at next level), just to 'o' (other, neither 'c' nor 'n') and 'a' (all migrating mons). --- src/cmd.c | 65 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/src/cmd.c b/src/cmd.c index 7373590ee..5a67425a0 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -4019,8 +4019,23 @@ sanity_check(void) } #ifdef DEBUG_MIGRATING_MONS +static int QSORTCALLBACK migrsort_cmp(const genericptr, const genericptr); static void list_migrating_mons(d_level *); +static int QSORTCALLBACK +migrsort_cmp(const genericptr vptr1, const genericptr vptr2) +{ + const struct monst *m1 = *(const struct monst **) vptr1, + *m2 = *(const struct monst **) vptr2; + int d1 = m1->mux, l1 = m1->muy, d2 = m2->mux, l2 = m2->muy; + + if (d1 < d2 || (d1 == d2 && l1 < l2)) + return -1; + if (d1 > d2 || (d1 == d2 && l1 > l2)) + return 1; + return 0; /* tie => same destination */ +} + /* called by #migratemons; might turn it into separate wizard mode command */ static void list_migrating_mons( @@ -4028,10 +4043,11 @@ list_migrating_mons( { winid win = WIN_ERR; boolean showit = FALSE; - int n, xyloc; + unsigned n; + int xyloc; coordxy x, y; char c, prmpt[10], xtra[10], buf[BUFSZ]; - struct monst *mtmp; + struct monst *mtmp, **marray; int here = 0, nxtlv = 0, other = 0; for (mtmp = g.migrating_mons; mtmp; mtmp = mtmp->nmon) { @@ -4078,8 +4094,12 @@ list_migrating_mons( } putstr(win, 0, buf); putstr(win, 0, ""); - /* TODO? make multiple passes in order to show mons in - destination order */ + /* collect the migrating monsters into an array; for 'o' and 'a' + where multiple destination levels might be present, sort by + the destination; no sorting needed for 'c' and 'n' but it's + simpler to use the array than to have separate traversal */ + marray = (struct monst **) alloc((n + 1) * sizeof *marray); + n = 0; for (mtmp = g.migrating_mons; mtmp; mtmp = mtmp->nmon) { if (c == 'a') showit = TRUE; @@ -4091,21 +4111,30 @@ list_migrating_mons( else showit = (c == 'o'); - if (showit) { - Sprintf(buf, " %s", minimal_monnam(mtmp, FALSE)); - /* minimal_monnam() appends map coordinates; strip that */ - (void) strsubst(buf, " <0,0>", ""); - if (c == 'o' || c == 'a') - Sprintf(eos(buf), " to %d:%d", mtmp->mux, mtmp->muy); - xyloc = mtmp->mtrack[0].x; /* (for legibility) */ - if (xyloc == MIGR_EXACT_XY) { - x = mtmp->mtrack[1].x; - y = mtmp->mtrack[1].y; - Sprintf(eos(buf), " at <%d,%d>", (int) x, (int) y); - } - putstr(win, 0, buf); - } + if (showit) + marray[n++] = mtmp;; } + marray[n] = (struct monst *) 0; + if (n > 1 && c != 'c' && c != 'n') + qsort((genericptr_t) marray, (size_t) n, sizeof *marray, + migrsort_cmp); /* sort elements [0] through [n-1] */ + for (n = 0; (mtmp = marray[n]) != 0; ++n) { + Sprintf(buf, " %s", minimal_monnam(mtmp, FALSE)); + /* minimal_monnam() appends map coordinates; strip that */ + (void) strsubst(buf, " <0,0>", ""); + if (has_mgivenname(mtmp)) /* if mtmp is named, include that */ + Sprintf(eos(buf), " named %s", MGIVENNAME(mtmp)); + if (c == 'o' || c == 'a') + Sprintf(eos(buf), " to %d:%d", mtmp->mux, mtmp->muy); + xyloc = mtmp->mtrack[0].x; /* (for legibility) */ + if (xyloc == MIGR_EXACT_XY) { + x = mtmp->mtrack[1].x; + y = mtmp->mtrack[1].y; + Sprintf(eos(buf), " at <%d,%d>", (int) x, (int) y); + } + putstr(win, 0, buf); + } + free((genericptr_t) marray); display_nhwindow(win, FALSE); destroy_nhwindow(win); } else if (c != 'q') {