#ifndef lint
static char *RCSid = "$Header: /sequent2/empire/EMP/player/subs/RCS/plnsub.c,v 1.10 89/09/18 00:00:59 mr-frog Exp $";
#endif

/*
 * plnsub.c
 *
 * Plane subroutine stuff
 *
 * Dave Pare, 1986
 */

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

int
pln_onewaymission(target, shipno, flagp)
	struct	sctstr *target;
	int	*shipno;
	int	*flagp;
{
	int	nships;
	char	*p;
	int	cno;
	int	flags;
	int	n,x;
	struct	shpstr ship;

	flags = *flagp;
#ifdef TOM_DEBUG
pr(fmt("Sector owner = %d\n",target->sct_own));
#endif /* TOM_DEBUG */
#ifdef TOM_DEBUG
pr(fmt("I am = %d\n",cnum));
#endif /* TOM_DEBUG */
	if ((target->sct_own && target->sct_own != cnum &&
		(getrel(getnatp(target->sct_own),cnum) != ALLIED)) &&
		(target->sct_type != SCT_HARBR) &&
		(target->sct_type != SCT_BSPAN)) {
		pr(fmt("Nowhere to land at sector %s!\n",
			xyas(target->sct_x, target->sct_y, cnum)));
		return -1;
	}
	if (target->sct_type == SCT_MOUNT) {
		pr(fmt("Nowhere to land at sector %s!\n",
			xyas(target->sct_x, target->sct_y, cnum)));
		return -1;
	}
	cno = -1;
	if (target->sct_type != SCT_AIRPT || target->sct_effic < 60)
		flags |= P_V;
	if (target->sct_type == SCT_WATER || target->sct_type == SCT_HARBR
					|| target->sct_type == SCT_BSPAN) {
#ifdef TOM_DEBUG
pr("SHIP!\n");
#endif /* TOM_DEBUG */
#ifdef SHIPCHOPPERS
#ifdef XLIGHT
		nships = shipsatxy(target->sct_x,
				target->sct_y, M_FLY|M_CHOPPER|M_XLIGHT, 0);
#else
		nships = shipsatxy(target->sct_x,
				target->sct_y, M_FLY|M_CHOPPER, 0);
#endif /* XLIGHT */
#else /* SHIPCHOPPERS */
#ifdef XLIGHT
		nships = shipsatxy(target->sct_x,
				target->sct_y, M_FLY|M_XLIGHT, 0);
#else
		nships = shipsatxy(target->sct_x, target->sct_y, M_FLY, 0);
#endif /* XLIGHT */
#endif /* SHIPCHOPPERS */
#ifdef TOM_DEBUG
pr(fmt("Nships=%d\n",nships));
#endif /* TOM_DEBUG */
		if (nships <= 0) {
                        if (target->sct_type == SCT_WATER){
                                pr(fmt("Nowhere to land at sector %s!\n",
                                xyas(target->sct_x, target->sct_y, cnum)));
    				return -1;
                        }else{
				if ((target->sct_own && target->sct_own != cnum)
					&& (getrel(getnatp(target->sct_own),cnum) != ALLIED)){
					pr(fmt("Nowhere to land at sector %s!\n",
						xyas(target->sct_x,
						target->sct_y, cnum)));
					return -1;
				}
                                *shipno=cno;
                                *flagp=flags;
                                return 0;
                        }
		}
#ifdef TOM_DEBUG
pr(fmt("Nships=%d\n",nships));
#endif /* TOM_DEBUG */
		cno = -1;
		n=(-1);
		while (cno < 0) {
#ifdef TOM_DEBUG
pr(fmt("N=%d\n",n));
#endif /* TOM_DEBUG */
			if ((p = getstring("Carrier #? ")) == 0 || *p == 0)
				break;

			n = atoi(p);
			for(x=0;x<strlen(p);x++)
				if (!isdigit(*(p+x)))
					n=-1;
#ifdef TOM_DEBUG
pr(fmt("1N=%d\n",n));
#endif /* TOM_DEBUG */
			if (n < 0 || !getship(n, &ship) || (!owner &&
			    (getrel(getnatp(ship.shp_own),cnum) != ALLIED))) {
				pr("Not yours\n");
				continue;
			}
			if (ship.shp_x != target->sct_x ||
			    ship.shp_y != target->sct_y) {
				pr(fmt("Ship #%d not in %s\n", n,
				    xyas(target->sct_x, target->sct_y, cnum)));
				continue;
			}
#if defined(XLIGHT) || defined(SHIPCHOPPERS)
			if (!(mchr[ship.shp_type].m_flags & M_FLY)
#ifdef XLIGHT
				&& !(mchr[ship.shp_type].m_flags & M_XLIGHT)
#endif /* XLIGHT */
#ifdef SHIPCHOPPERS
				&& !(mchr[ship.shp_type].m_flags & M_CHOPPER)
#endif /* SHIPCHOPPERS */
			){
#else
			if ((mchr[ship.shp_type].m_flags & M_FLY) == 0){
#endif /* XLIGHT | SHIPCHOPPERS */
#ifdef	SHIPNAMES
				pr(fmt("Can't land on %s %s(#%d).\n",
					mchr[ship.shp_type].m_name,
					ship.shp_name, n));
#else
				pr(fmt("Can't land on %s #%d.\n",
					mchr[ship.shp_type].m_name, n));
#endif	SHIPNAMES
				continue;
			}
			pr(fmt("landing on carrier %d\n",n));
			cno = n;
			flags &= ~P_V;
			flags |= P_L;
#ifdef SHIPCHOPPERS
			flags |= P_K;
#endif /* SHIPCHOPPERS */
#ifdef XLIGHT
			flags |= P_E;
#endif /* XLIGHT */
#ifdef TOM_DEBUG
pr(fmt("landing on ship %d, flags %d\n",n,flags));
#endif /* TOM_DEBUG */
		}
		if ((target->sct_own && target->sct_own != cnum) && (cno== -1)){
			pr(fmt("You don't own %s!\n", xyas(target->sct_x,
				target->sct_y, cnum)));
			return -1;
		}
	}

	if ((target->sct_own == 0) && (cno < 0)){
		pr("Can't land there!\n");
		return -1;
	}

	*shipno = cno;
	*flagp = flags;
#ifdef TOM_DEBUG
pr(fmt("1landing on ship %d, flags %d\n",n,flags));
#endif /* TOM_DEBUG */
	return 0;
}

pln_newlanding(list, tx, ty, cno)
	struct	qelem *list;
	coord	tx, ty;
	int	cno;
{
	struct	qelem *qp;
	struct	plist *plp;
	struct	shpstr ship;
	struct	sctstr sect;

	if (cno >= 0)
		getship(cno, &ship);
	for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
		plp = (struct plist *)qp;
		/* XXX - need to restrict # of planes per ship */
		if (cno >= 0){
                        count_planes(ship.shp_uid);
                        getship(ship.shp_uid,&ship);
			if (!can_be_on_ship(plp->plane.pln_uid,ship.shp_uid))
				pr(fmt("\tPlane #%d cannot land on ship %d! (#%d) %s aborts!\n",plp->plane.pln_uid,cno,plp->plane.pln_uid,plp->pcp->pl_name));
			else if (!put_plane_on_ship(&plp->plane,&ship))
				pr(fmt("\tNo room on ship %d! (#%d) %s aborts!\n",cno,plp->plane.pln_uid,plp->pcp->pl_name));
			else{
				if (plp->plane.pln_own != ship.shp_own){
					plp->plane.pln_own = ship.shp_own;
					wu(0,ship.shp_own,
				fmt("%s %s (#%d) lands on your %s #%d\n",
						cname(cnum),
						plchr[plp->plane.pln_type].pl_name,
						plp->plane.pln_uid,
						mchr[ship.shp_type].m_name,
						ship.shp_uid));
				}
			}
		}
		else{
			plp->plane.pln_x = tx;
			plp->plane.pln_y = ty;
			getsect(tx,ty,&sect);
			if (plp->plane.pln_own != sect.sct_own){
				plp->plane.pln_own = sect.sct_own;
				wu(0,sect.sct_own,
			fmt("%s %s (#%d) lands at your sector %s\n",
					cname(cnum),
					plchr[plp->plane.pln_type].pl_name,
					plp->plane.pln_uid,
					xyas(tx,ty,sect.sct_own)));
			}
			plp->plane.pln_ship = cno;
		}
	}
	if (cno >= 0)
		putship(cno, &ship);
}

