Complete.Org: Mailing Lists: Archives: freeciv-dev: October 2001:
[Freeciv-Dev] Re: RFC: 8-topology system
Home

[Freeciv-Dev] Re: RFC: 8-topology system

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: freeciv-dev <freeciv-dev@xxxxxxxxxxx>
Subject: [Freeciv-Dev] Re: RFC: 8-topology system
From: Jason Dorje Short <vze2zq63@xxxxxxxxxxx>
Date: Wed, 17 Oct 2001 02:11:30 -0400
Reply-to: jdorje@xxxxxxxxxxxx

Jason Dorje Short wrote:
> 
> Raimar Falke wrote:
> >
> > On Tue, Oct 16, 2001 at 06:22:35PM -0400, Jason Dorje Short wrote:
> > > Raimar Falke wrote:

> > > > I think that another shape is good. This may be of no real use but it
> > > > allows use to test the code. And a non-isometric ellipse has the
> > > > semantics of most north <=> y=0. Also such an ellipse will also have
> > > > non-real tiles in the rectangular xsize*ysize.

> Now, the next question: iso-ellipses.  Obviously we need them, but the
> math will be even trickier.  Do we have an ellipse inside an
> iso-rectangle inside a flat rectangle (which is what's done for
> iso-rectangles), or do we try to plant the ellipse directly within the
> rectangle?

Check out the attached file.  It implements normalize_map_pos,
is_real_map_pos, and is_normal_map_pos for all 10 of these topologies,
then prints stuff out to show you the setup.

Everything seems to work.

The 10 topologies are:

  rectangular flat unwrapping
  rectangular flat ns-wrap
  rectangular flat ew-wrap ("cylinder")
  rectangular flat wraps in both ("torus")
  rectangular iso  unwrapping
  rectangular iso  ns-wrap
  rectangular iso  ew-wrap
  rectangular iso  wraps in both (identical to torus)
  elliptical  flat unwrapping
  elliptical  iso  unwrapping

The implementation of an iso-ellipse is a bit inefficient; perhaps we
can do better but this would be acceptable.

jason
int shape;
int isometric;
int ns_wrap, ew_wrap;           /* not used...yet */
int width, height;

int xsize, ysize;

#define IS_EVEN(n) ( ((n)/2) * 2 == (n) )

int isometrize(int *x, int *y)
{
        int nx, ny;
        nx = *x - *y;
        ny = *y + *x;
        *x = nx;
        *y = ny;
}

int normalize_map_pos(int *x, int *y)
{
        if (!is_real_map_pos(*x, *y))
                return 0;

        switch(shape) {
        case 0:
                if (isometric) {
                        if (ns_wrap) {
                                while (*x + *y < (width - 1) / 2) {
                                        *x += height/2;
                                        *y += height/2;
                                }
                                while (*x + *y > (width-1)/2 + height-1) {
                                        *x -= height/2;
                                        *y -= height/2;
                                }
                        }
                        if (ew_wrap) {
                                while (*x-*y < -(width-1)/2) {
                                        *x += width/2;
                                        *y -= width/2;
                                }
                                while (*x-*y > -(width-1)/2 + width-1) {
                                        *x -= width/2;
                                        *y += width/2;
                                }
                        }
                } else {
                        if (ns_wrap) {
                                while (*y < 0) *y += height;
                                while (*y >= height) *y -= height;
                        }
                        if (ew_wrap) {
                                while (*x < 0) *x += width;
                                while (*x >= width) *x -= width;
                        }
                }
                break;
        case 1:
                /* ellipses can't wrap. */
                break;
        }
        return 1;
}

int is_real_map_pos(int x, int y)
{
        switch (shape) {
        case 0:
                if (isometric) {
                        if (!ns_wrap && 
                            (x + y < (width - 1) / 2 ||
                              x + y > (width - 1) / 2 + height - 1))
                                return 0;
                        if (!ew_wrap &&
                            (x - y < -(width-1)/2 ||
                             x - y > -(width-1)/2 + width-1))
                                return 0;
                        return 1;
                } else {
                        if (!ns_wrap &&
                            (y < 0 || y >= height))
                                return 0;
                        if (!ew_wrap &&
                            (x < 0 || x >= width))
                                return 0;
                        return 1;
                }
                break;
        case 1:
                /* ellipses cannot wrap. */
                return is_normal_map_pos(x, y);
                break;
        default:
                exit(1);
        }
}

