#ifndef lint
static char *RCSid = "$Header: spy.c,v 1.12 90/03/19 11:09:03 mr-frog Exp $";
#endif

/*
 * spy.c
 *
 * spy on your neighbors
 *
 * from PSL Empire, 1985
 * and Dave Pare, 1986
 */

#include "misc.h"
#include "var.h"
#include "sect.h"
#include "item.h"
#include "nat.h"
#include "xy.h"
#include "nsc.h"
#include "nuke.h"
#include "news.h"
#include "deity.h"
#include "path.h"
#include "file.h"


/*
 * format:  spy <SECTS>
 *
 */
static int nsects;
static int spyline();
static int insert();
static int check();

spy()
{
	extern	char *argp[];
	int     caught;
	natid	own;
	int     relat;
	coord	x, y;
	coord	nx, ny;
	int     military;
	int     savemil;
	int     btucost;
	int     i;
	coord   *table;		    /* sectors already seen */
	int	t_len = 0;
	int	vec[I_MAX+1];
	int	dvec[I_MAX+1];
	struct nstr_sect nstr;
	struct natstr *natp;
	struct sctstr from;
	struct sctstr dsect;

	/*
	 * first arg should be the range of sectors
	 */
	if (!snxtsct(&nstr, argp[1]))
		return RET_SYN;
	nsects = (nstr.range.width+1) * nstr.range.height / 2;
	btucost = (nsects / 40) + 1;
	natp = getnatp(cnum);
	if (natp->nat_btu < btucost) {
		pr("You don't have the BTU's for spying on that scale!\n");
		return RET_FAIL;
	}
	/*
	 * set up all the goodies we need later
	 * 6 = neighbors, 2 = x,y
	 */
	table = (coord *) malloc((nsects + 1) * 6 * 2 * sizeof(coord));
	bzero((char *)table, (nsects + 1) * 6 * 2 * sizeof(coord));
	pr("SPY report\n");
	prdate();
	pr("   sect   type own  eff  civ  mil  shl  gun  iron  pet  food\n");
	while (nxtsct(&nstr, &from)) {
		if (!owner && !god)
			continue;
		getvec(VT_ITEM, vec, (char *) &from, EF_SECTOR);
		if ((military = vec[I_MILIT]) == 0)
			continue;
		x = from.sct_x;
		y = from.sct_y;
		savemil = military;
		/*
		 * check the neighboring sectors.
		 */
		for (i = 1; i <= 6; i++) {
			if (military == 0)
				break;
			nx = x + diroff[i][0];
			ny = y + diroff[i][1];
			/*
			 * if we've already seen the
			 * sector, don't bother checking it
			 * out.
			 */
			if (check(table, &t_len, nx, ny)) {
				continue;
			}
			getsect(nx, ny, &dsect);
			getvec(VT_ITEM, dvec, (char *) &dsect, EF_SECTOR);
			if (owner || (!dvec[I_MILIT] && !dvec[I_CIVIL])) {
				/* mark sector as seen */
				insert(table, &t_len, nx, ny);
				continue;
			}
			/* catch spy N/200 chance, N = # military */
			caught = chance((double) dvec[I_MILIT] / 200.0);
			own = dsect.sct_own;
			/* determine spyee relations with spyer */
			relat = getrel(getnatp(own), cnum);
			if (relat == NEUTRAL && caught) {
				/* neutral spy-ee */
				pr(fmt("Spy deported from %s\n", 
					xyas(nx, ny, cnum)));
#ifdef MERC
				if(own != 0)
#endif
				wu(0, own, fmt("%s (#%d) spy deported from %s",
					cname(cnum), cnum, xyas(nx, ny, own)));
#ifdef SLOW_WAR
			} else if ((relat == AT_WAR || relat == HOSTILE
					|| relat == MOBILIZATION
					|| relat == SITZKRIEG)
#else
			} else if ((relat == AT_WAR || relat == HOSTILE)
#endif /* SLOW_WAR */
				   && caught) {
				/* at-war with spy-ee */
				pr(fmt("BANG!! A spy was shot in %s\n",
				       xyas(nx, ny, cnum)));
				military--;
#ifdef MERC
				if(own != 0)
#endif
				wu(0, own, fmt("%s (#%d) spy caught in %s",
					cname(cnum), cnum, xyas(nx, ny, own)));
				nreport(cnum, N_SPY_SHOT, own, 1);
			} else {
				insert(table, &t_len, nx, ny);
				spyline(&dsect);
#if	defined(BMAP) || defined(AUTONAV)
				setbigmap(dsect.sct_x, dsect.sct_y,
					dchr[dsect.sct_type].d_mnem);
#endif
			}
		}
#if	defined(BMAP) || defined(AUTONAV)
		writebigmap();
#endif
		/* subtract any military if necessary */
		if (savemil != military) {
			vec[I_MILIT] = military;
			putvec (VT_ITEM, vec, (char *) &from, EF_SECTOR);
			putsect(&from);
		}
	}
	NAT_DELTA(nat_btu, cnum, -btucost);
	free((char *)table);
	return RET_OK;
}


/*
 * just a big printf.
 */
static
spyline(sp)
	struct sctstr *sp;
{
	char   *fmt();
	int vec[I_MAX+1];

	getvec(VT_ITEM, vec, (char *) sp, EF_SECTOR);
	pr(xyfmt("%4d,%-4d",sp->sct_x, sp->sct_y, cnum));
	pr(fmt("   %c  %3d  %3d %4d  %3d  %3d  %3d   %3d  %3d  %4d\n",
	       dchr[sp->sct_type].d_mnem, sp->sct_own,
	       round((int)sp->sct_effic, 10),
	       round(vec[I_CIVIL], 10), round(vec[I_MILIT], 10),
	       round(vec[I_SHELL], 10), round(vec[I_GUN], 10),
	       round(vec[I_IRON], 10), round(vec[I_PETROL], 10),
	       round(vec[I_FOOD], 10)));
}


/*
 * insert a key into the table.
 */
static
insert(table, len, x, y)
	coord  *table;
	int    *len;
	coord     x;
	coord     y;
{
	if (!check(table, len, x, y)) {
	   table[(*len)++] = x;
	   table[(*len)++] = y;
	}
}
/*
 * see if a key is in the bitmask table
 */
static int
check(table, len, x, y)
	coord    *table;
	int    *len;
	coord     x;
	coord     y;
{
	int     i;

	for (i = 0; i < *len; i += 2)
	   if (table[i] == x && table[i + 1] == y)
	      return 1;
	return 0;
}
