#ifndef lint
static char *RCSid = "$Header: /usr/brule/guest/empire/empire/emprcs/old/util/empfix.c,v 2.1 1995/07/28 01:04:57 empire Exp $";
#endif

/*
 * empfix.c
 *
 * from PSL Empire, 1985
 */

#include <ctype.h>
#include "misc.h"
#include "var.h"
#include "nat.h"
#include "sect.h"
#include "ship.h"
#include "treaty.h"
#include "loan.h"
#include "tel.h"
#include "nuke.h"
#include "item.h"
#include "plane.h"
#include "file.h"

void    nations();
void    sectors();
void    ships();
void    treats();
void	planes();
void    loans();
void    tgms();
void    nukes();
void    bytefix();
void    shortfix();
int     fixnum();
void    strfix();
void    longfix();
void    floatfix();
void    varfix();
void    addvars();
s_char   *varname();

s_char    mflg;
s_char    wflg;
s_char    xflg;

struct	natstr nat;


void
floatfix(prompt,addr,def)
s_char	*prompt;
float	*addr;
double	*def;
{
	int	c;
	float	num = 0.0;
	float	scale = 0.1;

	printf (" %s (%.2f) :",prompt,*addr);
	while ((c=getchar())!='\n') {
		if (c == '.') {
			while ((c=getchar())!='\n') {
				if (!isdigit(c)) break;
				num += scale * ( c - '0');
				scale /= 10;
			}
			break;
		}
		if (!isdigit(c)) break;
		num = num * 10 + c - '0';
	}
	if (num > 0) {
		*addr = num;
		mflg++;
	}
	if (c == 'w') {
		while ((c=getchar())!='\n');
		*addr = (float)*def;
		mflg++;
	}
	if (c == 'x') {
		while ((c=getchar())!='\n');
		xflg++;
	}
}

main()
{
	extern	s_char *getstring();
	extern	int privuid;
	extern	s_char *natfil;
	extern	int natf;
	extern	s_char l_cvt;
	register s_char *buf;
	long    now;

	natf = open(natfil, 2);
	while (1) {
		time(&now);
		printf(l_cvt == 'l' ? "Curup is %ld\n" : "Curup is %D\n", now);
		printf("1:nation 2:sector 3:ship 4:treaty 5:loan 6:tgm 7:nuke 8:plane");
		buf = getstring("  : ");
		if (*buf == 0) {
			execl("/bin/date", "", 0);
		} else if (*buf == '1') {
			nations();
			continue;
		} else if (*buf == '2') {
			sectors();
			continue;
		} else if (*buf == '3') {
			ships();
			continue;
		} else if (*buf == '4') {
			treats();
			continue;
		} else if (*buf == '5') {
			loans();
			continue;
		} else if (*buf == '6') {
			tgms();
			continue;
		} else if (*buf == '7') {
			nukes();
			continue;
		} else if (*buf == '8') {
			planes();
			continue;
		}
		printf("Huh?\n");
	}
}

