#ifndef lint
static char *RCSid = "$Header: move.c,v 1.13 89/10/29 15:23:33 mr-frog Exp $";
#endif

/*
 * move.c
 *
 * move commodities around
 *
 * from PSL Empire, 1985
 */

#include "misc.h"
#include "var.h"
#include "sect.h"
#include "item.h"
#include "file.h"
#include "deity.h"
#include "xy.h"
#include "nat.h"

static	int move_map();

move()
{
	extern	char *argp[];
	register int amount;
	struct	sctstr sect;
	struct	sctstr endsect;
	struct	sctstr start;
	int     packing;
	double	weight;
	int     mcost;
	int     infected;
	int     stype;
	int     vtype;
	int     amt_src;
	int     amt_dst;
	struct	dchrstr *dp;
	struct	ichrstr *ip;
	int     work;
	int     loyal;
	int     own;
	int	istest;
	coord	x, y;
	char	*p;

	istest = *argp[0] == 't';
	if ((ip = whatitem(argp[1], "move what? ")) == 0)
		return RET_SYN;
	vtype = ip->i_vtype;
	if ((p = getstarg(argp[2], "from sector : ")) == 0)
		return RET_SYN;
	if (!sarg_xy(p, &x, &y))
		return RET_SYN;
	if (!getsect(x, y, &sect) || !owner) {
		pr("Not yours\n");
		return RET_FAIL;
	}
	/*
	 * military control necessary to move
	 * goodies in occupied territory.
	 */
	if (sect.sct_oldown != cnum && vtype != V_MILIT) {
		if (getvar(V_MILIT, (char *)&sect, EF_SECTOR) * 10
		    < getvar(V_CIVIL, (char *)&sect, EF_SECTOR)) {
			pr("Military control required to move goods.\n");
			return RET_FAIL;
		}
	}
	stype = sect.sct_type;
	dp = &dchr[stype];
	infected = getvar(V_PTIME, (char *)&sect, EF_SECTOR) == PLG_INFECT;
	if ((amt_src = getvar(vtype, (char *)&sect, EF_SECTOR)) <= 0) {
		pr(fmt("No %s in %s\n", ip->i_name, 
			xyas(sect.sct_x, sect.sct_y, cnum)));
		return RET_SYN;
	}
	own = sect.sct_own;
	if (vtype == V_CIVIL && sect.sct_oldown != own) {
		pr("You can't move conquered populace!\n");
		return RET_SYN;
	}
	if (vtype == V_CIVIL) {
		work = sect.sct_work;
		if (work != 100)
			pr("Warning: civil unrest\n");
		loyal = sect.sct_loyal;
	} else if (vtype == V_MILIT) {
		work = 100;
		loyal = 0;
	}
	amount = onearg(argp[3], fmt("Quantity? (max %d) ", amt_src));
	if (amount > amt_src) {
		amount = amt_src;
		pr(fmt("Only moving %d.\n", amount));
	}
	if (amount <= 0)
		return RET_SYN;
	packing = ip->i_pkg[dp->d_pkg];
	if (packing > 1 && sect.sct_effic < 60)
		packing = 1;
	weight = amount * ip->i_lbs / packing;
	/*
	 * Now parse the path and return ending sector.
	 */
	mcost = move_ground((char *)ip, &sect, &endsect,
		(double)sect.sct_mobil, weight, argp[4], move_map, 0);
	if (mcost < 0) {
		pr("Move aborted\n");
		return RET_FAIL;
	}
	if (getvar(V_CIVIL, (char *)&endsect, EF_SECTOR)+10 < amount/50) {
		pr("Too much traffic for workers in this sector\n");
		return RET_FAIL;
	}
	/*
	 * Re-read dest sector to minimize our
	 * window of vulnerability.  If we got this far, always
	 * charge the player mobility.
	 */
	getsect(endsect.sct_x, endsect.sct_y, &sect);
	if(sect.sct_own != cnum) {
		pr("Somebody has captured that sector!\n");
		return RET_FAIL;
	}
	if (sect.sct_x == x && sect.sct_y == y) {
		/* didn't go anywhere! */
		amount = 0;
	}
	if (vtype == V_CIVIL && getvar(V_CIVIL, (char *)&sect, EF_SECTOR) &&
	    sect.sct_oldown != cnum) {
		pr("Your civilians don't want to stay!\n");
		amount = 0;
	}
	amt_dst = getvar(vtype, (char *)&sect, EF_SECTOR);
	if (32767 - amt_dst < amount) {
		amount = 32767 - amt_dst;
		pr(fmt("Only %d can be left there.\n", amount));
	}
	if (istest)
		return RET_OK;
	if (putvar(vtype, amount + amt_dst, (char *)&sect, EF_SECTOR) < 0) {
		pr(fmt("No more room in %s.\n", 
			xyas(sect.sct_x, sect.sct_y, cnum)));
		/* charge the player mobility anyway */
		amount = 0;
	}
	/*
	 * First remove commodities from source sector,
	 * and decrement mobility appropriately.
	 */
	getsect(x, y, &start);
	amt_src = getvar(vtype, (char *)&start, EF_SECTOR);
	amt_src -= amount;
	if (amt_src < 0) {
		pr(fmt("%s in %s are gone!\n", ip->i_name, 
			xyas(start.sct_x, start.sct_y, cnum)));
		amount = 0;
	}
	start.sct_mobil -= mcost;
	putvar(vtype, amt_src, (char *)&start, EF_SECTOR);
	putsect(&start);
	/*
	 * Now add commodities to destination sector,
	 * along with plague that came along for the ride.
	 * Takeover unowned sectors if not deity.
	 */
	if (infected && getvar(V_PTIME, (char *)&sect, EF_SECTOR) == 0)
		putvar(V_PTIME, PLG_EXPOSED, (char *)&sect, EF_SECTOR);
	if (vtype == V_CIVIL) {
		/* It only takes one bad apple... */
		if (sect.sct_loyal < loyal)
			sect.sct_loyal = loyal;
		if (sect.sct_work > work)
			sect.sct_work = work;
	}
	putsect(&sect);
	return RET_OK;
}

/*
 * Pretty tacky, but it works.
 * If more commands start doing this, then
 * rewrite map to do the right thing.
 */
/*ARGSUSED*/
static
move_map(what, curx, cury, arg)
	char	*what;
	int	curx, cury;
	char	*arg;
{
	extern	char *argp[];
	extern	char *condarg;

	argp[1] = arg;
	condarg = 0;
	map();
}
