#ifndef lint
static char *RCSid = "$Header: /usr/brule/guest/empire/empire/emprcs/old/util/setup.c,v 2.0 1995/10/16 18:03:35 empire Exp $";
#endif

#if defined(aix) || defined(linux)
#include <unistd.h>
#endif /* aix or linux */

#include <stdio.h>

#include "misc.h"
#include "nat.h"
#include "sect.h"
#include "var.h"
#include "file.h"
#include "xy.h"
#include "nsc.h"
#include "product.h"

#include <fcntl.h>

s_char	*program = "setup";
int	(*leprfunc)();

main(argc, argv)
	int	argc;
	s_char	**argv;
{
	struct	natstr *np;
	int	techbase;
	int	natnum;
	int	radius;
	int	happyvec[I_MAX+1];
	int	nsect;
	float	sectratio;
	time_t	now;
	int	i;
	extern char *optarg;
	extern int optind;
	int opt;
	char *config_file = NULL;
	s_char *myname = *argv;

	while ((opt = getopt (argc, argv, "e:")) != EOF) {
		switch (opt) {
		    case 'e':
			config_file = optarg;
			break;
		}
	}

	emp_config (config_file);
	argc -= optind;
	argv += optind;

	if (argc != 3) {
		printf("usage: %s #nations techbase radius\n", myname);
		return -1;
	}
	natnum = atoi(argv[0]);
	techbase = atoi(argv[1]);
	radius = atoi(argv[2]);
	time(&now);
	srandom(now);
	ef_open(EF_SECTOR, O_RDWR, EFF_MEM);
	ef_open(EF_NATION, O_RDWR, EFF_MEM);
	bzero(happyvec, sizeof(happyvec));
	happyvec[I_CIVIL] = 500;
	happyvec[I_MILIT] = 5;
	happyvec[I_FOOD] = 2500;
	for (i=1; i <= natnum; i++) {
		np = getnatp(i);
		sprintf(np->nat_cnam, "%d", i);
		strcpy(np->nat_pnam, "ho");
		np->nat_stat = STAT_SANCT|STAT_NORM|STAT_INUSE;
		if (placecap(np) == 0)
			break;
		nsect = sectradius(np, (natid)i, happyvec, radius);
		sectratio = (1 + 3.14 * radius * radius) / nsect - 1.0;
		np->nat_level[NAT_TLEV] = techbase +
			sectratio * (random() % (techbase/3));
		np->nat_level[NAT_RLEV] = techbase +
			sectratio * (random() % (techbase/3));
		np->nat_level[NAT_HLEV] = 5 + (random() % 5);
		np->nat_level[NAT_ELEV] = 5 + (random() % 5);
		np->nat_money = (int) (10000 + 5000 * radius * sectratio);
		printf("%s; %d sectors, tech %7.3f res %7.3f, money %d\n",
			np->nat_cnam, nsect, np->nat_level[NAT_TLEV],
			np->nat_level[NAT_RLEV], np->nat_money);
	}
	ef_close(EF_NATION);
	ef_close(EF_SECTOR);
	return 0;
}

int
placecap(np)
	struct	natstr *np;
{
	struct	sctstr *sp;
	struct	sctstr *sp1;
	int	i;
	int	id;

	for (i=0; i < 300; i++) {
		/* Both x and y should be either odd or even */
		id = random() % (WORLD_X*WORLD_Y/2);
		sp = getsectid(id);
		if (sp->sct_own != 0 ||
		    sp->sct_type == SCT_WATER || sp->sct_type == SCT_MOUNT)
			continue;
		sp1 = getsectp(sp->sct_x + 2, sp->sct_y);
		if (sp1->sct_own != 0 ||
		    sp1->sct_type == SCT_WATER || sp->sct_type == SCT_MOUNT)
			continue;
		break;
	}
	if (i == 300) {
		printf("couldn't find an empty slot!\n");
		return 0;
	}
	np->nat_xorg = np->nat_xcap = sp->sct_x;
	np->nat_yorg = np->nat_ycap = sp->sct_y;
	return 1;
}