void
nations()
{
	extern	int natf;
	extern	struct natstr nat;
	register int country;
	register int i;
	register s_char *buf;
	long    file_pos;
	double	zero = 0.0;

	while (1) {
		wflg = xflg = mflg = 0;
		buf = getstring("#? ");
		if (*buf == 0)
			break;
		country = atoi(buf);
		file_pos = country * sizeof(nat);
		lseek(natf, file_pos, 0);
		i = read(natf, &nat, sizeof(nat));
		if (i < sizeof(nat)) {
			printf("Only %d bytes in that one...\n", i);
		} else {
			strfix("country name", nat.nat_cnam, 20);
			strfix("representative", nat.nat_pnam, 20);
			shortfix("btu", &nat.nat_btu, 0);
			longfix("reserves", &nat.nat_reserve, 0);
			bytefix("login", &nat.nat_login, 0);
			bytefix("tgms", &nat.nat_tgms, 0);
			bytefix("xcap", &nat.nat_xcap, 0);
			bytefix("ycap", &nat.nat_ycap, 0);
			bytefix("xorg", &nat.nat_xorg, 0);
			bytefix("yorg", &nat.nat_yorg, 0);
			bytefix("stat", &nat.nat_stat, 0);
			bytefix("dayno", &nat.nat_dayno, 0);
			shortfix("minused", &nat.nat_minused, 0);
			longfix("date", &nat.nat_last_login, 0);
			longfix("money", &nat.nat_money, 0);
			longfix("newstim", &nat.nat_newstim, 0);
			floatfix("t_level", &nat.nat_level[NAT_TLEV], &zero);
			floatfix("r_level", &nat.nat_level[NAT_RLEV], &zero);
			floatfix("e_level", &nat.nat_level[NAT_ELEV], &zero);
			floatfix("h_level", &nat.nat_level[NAT_HLEV], &zero);
			for (i = 0; i < 8; i++) {
				if (wflg == 0 && xflg == 0)
					printf("relate[%d]", i);
				shortfix("", &nat.nat_relate[i], 0);
			}
			for (i = 0; i < 8; i++) {
				if (wflg == 0 && xflg == 0)
					printf("nat_b[%d]\n", i);
				bytefix(" xl", &nat.nat_b[i].b_xl, 0);
				bytefix(" xh", &nat.nat_b[i].b_xh, 0);
				bytefix(" yl", &nat.nat_b[i].b_yl, 0);
				bytefix(" yh", &nat.nat_b[i].b_yh, 0);
			}
			if (mflg != 0) {
				lseek(natf, file_pos, 0);
				write(natf, &nat, sizeof(nat));
				printf("Rewritten\n");
			}
		}
	}
	return;
}

void
sectors()
{
	extern	int sectf;
	extern	s_char *sectfil;
	extern	int w_xsize, w_ysize;
	extern	struct sctstr sect;
	s_char   *buf;
	register int x;
	register int y;
	register int num_var;
	register int xcap;
	register int ycap;
	int     country;
	long    file_pos;

	buf = getstring("Offset as country #? ");
	if (*buf == 0)
		return;
	country = atoi(buf);
	file_pos = country * sizeof(nat);
	lseek(natf, file_pos, 0);
	x = read(natf, &nat, sizeof(nat));
	if (x < sizeof(nat)) {
		printf("Only %d bytes in that nation...\n", x);
		return;
	}
	xcap = nat.nat_xorg;
	ycap = nat.nat_yorg;
	sectf = open(sectfil, 2);
	while (1) {
		xflg = wflg = mflg = 0;
		buf = getstring("x,y? ");
		if (*buf == 0)
			break;
		x = atoip(&buf) + xcap;
		if (*buf++ != ',') {
			printf("format is x,y\n");
		} else {
			y = atoip(&buf) + ycap;
			if (((x ^ y) & 1) != 0) {
				printf("Both coordinates must be even or odd\n");
			} else {
				x = (x + w_xsize) % w_xsize;
				y = (y + w_ysize) % w_ysize;
				file_pos = ((y * w_xsize + x) >> 1) * sizeof(sect);
				lseek(sectf, file_pos, 0);
				read(sectf, &sect, sizeof(sect));
				printf("Sector %d, %d\n", x, y);
				bytefix("x", &sect.sct_x, x);
				bytefix("y", &sect.sct_y, y);
				bytefix("own", &sect.sct_own, 0);
				bytefix("type", &sect.sct_type,
					sect.sct_type > SCT_MOUNT ? SCT_RURAL : sect.sct_type);
				bytefix("effic", &sect.sct_effic, 0);
				bytefix("mobil", &sect.sct_mobil, 0);
				bytefix("loyal", &sect.sct_loyal, 0);
				bytefix("dist_x", &sect.sct_dist_x, x);
				bytefix("dist_y", &sect.sct_dist_y, y);
				bytefix("work", &sect.sct_work, 0);
				bytefix("flags", &sect.sct_flags, 0);
				bytefix("newtype", &sect.sct_newtype, 0);
				bytefix("miner", &sect.sct_min, sect.sct_min);
				bytefix("gmin", &sect.sct_gmin, sect.sct_gmin);
				bytefix("oil", &sect.sct_oil, sect.sct_oil);
				bytefix("fertil", &sect.sct_fertil,
					sect.sct_fertil);
				bytefix("uran", &sect.sct_uran, sect.sct_uran);
				bytefix("oldown", &sect.sct_oldown,
					sect.sct_oldown);
				bytefix("nv", &sect.sct_nv, sect.sct_nv);
				num_var = (long) sect.sct_nv;
				while (--num_var >= 0)
					varfix(num_var, &sect, EF_SECTOR);
				if (xflg == 0)
					addvars(&sect, EF_SECTOR);
				if (mflg == 0)
					continue;
				lseek(sectf, file_pos, 0);
				write(sectf, &sect, sizeof(sect));
				printf("Rewritten\n");
			}
		}
	}
	close(sectf);
	return;
}