pln_dropoff(list, ip, tx, ty, ptr, type)
	struct	qelem *list;
	struct	ichrstr *ip;
	coord	tx, ty;
	char	*ptr;
	int	type;
{
	struct	qelem *qp;
	struct	plist *plp;
	int	amt;
	struct	shpstr *ship;
	int	there;
	int	max;
	struct	mchrstr *mp;
#ifdef MINE_PLANES
	int	mines_there;
#endif /* MINE_PLANES */

	if (ip == 0)
		return;
	amt = 0;
	for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
		plp = (struct plist *)qp;
		amt += plp->misc;
	}
#ifdef MINE_PLANES
	if (type == EF_SECTOR &&
		(((struct sctstr *)ptr)->sct_type == SCT_WATER) &&
		ip->i_vtype == V_SHELL){
                mines_there = getvar(V_MINE, ptr, EF_SECTOR);
                putvar(V_MINE, amt + mines_there, ptr, EF_SECTOR);
                pr(fmt("%d mines laid in %s.\n", amt,
                        xyas(((struct sctstr *)ptr)->sct_x,
			((struct sctstr *)ptr)->sct_y, cnum)));
		putsect((struct sctstr *) ptr);
	}else{
		there = getvar(ip->i_vtype, ptr, type) + amt;
		max = 32767;
		if (type == EF_SHIP) {
			ship = (struct shpstr *) ptr;
			mp = &mchr[ship->shp_type];
			max = vl_find(ip->i_vtype, mp->m_vtype,
				mp->m_vamt, (int)mp->m_nv);
		}
		if (there > max) {
			pr(fmt("%d excess %s discarded\n",
				max-there, ip->i_name));
			amt = max - there;
			there = max;
		}
		putvar(ip->i_vtype, there, ptr, type);
		pr(fmt("%d %s landed safely", amt, ip->i_name));
		if (type == EF_SECTOR) {
			pr(fmt(" at %s\n", xyas(tx, ty, cnum)));
			putsect((struct sctstr *) ptr);
		} else {
			pr(fmt(" on carrier #%d\n", ship->shp_uid));
			putship(ship->shp_uid, ship);
		}
	}
