]> git.pond.sub.org Git - empserver/commitdiff
Rework code dealing with struct range fixing many bugs
authorMarkus Armbruster <armbru@pond.sub.org>
Sun, 17 Aug 2008 21:44:00 +0000 (17:44 -0400)
committerMarkus Armbruster <armbru@pond.sub.org>
Wed, 20 Aug 2008 11:40:32 +0000 (07:40 -0400)
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
src/lib/commands/real.c
src/lib/common/xy.c
src/lib/subs/border.c
src/lib/subs/maps.c
src/lib/subs/nxtitem.c
src/lib/subs/paths.c
src/lib/subs/sarg.c
src/lib/subs/snxtsct.c
src/lib/update/nxtitemp.c

index 574c1b679fb6a06bbb01bcd9387b430f264ab244..b3c1cbe6760d032718bfb839390fd40116a6ee73 100644 (file)
     (((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);
index a5dcb4611347e16bf310302de3e54bebdd1a06cf..b1f21b35145490ce03f51f7b724587506d0fce4b 100644 (file)
@@ -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);
     }
index 09472f1a6217649d1ac7708a2e473f2db25a9e62..87f3f4adcee879c2609ac06565a6c8b00bce39f2 100644 (file)
@@ -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;
index 34f32e8eefe5cd4a6244a4c973f198832edb7d54..a3157faab36f8f7a6bf69644f9f5ac0e2470699a 100644 (file)
@@ -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
             */
index 19974b42617bc4927d91ed90e01001cd378151dd..50964262e161e5bc14ee224ac979240dcfdceb5e 100644 (file)
@@ -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;
index 01af5b13b2ba5de7f06d421ff13e5325f1db19b1..9a11882f012585c2a645d81b228a050bab3b3258 100644 (file)
@@ -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)))
index e6ce39714c6bbc63a78b0914f5775b5109af9d4e..79b68030537fa03b5e6698746b6d2a4fbdad29fc 100644 (file)
@@ -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);
 }
index 37f8753c047a9d77e27e7a237ba4889968ea5b99..4c572edcd0d6ad9858f921cf73a60835f12eedc4 100644 (file)
@@ -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;
 }
 
index 79f15c24212470ce58262a1763f8ae6bc97f6cb9..c53fe0dad0ac92a39b940fcc5520b2651d2fdcd2 100644 (file)
@@ -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;
     }
 }
index eaba139eb0d93b0d42e8440de8c5b06b880a70f1..04b285fcaa6fa1057defc32256bb6865e38c06da 100644 (file)
@@ -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)))