#ifndef lint
static char *RCSid = "$Header: /usr/brule/guest/empire/empire/emprcs/lib/commands/skyw.c,v 2.0 1995/08/04 06:23:01 empire Exp $";
#endif /* not lint */

/*
 * skyw.c
 *
 * look at satellites in the sky.
 *
 * Ken Stevens 1995
 */

#include "misc.h"
#include "player.h"
#include "var.h"
#include "sect.h"
#include "plane.h"
#include "nat.h"
#include "xy.h"
#include "nsc.h"
#include "file.h"

#define	TSIZE	200

struct sky {
	struct sky *s_next;
	int s_spotted;
	struct plnstr s_sat;
};

static	showsat();

/*
 * format: skywatch [<SECTS>]
 */
skyw()
{
	struct sctstr sect;
	struct nstr_sect nstr;
	struct sky *skyp;
	struct sky *list[TSIZE];
	int i, k, j, n;
	int vrange, see;
	int x, y;
	int mink, minj, maxk, maxj;
	int nsat = 0;
	float tech;
	struct	nstr_item ni;

	if (snxtsct(&nstr, player->argp[1]) == 0)
		return RET_SYN;
	for (i = 0; i < TSIZE; i++)
		list[i] = 0;
	skyp = (struct sky *)malloc(sizeof(*skyp));
	snxtitem_all(&ni, EF_PLANE);
	while (nxtitem(&ni, (s_char *) &skyp->s_sat)) {
		if (!skyp->s_sat.pln_own)
			continue;
		if (!(skyp->s_sat.pln_flags & PLN_LAUNCHED))
			continue;
		getsect(skyp->s_sat.pln_x, skyp->s_sat.pln_y, &sect);
		n = scthash(skyp->s_sat.pln_x, skyp->s_sat.pln_y, TSIZE);
		skyp->s_spotted = 0;
		skyp->s_next = list[n];
		list[n] = skyp;
		skyp = (struct sky *)malloc(sizeof(*skyp));
		nsat++;
	}
	/* get that last one! */
	free((s_char *)skyp);
	pr("- = [ Skywatch report for %s ] = -\n", cname(player->cnum));
	pr(" %18s%20s        %s\n","Country", "Satellite", "Location");
	tech = tfact(player->cnum, 1.0);
	while (nxtsct(&nstr, &sect) && nsat) {
		if (sect.sct_own != player->cnum)
			continue;
		see = sect.sct_type == SCT_RADAR ? 14 : 4;
		vrange = (int) (sect.sct_effic / 100.0 * see * tech);
		if (vrange < 1)
			vrange = 1;
		maxk = vrange;
		maxj = vrange * 2;
		vrange *= vrange;
		mink = -maxk;
		minj = -maxj;
		for (j = minj; j <= maxj && nsat; j++) {
			x = xnorm(sect.sct_x + j);
			for (k = mink; k <= maxk && nsat; k++) {
				if ((j + k) & 01)
					 continue;
				/* quick range check to save time... */
				if (vrange < (j * j + 3 * k * k) / 4)
					continue;
				y = ynorm(sect.sct_y + k);
				n = scthash(x, y, TSIZE);
				if (list[n] == 0)
					continue;
				nsat -= showsat(&list[n], x, y);
			}
		}
	}
	/* free up the sky structs calloc'ed above */
	for (i = 0; i < TSIZE; i++) {
		while (skyp = list[i]) {
			list[i] = skyp->s_next;
			free((s_char *)skyp);
		}
	}
	return RET_OK;
}

static
showsat(skypp, x, y)
	struct	sky **skypp;
	int	x;
	int	y;
{
	register struct sky *skyp;
	register struct sky *todelete = 0;
	register struct sky **prev;
	register struct plchrstr *pcp;
	s_char	*name;
	int	nsat = 0;

	prev = 0;
	skyp = *skypp;
	prev = skypp;
	do {
		/* we delete it, we free it. */
		if (todelete) {
			free((s_char *)todelete);
			todelete = 0;
		}
		if (skyp->s_sat.pln_x != x || skyp->s_sat.pln_y != y) {
			prev = &(*prev)->s_next;
			continue;
		}
		pcp = &plchr[skyp->s_sat.pln_type];
		name = pcp->pl_name;
		pr(" %12.12s (#%d) %20s            %s\n",
			cname(skyp->s_sat.pln_own), skyp->s_sat.pln_own,
			name, xyas(x, y, player->cnum));
#ifdef HIDDEN
		/* FOUND_COAST should probably be changed to FOUND_SKY -KHS */
                setcont(player->cnum, skyp->s_sat.pln_own, FOUND_COAST);
#endif /* HIDDEN */

		*prev = skyp->s_next;
		todelete = skyp;
		nsat++;
	} while (skyp = skyp->s_next);
	/* check that last one! */
	if (todelete)
		free((s_char *)todelete);
	return (nsat);
}
