static char *RCSid = "$Header: /usr/brule/guest/empire/empire/emprcs/old/util/esck.c,v 2.3 1995/10/16 18:03:56 empire Exp $";

/*
 * $Log: esck.c,v $
 * Revision 2.3  1995/10/16  18:03:56  empire
 * 2.3.2.b changes
 *
 * Revision 2.1  1995/07/09  01:05:01  empire
 * b1r19 changes - see REVISIONS
 *
 * Revision 1.1  89/09/26  19:54:36  mr-frog
 * Initial revision
 * 
 * Revision 1.7  88/09/24  23:30:31  muir
 * after cap changes
 * 
 * Revision 1.6  88/07/15  16:35:03  muir
 * after jpo patch 16
 * 
 * Revision 1.5  88/04/01  04:52:59  muir
 * rcs header added
 * 
 */

/*
 * esck.c
 *
 * empire sector consistency check...because the
 * new game is so buggy!
 *
 * Dave Pare, 1986
 */

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

#include <stdio.h>
#include <sys/types.h>
#include "misc.h"
#include "var.h"
#include "sect.h"
#include "item.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/file.h>

#define	NULLCP ((s_char *)0)

struct	sctstr sects[128*64];

int	yesflag;
int	noflag;
int	mapfixed = 0;
int	sectfixed = 0;
s_char	*myname;

extern	s_char *malloc ();
void	adios (), advise ();