#else
	there = getvar(ip->i_vtype, ptr, type) + amt;
	max = 32767;
	if (type == EF_SHIP) {
		ship = (struct shpstr *) ptr;
		mp = &mchr[ship->shp_type];
		max = vl_find(ip->i_vtype, mp->m_vtype,
			mp->m_vamt, (int)mp->m_nv);
	}
	if (there > max) {
		pr(fmt("%d excess %s discarded\n",
			max-there, ip->i_name));
		amt = max - there;
		there = max;
	}
	putvar(ip->i_vtype, there, ptr, type);
	pr(fmt("%d %s landed safely", amt, ip->i_name));
	if (type == EF_SECTOR) {
		pr(fmt(" at %s\n", xyas(tx, ty, cnum)));
		putsect((struct sctstr *) ptr);
	} else {
		pr(fmt(" on carrier #%d\n", ship->shp_uid));
		putship(ship->shp_uid, ship);
	}
#endif /* MINE_PLANES */
}

pln_sel(ni, list, ap, ap_to_target, rangemult, wantflags, nowantflags)
	struct	nstr_item *ni;
	struct	qelem *list;
	struct	sctstr *ap;
	int	ap_to_target;
	int	rangemult;
	int	wantflags;
	int	nowantflags;
{
	struct	plnstr plane;
	struct	shpstr ship;
	struct	sctstr sect;
	int	range;
	struct	plchrstr *pcp;
	struct	plist *plp;
	register int	x,y,bad,bad1;

#ifdef TOM_DEBUG
pr("In pln_sel\n");
#endif /* TOM_DEBUG */
	initque(list);
	while (nxtitem(ni, (char *)&plane)) {
#ifdef TOM_DEBUG
pr(fmt("Looking at plane %d\n",plane.pln_own));
#endif /* TOM_DEBUG */
		if (!owner)
			continue;
#ifdef TOM_DEBUG
pr(fmt("Looking at plane mobil %d\n",plane.pln_mobil));
#endif /* TOM_DEBUG */
		if (plane.pln_mobil <= 0)
			continue;
		range = mapdist(plane.pln_x, plane.pln_y, ap->sct_x, ap->sct_y);
#ifdef TOM_DEBUG
pr(fmt("Looking at plane rtt %d\n",range));
#endif /* TOM_DEBUG */
		if (range > 4) {
			pr(fmt("%d too far from assembly point\n", ni->cur));
			continue;
		}
		range += ap_to_target;
		pcp = &plchr[plane.pln_type];
#ifdef TOM_DEBUG
pr("looking at wantflags\n");
#endif /* TOM_DEBUG */
		bad=0;
		bad1=0;
		if (wantflags) {
			for(x=0;x<sizeof(wantflags)*8;x++){
				y=(1<<x);
				if ((wantflags & y) == y)
					if ((pcp->pl_flags & y) != y){
						switch(y){
							case P_F:
							case P_ESC: bad1=2;
								    break;
#if defined(XLIGHT) || defined(SHIPCHOPPERS)
							case P_E:
							case P_L:
							case P_K: bad1=1;
								  break;
							default:  bad=1;
						}
#else
						}
						bad=1;
#endif
					}
			}
			if (bad)
				continue;
			if (bad1 == 2){
				if ((pcp->pl_flags &  P_ESC) ||
					(pcp->pl_flags & P_F))
					bad1=0;
			}
#if defined(XLIGHT) || defined(SHIPCHOPPERS)
			if (bad1 == 1){
				if ((pcp->pl_flags &  P_E) ||
					(pcp->pl_flags & P_K) ||
					(pcp->pl_flags & P_L))
					bad1=0;
			}
			if (bad1)
				continue;
#endif
		}
#ifdef TOM_DEBUG
pr("looking at no wantflags\n");
#endif /* TOM_DEBUG */
		bad=0;
		bad1=0;
		if (nowantflags) {
			for(x=0;x<sizeof(nowantflags)*8;x++){
				y=(1<<x);
				if ((nowantflags & y) == y)
					if ((pcp->pl_flags & y) == y)
						bad=1;
			}
			if (bad)
				continue;
		}
#ifdef TOM_DEBUG
pr("ok\n");
#endif /* TOM_DEBUG */
		range *= rangemult;
		if (plane.pln_range < range) {
			pr(fmt("%d out of range (%d:%d)\n", ni->cur,
				plane.pln_range, range));
			continue;
		}
		if (plane.pln_ship >= 0) {
#ifdef TOM_DEBUG
pr("Looking at ship\n");
#endif /* TOM_DEBUG */
			if (!getship(plane.pln_ship, &ship) ||
			    plane.pln_own != cnum) {
	shipsunk:
				plane.pln_effic = 0;
				pr(fmt("(note) ship not valid for #%d\n",
					ni->cur));
				putplane(ni->cur, &plane);
				continue;
			}
#if defined (SHIPCHOPPERS) || defined (XLIGHT)
			if (!can_be_on_ship(plane.pln_uid,ship.shp_uid))
				goto shipsunk;
#else
			if ((mchr[ship.shp_type].m_flags & M_FLY) == 0)
				goto shipsunk;
#endif
			if (ship.shp_effic < 20)
				goto shipsunk;
			if (ship.shp_effic < 50)
				continue;
		}
		/*
		 * if not vtol and not at an airport, you lose!
		 */
		if ((pcp->pl_flags & P_V) == 0 && plane.pln_ship < 0) {
			if (!getsect(plane.pln_x, plane.pln_y, &sect) ||
			    sect.sct_type != SCT_AIRPT) {
				pr(fmt("%d not at airport\n", ni->cur));
				continue;
			}
			if (sect.sct_effic < 40)
				continue;
		}
		pr(fmt("(#%d) %s standing by\n", ni->cur,
			plchr[plane.pln_type].pl_name));
		plp = (struct plist *) malloc(sizeof(struct plist));
		plp->state = P_OK;
		plp->misc = 0;
		plp->bombs = 0;
		plp->pcp = pcp;
		bcopy((char *)&plane, (char *)&plp->plane,
			sizeof(struct plnstr));
		insque(&plp->queue, list);
	}
}

