#ifndef lint
static char *RCSid = "$Header: /sequent2/empire/EMP/empmain/SUBS/RCS/detonate.c,v 1.6 89/08/18 17:04:51 jeffw Exp $";
#endif

/*
 * detonate.c
 *
 * detonate a nuclear device in a sector
 *
 * from PSL Empire, 1985
 */

#include "misc.h"
#include "xy.h"
#include "nat.h"
#include "file.h"
#include "sect.h"
#include "nuke.h"
#include "ship.h"
#include "news.h"
#include "plane.h"
#include "nsc.h"
#ifdef	FALLOUT
#include "var.h"
#endif	FALLOUT

detonate(nuketype, x, y, airburst, bombown)
	int	nuketype;
	int	x;
	int	y;
	int	airburst;
	natid	bombown;
{
	struct	nchrstr *ncp;
	struct	plnstr plane;
	struct	sctstr sect;
	struct	shpstr ship;
	struct	nukstr nuke;
	char	*bp;
	char	buf[128];
	natid	own;
	int	type;
	int	damage;
#ifdef	FALLOUT
	int	fallout;
#endif	FALLOUT
	int	rad;
	struct	nstr_sect ns;
	struct	nstr_item ni;
#ifdef DAVYJONES
	int	issea=0;
#endif /* DAVYJONES */

#ifndef	CONVASAT
	if (airburst == 2) {
		detonate_orbit(nuketype, x, y, bombown);
		return;
	}
#endif	CONVASAT
#ifdef DAVYJONES
	getsect(x,y,&sect);
	if (sect.sct_type == SCT_WATER)
		issea=1;
#endif /* DAVYJONES */
	ncp = &nchr[nuketype];
	kaboom(x, y, ncp->n_blast, bombown);
	rad = ncp->n_blast;
	if (!airburst)
		rad = rad * 2 / 3;
	snxtsct_dist(&ns, x, y, rad);
	while (nxtsct(&ns, &sect)) {
#ifdef DAVYJONES
		/* Nukes falling on water affect only 1 sector */
		if ((sect.sct_x != x) && issea)
			continue;
		if ((sect.sct_y != y) && issea)
			continue;
#endif /* DAVYJONES */
#ifdef BABY_NUKES
		if (sect.sct_x != x)
			continue;
		if (sect.sct_y != y)
			continue;
#endif /* BABY_NUKES */
		own = sect.sct_own;
		type = sect.sct_type;
		if ((damage = nukedamage(ncp, ns.curdist, airburst)) <= 0)
			continue;
		if (type == SCT_SANCT) {
			pr(fmt("bounced off %s\n", xyas(ns.x, ns.y, cnum)));
#ifdef MERC
			if(own != 0)
#endif
			wu(0, own, fmt("%s nuclear device bounced off %s",
				cname(bombown), xyas(ns.x, ns.y, cnum)));
			nreport(bombown, N_NUKE, own, 1);
			continue;
		}
#ifdef	FALLOUT
#ifdef	NEUTRON
		if (ncp->n_flags & N_NEUT)
			fallout = damage*50;
		else
#else
		fallout = damage*5;
#endif	NEUTRON
		fallout += getvar(V_FALLOUT,&sect,EF_SECTOR);
		putvar(V_FALLOUT,fallout,&sect,EF_SECTOR);
#endif	FALLOUT
		sectdamage(&sect, damage);
		if (damage > 100) {
			sect.sct_oldown = 0;
			sect.sct_own = 0;
			if (type == SCT_WATER || type == SCT_BSPAN) {
				bp = "left nothing but water in %s\n";
				if (type != SCT_WATER) {
					sect.sct_newtype = SCT_WATER;
					sect.sct_type = SCT_WATER;
				}
			} else {
#ifndef	FALLOUT
				sect.sct_newtype = SCT_WASTE;
				sect.sct_type = SCT_WASTE;
#endif	FALLOUT
				bp = "turned %s into a radioactive wasteland\n";
			}
		} else {
			bp = buf;
			copy(fmt("did %d%%%% damage in %%s\n", damage), bp);
		}
		if (type == SCT_CAPIT && damage >= 100)
			caploss(&sect, own, "\n%s lost its capital!\n\n");
		(void) putsect(&sect);
		if (type != SCT_WATER)
			nreport(bombown, N_NUKE, own, 1);
		pr(fmt(bp, xyas(ns.x, ns.y, cnum)));
		if (own != cnum && own != 0) {
			(void) copy(fmt(bp, xyas(ns.x, ns.y, own)), buf);
#ifdef MERC
			if(own != 0)
#endif
			wu(0, own, fmt("%s nuclear device %s",
				cname(bombown), buf));
		}
	}
	snxtitem_dist(&ni, EF_SHIP, x, y, rad);
	while (nxtitem(&ni, (caddr_t)&ship)) {
#ifdef DAVYJONES
		/* Nukes falling on water affect only 1 sector */
		if ((ship.shp_x != x) && issea)
			continue;
		if ((ship.shp_y != y) && issea)
			continue;
#endif /* DAVYJONES */
#ifdef BABY_NUKES
		if (ship.shp_x != x)
			continue;
		if (ship.shp_y != y)
			continue;
#endif /* BABY_NUKES */
		if ((own = ship.shp_own) == 0)
			continue;
		if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0)
			continue;
#ifdef	NONUKESUB
		{
			struct sctstr	sect1;
			struct sctstr	sect2;

			if (mchr[ship.shp_type].m_flags & M_SUB) {
				getsect(ship.shp_x,ship.shp_y,&sect1);
				getsect(x,y,&sect2);

				if ((sect1.sct_type != SCT_HARBR) &&
				    (sect2.sct_type != SCT_WATER)) {
					continue;
				}
			}
		}
#endif	NONUKESUB
		if (own == cnum) {
			shipdamage(&ship, damage);
#ifdef	SHIPNAMES
			pr(fmt("%s %s(#%d) at %s reports %d%% damage\n",
				mchr[ship.shp_type].m_name, ship.shp_name,
				ni.cur,
#else
			pr(fmt("%s #%d at %s reports %d%% damage\n",
				mchr[ship.shp_type].m_name, ni.cur,
#endif	SHIPNAMES
				xyas(ship.shp_x, ship.shp_y, own), damage));
		} else {
			check_retreat_and_do_shipdamage(&ship, damage);
#ifdef MERC
	if(own != 0)
#endif
#ifdef	SHIPNAMES
	wu(0, own, fmt("%s nuclear device did %d%% damage to %s %s(#%d) at %s",
#else
	wu(0, own, fmt("%s nuclear device did %d%% damage to %s #%d at %s",
#endif	SHIPNAMES
				cname(bombown), damage,
#ifdef	SHIPNAMES
				mchr[ship.shp_type].m_name, ship.shp_name,
				ni.cur,
#else
				mchr[ship.shp_type].m_name, ni.cur,
#endif	SHIPNAMES
				xyas(ship.shp_x, ship.shp_y, own)));
		}
		putship(ni.cur, &ship);
	}
	snxtitem_dist(&ni, EF_PLANE, x, y, rad);
	while (nxtitem(&ni, (caddr_t)&plane)) {
#ifdef DAVYJONES
		/* Nukes falling on water affect only 1 sector */
		if ((plane.pln_x != x) && issea)
			continue;
		if ((plane.pln_y != y) && issea)
			continue;
#endif /* DAVYJONES */
#ifdef BABY_NUKES
		if (plane.pln_x != x)
			continue;
		if (plane.pln_y != y)
			continue;
#endif /* BABY_NUKES */
		if ((own = plane.pln_own) == 0)
			continue;
		if ((plane.pln_flags & PLN_LAUNCHED) && (airburst != 2))
			continue;
		damage = nukedamage(ncp,ni.curdist,airburst) - plane.pln_harden;
		if (damage <= 0)
			continue;
#ifdef	NONUKESUB
		if(plane.pln_ship >= 0) {
			struct sctstr	sect1;
			struct sctstr	sect2;

			getship(plane.pln_ship, &ship);
			if (mchr[ship.shp_type].m_flags & M_SUB) {
				getsect(ship.shp_x,ship.shp_y,&sect1);
				getsect(x,y,&sect2);

				if ((sect1.sct_type != SCT_HARBR) &&
				    (sect2.sct_type != SCT_WATER)) {
					continue;
				}
			}
		}
#endif	NONUKESUB
		planedamage(&plane, damage);
		if (own == cnum) {
			pr(fmt("%s #%d at %s reports %d%% damage\n",
				plchr[plane.pln_type].pl_name, ni.cur,
				xyas(plane.pln_x, plane.pln_y, own),
				damage));
		} else {
#ifdef MERC
			if(own != 0)
#endif
			wu(0, own,
		    fmt("%s nuclear device did %d%% damage to %s #%d at %s",
				cname(bombown), damage,
				plchr[plane.pln_type].pl_name, ni.cur,
				xyas(plane.pln_x, plane.pln_y, own)));
		}
		putplane(ni.cur, &plane);
	}
	snxtitem_dist(&ni, EF_NUKE, x, y, rad);
	while (nxtitem(&ni, (caddr_t)&nuke)) {
#ifdef DAVYJONES
		/* Nukes falling on water affect only 1 sector */
		if ((nuke.nuk_x != x) && issea)
			continue;
		if ((nuke.nuk_y != y) && issea)
			continue;
#endif /* DAVYJONES */
#ifdef BABY_NUKES
		if (nuke.nuk_x != x)
			continue;
		if (nuke.nuk_y != y)
			continue;
#endif /* BABY_NUKES */
		if ((own = nuke.nuk_own) == 0)
			continue;
		if ((damage = nukedamage(ncp, ni.curdist, airburst)) <= 0)
			continue;
		if (roll(100) >= damage)
			continue;
		nuke.nuk_own = 0;
		if (own == cnum) {
			pr(fmt("nuclear stockpile #%d at %s destroyed\n",
				ni.cur, xyas(nuke.nuk_x, nuke.nuk_y, own)));
		} else {
#ifdef MERC
			if(own != 0)
#endif
			wu(0, own, fmt("nuclear stockpile #%d at %s destroyed",
				ni.cur, xyas(nuke.nuk_x, nuke.nuk_y, own)));
		}
		putnuke(ni.cur, &nuke);
	}
}

#ifndef	CONVASAT
detonate_orbit(nuketype, x, y, bombown)
	int	nuketype;
	int	x;
	int	y;
	natid	bombown;
{
	struct	nchrstr *ncp;
	struct	plnstr plane;
	struct	nstr_item ni;
	natid	own;
	int	damage;
	int	rad;

	ncp = &nchr[nuketype];
	kaboom(x, y, ncp->n_blast, bombown);
	rad = ncp->n_blast;
	snxtitem_dist(&ni, EF_PLANE, x, y, rad);
	while (nxtitem(&ni, (caddr_t)&plane)) {
		if ((own = plane.pln_own) == 0)
			continue;
		if ((plane.pln_flags&PLN_LAUNCHED) == 0)
			continue;
		if ((damage = nukedamage(ncp, ni.curdist, 1)) <= 0)
			continue;
		planedamage(&plane, damage);
		if (cnum == own) {
			pr(fmt("%s #%d over %s reports %d%% damage\n",
				plchr[plane.pln_type].pl_name, ni.cur,
				xyas(plane.pln_x, plane.pln_y, own),
				damage));
		} else {
#ifdef MERC
			if(own != 0)
#endif
			wu(0, own,
		    fmt("%s nuclear device did %d%% damage to %s #%d over %s",
				cname(bombown), damage,
				plchr[plane.pln_type].pl_name, ni.cur,
				xyas(plane.pln_x, plane.pln_y, own)));
		}
		nreport(bombown, N_SAT_KILL, own, 1);
		putplane(ni.cur, &plane);
	}
}
#endif	CONVASAT

/*
 * silly to be sure.
 */
kaboom(x, y, rad, cn)
	int	x;
	int	y;
	int	rad;
	natid	cn;
{
	pr("\n\nK A B ");
	while (rad-- > 0)
		pr("O O ");
	pr(fmt("M ! in %s\n\n", xyas(x, y, cn)));
}