main(argc, argv)
	int     argc;
	s_char  **argv;
{
	s_char	*ownxy();
	extern	s_char *sectfil;
	extern	s_char *mapfil;
	extern	int w_xsize, w_ysize;
	extern	int diroff[][2];
	struct stat statb;
	register struct sctstr *sp;
	register int nsect;
	register int i;
	int	n;
	int	loc;
	int     sectf;
	int	mapf;
	s_char	*sctown;
	s_char	*sctdes;
	int	mode;
	int	opt;

	myname = argv[0];
	mode = O_RDWR;

	while ((opt = getopt (argc, argv, "yn")) != EOF)
	{
		switch (opt) {
		    case 'y':
			noflag = 0;
			yesflag = 1;
			mode = O_RDWR;
			break;
		    case 'n':
			noflag = 1;
			yesflag = 0;
			mode = O_RDONLY;
			break;
		    default:
			adios (NULLCP, "Usage: %s [-yn]", argv[0]);
		}
	}
	sectf = open(sectfil, mode, 0);
	if (sectf < 0)
		adios (sectfil, "Can't open with mode %o file", mode);

	if (fstat (sectf, &statb) == -1)
		adios (sectfil, "Can't stat");
	nsect = w_xsize * w_ysize/2;
	i = nsect * sizeof(struct sctstr);
	if (i != statb.st_size)
		adios (sectfil, "Size mismatch %d expected really %d on",
		       i, statb.st_size);
	sctown = malloc ((unsigned) nsect);
	sctdes = malloc ((unsigned) nsect);
	if ((n = read(sectf, (s_char *)sects, i)) != i) {
		switch (n) {
		    case -1:
			adios (sectfil, "Read error on");
		    case 0:
			adios (sectfil, "Empty file");
		    default:
			adios (sectfil,
			       "Read error got %d bytes expecting %d on",
			       n, i);
		}
	}
	if ((mapf = open (mapfil, mode, 0)) < 0)
		adios (mapfil, "Can't open");
	if ((n = read (mapf, sctown, nsect)) != nsect)
		adios (mapfil, "Short read got %d bytes expecting %d on",
		       n, nsect);
	if ((n = read (mapf, sctdes, nsect)) != nsect)
		adios (mapfil, "Short read got %d bytes expecting %d on",
		       n, nsect);
	sp = sects;
	printf("Checking %d sectors...\n", nsect);
	printf("PHASE 1: coordinates, designations, owners.\n");
	for (sp=sects, i=0; i < nsect; i++, sp++) {
		if (sctoff(sp->sct_x, sp->sct_y) != i) {
			printf("Sect coord error: %d,%d offset not %d\n",
				sp->sct_x, sp->sct_y, i);
			if (noflag || yesflag) {
				printf("Fix interactively!!!\n");
				continue;
			}
			if (yes("Attempt to fix? ")) {
				int new_x, new_y;
				s_char buf[256];
				if (i)
					printf("Previous sector at (%d,%d)\n",
					    (sp-1)->sct_x, (sp-1)->sct_y);
				else
					printf("Damaged sector is first\n");
				if (i < nsect-1)
					printf("Next sector at (%d,%d)\n",
					    (sp+1)->sct_x, (sp+1)->sct_y);
				else
					printf("Damaged sector is last\n");
				printf("Enter new x,y coordinate: ");
				gets(buf);
				if (sscanf(buf, "%d,%d", &new_x, &new_y) != 2)
					printf("Bad format, aborting.\n");
				else {
					sp->sct_x = new_x;
					sp->sct_y = new_y;
					sectfixed ++;
				}
			}
		}
		if (sp->sct_type < 0 || sp->sct_type > SCT_MAXDEF) {
			printf("Sect %s designation is %d\n",
				ownxy(sp), sp->sct_type);
			if (yes("Set to rural? ")) {
				sp->sct_type = SCT_RURAL;
				sectfixed ++;
			}
		}
		if (sp->sct_newtype < 0 || sp->sct_newtype > SCT_MAXDEF) {
			printf("Sect %s new type is %d\n",
				ownxy(sp), sp->sct_newtype);
			if (yes("Set to rural? ")) {
				sp->sct_type = SCT_RURAL;
				sectfixed ++;
			}
		}
		if (sp->sct_own > MAXNOC || sp->sct_own < 0) {
			printf("Sect %s owner %d bad\n",
				ownxy(sp), sp->sct_own);	
			if (yes("Clear owner? ")) {
				sp->sct_own = 0;
				sectfixed ++;
			}
		}
		if (sp->sct_oldown > MAXNOC || sp->sct_oldown < 0) {
			printf("Sect %s oldown is %d\n",
				ownxy(sp), sp->sct_oldown);
			if (yes ("Set old owner to present owner? ")) {
				sp -> sct_oldown = sp->sct_own;
				sectfixed ++;
			}
			else if (yes ("Zero owner ? ")) {
				sp->sct_oldown = 0;
				sectfixed ++;
			}
		}
		loc = (sp ->sct_y * w_xsize + sp->sct_x) / 2;
		if (sp->sct_own != sctown[loc]) {
			printf ("Sect %s sectmap/empsect %d/%d owner mismatch\n",
				ownxy(sp), sp->sct_own, sctown[loc]);
			if (yes ("Reset? ")) {
				sctown[loc] = sp->sct_own;
				mapfixed ++;
			}
		}
		if (sp->sct_type != sctdes[loc]) {
			printf ("Sector %s sectmap/empsect %d/%d des mismatch\n",
				ownxy(sp), sp->sct_type, sctdes[loc]);
			if (yes ("Reset? ")) {
				sctdes[loc] = sp->sct_type;
				mapfixed ++;
			}
		}
	}
	printf("PHASE 2: efficiency, loyalty, work.\n");
	for (sp=sects, i=0; i < nsect; i++, sp++) {
		if (sp->sct_effic > 100 || sp->sct_effic < 0) {
			printf("Sect %s eff is %d\n",
				ownxy(sp), sp->sct_effic);
			if (yes("Set to zero? ")) {
				sp->sct_effic = 0;
				sectfixed ++;
			}
		}
		if (sp->sct_loyal < 0) {
			printf("Sect %s loyal is %d\n",
				ownxy(sp), sp->sct_loyal);
			if (yes ("Set to 0? ")) {
				sp->sct_loyal = 0;
				sectfixed ++;
			}
		}
		if (sp->sct_work < 0 || sp->sct_work > 100) {
			printf("Sect %s work is %d\n",
				ownxy(sp), sp->sct_work);
			if (yes ("Set to zero? ")) {
				sp->sct_work = 0;
				sectfixed ++;
			}
		}
	}
	printf("PHASE 3: Ores (fertil, min, gmin, oil, uran)\n");
	for (sp=sects, i=0; i < nsect; i++, sp++) {
		if (sp->sct_min < 0 || sp->sct_min > 100) {
			printf("Sect %s min content is %d\n",
				ownxy(sp), sp->sct_min);
			if (yes("Set to 0? ")) {
				sp->sct_min = 0;
				sectfixed ++;
			}
		}
		if (sp->sct_gmin < 0 || sp->sct_gmin > 100) {
			printf("Sect %s gmin content is %d\n",
				ownxy(sp), sp->sct_gmin);
			if (yes ("Set to 0? ")) {
				sp->sct_gmin = 0;
				sectfixed ++;
			}
		}
		if (sp->sct_oil < 0 || sp->sct_oil > 100) {
			printf("Sect %s oil content is %d\n",
				ownxy(sp), sp->sct_oil);
			if (yes ("Set to 0? ")) {
				sp->sct_oil = 0;
				sectfixed ++;
			}
		}
		if (sp->sct_fertil < 0 || sp->sct_fertil > 120) {
			printf("Sect %s fertil content is %d\n",
				ownxy(sp), sp->sct_fertil);
			if (yes ("Set to 0? ")) {
				sp->sct_fertil = 0;
				sectfixed ++;
			}
		}
		if (sp->sct_uran < 0 || sp->sct_uran > 100) {
			printf("Sect %s uran content is %d\n",
				ownxy(sp), sp->sct_uran);
			if (yes ("Set to 0? ")) {
				sp->sct_uran = 0;
				sectfixed ++;
			}
		}
	}
	printf("PHASE 4: deliveries, distributions, items.\n");
	for (sp=sects, i=0; i < nsect; i++, sp++) {
		varcheck(sp);
	}
	if (mapfixed) {
		printf ("Rewriting %s...\n", mapfil);
		if(lseek (mapf, 0L, L_SET) == -1L)
			adios (mapfil, "Seek error");
		if (write (mapf, sctown, nsect) != nsect)
			adios (mapfil, "Write error");
		if (write (mapf, sctdes, nsect) != nsect)
			adios (mapfil, "Write Error");
	}
	(void) close (mapf);

	if (sectfixed) {
		printf ("Rewriting %s...\n", sectfil);
		lseek(sectf, 0L, L_SET);
		n = nsect * sizeof(struct sctstr);
		if (write(sectf, (s_char *)sects, n) != n)
			adios (sectfil, "write error");
	}
	(void) close(sectf);
}