int
pln_arm(list, mission, ip, flags, mission_flags, tech)
	struct	qelem *list;
	int	mission;
	struct	ichrstr *ip;
	int	flags;
	int	mission_flags;
	int	*tech;
{
	struct	qelem *qp;
	struct	qelem *next;
	struct	plist *plp;

	for (qp = list->q_forw; qp != list; qp = next) {
		next = qp->q_forw;
		plp = (struct plist *) qp;
#ifdef TOM_DEBUG
pr(fmt("Arming plane %d\n",plp->plane.pln_uid));
#endif /* TOM_DEBUG */
		if (pln_equip(plp, ip, flags, mission) < 0) {
			remque(qp);
			free((char *)qp);
			continue;
		}
#ifdef TOM_DEBUG
pr(fmt("plane equipped %d\n",plp->plane.pln_uid));
#endif /* TOM_DEBUG */
		if (flags & (P_S|P_I)) {
			if(plp->pcp->pl_flags & P_S)
				mission_flags |= P_S;
			if(plp->pcp->pl_flags & P_I)
				mission_flags |= P_I;
		}
#ifdef CHOPPER_STEALTH
		if (plp->pcp->pl_flags & P_H) {
			if (*tech > plp->plane.pln_tech)
				*tech = plp->plane.pln_tech;
		} else {
			/* no stealth on this mission */
			mission_flags &= ~P_H;
		}
#endif /* CHOPPER_STEALTH */
		if (plp->pcp->pl_flags & P_X) {
			if (*tech > plp->plane.pln_tech)
				*tech = plp->plane.pln_tech;
		} else {
			/* no stealth on this mission */
			mission_flags &= ~P_X;
		}
#ifdef ASW_PLANES
		if (!(plp->pcp->pl_flags & P_A)) {
			/* no asw on this mission */
			mission_flags &= ~P_A;
		}
#endif /* ASW_PLANES */
#ifdef MINE_PLANES
		if (!(plp->pcp->pl_flags & P_MINE)) {
			/* no asw on this mission */
			mission_flags &= ~P_MINE;
		}
#endif /* MINE_PLANES */
#ifdef MERC
		if ((flags & P_F) || (flags & P_ESC))
			plp->plane.pln_mobil -= (char) min(32 + plp->plane.pln_mobil,(12 * 100 / (char) plp->plane.pln_effic));
		else
			plp->plane.pln_mobil -= (char) min(32 + plp->plane.pln_mobil,(20 * 100 / (char) plp->plane.pln_effic));
#else
		if ((flags & P_F) || (flags & P_ESC))
			plp->plane.pln_mobil -= 12;
		else
			plp->plane.pln_mobil -= 20;
#endif
#ifdef TOM_DEBUG
pr(fmt("plane equipped %d\n",plp->plane.pln_uid));
#endif /* TOM_DEBUG */
		pr(fmt("(#%d) %s equipped\n", plp->plane.pln_uid,
			plp->pcp->pl_name));
	}
	return mission_flags;
}

