/*
 * land.c
 *
 * new version of empcre
 * Create the land masses in the game.
 *
 * Original created by James W. Anderson, 1987
 * Revised by Dave Pare, 1989
 *
 */

/* 
* This program was written by Dan Bennett and Yasser Doleh 
* The Graph Widget is the property of Kent State University
*
*  This contains code from land.c as noted above
*/

#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <math.h>
#include <stdio.h>
#include "Command.h"
#include "Form.h"
#include "Graph.h"
#include <X11/Xlib.h>
#include <stdlib.h>
#include <fcntl.h>
#include "globals.h"
#include "misc.h"
#include "sect.h"
#include "file.h"
#include <ctype.h>

#define	MIN(x,y)	((x) < (y) ? (x) : (y))
char SaveFileName[80];
int mono = 0, last_x,last_y;

int X_Size, Y_Size;

#define rnd(x) (random() % (x))

Widget thegraph,button[3],EXACTB,value,
       toplevel;

Widget  box, Quit, Stop, Clear, UnDo, Save, Load, TITLE;

void DoPoint(),UnDoPoint(),CountIt(),fillit(),DoAction();

static XtActionsRec actionList[] = {{"draw",DoPoint},
                                    {"nodraw",UnDoPoint},
                                    {"fillit",fillit},
                                    {"CountIt",CountIt},
                                    {"move",DoAction}};

int RED,GREEN,BLUE,BLACK,WHITE;
int Current_Color;
int Draw_Mode;
int Exact = False;

#define BIGV            256             /* used in making altitude */
#define SMALLV          128             /* ex-ocean: rnd(SMALLV) - rnd(BIGV) */
#define LANDMIN         1               /* altitude for normal land */
#define MOUNTMIN        108             /* altitude for mountains */


#define SECTRANGE       3               /* smoothing area */

int sectrange = SECTRANGE;

int world[MAX_WORLD_X][MAX_WORLD_Y];
int uimage[MAX_WORLD_X][MAX_WORLD_Y];
int buimage[MAX_WORLD_X][MAX_WORLD_Y];
int tmp[MAX_WORLD_X][MAX_WORLD_Y];

int widget_height,widget_width,box_size;
#define LMIN 0
#define LMAX 254 

flood_fill(x,y,color,n)
int  x,y,color,n;
{
    if (n>6)
        return; /* Don't fill more than 6 levels at a time */

    if (((x<X_Size) & (x>-1)) & ((y<Y_Size)&(y>-1)))
        if (uimage[x][y] == BLUE){
            uimage[x][y] = color;
            XGPDrawPoint(thegraph,x,y,X_Size,Y_Size,box_size,color);
            flood_fill(x-1,y-1,color,n+1);
            flood_fill(x-1,y+1,color,n+1);
            flood_fill(x+1,y-1,color,n+1);
            flood_fill(x+1,y+1,color,n+1);
            flood_fill(x-2,y,color,n+1);
            flood_fill(x+2,y,color,n+1);
            }
}

flood_count(x,y)
int  x,y;
{
    register int    total=0;

    if (((x<X_Size) & (x>-1)) & ((y<Y_Size)&(y>-1)))
        if (tmp[x][y] == GREEN){
            total += 1;
            tmp[x][y] = -1;
            total += flood_count(x-1,y-1);
            total += flood_count(x-1,y+1);
            total += flood_count(x+1,y-1);
            total += flood_count(x+1,y+1);
            total += flood_count(x-2,y);
            total += flood_count(x+2,y);
            return(total);
            }
    return(0);
}

flood_repair(x,y,n)
int  x,y,n;
{
    if (n>6)
        return; /* Only repair 6, since we only fill 10 */

    if (((x<X_Size) & (x>-1)) & ((y<Y_Size)&(y>-1)))
        if (uimage[x][y] == -1){
            uimage[x][y] = GREEN;
            flood_repair(x-1,y-1,n+1);
            flood_repair(x-1,y+1,n+1);
            flood_repair(x+1,y-1,n+1);
            flood_repair(x+1,y+1,n+1);
            flood_repair(x-2,y,n+1);
            flood_repair(x+2,y,n+1);
            }
}