void pr() {
}

static	int w_xshift = -1;
static	int w_yshift = -1;

sctoff(x, y)
	int	x;
	int	y;
{
	extern	int xorg, yorg;
	extern	int w_xsize, w_ysize;
	register int r10;
	register int r9;

	if ((x + y) & 01)
		return -1;
	if (w_xshift < 0) {
		w_xshift = w_xsize << 7;
		w_yshift = w_ysize << 7;
	}
	x += w_xshift + xorg;
	y += w_yshift + yorg;
	r10 = x - (x / w_xsize * w_xsize);
	r9 = y - (y / w_ysize * w_ysize);
	return ((w_xsize * r9) + r10) / 2;
}

s_char *
xytoa(x, y, country)
	int x;
	int y;
	int country;
{
	return prbuf("%d,%d", x, y);
}

s_char *
ownxy(sp)
	struct sctstr *sp;
{
	return prbuf("%d,%d", sp->sct_x, sp->sct_y);
}

s_char *vt_names[8] = {
	"bad vt_type",
	"item",
	"condition",
	"distribute",
	"delivery",
	"sell order",
	"bad vt_type",
	"bad_vt_type",
};

varcheck(sp)
	struct	sctstr *sp;
{
	extern	struct ichrstr ichr[];
	register u_char *tp;
	int	type;
	int	var;
	int	n;

	if (sp->sct_nv < 0 || sp->sct_nv > MAXSCTV) {
		printf("%s, bad maxsctv %d (FIX BY HAND!)\n",
			ownxy(sp), sp->sct_nv);
		return;
	}
	tp = sp->sct_vtype + sp->sct_nv - 1;
	for (n=sp->sct_nv-1; n >= 0; tp--, n--) {
		type = *tp & VT_TYPE;
		var = *tp & ~VT_TYPE;
		if (var < 1 || var > I_MAX) {
			printf("%s, var slot %d bad var i-type %d (abs %d)\n",
				ownxy(sp), n, var, *tp);
rmslot:
			if (yes("Remove? "))
				trashslot(sp, n);
			continue;
		}
		if (type != VT_ITEM && type != VT_DIST && type != VT_COND &&
		    type != VT_DEL) {
			printf("%s, var slot %d bad upper mask %x (name %s)\n",
				ownxy(sp), n, type, vt_names[type>>5]);
			goto rmslot;
		}
		type = type >> 5;
		if (chkdup(sp, n, type)) {
			printf("%s, var slot %d, dup var %s (%s), type %d\n",
				ownxy(sp), n, ichr[var].i_name,
				vt_names[type], type);
			goto rmslot;
		}
	}
}

int
yes(prompt)
	s_char	*prompt;
{
	s_char	buf[80];

	printf(prompt);
	fflush(stdout);
	if (noflag) {
		puts ("no");
		return 0;
	}
	if (yesflag) {
		puts ("yes");
		return 1;
	}
	if (gets(buf) == 0 || (*buf != 'y' && *buf != 'Y'))
		return 0;
	return 1;
}

trashslot(sp, n)
	register struct sctstr *sp;
	int	n;
{
	int	i;

	if (sp->sct_nv > n) {
		for (i = n; i < sp->sct_nv; i++) {
			sp->sct_vtype[i] = sp->sct_vtype[i+1];
			sp->sct_vamt[i] = sp->sct_vamt[i+1];
		}
	}
	sp->sct_nv--;
	sectfixed ++;
}

int
chkdup(sp, n, type)
	register struct sctstr *sp;
	int	n;
	int	type;
{
	register int i;

	for (i = 0; i < sp->sct_nv; i++) {
		if (i == n)
			continue;
		if (sp->sct_vtype[i] == type)
			return 1;
	}
	return 0;
}

/* VARARGS2 */
void	adios (what, fmt, a, b, c, d, e, f, g, h, i, j)
s_char   *what,
       *fmt,
       *a,
       *b,
       *c,
       *d,
       *e,
       *f,
       *g,
       *h,
       *i,
       *j;
{
    advise (what, fmt, a, b, c, d, e, f, g, h, i, j);
    _exit (1);
}

/* VARARGS2 */
void	advise (what, fmt, a, b, c, d, e, f, g, h, i, j)
s_char   *what,
       *fmt,
       *a,
       *b,
       *c,
       *d,
       *e,
       *f,
       *g,
       *h,
       *i,
       *j;
{
    (void) fflush (stdout);

    fprintf (stderr, "%s: ", myname);
    fprintf (stderr, fmt, a, b, c, d, e, f, g, h, i, j);
    if (what)
	(void) putc (' ', stderr), perror (what);
    else
	(void) putc ('\n', stderr);

    (void) fflush (stderr);
}