int
pln_equip(plp, ip, flags, mission)
	struct	plist *plp;
	struct	ichrstr *ip;
	int	flags;
	char	mission;
{
	register struct plchrstr *pcp;
	struct	plnstr *pp;
	int	needed;
	struct	shpstr ship;
	struct	sctstr sect;
	int	type;
	char	*ptr;
	int	item;
	int	rval;
	int	vec[I_MAX+1];

	pp = &plp->plane;
	pcp = plp->pcp;
#ifdef TOM_DEBUG
pr(fmt("Equipping p\lane %d\n",pp->pln_uid));
#endif /* TOM_DEBUG */
	if (pp->pln_ship >= 0) {
		getship(pp->pln_ship, &ship);
		type = EF_SHIP;
		ptr = (char *) &ship;
#ifdef TOM_DEBUG
pr(fmt("plane %d is on ship %d\n",pp->pln_uid,pp->pln_ship));
#endif /* TOM_DEBUG */
	} else {
		getsect(pp->pln_x, pp->pln_y, &sect);
		type = EF_SECTOR;
		ptr = (char *) &sect;
	}
	getvec(VT_ITEM, vec, ptr, type);
	if (pcp->pl_fuel > vec[I_PETROL]) {
		pr(fmt("(#%d) %s not enough petrol there!\n",
			pp->pln_uid, plp->pcp->pl_name));
		return -1;
	}
	vec[I_PETROL] -= pcp->pl_fuel;
#ifdef TOM_DEBUG
pr(fmt("plane %d is using %d petrol\n",pp->pln_uid,pcp->pl_fuel));
#endif /* TOM_DEBUG */
	rval = 0;
	if ((flags & P_F) == 0) {
#ifdef TOM_DEBUG
pr("Non intercept mission\n");
#endif /* TOM_DEBUG */
		item = 0;
		needed = 0;
		switch (mission) {
		case 's':
		case 'p':
			item = I_SHELL;
			needed = pcp->pl_load;
			break;
		case 't':
			if ((pcp->pl_flags & P_C) == 0 || ip == 0)
				break;
			item = ip - ichr;
			needed = (pcp->pl_load * 2) / ip->i_lbs;
			break;
		case 'd':
			if ((pcp->pl_flags & P_C) == 0 || ip == 0)
				break;
			item = ip - ichr;
			needed = (pcp->pl_load * 2) / ip->i_lbs;
			break;
		case 'a':
			if ((pcp->pl_flags & (P_V|P_C)) == 0)
				break;
			item = I_MILIT;
			needed = pcp->pl_load / ip->i_lbs;
			break;
		case 'n':
			if (pp->pln_nukeamt == 0)
				rval = -1;
			break;
		default:
			break;
		}
		if (rval < 0 || (item && needed <= 0)) {
			pr(fmt("%s #%d can't contribute to mission\n",
				pcp->pl_name, pp->pln_uid));
			return -1;
		}
		if (vec[item] < needed) {
			pr(fmt("Not enough %s for plane #%d\n",
				ichr[item].i_name, pp->pln_uid));
			return -1;
		} else {
			vec[item] -= needed;
		}
		if (item == I_SHELL && (mission == 's' || mission == 'p'))
			plp->bombs = needed;
		else
			plp->misc = needed;
	}
#ifdef TOM_DEBUG
pr(fmt("eq\n"));
#endif /* TOM_DEBUG */
		putvec(VT_ITEM, vec, ptr, type);
	if (type == EF_SHIP)
		putship(ship.shp_uid,&ship);
	else
		putsect(&sect);
	return rval;
}