void fillit(w,event,params,num_params)
Widget  w;
XEvent  *event;
String  *params;
int     num_params;
{ 
    int   x,y;

    bzero(buimage,MAX_WORLD_X*MAX_WORLD_Y*sizeof(int));
    bcopy(uimage,buimage,MAX_WORLD_X*MAX_WORLD_Y*sizeof(int)); 
    x = (int) event->xmotion.x/ box_size;
    y = (int) event->xmotion.y/ box_size;
    if ((even(x) & !even(y)) | (even(y)& !even(x)))
          y++;
    flood_fill(x,y,Current_Color,0);
}

void CountIt(w,event,params,num_params)
Widget  w;
XEvent  *event;
String  *params;
int     num_params;
{ 
    int   x,y,z=0;
    Arg   args[4];
    char  *sprintf(), buf[80];

    x = (int) event->xmotion.x/ box_size;
    y = (int) event->xmotion.y/ box_size;
    if ((even(x) & !even(y)) | (even(y)& !even(x)))
          y++;
    bzero(tmp,MAX_WORLD_X*MAX_WORLD_Y*sizeof(int));
    bcopy(uimage,tmp,MAX_WORLD_X*MAX_WORLD_Y*sizeof(int)); 
    z=flood_count(x,y);
    sprintf(buf,"%3d Sectors",z);
    XtSetArg(args[0],XtNlabel,(XtArgVal) buf);
    XtSetValues(value,args,1);
    XtRealizeWidget(value);
}

make_altitude(world)
register int world[MAX_WORLD_X][MAX_WORLD_Y];
{
    register int x, y,r;

    for (x = 0; x < X_Size; x++)
        for (y = 0; y < Y_Size; y++){
            if (((x ^ y) & 1)){
                continue;
                }
            else{
                r = rnd(100)+1;
                if (uimage[x][y] == BLUE){ 
                    if(Exact)
                        world[x][y] = -1-rnd(100);
                    else{
                        if (r < 5)
                            world[x][y] = rnd(107)+1;
                        else if (r > 99)
                            world[x][y] = 108+rnd(10);
                        else
                            world[x][y] = -1-rnd(100);
                        }
                    }
                else if (uimage[x][y] == RED){ 
                    if(Exact)
                        world[x][y] = 108+rnd(10);
                    else{
                        if (r < 2)
                            world[x][y] = rnd(107)+1;
                        else if (r > 99)
                            world[x][y] = -1-rnd(100);
                        else
                            world[x][y] = 108+rnd(10);
                        }
                    }
                else{ 
                    if(Exact)
                        world[x][y] = rnd(107)+1;
                    else{
                        if (r < 5)
                            world[x][y] = -1-rnd(100);
                        else if (r > 96)
                            world[x][y] = 108+rnd(10);
                        else
                            world[x][y] = rnd(107)+1;
                        }
                    }
                }
            }
}

make_sects(world, s)
register int world[MAX_WORLD_X][MAX_WORLD_Y];
struct sctstr *s;
{
    register struct sctstr *sct;
    register int i;
    register int x, y;
    int     elev[12+12+3]; /* # sects from -12 to 12 in steps of 10 elev */
    int     range;
    int     rangesq;
    int     total;
    int     sum;

    for (i = 0; i < 12+12+3; i++)
        elev[i] = 0;