int is_normal_map_pos(int x, int y)
{
        switch (shape) {
        case 0:         /* rectangle */
                if (isometric) {
                        /* The northern border travels from (0, (width-1)/2) to
                           ((width-1)/2, 0). */
                        /* test northern edge */
                        if (x + y < (width - 1) / 2)
                                return 0;

                        /* test western edge */
                        if (x - y < -(width - 1) / 2)
                                return 0;

                        /* test southern edge */
                        if (x + y > (width - 1) / 2 + height - 1)
                                return 0;

                        /* test eastern edge */
                        if (x - y > -(width - 1) / 2 + width - 1)
                                return 0;

                        return 1;
                } else {
                        return y >= 0 && y < height && x >= 0 && x < width;
                }
                break;
        case 1:         /* ellipse */
                {
                        int xr = width / 2;
                        int yr = height / 2;
                        if (isometric) {
                                /* This isn't a great way to handle 
iso-ellipses, but it would work. */
                                int d = (yr + xr)/2;
                                x -= d, y -= d;
                                isometrize(&x, &y);
                        } else {
                                x -= xr, y -= yr;
                        }
                        xr++, yr++;
                        return (x * x * yr * yr + y * y * xr * xr <
                                xr * xr * yr * yr);
                }
        default:
                exit(-1);
        }

}

int init_topology(void)
{
        /* default */
        xsize = width;
        ysize = height;
        
        switch (shape) {
        case 0:
                if (isometric) {
                        if (ew_wrap && !IS_EVEN(width)) width++;
                        if (ns_wrap && !IS_EVEN(height)) height++;

                        ysize = (height - 1) / 2 + (width - 1) / 2 + 1;
                        /* xsize is correctly determined by taking the 
intersection of the
                           southern and eastern world edges, as above, rounding 
down, and adding 1. */
                        xsize = (height + width) / 2;
                } else {
                        xsize = width;
                        ysize = height;
                }
                break;
        case 1:
                if (isometric) {
                        xsize = ysize = (width + height) / 2 + 1;
                } else {
                        /* Did I say we must have even dimension? I meant we 
must
                           have ODD dimension. */
                        if (IS_EVEN(width)) width++;
                        if (IS_EVEN(height)) height++;
                        xsize = width;
                        ysize = height;
                }
        }
}

void print_map(void)
{
        int x, y;

        for (y = -1; y <= ysize; y++) {
                for (x = -1; x <= xsize; x++) {
                        char c = ' ';
                        if (x < 0 || x >= xsize)
                                c = '|';
                        if (y < 0 || y >= ysize)
                                c = '-';

                        if (is_normal_map_pos(x, y))
                                c = '#';
                        printf("%c ", c);
                }
                printf("\n");
        }

}

void print_wrap(void)
{
        int x, y;
        for (y= -2*ysize; y <= ysize * 3; y++) {
                for (x = -2*xsize; x <= xsize * 3; x++) {
                        char c = ' ';
                        if (is_real_map_pos(x, y))
                                c = '#';
                        printf("%c", c);
                }
                printf("\n");
        }
}

void print_coords(void)
{
        int x, y;
        for (y = -ysize/2; y <= ysize * 3/2; y++) {
                for (x = -xsize/2; x <= xsize * 3/2; x++) {
                        int x1 = x, y1=y;
                        if (normalize_map_pos(&x1, &y1)) {
                                printf("(%2d,%2d)  ", x1, y1);
                        } else {
                                printf("         ");
                        }
                }
                printf("\n");
        }
}

int main(int argc, char **argv)
{
        if (argc != 7) {
                printf("Usage: %s <shape> <isometric> <ew_wrap> <ns_wrap> 
<width> <height>.\n",
                       argv[0]);
                return -1;
        }

        sscanf(argv[1], "%d", &shape);
        sscanf(argv[2], "%d", &isometric);
        sscanf(argv[3], "%d", &ew_wrap);
        sscanf(argv[4], "%d", &ns_wrap);
        sscanf(argv[5], "%d", &width);
        sscanf(argv[6], "%d", &height);

        init_topology();

        print_map();
        printf("\n");
        //      print_wrap();
        //printf("\n");
        print_coords();
}

[Prev in Thread] Current Thread [Next in Thread]