pln_put(list)
	struct	qelem *list;
{
	register struct qelem *qp;
	register struct qelem *newqp;
	struct	plist *plp;

	qp = list->q_forw;
	while (qp != list) { 
		plp = (struct plist *) qp;
		putplane(plp->plane.pln_uid, &plp->plane);
		newqp = qp->q_forw;
		remque(qp);
		free((char *)qp);
		qp = newqp;
	}
}

pln_removedupes(bomb_list, esc_list)
	struct	qelem *bomb_list;
	struct	qelem *esc_list;
{
	struct	qelem *bomb;
	struct	qelem *esc;
	struct	plist *bombp;
	struct	plist *escp;

	if (QEMPTY(bomb_list) || QEMPTY(esc_list))
		return;
	bomb = bomb_list->q_forw;
	while (bomb != bomb_list) {
		if (QEMPTY(esc_list)) {
			bomb = bomb_list;
			continue;
		}
		esc = esc_list->q_forw;
		bombp = (struct plist *) bomb;
		while (esc != esc_list) {
			escp = (struct plist *) esc;
			if (escp->plane.pln_uid == bombp->plane.pln_uid) {
				remque(esc);
				free((char *)esc);
				esc = esc_list;
			} else
				esc = esc->q_forw;
		}
		bomb = bomb->q_forw;
	}
}

put_plane_on_ship(plane,ship)
struct plnstr	*plane;
struct shpstr	*ship;
{
	struct	plchrstr *pcp;
	struct	mchrstr *mcp;

	pcp = &plchr[plane->pln_type];
	mcp = &mchr[ship->shp_type];

#ifdef TOM_DEBUG
	pr(fmt("\nShip %d can hold %d choppers, %d x-light, and %d light planes\n",ship->shp_uid,mcp->m_nchoppers,mcp->m_nxlight,mcp->m_nplanes));
#endif /* TOM_DEBUG */