    sum = 0;
    sct = s;
    for (y = 0; y < Y_Size; y++)
        for (x = 0; x < (X_Size/2); x++, sct++){
            sct->sct_x = x*2 + (y & 01);
            sct->sct_y = y;
            sct->sct_dist_x = x*2 + (y & 01);
            sct->sct_dist_y = y;
            total = world[sct->sct_x][sct->sct_y];
            if (total < LANDMIN)
                sct->sct_type = SCT_WATER;
            else if (total < MOUNTMIN)
                sct->sct_type = SCT_RURAL;
            else
                sct->sct_type = SCT_MOUNT;

            if (Exact)
                switch (sct->sct_type){
                    case SCT_WATER: if (uimage[sct->sct_x][sct->sct_y] != BLUE){
                                        fprintf(stderr,"Sector %d,%d is water, should be %d (%d)!\n",sct->sct_x,sct->sct_y,uimage[sct->sct_x][sct->sct_y],total);
                                        fflush(stderr);
                                        if (uimage[sct->sct_x][sct->sct_y] == GREEN){
                                            sct->sct_type = SCT_RURAL;
                                            total = 50;
                                            }

                                        if (uimage[sct->sct_x][sct->sct_y] == RED){
                                            sct->sct_type = SCT_MOUNT;
                                            total = 120;
                                            }
                                        }
                                    break;
                    case SCT_RURAL: if (uimage[sct->sct_x][sct->sct_y] !=GREEN){
                                        fprintf(stderr,"Sector %d,%d is rural, should be %d (%d)!\n",sct->sct_x,sct->sct_y,uimage[sct->sct_x][sct->sct_y],total);
                                        fflush(stderr);
                                        if (uimage[sct->sct_x][sct->sct_y] == BLUE){
                                            sct->sct_type = SCT_WATER;
                                            total = -50;
                                            }

                                        if (uimage[sct->sct_x][sct->sct_y] == RED){
                                            sct->sct_type = SCT_MOUNT;
                                            total = 120;
                                            }

                                        }
                                    break;
                    case SCT_MOUNT: if (uimage[sct->sct_x][sct->sct_y] != RED){
                                        fprintf(stderr,"Sector %d,%d is mountain, should be %d (%d)!\n",sct->sct_x,sct->sct_y,uimage[sct->sct_x][sct->sct_y],total);
                                        fflush(stderr);

                                        if (uimage[sct->sct_x][sct->sct_y] == BLUE){
                                            sct->sct_type = SCT_WATER;
                                            total = -50;
                                            }

                                        if (uimage[sct->sct_x][sct->sct_y] == GREEN){
                                            sct->sct_type = SCT_RURAL;
                                            total = 50;
                                            }
                                        }
                                    break;
                    }
            sct->sct_elev = total;
            sct->sct_newtype = sct->sct_type;
            sum += total;
            if (total < -129)
                elev[0]++;
            else if (total > 129)
                elev[26]++;
            else
                elev[13+total/10]++;
            }

    for (i = 0; i < 12+12+3; i++)
        if (elev[i] != 0)
            printf("%4d sectors elevation %4d to %4d\n", elev[i], 10*i - 140, 10*i - 130);
}



void stopit(wid,cdat,rdat)
Widget   wid;
caddr_t  cdat,rdat;
{
    exit(0);
}

void quitit(wid,cdat,rdat)
Widget   wid;
caddr_t  cdat,rdat;
{
    struct  sctstr xx;
    char    *sectors;
    register int n;
    int     x, y;
    int     i, j;
    long    now;
    int     fd;
    int     left;
    int     big,total;

    total=(Y_Size)*(X_Size/2)*sizeof(struct sctstr);

    if ((sectors=malloc(total)) == NULL){
        fprintf(stderr,"Can't get a lousy %d bytes, damnit!\n",MAX_WORLD_X*MAX_WORLD_Y*sizeof(struct sctstr));
        fflush(stderr);
        exit(-1);
        }

    bzero(sectors,total);
    fd = open("xland.sector.dat", O_RDWR|O_CREAT|O_TRUNC, 0660);

    if (fd < 0)
        perror("xland.sector.dat");

    time(&now);
    srandom(now+getpid());
    printf("Making altitude\n");
    fflush(stdout);
    make_altitude(world);
    printf("Creating sectors\n");
    fflush(stdout);
    make_sects(world, sectors);
    printf("Writing sectors\n");
    fflush(stdout);

    n = write(fd, sectors, total);

    if (n < 0)
        perror("xland.sector.dat");

    if (n != total)
        printf("%s: partial write\n", "xland.sector.dat");

    close(fd);
    exit(0);
}

typedef enum plates {
        OCEAN, MOUNTAIN, LAND
} plate_e;

load_sectors(fn)
char    *fn;
{
    FILE*  fp;
    int x,y,q;

    if ((fp = fopen(fn,"r")) == NULL){
        fprintf(stderr,"Cannot open %s\n",fn);
        fflush(stderr);
        return;
        }

    fscanf(fp,"%dx%d\n",&x,&y);

    if ((x != X_Size) || (y != Y_Size)){
        fprintf(stderr,"Save file is made for a %dx%d world, not %dx%d!\n",x,y,X_Size,Y_Size);
        return;
        }

    bzero(uimage,MAX_WORLD_X*MAX_WORLD_Y*sizeof(int));
    for(y=0;y<Y_Size;y++){
        for(x=0;x<X_Size;x++){
            fscanf(fp,"%d",&q);
            if (q == OCEAN)
                uimage[x][y] = BLUE;
            else if (q == MOUNTAIN)
                uimage[x][y] = RED;
            else
                uimage[x][y] = GREEN;
            }
        fscanf(fp,"\n");
        }
    fclose(fp);
}

