static char *RCSid = "$Header: land.c,v 1.5 89/09/26 19:54:31 mr-frog Exp $";

/*
 * land.c
 *
 * new version of empcre
 * Create the land masses in the game.
 *
 * James W. Anderson, 1987
 *
 */

#include <stdio.h>
#include <fcntl.h>
#include "var.h"
#include "misc.h"
#include "power.h"
#include "nat.h"
#include "sect.h"
#include "gamesdef.h"
#include "file.h"
#include "xy.h"

struct powstr powbuf;

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

#define SIZE		1		    /* must always be > 1 */
#define XPLATES		(WORLD_X / 2)
#define YPLATES		WORLD_Y
#define	XSIZE		(SIZE*XPLATES)
#define YSIZE		(SIZE*YPLATES)
#define SECTSIZE	1
#define BIGV		256
#define SMALLV	 	256	

#define OCEAN	  0
#define ISLAND	  1
#define CONTINENT 2

#define HIGHMIN 90
#define PLATMIN 35
#define HILLMIN 32
#define LANDMIN 1

#define LANDCH	35	/*30-40*/	    /* land plate percentage */
#define NUMLAND		(YPLATES * XPLATES * LANDCH)/100
#define NUMISLE		NUMLAND/5	    /* 1 isle for 5 land */
#define NUMWATER	(XPLATES * YPLATES) - (NUMLAND + NUMISLE)


FILE   *sectf;
struct sctstr sects[YSIZE][XSIZE];

int    world[YSIZE][XSIZE];
int    plates[YPLATES][XPLATES];
s_char    buf[80];

main()
{
	extern	struct empfile empfile[];
	extern	int maxnoc;
	register int j,
	        ibase,
	        jbase,
		elev[12+12+3], /* # sects from -12 to 12 in steps of 10 elev */
		sum,
	        total;			    /* inner loop variables */
	int     i,
	        range,
	        rangesq,
	        sectrow,
	        sectcol,
	        ifail,
	        jfail,
	        pass;
	long    now;
	register int *irow;
	int     file_d;
	struct sctstr *sct;
	int	i1, j1;
	s_char	*sectfil;

	sectfil = empfile[EF_SECTOR].file;
	file_d = open(sectfil, O_RDWR|O_CREAT|O_TRUNC, 0660);
	if (file_d < 0) {
		perror(sectfil);
		exit(1);
	}
	time(&now);
	srandom(now+getpid());
	for (i = 0; i < YPLATES; i++)
		for (j = 0; j < XPLATES; j++)
			plates[i][j] = OCEAN;
	for (pass = 0, total = 0;;) {
/*make a continent*/
retry1:
		if ((pass++ % 12) == 7) {   /* merge with another one */
			while (plates[(i=rnd(YPLATES))][(j=rnd(XPLATES))] == OCEAN)
				;
		} else {
			i = rnd(YPLATES);
			j = rnd(XPLATES);
			/* avoid collision */
			for (ibase = i - 4; ibase <= i + 4; ibase++)
				for (jbase = j - 4; jbase <= j + 4; jbase++) {
					i1 = ibase < 0 ? ibase+YPLATES : ibase;
					j1 = jbase < 0 ? jbase+XPLATES : jbase;
					if (plates[i1 % YPLATES][j1 % XPLATES] != OCEAN)
						goto retry1;
				}
		}
		for (ibase = i - 3; ibase <= i + 3; ibase++) {
			ifail = i - ibase;
			if (ifail < 0)
				ifail = -ifail;
			for (jbase = j - 3; jbase <= j + 3; jbase++) {
				i1 = ibase < 0 ? ibase+YPLATES : ibase;
				j1 = jbase < 0 ? jbase+XPLATES : jbase;
				if (plates[i1 % YPLATES][j1 % XPLATES] == OCEAN) {
					jfail = j - j1;
					if (jfail < 0)
						jfail = -jfail;
					if (jfail < ifail)
						jfail = ifail;
					if (jfail < 2 || !rnd(jfail + 1) || !rnd(jfail + 1)) {
						plates[i1 % YPLATES][j1 % XPLATES] = CONTINENT;
						if (++total >= NUMLAND)
							goto make_isles;
					}
				}
			}
		}
	}
make_isles:
	for (total = 0; total < NUMISLE; total++) {
		/* find an open spot */
		while (plates[(i = rnd(YPLATES))][(j = rnd(XPLATES))] != OCEAN)
			;
		plates[i][j] = ISLAND;
	}
	for (sectrow = 0; sectrow < YPLATES; sectrow++) {
		ibase = sectrow * SECTSIZE;
		for (sectcol = 0; sectcol < XPLATES; sectcol++) {
			jbase = sectcol * SECTSIZE;
			total = plates[sectrow][sectcol];
			for (i = ibase + SECTSIZE; i-- > ibase;) {
				irow = world[i];
				for (j = jbase + SECTSIZE; j-- > jbase;)
					switch (total) {
					case OCEAN:	/*-BIGV, -SMALLV/2, SMALLV*/
						irow[j] = rnd(SMALLV) - rnd(BIGV);
						break;
					case ISLAND:	/*-BIGV, 0, BIGV*/
						irow[j] = rnd(BIGV) - rnd(BIGV) + 2;
						break;
					case CONTINENT:	/*-SMALLV, SMALLV/2, BIGV*/
						irow[j] = rnd(BIGV) - rnd(SMALLV);
					}
			}
		}
	}
	sct = (struct sctstr *) sects;
	sum = 0;
	for (i = 0; i < 12+12+3; i++)
		elev[i] = 0;
	for (i = 0; i < YSIZE; i++) {
		for (j = 0; j < XSIZE; j++, sct++) {
			sct->sct_x = j*2 + (i & 01);
			sct->sct_y = i;
			sct->sct_dist_x = j*2 + (i & 01);
			sct->sct_dist_y = i;
			range = 3 + rnd(SIZE + 1);
			rangesq = range * range;
			total = 0;
			for (ibase = i + range; ibase-- > i;) {
				irow = world[ibase % YSIZE];
				for (jbase = j + range; jbase-- > j;)
					total += irow[jbase % XSIZE];
			}
			total /= rangesq;
			if (total < LANDMIN) {
				sct->sct_type = SCT_WATER;
			} else if (total < HILLMIN)
				sct->sct_type = SCT_RURAL;
			else if (total < PLATMIN)
				sct->sct_type = SCT_MOUNT;
			else if (total < HIGHMIN)
				sct->sct_type = SCT_RURAL;
			else
				sct->sct_type = SCT_MOUNT;
			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]++;
		}
	}
	write(file_d, sects, sizeof(sects));
	close(file_d);
	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);
	exit(0);
}
