#ifndef lint
static char *RCSid = "$Header: /sequent2/empire/EMP/empmain/COMS/RCS/para.c,v 1.7 89/08/17 22:11:25 jeffw Exp $";
#endif

/*
 * para.c
 *
 * Drop paratroops onto a sector
 *
 * 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"
#include "treaty.h"

static	paradrop();

para()
{
	extern	char *argp[];
	char	*p;
	int	mission_flags;
	int	tech;
	coord	tx, ty;
	coord	ax, ay;
	int	ap_to_target;
	char	flightpath[256];
	struct	nstr_item ni_bomb;
	struct	nstr_item ni_esc;
	coord	x, y;
	struct	sctstr target;
	struct	qelem bomb_list;
	struct	qelem esc_list;
	int	wantflags;
	struct	sctstr ap_sect;
#ifdef SLOW_WAR
	int	rel;
	struct natstr	*natp;
#endif /* SLOW_WAR */

#ifdef PARAFLAG
	wantflags = P_P;
#else
	wantflags = 0;
#endif /* PARAFLAG */
	if (!snxtitem(&ni_bomb, EF_PLANE, argp[1]))
		return RET_SYN;
	if (!snxtitem(&ni_esc, EF_PLANE, argp[2]))
		pr("No escorts...\n");
	if ((p = getstarg(argp[3], "assembly point? ")) == 0 || *p == 0)
		return RET_SYN;
	if (!sarg_xy(p, &x, &y) || !getsect(x, y, &ap_sect))
		return RET_SYN;
	if (ap_sect.sct_own && ap_sect.sct_own != cnum) {
		pr("Assembly point not owned by you!\n");
		return RET_SYN;
	}
	ax = x;
	ay = y;
	if ((p = getpath(argp[4], ax, ay, 0, 0, 0)) == 0 || *p == 0)
		return RET_SYN;
	(void)strcpy(flightpath, p);
	tx = ax;
	ty = ay;
	(void) pathtoxy(flightpath, &tx, &ty, fcost);
	getsect(tx, ty, &target);
	if (target.sct_own == cnum) {
		/* we *could* just drop them off .. */
		pr(fmt("You already own %s\n", xyas(tx, ty, cnum)));
		return RET_SYN;
	}
	pr(fmt("LZ is %s\n", xyas(tx, ty, cnum)));
	ap_to_target = strlen(flightpath);
	if (*(flightpath+strlen(flightpath)-1) == 'h')
		ap_to_target--;
	pr(fmt("range to target is %d\n", ap_to_target));
	/*
	 * select planes within range
	 */
	pln_sel(&ni_bomb, &bomb_list, &ap_sect, ap_to_target,
		2, P_C|wantflags, P_M|P_O);
	pln_sel(&ni_esc, &esc_list, &ap_sect, ap_to_target,
		2, P_ESC|P_F, P_M|P_O);
	/*
	 * now arm and equip the bombers, transports, whatever.
	 * tech is stored in high 16 bits of mission_flags.
	 * yuck.
	 */
	tech=0;
	mission_flags |= P_X;		/* stealth (shhh) */
#ifdef CHOPPER_STEALTH
	mission_flags |= P_H; /* gets turned off if not all choppers */
#endif /* CHOPPER_STEALTH */
	mission_flags = pln_arm(&bomb_list, 'a', &ichr[I_MILIT],
		0, mission_flags,&tech);
	if (QEMPTY(&bomb_list)) {
		pr("No planes could be equipped for the mission.\n");
		return RET_FAIL;
	}
	mission_flags = pln_arm(&esc_list, 'a', &ichr[I_MILIT],
		P_ESC|P_F, mission_flags,&tech);
	ac_encounter(&bomb_list, &esc_list, ax, ay, flightpath, mission_flags,&tech);