void loadit(wid,cdat,rdat)
Widget   wid;
caddr_t  cdat,rdat;
{
    load_sectors(SaveFileName);
    displaypicture(uimage,thegraph,X_Size,Y_Size,box_size);
}

void saveit(wid,cdat,rdat)
Widget   wid;
caddr_t  cdat,rdat;
{
    FILE*  fp;
    int x,y;

    if ((fp = fopen(SaveFileName,"w")) == NULL){
        fprintf(stderr,"Cannot open %s\n",SaveFileName);
        fflush(stderr);
        return;
        }

    fprintf(fp,"%dx%d\n",X_Size,Y_Size);
    for(y=0;y<Y_Size;y++){
        for(x=0;x<X_Size;x++){
            if (uimage[x][y]== BLUE )
                fprintf(fp," %d",OCEAN);
            else if (uimage[x][y] == RED)
                fprintf(fp," %d",MOUNTAIN);
            else
                fprintf(fp," %d",LAND);
            }
        fprintf(fp,"\n");
        }
     fclose(fp);
}

void undoit(wid,cdat,rdat)
Widget   wid;
caddr_t  cdat,rdat;
{

    bzero(tmp,MAX_WORLD_X*MAX_WORLD_Y*sizeof(int));
    bcopy(uimage,tmp,MAX_WORLD_X*MAX_WORLD_Y*sizeof(int)); 
    bzero(uimage,MAX_WORLD_X*MAX_WORLD_Y*sizeof(int));
    bcopy(buimage,uimage,MAX_WORLD_Y*MAX_WORLD_Y*sizeof(int)); 
    bzero(buimage,MAX_WORLD_X*MAX_WORLD_Y*sizeof(int));
    bcopy(tmp,buimage,MAX_WORLD_Y*MAX_WORLD_Y*sizeof(int)); 
    displaypicture(uimage,thegraph,X_Size,Y_Size,box_size);
}

void DoExact(wid,cdat,rdat)
Widget   wid;
caddr_t  cdat,rdat;
{
    Arg  args[2];

    if(Exact){
        XtSetArg(args[0],XtNforeground,BLACK);
        XtSetArg(args[1],XtNbackground,WHITE);
        XtSetValues(EXACTB,args,2);  
        Exact = False;
    } else {
        XtSetArg(args[0],XtNforeground,WHITE);
        XtSetArg(args[1],XtNbackground,BLACK);
        XtSetValues(EXACTB,args,2);  
        Exact = True;
    }
}

void ClearIt(wid,cdat,rdat)
Widget   wid;
caddr_t  cdat,rdat;
{
    int i,j;

    bzero(buimage,MAX_WORLD_X*MAX_WORLD_Y*sizeof(int)); 
    bcopy(uimage,buimage,MAX_WORLD_X*MAX_WORLD_Y*sizeof(int)); 
    for(i=0;i<X_Size;i++)
        for(j=0;j<Y_Size;j++)
	   uimage[i][j] = BLUE;

    displaypicture(uimage,thegraph,X_Size,Y_Size,box_size);
}

/*   Selected: light on dark */
/* Unselected: dark on light */

void ocean(wid,cdat,rdat)
Widget   wid;
caddr_t  cdat,rdat;
{ 
    Arg args[2];

    XtSetArg(args[0],XtNforeground,BLUE);
    XtSetArg(args[1],XtNbackground,BLACK);
    XtSetValues(button[0],args,2);  

    XtSetArg(args[0],XtNforeground,BLACK);
    XtSetArg(args[1],XtNbackground,RED);
    XtSetValues(button[1],args,2);  

    XtSetArg(args[0],XtNforeground,BLACK);
    XtSetArg(args[1],XtNbackground,GREEN);
    XtSetValues(button[2],args,2);  

    Current_Color = BLUE;
}

/*   Selected: light on dark */
/* Unselected: dark on light */

