#ifndef lint
static char *RCSid = "$Header: tran.c,v 1.12 89/12/08 02:28:48 mr-frog Exp $";
#endif /* not lint */

/*
 * tran.c
 *
 * transport nuclear devices and planes
 */

#include "misc.h"
#include "var.h"
#include "sect.h"
#include "nuke.h"
#include "xy.h"
#include "nsc.h"
#include "plane.h"
#include "ship.h"
#include "file.h"
#include "nat.h"

#include <stdio.h>

static	tran_map();
static	tran_nuke();
static	tran_plane();

tran()
{
	extern	char *argp[];
	char	*what;

	what = getstarg(argp[1], "transport what (nuke or plane): ");
	if (what == 0)
		return RET_SYN;
	if (*what == 'n')
		return tran_nuke();
	else if (*what == 'p')
		return tran_plane();
	return RET_SYN;
}

/*
 * Kinda silly; only moves the first nuke.
 * Maybe nukes should be made into commodities?
 */
static
tran_nuke()
{
	extern	char *argp[];
	struct	nchrstr *ncp;
	int	len;
	int	dstx, dsty;
	char	*p;
	int	i;
	int	nukenum;
	int	nuketype;
	int	moving;
	struct	nukstr nuke;
	struct	sctstr sect;
	struct	sctstr endsect;
	int	mcost;
	struct	nstr_item nstr;
	int	found;

	if (!snxtitem(&nstr, EF_NUKE, argp[2]))
		return RET_SYN;
	while (found = nxtitem(&nstr, (char *)&nuke)) {
		if (nuke.nuk_own == cnum)
			break;
	}
	if (found == 0) {
		pr("No nukes found\n");
		return RET_FAIL;
	}
	nukenum = nstr.cur;
	if ((p = getstarg(argp[3], "warhead type : ")) == 0)
		return RET_SYN;
	len = strlen(p);
	for (i=0, ncp = nchr; i<N_MAXNUKE; i++, ncp++) {
		if (strncmp(ncp->n_name, p, len) == 0)
			break;
	}
	if (i >= N_MAXNUKE) {
		pr("No such nuke type!\n");
		return RET_SYN;
	}
	nuketype = i;
	if (nuke.nuk_types[nuketype] == 0) {
		pr("No nukes of that type in that sector\n");
		return RET_FAIL;
	}
	p = getstarg(argp[4], "number of warheads : ");
	if (p == 0 || *p == 0 || (moving = atoi(p)) < 0)
		return RET_FAIL;
	if (moving > nuke.nuk_types[nuketype]) {
		moving = nuke.nuk_types[nuketype];
		pr(fmt("only moving %d\n", moving));
	}
	getsect(nuke.nuk_x, nuke.nuk_y, &sect);
	mcost = move_ground((char *)&nuke, &sect, &endsect,
		(double)sect.sct_mobil,
		(double) ncp->n_weight * moving,
		argp[5], tran_map, 0);
	if (mcost < 0)
		return 0;
	dstx = endsect.sct_x;
	dsty = endsect.sct_y;
	/*
	 * decrement mobility from src sector
	 */
	getsect(nuke.nuk_x, nuke.nuk_y, &sect);
	sect.sct_mobil -= mcost;
	putsect(&sect);
	/*
	 * update old nuke
	 */
	getnuke(nukenum, &nuke);
	if (nuke.nuk_types[nuketype] < moving) {
		pr("Stockpile changed!\n");
		return RET_FAIL;
	}
	nuke.nuk_types[nuketype] -= moving;
	nuke.nuk_n -= moving;
	if (nuke.nuk_n <= 0)
		nuke.nuk_own = 0;
	putnuke(nukenum, &nuke);
	/*
	 * either find a stockpile in dst sector, or add
	 * a new one
	 */
	snxtitem_all(&nstr, EF_NUKE);
	nukenum = -1;
	while (found = nxtitem(&nstr, (char *)&nuke)) {
		if (nuke.nuk_own == cnum &&
		   (nuke.nuk_x == dstx && nuke.nuk_y == dsty)) {
			nukenum = nstr.cur;
			break;
		}
		if (nuke.nuk_own == 0)
			nukenum = nstr.cur;
	}
	if (!found) {
		if (nukenum < 0)
			nukenum = nstr.cur;
		bzero((char *)&nuke, sizeof(nuke));
		nuke.nuk_x = dstx;
		nuke.nuk_y = dsty;
		nuke.nuk_ship = -1;
		nuke.nuk_n = 0;
		nuke.nuk_own = cnum;
	}
	nuke.nuk_types[nuketype] += moving;
	nuke.nuk_n += moving;
	pr(fmt("adding to stockpile #%d\n", nukenum));
	putnuke(nukenum, &nuke);
	return RET_OK;
}

static int
tran_plane()
{
	extern	char *argp[];
	int	srcx, srcy;
	int	dstx, dsty;
	int	mcost;
	int	weight;
	int	first;
	int	type;
	struct	nstr_item nstr;
	struct	plnstr plane;
	struct	sctstr sect;
	struct	sctstr endsect;

	first = 1;
	weight = 0;
	if (!snxtitem(&nstr, EF_PLANE, argp[2]))
		return RET_SYN;
	/*
	 * First do some sanity checks: make sure that they are all in the,
	 * same sector, not on ships, owned, etc.
	 * No one could seriously want to move planes in parallel from
	 * several sectors!
	 */
	while (nxtitem(&nstr, (char *)&plane)) {
		if (!owner)
			continue;
		type = plane.pln_type;
		if (plane.pln_ship >= 0) {
			pr(fmt("%s (#%d) is at sea and can't be transported\n",
				plchr[type].pl_name, plane.pln_uid));
			return RET_FAIL;
		} else if (plane.pln_harden != 0) {
			pr(fmt("%s (#%d) has been hardened and can't be transported\n",
				plchr[type].pl_name, plane.pln_uid));
			return RET_FAIL;
		} else if ((plane.pln_flags & PLN_LAUNCHED) && 
						(plchr[type].pl_flags & P_O)) {
			pr(fmt("%s (#%d) is in space and can't be transported\n",
				plchr[type].pl_name, plane.pln_uid));
			return RET_FAIL;
		}
		if (first == 1) {
			srcx = plane.pln_x;
			srcy = plane.pln_y;
			first = 0;
		} else {
			if (plane.pln_x != srcx || plane.pln_y != srcy) {
				pr("All planes must be in the same sector.\n");
				return RET_FAIL;	
			}
		}
		weight += plchr[type].pl_lcm + (plchr[type].pl_hcm * 2);
	}
	if (first == 1) {
		/* no planes */
		return RET_FAIL;
	}
	getsect(srcx, srcy, &sect);
	mcost = move_ground((char *)&plane, &sect, &endsect,
		(double)sect.sct_mobil, (double)weight,
		argp[3], tran_map, 0);
	if (mcost < 0)
		return 0;
	dstx = endsect.sct_x;
	dsty = endsect.sct_y;
	snxtitem_rewind(&nstr);
	while (nxtitem(&nstr, (char *)&plane)) {
		if (!owner)
			continue;
		plane.pln_x = dstx;
		plane.pln_y = dsty;
		putplane(nstr.cur, &plane);
	}
	sect.sct_mobil -= mcost; 
	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
tran_map(what, curx, cury, arg)
	char	*what;
	int	curx, cury;
	char	*arg;
{
	extern	char *argp[];
	extern	char *condarg;

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