int
sectradius(np, cn, vec, radius)
	struct	natstr *np;
	natid	cn;
	int	*vec;
	int	radius;
{
	struct	nstr_sect ns;
	struct	sctstr *sp;
	int	nsect;

	if (snxtsct_dist(&ns, np->nat_xcap, np->nat_ycap, radius) == 0) {
		printf("Couldn't set up radius %d\n", radius);
		return 0;
	}
	nsect = 0;
	while (nxtsct(&ns, &sp)) {
		if (sp->sct_type == SCT_WATER || sp->sct_type == SCT_MOUNT ||
		    sp->sct_own != 0)
			continue;
		sp->sct_own = cn;
		sp->sct_oldown = cn;
		sp->sct_loyal = 0;
		sp->sct_mobil = 127;
		sp->sct_avail = 50;
		sp->sct_work = 100;
		sp->sct_effic = 100;
		putvec(VT_ITEM, vec, sp, EF_SECTOR);
		picktype(sp, 100);
		nsect++;
	}
	sp = getsectp(np->nat_xcap, np->nat_ycap);
	sp->sct_type = SCT_CAPIT;
	sp->sct_newtype = SCT_CAPIT;
	putvar(V_MILIT, 500, sp, EF_SECTOR);
	return nsect;
}

picktype(sp, amt)
	struct	sctstr *sp;
	int	amt;
{
	int	type;
	int	product;
	int	i;
	struct	pchrstr *p;
	int	vtype;
	int	vamt;

	if (chance(0.85)) {
		sp->sct_type = SCT_AGRI;
		sp->sct_newtype = SCT_AGRI;
	} else {
		type = (random() % (SCT_MAXDEF + 1 - SCT_RURAL)) + SCT_RURAL;
		sp->sct_type = type;
		sp->sct_newtype = type;
		product = dchr[type].d_prd;
		p = &pchr[product];
		for (i=0; i < p->p_nv; i++) {
			putvar(p->p_vtype[i], amt * p->p_vamt[i],
				(s_char *) sp, EF_SECTOR);
		}
	}
}

snxtsct_dist(np, cx, cy, dist)
	register struct nstr_sect *np;
	coord	cx, cy;
	int	dist;
{
	bzero(np, sizeof(*np));
	xydist_range(cx, cy, dist, &np->range);
	np->cx = cx;
	np->cy = cy;
	np->ncond = 0;
	np->dist = dist;
	np->type = NS_DIST;
	np->read = ef_read;
	np->x = np->range.lx - 1;
	np->y = np->range.ly;
	np->dx = -1;
	np->dy = 0;
	xysize_range(&np->range);
	ef_zapcache(EF_SECTOR);
	return 1;
}

xysize_range(rp)
	register struct range *rp;
{
	if (rp->lx >= rp->hx)
		rp->width = WORLD_X + rp->hx - rp->lx;
	else
		rp->width = rp->hx - rp->lx;
	if (rp->ly >= rp->hy)
		rp->height = WORLD_Y + rp->hy - rp->ly;
	else
		rp->height = rp->hy - rp->ly;
}

xydist_range(x, y, dist, rp)
	coord	x;
	coord	y;
	int	dist;
	struct	range *rp;
{
	rp->lx = xnorm((coord)(x - 2 * dist));
	rp->hx = xnorm((coord)(x + 2 * dist) + 1);
	rp->ly = ynorm((coord)(y - dist));
	rp->hy = ynorm((coord)(y + dist) + 1);
	rp->height = 0;
	rp->width = 0;
}


/*
 * get the next sector in the range
 * that matches the conditions.
 */
int
nxtsct(np, sp)
	register struct nstr_sect *np;
	struct	sctstr **sp;
{
	while (1) {
		np->dx++;
		np->x++;
		if (np->x >= WORLD_X)
			np->x = 0;
		if (np->dx >= np->range.width) {
			np->dx = 0;
			np->x = np->range.lx;
			np->dy++;
			if (np->dy >= np->range.height)
				return 0;
			np->y++;
			if (np->y >= WORLD_Y)
				np->y = 0;
		}
		if ((np->y + np->x) & 01)
			continue;
		if (np->type == NS_DIST) {
			np->curdist = mapdist(np->x, np->y, np->cx, np->cy);
			if (np->curdist > np->dist)
				continue;
		}
		np->id = sctoff(np->x, np->y);
		*sp = (struct sctstr *) ef_ptr(EF_SECTOR, np->id);
		return 1;
	}
	/*NOTREACHED*/
}