void mountain(wid,cdat,rdat)
Widget   wid;
caddr_t  cdat,rdat;
{
    Arg args[2];

    XtSetArg(args[0],XtNforeground,RED);
    XtSetArg(args[1],XtNbackground,BLACK);
    XtSetValues(button[1],args,2);  

    XtSetArg(args[0],XtNforeground,BLACK);
    XtSetArg(args[1],XtNbackground,BLUE);
    XtSetValues(button[0],args,2);  

    XtSetArg(args[0],XtNforeground,BLACK);
    XtSetArg(args[1],XtNbackground,GREEN);
    XtSetValues(button[2],args,2);  

    Current_Color = RED;
}

/*   Selected: light on dark */
/* Unselected: dark on light */

void wilderness(wid,cdat,rdat)
Widget   wid;
caddr_t  cdat,rdat;
{
    Arg args[2];

    XtSetArg(args[0],XtNforeground,GREEN);
    XtSetArg(args[1],XtNbackground,BLACK);
    XtSetValues(button[2],args,2);  

    XtSetArg(args[0],XtNforeground,BLACK);
    XtSetArg(args[1],XtNbackground,RED);
    XtSetValues(button[1],args,2);  

    XtSetArg(args[0],XtNforeground,BLACK);
    XtSetArg(args[1],XtNbackground,BLUE);
    XtSetValues(button[0],args,2);  

    Current_Color = GREEN;
}

void DoPoint(w,event,params,num_params)
Widget  w;
XEvent  *event;
String  *params;
int     num_params;
{
    int    x,y,z;

    Draw_Mode = True; 
    x = (int) event->xmotion.x/box_size;
    y = (int) event->xmotion.y/box_size;
    if (((x/2)<(X_Size/2))&&((y/2)<(Y_Size/2))){
        buimage[x][y] = uimage[x][y];
        uimage[x][y]=z=Current_Color;
        XGPDrawPoint(w,x,y,X_Size,Y_Size,box_size,z);
        }
}

void UnDoPoint(w,event,params,num_params)
Widget  w;
XEvent  *event;
String  *params;
int     num_params;
{
    Draw_Mode = False; 
}

void DoAction(w,event,params,num_params)
Widget  w;
XEvent  *event;
String  *params;
int     num_params;
{ 
    int   x,y,z;

    if (Draw_Mode) {
        x = (int) event->xmotion.x/box_size;
        y = (int) event->xmotion.y/box_size;
        if (((x/2)<(X_Size/2))&&((y/2)<(Y_Size/2))){
            buimage[x][y] = uimage[x][y];
            uimage[x][y]=z=Current_Color;
            XGPDrawPoint(w,x,y,X_Size,Y_Size,box_size,z);
            }
        }
}

roll(c)
int    c;
{
    if (c == GREEN)
        return(BLUE);
    if (c == BLUE)
        return(RED);
    if (c == RED)
        return(GREEN);
}