void
ships()
{
	extern	int shipf;
	extern	s_char *shipfil;
	extern	struct shpstr ship;
	register int ship_num;
	register int i;
	register int num_vars;
	register s_char *buf;
	long    file_pos;

	shipf = open(shipfil, 2);
	while (1) {
		xflg = wflg = mflg = 0;
		buf = getstring("#? ");
		if (*buf == 0)
			break;
		ship_num = atoi(buf);
		file_pos = ship_num * sizeof(ship);
		lseek(shipf, file_pos, 0);
		i = read(shipf, &ship, sizeof(ship));
		if (i < sizeof(ship)) {
			printf("Only %d bytes in that one...\n", i);
		}
		printf("Ship #%d\n", ship_num);
		bytefix("x", &ship.shp_x, ship.shp_x);
		bytefix("y", &ship.shp_y, ship.shp_y);
		bytefix("own", &ship.shp_own, 0);
		bytefix("type", &ship.shp_type, 0);
		bytefix("effic", &ship.shp_effic, 0);
		bytefix("mobil", &ship.shp_mobil, 0);
		shortfix("uid", &ship.shp_uid, 0);
		bytefix("nplane", &ship.shp_nplane, 0);
		bytefix("fleet", &ship.shp_fleet, 0);
		shortfix("tech", &ship.shp_tech, 0);
		bytefix("nv", &ship.shp_nv, 0);
		num_vars = ship.shp_nv;
		while (--num_vars >= 0)
			varfix(num_vars, &ship, EF_SHIP);
		if (xflg == 0)
			addvars(&ship, EF_SHIP);
		if (mflg != 0) {
			lseek(shipf, file_pos, 0);
			write(shipf, &ship, sizeof(ship));
			printf("Rewritten\n");
		}
	}
	close(shipf);
	return;
}

void
treats()
{
	extern	int trtf;
	extern	s_char *treatfil;
	extern	struct trtstr trty;
	register int i;
	register s_char *buf;
	long    file_pos;

	trtf = open(treatfil, 2);
	while (1) {
		wflg = xflg = mflg = 0;
		buf = getstring("#? ");
		if (*buf == 0)
			break;
		i = atoi(buf);
		file_pos = i * sizeof(trty);
		lseek(trtf, file_pos, 0);
		i = read(trtf, &trty, sizeof(trty));
		if (i < sizeof(trty))
			printf("Only %d bytes in that one...\n", i);

		bytefix("cna", &trty.trt_cna, 0);
		bytefix("cnb", &trty.trt_cnb, 0);
		bytefix("acond", &trty.trt_acond, 0);
		bytefix("bcond", &trty.trt_bcond, 0);
		longfix("exp", &trty.trt_exp, 0);

		if (mflg != 0) {
			lseek(trtf, file_pos, 0);
			write(trtf, &trty, sizeof(trty));
			printf("Rewritten\n");
		}
	}

	close(trtf);
	return;
}