	if (((int)plane->pln_ship) == ((int)ship->shp_uid))
		return 1; /* Already on ship */

#ifdef SHIPCHOPPERS
	/* Try to put on ship as a chopper plane */
	if ((pcp->pl_flags & P_K) &&
		(mcp->m_flags & M_CHOPPER) &&
		(ship->shp_nchoppers < mcp->m_nchoppers)){
#ifdef TOM_DEBUG
pr(fmt("plane %d (%s) is a helo\n",plane->pln_uid,pcp->pl_name));
#endif /* TOM_DEBUG */

		ship->shp_nchoppers++;
		plane->pln_x = ship->shp_x;
		plane->pln_y = ship->shp_y;
		plane->pln_ship = ship->shp_uid;
		putship(ship->shp_uid,ship);
#ifdef TOM_DEBUG
pr(fmt("Putting plane %d owned by %d\n",plane->pln_uid,plane->pln_own));
#endif /* TOM_DEBUG */
		putplane(plane->pln_uid,plane);
#ifdef TOM_DEBUG
pr(fmt("Put plane %d\n",plane->pln_uid));
#endif /* TOM_DEBUG */
		return 1;
	}
#endif /* SHIPCHOPPERS */

#ifdef XLIGHT
	/* Try to put on ship as an xlight plane */
	if ((pcp->pl_flags & P_E) &&
		(mcp->m_flags & M_XLIGHT) &&
		(ship->shp_nxlight < mcp->m_nxlight)){

#ifdef TOM_DEBUG
pr(fmt("plane %d (%s) is a xlight plane\n",plane->pln_uid,pcp->pl_name));
#endif /* TOM_DEBUG */
		ship->shp_nxlight++;
		plane->pln_x = ship->shp_x;
		plane->pln_y = ship->shp_y;
		plane->pln_ship = ship->shp_uid;
		putship(ship->shp_uid,ship);
		putplane(plane->pln_uid,plane);
		return 1;
	}
#endif /* XLIGHT */

	/* Try to put on ship as a normal plane */
	if ( ( ((pcp->pl_flags & P_L) && (mcp->m_flags & M_FLY)) ||
		((pcp->pl_flags & P_M) && (pcp->pl_flags & P_L) &&
		(mcp->m_flags & M_MSL)) ) &&
		(ship->shp_nplane < mcp->m_nplanes)){
#ifdef TOM_DEBUG
pr(fmt("plane %d (%s) is a light plane\n",plane->pln_uid,pcp->pl_name));
#endif /* TOM_DEBUG */

		ship->shp_nplane++;
		plane->pln_x = ship->shp_x;
		plane->pln_y = ship->shp_y;
		plane->pln_ship = ship->shp_uid;
#ifdef TOM_DEBUG
pr(fmt("Put ship %d\n",ship->shp_uid));
#endif /* TOM_DEBUG */
		putship(ship->shp_uid,ship);
#ifdef TOM_DEBUG
pr(fmt("Put plane %d\n",plane->pln_uid));
#endif /* TOM_DEBUG */
		putplane(plane->pln_uid,plane);
#ifdef TOM_DEBUG
getplane(plane->pln_uid,plane);
pr(fmt("Plane %d ship is %d\n",plane->pln_uid,plane->pln_ship));
#endif /* TOM_DEBUG */

		return 1;
	}

#ifdef TOM_DEBUG
pr("Nope, I just can't bring myself to do it...\n");
#endif /* TOM_DEBUG */
	/* We have failed */
	return 0;
}

take_plane_off_ship(plane,ship)
struct plnstr	*plane;
struct shpstr	*ship;
{
	struct plchrstr	*pcp;
	struct mchrstr	*mcp;
	int	off=0;

	pcp = &plchr[plane->pln_type];
	mcp = &mchr[ship->shp_type];

#ifdef SHIPCHOPPERS
	/* Try to take off ship as a chopper plane */
	if ((pcp->pl_flags & P_K) &&
		(mcp->m_flags & M_CHOPPER) &&
		(ship->shp_nchoppers > 0)){

		ship->shp_nchoppers--;
		plane->pln_ship = -1;
		putship(ship->shp_uid,ship);
		putplane(plane->pln_uid,plane);
		return 1;
	}
#endif /* SHIPCHOPPERS */

#ifdef XLIGHT
	/* Try to take off ship as an xlight plane */
	if ((pcp->pl_flags & P_E) &&
		(mcp->m_flags & M_XLIGHT) &&
		(ship->shp_nxlight > 0)){

		ship->shp_nxlight--;
		plane->pln_ship = -1;
		putship(ship->shp_uid,ship);
		putplane(plane->pln_uid,plane);
		return 1;
	}
#endif /* XLIGHT */