main(argc,argv)
int argc;
char *argv[];
{

    Arg     args[10];
    int     i,j,x,good=0,y,SaveFile=0;
	    
    XtTranslations trans;

    static char trans_string[]="<Btn1Down>: draw()\n \
                                <Btn1Up>: nodraw()\n \
                                <Btn2Down>,<Btn2Up>: CountIt()\n \
                                <Btn3Down>,<Btn3Up>: fillit()\n \
                                <MotionNotify>:move()\n";

    static XtCallbackRec action[][2]= {{{ocean,NULL},{NULL,NULL}},
                                      {{mountain,NULL},{NULL,NULL}},
                                      {{wilderness,NULL},{NULL,NULL}}};

    static XtCallbackRec quiter[][2]= { {{quitit,NULL}, {NULL,NULL}},
                                        {{DoExact,NULL},{NULL,NULL}},
                                        {{undoit,NULL}, {NULL,NULL}},
                                        {{saveit,NULL}, {NULL,NULL}},
                                        {{stopit,NULL}, {NULL,NULL}},
                                        {{ClearIt,NULL},{NULL,NULL}},
                                        {{loadit,NULL}, {NULL,NULL}}};

    Exact=1;
    bzero(SaveFileName,80);
    bcopy("xland.save",SaveFileName,10);

    bzero(world,sizeof(int)*MAX_WORLD_X*MAX_WORLD_Y);
    bzero(uimage,sizeof(int)*MAX_WORLD_X*MAX_WORLD_Y);
    bzero(buimage,sizeof(int)*MAX_WORLD_X*MAX_WORLD_Y);

    if (strncmp(argv[0],"mxland",6) == 0)
        mono = 1;

    x=1;
    while (x < argc){
        if (argv[x][0] != '-'){
            x++;
            continue;
            }
        switch(argv[x][1]){
            case 'M':
                x++;
                y=0;
                if (!isdigit(argv[x][y])){
                    printf("Usage: %s -M <XxY> [-G] [-S name] [-N]\n",argv[0]);
                    printf("\n\t-G = Generate map from save file only. Don't start X\n");
                    printf("\t-S = Set save file name\n");
                    printf("\t-N = Not exact. Add miscellaneous small islands\n");
                    exit(0);
                    }
                good=0;
                while (y<strlen(argv[x]))
                    if (argv[x][y++] == 'x')
                        good=1;
                sscanf(argv[x],"%dx%d",&X_Size,&Y_Size);
                break;

            case 'h':
                printf("Usage: %s -M <XxY> [-G] [-S name] [-N]\n",argv[0]);
                printf("\n\t-G = Generate map from save file only. Don't start X\n");
                printf("\t-S = Set save file name\n");
                printf("\t-N = Not exact. Add miscellaneous small islands\n");
                exit(0);
                break;

            case 'S':
                x++;
                if (argv[x][0] == '-'){
                    printf("Usage: %s -M <XxY> [-G] [-S name] [-N]\n",argv[0]);
                    printf("\n\t-G = Generate map from save file only. Don't start X\n");
                    printf("\t-S = Set save file name\n");
                    printf("\t-N = Not exact. Add miscellaneous small islands\n");
                    exit(0);
                    }
                bzero(SaveFileName,80);
                bcopy(argv[x],SaveFileName,strlen(argv[x]));
                break;
            case 'G':
                SaveFile=1;
                break;
            case 'N':
                Exact=0;
                break;
            default:
                x++;
                break;
            }
        x++;
        }

    if (!good){
        printf("Usage: %s -M <XxY> [-G] [-S name] [-N]\n",argv[0]);
        printf("\n\t-G = Generate map from save file only. Don't start X\n");
        printf("\n\t-S = Set save file name\n");
        printf("\n\t-N = Not exact. Add miscellaneous small islands\n");
        exit(0);
        }


    if ((X_Size < 16) || (Y_Size < 16)){
        fprintf(stderr,"Real men don't play with worlds with dimensions smaller than 16!\n");
        fflush(stderr);
        exit(-1);
        }

    if (SaveFile){
        BLUE=1;
        RED=2;
        GREEN=3;
        load_sectors(SaveFileName);
        quitit(NULL,NULL,NULL);
        }

    toplevel = XtInitialize(argv[0],"FOURIER",NULL,0,&argc,argv);
    XtSetArg(args[0],XtNborderWidth,0);
    box = XtCreateManagedWidget("FOURIER",formWidgetClass,toplevel,args,1);

    XtSetArg(args[0],XtNlabel,(XtArgVal) "Empire Land Map Maker");
    TITLE = XtCreateManagedWidget("label",labelWidgetClass,box,args,1);

    XtSetArg(args[0],XtNlabel,(XtArgVal) "Quit - Make Sector File");
    XtSetArg(args[1],XtNcallback,quiter[0]);
    XtSetArg(args[2],XtNfromHoriz,TITLE);
    Quit = XtCreateManagedWidget("label",commandWidgetClass,box,args,3);

    XtSetArg(args[0],XtNlabel,(XtArgVal) "Stop - DO NOT MAKE SECTOR FILE");
    XtSetArg(args[1],XtNfromHoriz,Quit);
    XtSetArg(args[2],XtNcallback,quiter[4]);
    Stop= XtCreateManagedWidget("label",commandWidgetClass,box,args,3);
     
    XtSetArg(args[0],XtNlabel,(XtArgVal) "OCEAN");
    XtSetArg(args[1],XtNcallback,action[0]);
    XtSetArg(args[2],XtNfromVert,TITLE);
    button[0] = XtCreateManagedWidget("label",commandWidgetClass,box,args,3);

    XtSetArg(args[0],XtNlabel,(XtArgVal) "MOUNTAIN");
    XtSetArg(args[1],XtNfromHoriz,button[0]);
    XtSetArg(args[2],XtNcallback,action[1]);
    XtSetArg(args[3],XtNfromVert,TITLE);
    button[1] = XtCreateManagedWidget("label",commandWidgetClass,box,args,4);

    XtSetArg(args[0],XtNlabel,(XtArgVal) "LAND");
    XtSetArg(args[1],XtNfromHoriz,button[1]);
    XtSetArg(args[2],XtNcallback,action[2]);
    XtSetArg(args[3],XtNfromVert,TITLE);
    button[2] = XtCreateManagedWidget("label",commandWidgetClass,box,args,4);

    XtSetArg(args[0],XtNlabel,(XtArgVal) "000 Sectors");
    XtSetArg(args[1],XtNfromHoriz,button[2]);
    XtSetArg(args[2],XtNfromVert,TITLE);
    value = XtCreateManagedWidget("label",labelWidgetClass,box,args,3);

    XtSetArg(args[0],XtNlabel,(XtArgVal) "Exact");
    XtSetArg(args[1],XtNfromHoriz,value);
    XtSetArg(args[2],XtNcallback,quiter[1]);
    XtSetArg(args[3],XtNfromVert,TITLE);
    EXACTB = XtCreateManagedWidget("label",commandWidgetClass,box,args,4);

    XtSetArg(args[0],XtNlabel,(XtArgVal) "UnDo");
    XtSetArg(args[1],XtNfromHoriz,EXACTB);
    XtSetArg(args[2],XtNcallback,quiter[2]);
    XtSetArg(args[3],XtNfromVert,TITLE);
    UnDo = XtCreateManagedWidget("label",commandWidgetClass,box,args,4);

    XtSetArg(args[0],XtNlabel,(XtArgVal) "Save");
    XtSetArg(args[1],XtNfromHoriz,UnDo);
    XtSetArg(args[2],XtNcallback,quiter[3]);
    XtSetArg(args[3],XtNfromVert,TITLE);
    Save = XtCreateManagedWidget("label",commandWidgetClass,box,args,4);

    XtSetArg(args[0],XtNlabel,(XtArgVal) "Load");
    XtSetArg(args[1],XtNfromHoriz,Save);
    XtSetArg(args[2],XtNcallback,quiter[6]);
    XtSetArg(args[3],XtNfromVert,TITLE);
    Load = XtCreateManagedWidget("label",commandWidgetClass,box,args,4);

    XtSetArg(args[0],XtNlabel,(XtArgVal) "Clear");
    XtSetArg(args[1],XtNfromHoriz,Load);
    XtSetArg(args[2],XtNcallback,quiter[5]);
    XtSetArg(args[3],XtNfromVert,TITLE);
    Clear = XtCreateManagedWidget("label",commandWidgetClass,box,args,4);

    box_size = MIN(800/X_Size,800/Y_Size);

    XtSetArg(args[0],XtNheight,Y_Size*box_size);
    XtSetArg(args[1],XtNwidth,X_Size*box_size);
    XtSetArg(args[2],XtNfromVert,button[0]);
    thegraph = XtCreateManagedWidget("hello",graphWidgetClass,box,args,3);

    XtAddActions(actionList,XtNumber(actionList));
    trans = XtParseTranslationTable(trans_string);
    XtOverrideTranslations(thegraph,trans);

    XtRealizeWidget(toplevel);

    BLACK = MakeColor(thegraph,"BLACK");
    WHITE = MakeColor(thegraph,"WHITE");

    if (mono){
        RED = MakeColor(thegraph,"BLACK");
        GREEN = MakeColor(thegraph,"BLACK");
        BLUE = MakeColor(thegraph,"WHITE");
    }else{
        RED = MakeColor(thegraph,"RED");
        GREEN = MakeColor(thegraph,"Green");
        BLUE = MakeColor(thegraph,"Blue");
        }

    Current_Color = RED;

    ClearIt(thegraph,NULL,NULL);
    wilderness(button[1],NULL,NULL);
    Exact = (Exact == 1 ? 0 : 1);
    DoExact(EXACTB,NULL,NULL);

    XtMainLoop();
}