void
loans()
{
	extern	int loanf;
	extern	s_char *loanfil;
	extern	struct lonstr loan;
	register int i;
	register s_char *buf;
	long    file_pos;

	loanf = open(loanfil, 2);
	while (1) {
		wflg = xflg = mflg = 0;
		buf = getstring("#? ");
		if (*buf == 0)
			break;

		i = atoi(buf);
		file_pos = i * sizeof(loan);
		lseek(loanf, file_pos, 0);
		i = read(loanf, &loan, sizeof(loan));
		if (i < sizeof(loan))
			printf("Only %d bytes in that one...\n", i);

		bytefix("loner", &loan.l_loner, 0);
		bytefix("lonee", &loan.l_lonee, 0);
		bytefix("irate", &loan.l_irate, 0);
		bytefix("ldur", &loan.l_ldur, 0);
		shortfix("amtpaid", &loan.l_amtpaid, 0);
		shortfix("amtdue", &loan.l_amtdue, 0);
		longfix("lastpay", &loan.l_lastpay, 0);
		longfix("duedate", &loan.l_duedate, 0);

		if (mflg != 0) {
			lseek(loanf, file_pos, 0);
			write(loanf, &loan, sizeof(loan));
			printf("Rewritten\n");
		}
	}
	close(loanf);
	return;
}

void
tgms()
{
	extern	struct telstr tgm;
	s_char   *buf;
	s_char    message[2048];
	int     tel_file;
	int     size;
	int     country;
	long    file_pos;

	buf = getstring("To which country number? ");
	country = atoi(buf);
	tel_file = open(mailbox(country), 2);
	if (tel_file < 0) {
		printf("Can't open %s\n", mailbox(country));
		return;
	}
	file_pos = 0;
	while (1) {
		wflg = xflg = mflg = 0;
		size = read(tel_file, &tgm, sizeof(tgm));
		if (size != sizeof(tgm)) {
			printf("Only %d bytes in this one...\n");
			return;
		}
		bytefix("tel_from", &tgm.tel_from, 0);
		longfix("tel_date", &tgm.tel_date, 0);
		shortfix("tel_length", &tgm.tel_length, 0);

		buf = getstring("Look at text? ");
		size = read(tel_file, message, tgm.tel_length);
		if (size != tgm.tel_length)
			printf("Only read %d bytes instead of %d\n", size,
			       tgm.tel_length);

		if (*buf == 'y')
			write(1, message, size);

		if (mflg != 0) {
			lseek(tel_file, file_pos, 0);
			write(tel_file, &tgm, sizeof(tgm));
			write(tel_file, message, size);
			printf("Rewritten\n");
		}
		file_pos += size + sizeof(tgm);

		xflg = 0;
		if (xflg == 0)
			break;
	}
	close(tel_file);
	return;
}

void
nukes()
{
	extern	struct nchrstr nchr[];
	extern	int nukf;
	extern	s_char *nukfil;
	register int i;
	register s_char *buf;
	register long file_pos;
	struct nukstr nuk;

	nukf = open(nukfil, 2);
	while (1) {
		wflg = xflg = mflg = 0;
		buf = getstring("#? ");
		if (*buf == 0)
			break;

		i = atoi(buf);
		file_pos = i * sizeof(nuk);
		lseek(nukf, file_pos, 0);
		i = read(nukf, &nuk, sizeof(nuk));
		if (i < sizeof(nuk)) {
			printf("Only %d bytes in that one...\n", i);
		}
		bytefix("nuk_x", &nuk.nuk_x, 0);
		bytefix("nuk_y", &nuk.nuk_y, 0);
		bytefix("nuk_own", &nuk.nuk_own, 0);
		bytefix("nuk_n", &nuk.nuk_ship, 0);
		shortfix("nuk_ship", &nuk.nuk_ship, 0);
		for (i=0; i<N_MAXNUKE; i++)
			bytefix(nchr[i].n_name, &nuk.nuk_types[i]);
		if (mflg != 0) {
			lseek(nukf, file_pos, 0);
			write(nukf, &nuk, sizeof(nuk));
			printf("Rewritten\n");
		}
	}
	close(nukf);
}