	/* Try to take off ship as a normal plane */
	if ( ( ((pcp->pl_flags & P_L) && (mcp->m_flags & M_FLY)) ||
		((pcp->pl_flags & P_M) && (pcp->pl_flags & P_L) &&
		(mcp->m_flags & M_MSL)) ) &&
		(ship->shp_nplane > 0)){

		ship->shp_nplane--;
		plane->pln_ship = -1;
		putship(ship->shp_uid,ship);
		putplane(plane->pln_uid,plane);
		return 1;
	}

	/* We have failed */
	return 0;
}

can_be_on_ship(p,s)
int    p,s;
{
	struct plnstr	plane;
	struct shpstr	ship;
	struct plchrstr	*pcp;
	struct mchrstr	*mcp;
	int	off=0;

	getplane(p,&plane);
	getship(s,&ship);

	pcp = &plchr[plane.pln_type];
	mcp = &mchr[ship.shp_type];

#ifdef SHIPCHOPPERS
	if (pcp->pl_flags & P_K)
		if (mcp->m_flags & M_CHOPPER)
			return 1;
#endif /* SHIPCHOPPERS */

#ifdef XLIGHT
	if (pcp->pl_flags & P_E)
		if (mcp->m_flags & M_XLIGHT)
			return 1;
#endif /* XLIGHT */

	if (pcp->pl_flags & P_L)
		if (mcp->m_flags & M_FLY)
			return 1;

	return 0;
}

#ifdef SWEEP_PLANES
plane_sweep(plane_list,x,y,head)
struct  qelem *plane_list;
int	x,y;
struct	shiplook *head;
{
	struct	plnstr	*pp;
	struct	plchrstr *pcp;
	struct  qelem   *qp;
	struct  qelem   *next;
	struct  plist   *ip;
	struct  sctstr  sect;
	int	mines_there;

	getsect(x,y,&sect);
	mines_there = getvar(V_MINE, (char *)&sect, EF_SECTOR);

	if (mines_there == 0)
		return;

	if ((sect.sct_type != SCT_WATER) && (sect.sct_type != SCT_HARBR))
		return;

        for (qp = plane_list->q_forw; qp != plane_list; qp = next) {
                next = qp->q_forw;
                ip = (struct plist *) qp;
                pp = &ip->plane;
                pcp = ip->pcp;
		if (!(pcp->pl_flags & P_SWEEP)) /* if it isn't an sweep plane */
			continue;

		if (chance( ((double) (100-pcp->pl_acc))/100.0 )){
			pr(fmt("Sweep\n"));
			mines_there--;
		}
	}

	putvar(V_MINE, mines_there, (char *)&sect, EF_SECTOR);
	putsect(&sect);
}
#endif /* SWEEP_PLANES */

count_planes(s)
        int s;
{
        struct  shpstr ship;
        struct  nstr_item ni;
        struct  plnstr plane;
        struct  plchrstr *pcp;
        struct  mchrstr *mcp;

        getship(s, &ship);
        if (ship.shp_effic < 20)
                return;

        mcp = &mchr[ship.shp_type];
        ship.shp_nplane=0;
#ifdef SHIPCHOPPERS
        ship.shp_nchoppers=0;
#endif /* SHIPCHOPPERS */
#ifdef XLIGHT
        ship.shp_nxlight=0;
#endif /* XLIGHT */
        snxtitem_all(&ni, EF_PLANE);
        while (nxtitem(&ni, (char *)&plane)){
                if (plane.pln_ship == s){
                        pcp = &plchr[plane.pln_type];
#ifdef SHIPCHOPPERS
                        if ((pcp->pl_flags & P_K) &&
				(ship.shp_nchoppers < mcp->m_nchoppers))
                                ship.shp_nchoppers++;
			else
#endif /* SHIPCHOPPERS */
#ifdef XLIGHT
                        if ((pcp->pl_flags & P_E) &&
				(ship.shp_nxlight < mcp->m_nxlight))
                                ship.shp_nxlight++;
			else
#endif /* XLIGHT */
                        if ((pcp->pl_flags & P_L) || (pcp->pl_flags & P_M))
                                ship.shp_nplane++;
                }
        }

        putship(s,&ship);
}
