/*
 * 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 <math.h>
#include <stdio.h>
#include <fcntl.h>
#include "globals.h"
#include "misc.h"
#include "sect.h"
#include "file.h"
#include <ctype.h>

char SaveFileName[80];

int X_Size, Y_Size;

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

int RED,GREEN,BLUE,BLACK,WHITE;
int Exact = 0;

#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];

#define LMIN 0
#define LMAX 254 

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

    for (y = 0; y < Y_Size; y++)
        for (x = 0; x < X_Size; x++){
            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 quitit()
{
    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;
        }

    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);
}

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

    int     i,j,x,good=0,y,SaveFile=0;
	    
    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);

    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("\t-S = Set save file name\n");
        printf("\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);
        }

    BLUE=0;
    RED=1;
    GREEN=2;
    load_sectors(SaveFileName);
    quitit();
}