void
planes()
{
	extern	int planef;
	extern	s_char *planefil;
	register int i;
	register s_char *buf;
	register long file_pos;
	struct plnstr pln;

	planef = open(planefil, 2);
	if (planef < 0) {
		perror(planefil);
		return;
	}
	while (1) {
		wflg = xflg = mflg = 0;
		buf = getstring("#? ");
		if (*buf == 0)
			break;
		i = atoi(buf);
		file_pos = i * sizeof(struct plnstr);
		lseek(planef, file_pos, 0);
		i = read(planef, &pln, sizeof(pln));
		if (i < sizeof(pln)) {
			printf("Only %d bytes in that one...\n", i);
		}
		bytefix("pln_x", &pln.pln_x, 0);
		bytefix("pln_y", &pln.pln_y, 0);
		bytefix("pln_own", &pln.pln_own, 0);
		bytefix("pln_type", &pln.pln_type, 0);
		bytefix("pln_effic", &pln.pln_effic, 0);
		bytefix("pln_mobil", &pln.pln_mobil, 0);
		bytefix("pln_range", &pln.pln_range, 0);
		bytefix("pln_att", &pln.pln_att, 0);
		bytefix("pln_def", &pln.pln_def, 0);
		bytefix("pln_wing", &pln.pln_wing, 0);
		shortfix("pln_tech", &pln.pln_tech, 0);
		shortfix("pln_ship", &pln.pln_ship, 0);
		shortfix("pln_uid", &pln.pln_uid, 0);
		bytefix("pln_nuketype", &pln.pln_nuketype, 0);
		bytefix("pln_harden", &pln.pln_harden, 0);
		bytefix("pln_flags", &pln.pln_flags, 0);
		if (mflg != 0) {
			lseek(planef, file_pos, 0);
			write(planef, &pln, sizeof(pln));
			printf("Rewritten\n");
		}
	}
	close(planef);
}

void
bytefix(prompt, byte_ptr, wipe_val)
	s_char   *prompt;
	s_char   *byte_ptr;
	s_char    wipe_val;
{
	*byte_ptr = fixnum(prompt, *byte_ptr, wipe_val);
}

void
shortfix(prompt, short_ptr, wipe_val)
	s_char   *prompt;
	short  *short_ptr;
	short   wipe_val;
{
	*short_ptr = fixnum(prompt, *short_ptr, wipe_val);
}

int
fixnum(prompt, value, wipe_val)
	s_char   *prompt;
	int     value;
	int     wipe_val;
{
	register s_char *buf;

	if (wflg != 0)
		return wipe_val;

	if (xflg == 0) {
		printf("  %8s %d  ", prompt, value);
		buf = getstring("");
		if (*buf == 'x') {
			xflg++;
		} else if (*buf == 'w') {
			wflg = mflg = 1;
			return wipe_val;
		} else if (*buf != 0) {
			value = atoi(buf);
			mflg++;
		}
	}
	return value;
}

void
strfix(prompt, str_ptr, length)
	s_char   *prompt;
	s_char   *str_ptr;
	int     length;
{
	register s_char *buf;
	register s_char *end;

	if (xflg != 0)
		return;

	if (wflg == 0) {
		printf("  %8s `%s'  ", prompt, str_ptr);
		buf = getstring("");
		if (*buf == 0)
			return;

		if (buf[1] == 0) {
			if (*buf == 'x') {
				xflg++;
				return;
			}
			if (*buf == 'w')
				wflg++;
		}
	}
	if (wflg != 0) {
		*str_ptr = 0;
	} else {
		while (*buf == ' ')
			buf++;

		end = str_ptr + length;
		while (str_ptr < end) {
			if ((*str_ptr++ = *buf++) == 0)
				break;
		}
	}
	mflg++;
}

void
longfix(prompt, long_ptr, wipe_val)
	s_char   *prompt;
	long   *long_ptr;
	int     wipe_val;
{
	register s_char *buf;

	if (xflg != 0)
		return;

	if (wflg == 0) {
		printf(l_cvt == 'l' ? "  %8s %ld  " : "  %8s %D  ", prompt,
		       *long_ptr);

		buf = getstring("");
		if (*buf == 0)
			return;

		if (*buf == 'x') {
			xflg++;
			return;
		}
		if (*buf == 'w')
			wflg++;
	}
	if (wflg != 0)
		*long_ptr = wipe_val;
	else
		*long_ptr = atol(buf);

	mflg++;
}