#ifdef SLOW_WAR
	natp = getnatp(cnum);
	rel = getrel(natp,target.sct_own);
	if ((rel != AT_WAR) && (target.sct_own) && (target.sct_oldown != cnum)){
		pr("You're not at war with them!\n");
		return RET_FAIL;
	}
#endif /* SLOW_WAR */
	if (QEMPTY(&bomb_list)) {
		pr(fmt("No planes got through fighter defenses\n"));
	} else {
		getsect(tx, ty, &target);
		if (target.sct_own && !trechk(cnum, target.sct_own, LANATT)) {
			pln_put(&bomb_list);
			pln_put(&esc_list);
			return RET_OK;
		}
		paradrop(&bomb_list, &target);
		putsect(&target);
	}
	pln_put(&bomb_list);
	pln_put(&esc_list);
	return RET_OK;
}

static
paradrop(list, target)
	struct	qelem *list;
	struct	sctstr *target;
{
	extern	int btused;
	register struct plist *plp;
	int	a_mil;
	int	a_cas;
	int	d_mil;
	int	d_cas;
	int	success;
	double	odds;
	double	shuffle;
	struct	qelem *qp;
	double	d_bonus;

	d_mil = getvar(V_MILIT, (char *)target, EF_SECTOR);
	a_mil = 0;
	a_cas = 0;
	d_cas = 0;
	success = 0;
	for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
		plp = (struct plist *) qp;
		if (plp->pcp->pl_flags & (P_V|P_C))
			a_mil += plp->misc;
	}
	switch (target->sct_type) {
	case SCT_MOUNT:
	case SCT_WATER:
	case SCT_CAPIT:
	case SCT_FORTR:
	case SCT_WASTE:
		a_cas = a_mil;
		goto fail;
	default:
		d_bonus = dchr[target->sct_type].d_dstr *
			target->sct_effic / 100.0;
		if (d_bonus < 2.0)
			d_bonus = 2.0;
		break;
	}
	if (a_mil <= 0)
		odds = 0.0;
	else if (d_mil <= 0)
		odds = 1.0;
	else
		odds = a_mil / (d_bonus * (d_mil + a_mil));
	if (d_mil == 0 && a_mil > 0)  {
		pr("There are no defenders\n");
		success++; 
	} else
		pr(fmt("Your odds are %.2f%%\n", 100*odds));
	while (!success && a_mil > 0 && d_mil > 0) {
		if (chance(odds)) {
			pr("!");
			d_cas++;
			d_mil--;
			if (d_mil <= 0)
				success++;
		} else {
			pr("@");
			a_mil--;
			a_cas++;
		}
	}
fail:
	if (target->sct_own)
		wu(0, target->sct_own,
			fmt("Country #%d lost %d air-assaulting %ssector %s",
			cnum, a_cas, success ? "(and taking) " : "",
			xyas(target->sct_x, target->sct_y, target->sct_own)));
	if (success) {
		pr(fmt("You have taken sector %s\n",
			xyas(target->sct_x, target->sct_y, cnum)));
		nreport(cnum, N_WON_SECT, target->sct_own, 1);
		if (target->sct_type == SCT_CAPIT)
			caploss(target, target->sct_own,
				"which is also %s's capital!\n");
		a_mil = takeover(target, a_mil);
		target->sct_mobil = 0;
		putvar(V_MILIT, a_mil, (char *)target, EF_SECTOR);
	} else {
		pr("You have been defeated!\n");
		nreport(cnum, N_SCT_LOSE, target->sct_own, 1);
		putvar(V_MILIT, d_mil, (char *)target, EF_SECTOR);
	}
	if (a_cas > 0 || d_cas > 0) {
		pr(fmt("Casualties :\nYours... %d\n", a_cas));
		pr(fmt("Theirs.. %d\n", d_cas));
		shuffle = 2 * (a_cas + d_cas) * 0.15;
		pr(fmt("Papershuffling ... %.1f B.T.U\n", shuffle));
		NAT_DELTA(nat_btu, cnum, -roundavg(shuffle));
	}
}
