#ifndef lint
static char *RCSid = "$Header: /sequent2/empire/EMP/lib/common/RCS/damage.c,v 1.3 89/09/17 22:31:18 mr-frog Exp $";
#endif

/*
 * damage.c
 *
 * damage a sector, ship, or plane.
 *
 * Should probably do this in some regular fashion, but
 * we don't yet have a list of fields we can iterate through
 * and find the "damageable" ones.
 *
 * Dave Pare, 1989
 */

#include "misc.h"
#include "var.h"
#include "sect.h"
#include "ship.h"
#include "plane.h"
#include "nuke.h"
#ifdef EASY_BRIDGES
#include "file.h"
#endif /* EASY_BRIDGES */

sectdamage(sp, dam)
	register struct sctstr *sp;
	int	dam;
{
#ifdef EASY_BRIDGES
        register struct plnstr *pp;
        struct  plnstr p;
        int     n,old=sp->sct_own;
        int     mines;
#endif /* EASY_BRIDGES */
	if (dam <= 0)
		return;
	if (dam > 100)
		dam = 100;
	sp->sct_effic = damage((int)sp->sct_effic, dam);
	sp->sct_mobil = damage((int)sp->sct_mobil, dam);
	sp->sct_nv = vl_damage(dam, sp->sct_vtype, sp->sct_vamt,
		(int)sp->sct_nv);
#ifndef EASY_BRIDGES
	if (sp->sct_effic < 20 && sp->sct_type == SCT_BHEAD)
		bridgefall(sp);
#else
	if (sp->sct_effic < 20 && sp->sct_type == SCT_BSPAN){
		wu(0, sp->sct_own, fmt("Crumble... SCREEEECH!  Splash! Bridge falls at %s!\n",
                                xyas(sp->sct_x, sp->sct_y, sp->sct_own)));
		sp->sct_type = SCT_WATER;
		sp->sct_newtype = SCT_WATER;
		sp->sct_own = 0;
		sp->sct_oldown = 0;
		pp = &p;
		for (n=0; ef_read(EF_PLANE, n, pp); n++) {
			if(pp->pln_x != sp->sct_x || pp->pln_y != sp->sct_y)
				continue;
			wu(0, old, fmt("     \07AARGH! Plane #%d tumbles to its doom!\n", pp->pln_uid));
			pp->pln_own = 0;
			putplane(n, pp);
		}
		/*
		 * save only the mines; zero the rest of the
		 * commodities.
		 */
		mines = getvar(V_MINE, (caddr_t)sp, EF_SECTOR);
		sp->sct_nv = 0;
		if (mines > 0)
			(void) putvar(V_MINE, mines, (caddr_t)sp, EF_SECTOR);
		(void) putsect(sp);
	}
#endif /* EASY_BRIDGES */
}

shipdamage(sp, dam)
	struct	shpstr *sp;
	int	dam;
{
	if (dam <= 0)
		return;
	if (dam > 100)
		dam = 100;
	sp->shp_effic = damage((int)sp->shp_effic, dam);
	if (sp->shp_mobil > 0)
		sp->shp_mobil = damage((int)sp->shp_mobil, dam);
#ifdef FUEL
	if (sp->shp_fuel > 0)
		sp->shp_fuel = damage((int)sp->shp_fuel, dam);
#endif /* FUEL */
	sp->shp_nv = vl_damage(dam, sp->shp_vtype, sp->shp_vamt,
		(int) sp->shp_nv);
}

planedamage(pp, dam)
	struct	plnstr *pp;
	int	dam;
{
	if (dam <= 0)
		return;
	if (dam > 100)
		dam = 100;
	pp->pln_effic = damage((int)pp->pln_effic, dam);
	if (pp->pln_mobil > 0)
		pp->pln_mobil = damage((int)pp->pln_mobil, dam);
}

/*
 * nukedamage() actually just calculates damage
 * rather than inflicting it.
 */
int
nukedamage(ncp, range, airburst)
	struct	nchrstr *ncp;
	int	range;
	int	airburst;
{
	int	dam;
	int	rad;

	rad = ncp->n_blast;
	if (airburst)
		rad = (int) (rad * 1.5);
	if (rad < range)
		return 0;
	if (airburst) {
		/* larger area, less center damage */
		dam = (int) ((ncp->n_dam * 0.75) - (range * 20));
	} else {
		/* smaller area, more center damage */
		dam = (int) (ncp->n_dam / (range + 1.0));
	}
	if (dam < 5)
		dam = 0;
	return dam;
}

int
damage(amt, pct)
	register int amt;
	int	pct;
{
	register int tmp;
	register int lost;

	if (amt <= 0)
		return 0;
	tmp = amt * pct;
	lost = tmp / 100;
	if ((random() % 100) < (tmp % 100))
		lost++;
	return amt - lost;
}