#ifdef notdef
void
floatfix(prompt, float_ptr, wipe_val)
	s_char   *prompt;
	float  *float_ptr;
	double  wipe_val;
{
	register s_char *buf;

	if (xflg != 0)
		return;

	if (wflg == 0) {
		printf("  %8s %.2f  ", prompt, (double) *float_ptr);
		buf = getstring("");
		if (*buf == 0)
			return;

		if (*buf == 'x') {
			xflg++;
			return;
		}
		if (*buf == 'w')
			wflg++;
	}
	if (wflg != 0)
		*float_ptr = wipe_val;
	else
		*float_ptr = atof(buf);

	mflg++;
}
#endif

void
varfix(slot_num, sct, fixtype)
	int     slot_num;
	struct	sctstr *sct;
	int	fixtype;
{
	register s_char *buf;
	register int type;
	register int qty;

	if (xflg != 0)
		return;
	switch (fixtype) {
	  case GT_SECT:
		type = sct->sct_vtype[slot_num];
		qty = sct->sct_vamt[slot_num];
		break;
	  case GT_SHIP:
		type = ((struct shpstr *)sct)->shp_vtype[slot_num];
		qty = ((struct shpstr *)sct)->shp_vamt[slot_num];
		break;
	  default:
		return;
	}

	if (wflg != 0) {
		putvar(type, 0, sct, fixtype);
		return;
	}
	printf("V[%d] type %d `%s' %d ", slot_num, type, varname(type), qty);
	buf = getstring("");
	if (*buf == 120) {
		xflg++;
		return;
	}
	if (*buf == 'w') {
		wflg = mflg = 1;
		varfix(slot_num, sct, fixtype);
		return;
	}
	if (*buf != 0) {
		putvar(type, atoi(buf), sct, fixtype);
		mflg++;
	}
}

void
addvars(sct_or_shp, fixtype)
	struct	sctstr *sct_or_shp;
	int     fixtype;
{
	register s_char *buf;
	register int var_num;
	register int var_qty;

	while (1) {
		buf = getstring("Add var type? ");
		if (*buf == 'x') {
			xflg++;
			return;
		}
		if (*buf == 0)
			return;

		var_num = atoi(buf);
		printf("type %d `%s' value?", var_num, varname(var_num));
		buf = getstring(" [CR to respecify var number] ");
		if (*buf == 'x') {
			xflg++;
			return;
		}
		if (*buf != 0) {
			var_qty = atoi(buf);
			if (putvar(var_num, var_qty, sct_or_shp, fixtype) < 0) {
				break;
			}
			mflg++;
			printf("`%s' set to %d\n", varname(var_num), var_qty);
		}
	}
	printf("No more variable slots available\n");
	return;
}

s_char   *
varname(var_num)
	int     var_num;
{
	extern	s_char *copy();
	extern	struct ichrstr ichr[];
	static	s_char buf[32];
	s_char	*bp;

	if (var_num <= 0 || var_num > 255)
		return "bad vtype number";
	if (iscond(var_num)) {
		switch (var_num) {
		case V_MINE:
			return "mine";
		case V_CHKPT:
			return "checkpoint";
		case V_PSTAGE:
			return "plague stage";
		case V_PTIME:
			return "plague time";
		case V_RAD:
			return "radiation";
		case V_FALL:
			return "fallout";
		}
		return "bad vtype";
	} else {
		bp = copy(ichr[var_num & ~VT_TYPE].i_name, buf);
		if (isdel(var_num))
			copy(" delivery", bp);
		else if (isdist(var_num))
			copy(" distribute", bp);
		return buf;
	}
}

s_char *
recvclient(cmd, bp)
	s_char	*cmd;
	s_char	*bp;
{
	extern	s_char *gets();

	return gets(bp);
}

s_char *
getstring(p)
	s_char	*p;
{
	static	s_char buf[80];

	printf(p);
	return gets(buf);
}

gencore()
{
	exit(1);
}
