#ifndef lint
static char *RCSid = "$Header: /sequent2/empire/EMP/empmain/SUBS/RCS/fortdef.c,v 1.8 89/09/02 01:59:58 mr-frog Exp $";
#endif

/*
 * fortdef.c
 *
 * fort defends an area
 *
 * from PSL Empire, 1985
 */

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

/*
 * See if the sector being fired at will defend itself.
 */
int
fortdef(sp, ac, tx, ty)
	struct	sctstr *sp;
	int	ac;
	coord	tx;
	coord	ty;
{
	return shootback(sp, ac, tx, ty);
}

/*
 * See if any nearby ships will open up on the attacker
 * Return damage done to attacker, if any.
 * Subtracts shells used for firing.  Responding ships
 * require military, shells, and guns.
 */
int
shipdef(own, armor, x, y)
	natid	own;
	int	armor;
	coord	x;
	coord	y;
{
	int	nshot;
	double	range;
	double	eff;
	struct	shpstr ship;
	struct	nstr_item ni;
	int	vec[I_MAX+1];
	int	dam;

	if (own == 0)
		return 0;
	eff = 1.0;
	snxtitem_dist(&ni, EF_SHIP, x, y, 7);
	while (nxtitem(&ni, (caddr_t)&ship) && eff > 0.30) {
		if (ship.shp_own != own)
			continue;
		if (ship.shp_effic < 60)
			continue;
		range = techfact(ship.shp_tech, 
			mchr[ship.shp_type].m_frnge * ship.shp_effic / 200.0);
		if (range < ni.curdist)
			continue;
		/* must have gun, shell, and milit to fire */
		if (getvec(VT_ITEM, vec, (caddr_t)&ship, EF_SHIP) < 3)
			continue;
		nshot = min(min(vec[I_GUN], vec[I_SHELL]), vec[I_MILIT]);
		nshot = min(nshot, mchr[ship.shp_type].m_glim);
		if (nshot == 0)
			continue;
		(void) putvar(V_SHELL, vec[I_SHELL] - nshot,
			(caddr_t)&ship, EF_SHIP);
		putship(ship.shp_uid, &ship);
		nreport(own, N_FIRE_BACK, cnum, 1);
		dam = shelldam(seagun(ship.shp_type, ship.shp_effic, nshot),
			armor);
		eff *= (1.0 - (0.01 * dam));
		pr(fmt("\07Incoming shell%s %d%% damage!\n",
			nshot == 1 ? " does" : "s do", dam));
#ifdef MERC
		if(own != 0)
#endif
		wu(0, own, fmt("Ship #%d fired on %s at %s", ni.cur,
			cname(cnum), xyas(x, y, own)));
	}
	return (int) 100 - (eff * 100);
}

/*
 * Determine if any nearby gun-equipped sectors are within
 * range and able to fire at an attacker.  Firing sectors
 * need to have guns, shells, and military.  Sector being
 * attacked is x,y -- attacker is at ax,ay.
 */
int
defdef(def_own, defval, ax, ay)
	natid	def_own;
	int	defval;
	coord	ax;
	coord	ay;
{
	int	dam;
	double	tech;
	int	range;
	struct	sctstr firing;
	struct	nstr_sect ns;
	int	vec[I_MAX+1];

	tech = tfact(def_own, 1.0);
	dam = 0;
	snxtsct_dist(&ns, ax, ay, (int) (tech * 7.0));
	while (nxtsct(&ns, &firing) && dam < 80) {
		if (firing.sct_own != def_own)
			continue;
		if (getvec(VT_ITEM, vec, (caddr_t)&firing, EF_SECTOR) < 0)
			continue;
		if (vec[I_GUN] == 0 || vec[I_MILIT] < 5 || vec[I_SHELL] == 0)
			continue;
		range = tech * min(vec[I_GUN], 7);
		if (range < ns.curdist)
			continue;
		/* XXX defdef damage is additive, but ship damage isn't */
		dam += shootback(&firing, defval, ax, ay);
	}
	return dam;
}

int
shootback(sp, ac, tx, ty)
	struct	sctstr *sp;
	int	ac;
	coord	tx;
	coord	ty;
{
	register int damage;
	natid	own;
	int	shell;
	float	range;
	int	range2;

	if (sp->sct_type != SCT_FORTR) {
		/* XXX I don't like this restriction */
		return 0;
	}
	own = sp->sct_own;
	range = tfact(own, (double)
		min(getvar(V_GUN, (caddr_t)sp, EF_SECTOR), 7));
	range2 = mapdist((int)sp->sct_x, (int)sp->sct_y, tx, ty);
	if ((shell = getvar(V_SHELL, (caddr_t)sp, EF_SECTOR)) <= 0)
		return 0;
	if (range < range2)
		return 0;
	putvar(V_SHELL, shell - 1, (caddr_t)sp, EF_SECTOR);
	putsect(sp);
	nreport(sp->sct_own, N_FIRE_BACK, cnum, 1);
	damage = shelldam(landgun((int)sp->sct_effic), ac);
	pr(fmt("Incoming shell! %d%% damage done.\007\n", damage));
	return damage;
}
