#ifndef lint
static char *RCSid = "$Header: load.c,v 1.15 90/03/19 11:09:53 mr-frog Exp $";
#endif /* not lint */

/*
 * load.c
 *
 * load (unload) goods from a sector onto a ship
 *
 * from PSL Empire, 1985
 *
 * hacked to allow planes/missiles to be loaded onto carriers/subs
 * by David Sharnoff 1987 
 * XXX needs to be told "plane" or commodity before amount.
 */

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

/*
 * The values 1 and -1 are important below, don't change them.
 */
#define	LOAD	1
#define	UNLOAD	-1

int
load()
{
	extern	char *argp[];
	register struct ichrstr *ich;
	register int item;
	register int max_amt;
	register int move_amt;
	register int ship_amt;
	register int sect_amt;
	struct shpstr ship;
	struct sctstr sect;
	struct plnstr pln;	/* for nuke subs */
	int     load_unload;
	int     ship_num;
	int     amount;
	int     is_fleet=0,is_plane;
	int     nplanes;
	struct nstr_item nbst;
	char	*p;
	char	*i;
	int	nships;
	struct natstr *np;
	int	rel;
#ifdef WING_LOAD
	struct nstr_item pl;
#endif /* WING_LOAD */

	if (!(p = getstarg(argp[1], "Ship(s): ")))
		return RET_SYN;
	if (!snxtitem(&nbst, EF_SHIP, p))
		return RET_SYN;
	if (isalpha(*p))
		is_fleet=1;
#ifdef	ALLYHARBOR
	nbst.flags &= ~(EFF_OWNER);
#endif	ALLYHARBOR
	load_unload = **argp == 'l' ? LOAD : UNLOAD;
	p = getstarg(argp[2], "Amount or plane #: ");
	if (p == 0 || *p == 0)
		return RET_SYN;
#ifdef WING_LOAD
	if (isalpha(*p))
		is_plane=1;
	else{
#endif /* WING_LOAD */
	amount = atoi(p);
	if (amount < 0) {	/* plane 0 is a valid plane number */
		pr("Amount must be non-negative.\n");
		return RET_SYN;
	}
#ifdef WING_LOAD
	}
#endif /* WING_LOAD */
	i = getstarg(argp[3], "What commodity ('plane' for a plane): ");
	if (i == 0 || i[0] == '\0')
		return RET_SYN;
#ifdef WING_LOAD
	is_plane = (is_plane == 1 ? 1 : !strncmp(i, "plane", 5));/* XXX */
#else
	is_plane = !strncmp(i, "plane", 5);	/* XXX */
#endif /* WING_LOAD */
	if (!is_plane) {
		ich = whatitem(i, (char *)0);
		if (ich == 0) {
			pr("Bad commodity.\n");
			return RET_SYN;
		}
		if (amount == 0) {
			pr("Amount must be positive\n");
			return RET_SYN;
		}
	}
#ifndef WING_LOAD
	if (is_plane) {	/* plane sanity */
		if (!getplane(amount, &pln))
			return RET_SYN;
		if (pln.pln_own != cnum) {
			pr("Not your plane\n");
			return RET_FAIL;
		}
		if (!(plchr[pln.pln_type].pl_flags & P_L)
#ifdef XLIGHT
		&&  !(plchr[pln.pln_type].pl_flags & P_E)
#endif /* XLIGHT */
#ifdef SHIPCHOPPERS
		&&  !(plchr[pln.pln_type].pl_flags & P_K)
#endif /* SHIPCHOPPERS */
		) {
			pr(fmt(
	"You can only load light planes %s %s onto ships.\n"
#ifdef SHIPCHOPPERS
		,"or helos",
#else
		,"",
#endif /* SHIPCHOPPERS */
#ifdef XLIGHT
		"or xtra-light planes"
#else
		""
#endif /* XLIGHT */
			));
			return RET_FAIL;
		}
		if (load_unload == LOAD && pln.pln_ship > -1) {
			pr(fmt("Plane #%d is already on ship #%d!\n",
				pln.pln_uid, pln.pln_ship));
			return RET_FAIL;
		}
	}
#endif /* WING_LOAD */
	nships = 0;
	while (nxtitem(&nbst, (char *)&ship)) {
#ifdef	ALLYHARBOR
		if (!ship.shp_own)
#else
		if (!owner)
#endif	ALLYHARBOR
			continue;
#ifdef	ALLYHARBOR
		if (!owner && (load_unload == UNLOAD)) {
			continue;
		}
		if (ship.shp_own != cnum){
			if (is_fleet)
				continue;
			np=getnatp(cnum);
			rel=getrel(np,ship.shp_own);
			if (rel != ALLIED)
				continue;
		}
#endif	ALLYHARBOR
		ship_num = ship.shp_uid;
#ifdef	ALLYHARBOR
		if (!getsect(ship.shp_x, ship.shp_y, &sect)) /* XXX */
			continue;
		if ((sect.sct_own != cnum) && (ship.shp_own != cnum))
			continue;
		if (!owner && (sect.sct_type != SCT_HARBR))
			continue;
#endif	ALLYHARBOR
#ifdef	SHIPNAMES
		pr(fmt("\t%s %s(#%d) at %s\n", mchr[ship.shp_type].m_name,
			ship.shp_name, ship_num, xyas(ship.shp_x, ship.shp_y,
			cnum)));
#else
		pr(fmt("\t%s #%d at %s\n", mchr[ship.shp_type].m_name,
			ship_num, xyas(ship.shp_x, ship.shp_y, cnum)));
#endif	SHIPNAMES
#ifdef	ALLYHARBOR
		if ((sect.sct_own != cnum) && (load_unload == LOAD)) {
			pr(fmt("You don't own %s \n",
#else
		if (!getsect(ship.shp_x, ship.shp_y, &sect)) /* XXX */
			continue;
		if (sect.sct_own != ship.shp_own) {
			pr(fmt("Sector %s is not yours.\n",
#endif	ALLYHARBOR
				xyas(ship.shp_x, ship.shp_y, cnum)));
			continue;
		}
		if (sect.sct_type != SCT_HARBR) {
			pr(fmt("Sector %s is not a harbor.\n",
				xyas(ship.shp_x, ship.shp_y, cnum)));
			continue;
		}
		if (sect.sct_effic < 2) {
			pr(fmt("The harbor at %s is not 2%% efficient yet.\n",
				xyas(ship.shp_x, ship.shp_y, cnum)));
			continue;
		}
		if (is_plane) {
#ifdef WING_LOAD
		        if (!snxtitem(&pl, EF_PLANE, p))
                		return RET_SYN;

			while(nxtitem(&pl, (char *)&pln)) {
#endif /* WING_LOAD */
			
#ifndef WING_LOAD
			/* Note that there is only one plane per transaction */
#endif /* WING_LOAD */
#ifdef WING_LOAD
                		if (pln.pln_own != cnum)
                        		continue;
                		if (!(plchr[pln.pln_type].pl_flags & P_L)
#ifdef XLIGHT
                		&&  !(plchr[pln.pln_type].pl_flags & P_E)
#endif /* XLIGHT */
#ifdef SHIPCHOPPERS
                		&&  !(plchr[pln.pln_type].pl_flags & P_K)
#endif /* SHIPCHOPPERS */
                		) {
                        		pr(fmt(
        	"You can only load light planes %s %s onto ships.\n"
#ifdef SHIPCHOPPERS
                			,"or helos",
#else
                			,"",
#endif /* SHIPCHOPPERS */
#ifdef XLIGHT
                			"or xtra-light planes"
#else
                			""
#endif /* XLIGHT */
                        		));
                        		continue;
                		}
                		if (load_unload == LOAD && pln.pln_ship > -1) {
                        		pr(fmt("Plane #%d is already on ship #%d!\n",
                                		pln.pln_uid, pln.pln_ship));
                        		continue;
	                	}
#endif /* WING_LOAD */
			/* Plane sanity done */
			/* Find the right ship */
			if (load_unload == UNLOAD) {
				if (pln.pln_ship != ship.shp_uid)
					continue;
			} else if (ship.shp_x != pln.pln_x
			    	|| ship.shp_y != pln.pln_y)
				continue;

			/* ship to (plane or missle) sanity */
#if defined (XLIGHT) || defined (SHIPCHOPPERS)
#else
			if (plchr[pln.pln_type].pl_flags & P_M) {
				if (!(mchr[ship.shp_type].m_flags &
					M_MSL)) {
#ifdef	SHIPNAMES
					pr(fmt("%s %s(#%d) cannot carry missles.\n",
						mchr[ship.shp_type].m_name,
						ship.shp_name,
#else
					pr(fmt("%s #%d cannot carry missles.\n",
						mchr[ship.shp_type].m_name,
#endif	SHIPNAMES
						ship.shp_uid));
					continue;
				}
			} else if (plchr[pln.pln_type].pl_flags & P_L) {
				if (!(mchr[ship.shp_type].m_flags & M_FLY)) {
#ifdef	SHIPNAMES
					pr(fmt("%s %s(#%d) cannot carry planes.\n",
						mchr[ship.shp_type].m_name,
						ship.shp_name,
#else
					pr(fmt("%s #%d cannot carry planes.\n",
						mchr[ship.shp_type].m_name,
#endif	SHIPNAMES
						ship.shp_uid));
					continue;
				}
			} /* else cannot happen */
#endif
			/* Fit plane on ship */
                        count_planes(ship.shp_uid);
                        getship(ship.shp_uid,&ship);
			if (load_unload == LOAD){
				if (!put_plane_on_ship(&pln,&ship)){
					pr(fmt("No room on this ship for plane %d!\n",pln.pln_uid));
					continue;
				}
				pln.pln_own = ship.shp_own;
				putplane(pln.pln_uid,&pln);
			}else{
				if (!take_plane_off_ship(&pln,&ship)){
					pr(fmt("Unable to take plane off ship!\n"));
					logerror("load: plane %d could not be taken off ship %d\n",pln.pln_uid,ship.shp_uid);
					continue;
				}
				pln.pln_own = sect.sct_own;
				putplane(pln.pln_uid,&pln);
			}
			pr(fmt("%s #%d %s ship #%d.\n",
				plchr[pln.pln_type].pl_flags & P_M ?
					"Missile" : "Plane",
				pln.pln_uid,
				(load_unload==UNLOAD)?
					"unloaded from":"loaded onto",
				ship.shp_uid,
				xyas(ship.shp_x, ship.shp_y, cnum)));
#ifdef WING_LOAD
			}
#endif /* WING_LOAD */
			return RET_OK;
		}
		item = ich->i_vtype;
		ship_amt = getvar(item, (char *)&ship, EF_SHIP);
		sect_amt = getvar(item, (char *)&sect, EF_SECTOR);
		if (sect.sct_oldown != cnum && item == V_CIVIL) {
			pr(fmt("%s civilians refuse to %s at %s!\n",
				load_unload == UNLOAD ? "Your" : "Foreign",
				load_unload == UNLOAD ?
					"disembark" : "board",
				xyas(sect.sct_x, sect.sct_y, cnum)));
			continue;
		}
		if (load_unload == UNLOAD) {
			max_amt = min(999 - sect_amt, ship_amt);
		} else {
			struct mchrstr *vbase;
			vbase = &mchr[ship.shp_type];
			max_amt = vl_find(item, vbase->m_vtype,
				vbase->m_vamt, (int) vbase->m_nv);
			max_amt = min(sect_amt, max_amt - ship_amt);
		}
		if (max_amt <= 0)
			continue;
		move_amt = load_unload * min(amount, max_amt);
		if (move_amt == 0)
			continue;
		putvar(item, sect_amt - move_amt, (char *)&sect, EF_SECTOR);
		putvar(item, ship_amt + move_amt, (char *)&ship, EF_SHIP);
		/* load/unload plague */
		if (getvar(V_PSTAGE, (char *)&sect, EF_SECTOR) == PLG_INFECT &&
		    getvar(V_PSTAGE, (char *)&ship, EF_SHIP) == PLG_HEALTHY)
			putvar(V_PSTAGE, PLG_EXPOSED, (char *)&ship, EF_SHIP);
		if (getvar(V_PSTAGE, (char *)&ship, EF_SHIP) == PLG_INFECT &&
		    getvar(V_PSTAGE, (char *)&sect, EF_SECTOR) == PLG_HEALTHY)
			putvar(V_PSTAGE, PLG_EXPOSED, (char *)&sect, EF_SECTOR);

		putsect(&sect);
		putship(ship_num, &ship);
		nships++;
	}
	if (nships == 0)
		pr("No ships affected\n");
	else
		pr(fmt("%d ship%s %sloaded\n", nships, splur(nships),
			load_unload == UNLOAD ? "un" : ""));
	return RET_OK;
}
