From 68f7c0ceda167494606d4066259bcadaa9ba7f9c Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sun, 17 Aug 2008 17:44:00 -0400 Subject: [PATCH] Rework code dealing with struct range fixing many bugs Change struct range from exclusive to inclusive upper bounds, for consistency with struct realmstr and the area syntax. Also fix many bugs. real()'s conversion from struct range's exclusive upper bounds to struct realmstr's inclusive upper bounds could underflow and store -1 in the realms file. Harmless, because its users didn't mind: list_realm() and nstr_exec_val() convert back to relative coordinates, and sarg_getrange() is only used by sarg_area(), which happened to undo the damage. The change to inclusive upper bounds gets rid of the broken conversion. xyinrange() incorrectly treated the upper bound as inclusive, unless the bounds were equal. Impact: * nxtitem() and nxtitemp() cases NS_AREA and NS_DIST attempted to hack around xyinrange()'s lossage(!), but screwed up: sectors on the lower bound of of a range spanning the the whole world were skipped. This affected all command arguments that support area or distance syntax for items. In sufficiently small worlds, it could also make radar miss satellites and ships, sonar miss ships, satellite miss ships and land units, nuclear detonations miss ships, planes, land units and nukes, automatic supply miss ship and land unit supply sources, ships and land units fail to return fire, ships fail to fire support. * draw_map() could draw units sitting just right or just below of the mapped area. No effect, as these parts of the map weren't actually shown. xydist_range() produced an inclusive upper bound when it decided that the range covers everything in that dimension (which it didn't get quite right either). This could make snxtsct_dist() and snxtitem_dist() initialize the iterator with an incorrect upper bound. Similar impact as the xyinrange() / nxtitem() lossage. border() could print the hundreds line unnecessarily. snxtsct() and snxtsct_all() screwed up for odd WORLD_Y: they failed to include (WORLD_Y - 1) / 2 in the y-range. This affected all command arguments that support "*" syntax for sectors, plus add ... c, power n, and break. snxtsct_all() failed to normalize the bounds (presumed harmless). There were a few correct, but somewhat unclean uses of struct range with inclusive upper bounds: * nat_reset() used one internally. * pathrange() worked with inclusive upper bounds internally, but corrected to exclusive upper bounds before passing the range out. * sarg_getrange() worked with inclusive upper bounds. Its only caller sarg_area() corrected that to exclusive upper bounds. The change to inclusive upper bounds cleans this up. unit_map() and xysize_range() had no issues (isn't that amazing?), but need to be updated for the changed struct range semantics. --- include/xy.h | 9 +++----- src/lib/commands/real.c | 4 ++-- src/lib/common/xy.c | 4 ++-- src/lib/subs/border.c | 2 +- src/lib/subs/maps.c | 4 ++-- src/lib/subs/nxtitem.c | 2 -- src/lib/subs/paths.c | 6 ++--- src/lib/subs/sarg.c | 7 ------ src/lib/subs/snxtsct.c | 48 ++++++++++++++++++--------------------- src/lib/update/nxtitemp.c | 2 -- 10 files changed, 34 insertions(+), 54 deletions(-) diff --git a/include/xy.h b/include/xy.h index 574c1b679..b3c1cbe67 100644 --- a/include/xy.h +++ b/include/xy.h @@ -48,12 +48,9 @@ (((y) < 0) ? (WORLD_Y - 1 - ((-(y) - 1) % WORLD_Y)) : ((y) % WORLD_Y)) struct range { - coord lx; /* low-range x,y */ - coord ly; - coord hx; /* high-range x,y */ - coord hy; - int width; /* range width, height */ - int height; + coord lx, ly; /* low-range x,y (inclusive) */ + coord hx, hy; /* high-range x,y (inclusive) */ + int width, height; }; extern char *xyas(coord x, coord y, natid country); diff --git a/src/lib/commands/real.c b/src/lib/commands/real.c index a5dcb4611..b1f21b351 100644 --- a/src/lib/commands/real.c +++ b/src/lib/commands/real.c @@ -86,9 +86,9 @@ real(void) return RET_SYN; getrealm(curr, natp->nat_cnum, &realm); realm.r_xl = abs.lx; - realm.r_xh = abs.hx - 1; + realm.r_xh = abs.hx; realm.r_yl = abs.ly; - realm.r_yh = abs.hy - 1; + realm.r_yh = abs.hy; putrealm(&realm); list_realm(curr, natp); } diff --git a/src/lib/common/xy.c b/src/lib/common/xy.c index 09472f1a6..87f3f4adc 100644 --- a/src/lib/common/xy.c +++ b/src/lib/common/xy.c @@ -183,7 +183,7 @@ ynorm(coord y) int xyinrange(coord x, coord y, struct range *rp) { - if (rp->lx < rp->hx) { + if (rp->lx <= rp->hx) { /* xrange doesn't wrap */ if (x < rp->lx || x > rp->hx) return 0; @@ -191,7 +191,7 @@ xyinrange(coord x, coord y, struct range *rp) if (x < rp->lx && x > rp->hx) return 0; } - if (rp->ly < rp->hy) { + if (rp->ly <= rp->hy) { /* yrange doesn't wrap */ if (y < rp->ly || y > rp->hy) return 0; diff --git a/src/lib/subs/border.c b/src/lib/subs/border.c index 34f32e8ee..a3157faab 100644 --- a/src/lib/subs/border.c +++ b/src/lib/subs/border.c @@ -68,7 +68,7 @@ border(struct range *rp, char *prefstr, char *sep) int posi, n, x; if ((WORLD_X / 2) >= 100) { - if (rp->lx + rp->width > 99 || rp->hx - rp->width < -99) { + if (rp->lx + rp->width > 100 || rp->hx - rp->width < -100) { /* * hundreds */ diff --git a/src/lib/subs/maps.c b/src/lib/subs/maps.c index 19974b426..50964262e 100644 --- a/src/lib/subs/maps.c +++ b/src/lib/subs/maps.c @@ -366,9 +366,9 @@ unit_map(int unit_type, int uid, struct nstr_sect *nsp, char *originp) } range.lx = xnorm(unit.gen.x - 10); - range.hx = xnorm(unit.gen.x + 11); + range.hx = xnorm(unit.gen.x + 10); range.ly = ynorm(unit.gen.y - 5); - range.hy = ynorm(unit.gen.y + 6); + range.hy = ynorm(unit.gen.y + 5); xysize_range(&range); snxtsct_area(nsp, &range); return RET_OK; diff --git a/src/lib/subs/nxtitem.c b/src/lib/subs/nxtitem.c index 01af5b13b..9a11882f0 100644 --- a/src/lib/subs/nxtitem.c +++ b/src/lib/subs/nxtitem.c @@ -87,8 +87,6 @@ nxtitem(struct nstr_item *np, void *ptr) return 0; if (!xyinrange(gp->x, gp->y, &np->range)) selected = 0; - if (gp->x == np->range.hx || gp->y == np->range.hy) - selected = 0; break; case NS_XY: if (CANT_HAPPEN(!(ef_flags(np->type) & EFF_XY))) diff --git a/src/lib/subs/paths.c b/src/lib/subs/paths.c index e6ce39714..79b680305 100644 --- a/src/lib/subs/paths.c +++ b/src/lib/subs/paths.c @@ -243,8 +243,6 @@ pathrange(coord cx, coord cy, char *pp, int border, struct range *range) range->hx = cx; range->ly = cy; range->hy = cy; - range->width = 0; - range->height = 0; for (; *pp; pp++) { dir = diridx(*pp); if (dir == DIR_STOP) @@ -262,7 +260,7 @@ pathrange(coord cx, coord cy, char *pp, int border, struct range *range) } range->lx = xnorm(range->lx - border * 2); range->ly = ynorm(range->ly - border); - range->hx = xnorm(range->hx + border * 2 + 1); - range->hy = ynorm(range->hy + border + 1); + range->hx = xnorm(range->hx + border * 2); + range->hy = ynorm(range->hy + border); xysize_range(range); } diff --git a/src/lib/subs/sarg.c b/src/lib/subs/sarg.c index 37f8753c0..4c572edcd 100644 --- a/src/lib/subs/sarg.c +++ b/src/lib/subs/sarg.c @@ -165,13 +165,6 @@ sarg_area(char *str, struct range *rp) { if (!sarg_getrange(str, rp)) return 0; - rp->hx += 1; - if (rp->hx >= WORLD_X) - rp->hx = 0; - rp->hy += 1; - if (rp->hy >= WORLD_Y) - rp->hy = 0; - xysize_range(rp); return 1; } diff --git a/src/lib/subs/snxtsct.c b/src/lib/subs/snxtsct.c index 79f15c242..c53fe0dad 100644 --- a/src/lib/subs/snxtsct.c +++ b/src/lib/subs/snxtsct.c @@ -83,8 +83,8 @@ snxtsct(struct nstr_sect *np, char *str) natp = getnatp(player->cnum); range.lx = xabs(natp, -WORLD_X / 2); range.ly = yabs(natp, -WORLD_Y / 2); - range.hx = xabs(natp, WORLD_X / 2); - range.hy = yabs(natp, WORLD_Y / 2); + range.hx = xnorm(range.lx + WORLD_X - 1); + range.hy = ynorm(range.ly + WORLD_Y - 1); xysize_range(&range); snxtsct_area(np, &range); break; @@ -104,10 +104,10 @@ snxtsct_all(struct nstr_sect *np) { struct range worldrange; - worldrange.lx = -WORLD_X / 2; - worldrange.ly = -WORLD_Y / 2; - worldrange.hx = WORLD_X / 2; - worldrange.hy = WORLD_Y / 2; + worldrange.lx = 0; + worldrange.ly = 0; + worldrange.hx = WORLD_X - 1; + worldrange.hy = WORLD_Y - 1; xysize_range(&worldrange); snxtsct_area(np, &worldrange); } @@ -156,44 +156,40 @@ snxtsct_dist(struct nstr_sect *np, coord cx, coord cy, int dist) void xysize_range(struct range *rp) { - if (rp->lx >= rp->hx) - rp->width = WORLD_X + rp->hx - rp->lx; + if (rp->lx > rp->hx) + rp->width = WORLD_X + rp->hx + 1 - rp->lx; else - rp->width = rp->hx - rp->lx; + rp->width = rp->hx + 1 - rp->lx; if (CANT_HAPPEN(rp->width > WORLD_X)) rp->width = WORLD_X; - if (rp->ly >= rp->hy) - rp->height = WORLD_Y + rp->hy - rp->ly; + if (rp->ly > rp->hy) + rp->height = WORLD_Y + rp->hy + 1 - rp->ly; else - rp->height = rp->hy - rp->ly; + rp->height = rp->hy + 1 - rp->ly; if (CANT_HAPPEN(rp->height > WORLD_Y)) rp->height = WORLD_Y; } -/* This is called also called in snxtitem.c */ void xydist_range(coord x, coord y, int dist, struct range *rp) { - if (dist < WORLD_X / 4) { - rp->lx = xnorm((coord)(x - 2 * dist)); - rp->hx = xnorm((coord)(x + 2 * dist) + 1); + if (4 * dist + 1 < WORLD_X) { + rp->lx = xnorm(x - 2 * dist); + rp->hx = xnorm(x + 2 * dist); rp->width = 4 * dist + 1; } else { - /* Range is larger than the world */ - /* Make sure we get lx in the right place. */ - rp->lx = xnorm((coord)(x - WORLD_X / 2)); - rp->hx = xnorm((coord)(rp->lx + WORLD_X - 1)); + rp->lx = xnorm(x - WORLD_X / 2); + rp->hx = xnorm(rp->lx + WORLD_X - 1); rp->width = WORLD_X; } - if (dist < WORLD_Y / 2) { - rp->ly = ynorm((coord)(y - dist)); - rp->hy = ynorm((coord)(y + dist) + 1); + if (2 * dist + 1 < WORLD_Y) { + rp->ly = ynorm(y - dist); + rp->hy = ynorm(y + dist); rp->height = 2 * dist + 1; } else { - /* Range is larger than the world */ - rp->ly = ynorm((coord)(y - WORLD_Y / 2)); - rp->hy = ynorm((coord)(rp->ly + WORLD_Y - 1)); + rp->ly = ynorm(y - WORLD_Y / 2); + rp->hy = ynorm(rp->ly + WORLD_Y - 1); rp->height = WORLD_Y; } } diff --git a/src/lib/update/nxtitemp.c b/src/lib/update/nxtitemp.c index eaba139eb..04b285fca 100644 --- a/src/lib/update/nxtitemp.c +++ b/src/lib/update/nxtitemp.c @@ -82,8 +82,6 @@ nxtitemp(struct nstr_item *np) return 0; if (!xyinrange(gp->x, gp->y, &np->range)) selected = 0; - if (gp->x == np->range.hx || gp->y == np->range.hy) - selected = 0; break; case NS_XY: if (CANT_HAPPEN(!(ef_flags(np->type) & EFF_XY))) -- 2.43.0