#ifndef lint
static char *RCSid = "$Header: /usr/brule/guest/empire/empire/emprcs/lib/commands/look.c,v 2.5 1995/10/24 04:27:59 empire Exp $";
#endif /* not lint */

/*
 * look.c
 *
 * lookout from a ship or land unit
 *
 * from PSL Empire, 1985
 */

#include "misc.h"
#include "player.h"
#include "var.h"
#include "xy.h"
#include "sect.h"
#include "ship.h"
#include "land.h"
#include "plane.h"
#include "nsc.h"
#include "nat.h"
#include "path.h"
#include "file.h"
#include "edb.h"
#include <fcntl.h>

static	look_ship();

look()
{
	register int i;
	struct	nstr_item ni;
	struct	shpstr myship;
	struct	sctstr sect;
	int	x, y;
	int	civ;
	int	mil;
	u_char	bitmap[WORLD_X*WORLD_Y/8];
	int	changed = 0;

	if (!snxtitem(&ni, EF_SHIP, player->argp[1]))
		return RET_SYN;
	bzero((s_char *)bitmap, sizeof (bitmap));
	while (nxtitem(&ni, (s_char *)&myship)) {
		if (!player->owner)
			continue;
		look_ship(&myship);
		for (i = 0; i <= 6; i++) {
			x = diroff[i][0] + myship.shp_x;
			y = diroff[i][1] + myship.shp_y;
			if (getbit(x, y, bitmap))
				continue;
			setbit(x, y, bitmap);
			getsect(x, y, &sect);
			if (sect.sct_type == SCT_WATER)
				continue;
			if (player->owner)
				pr("Your ");
			else
				pr("%s (#%d) ", cname(sect.sct_own),
					sect.sct_own);
			pr(dchr[sect.sct_type].d_name);
			changed += map_set(player->cnum, x, y,
				dchr[sect.sct_type].d_mnem, 0);
			pr(" %d%% efficient ", player->owner ? sect.sct_effic :
				round((int)sect.sct_effic, 10));
			civ = getvar(V_CIVIL, (s_char *)&sect, EF_SECTOR);
			mil = getvar(V_MILIT, (s_char *)&sect, EF_SECTOR);
			if (civ)
				pr("with %s%d civ ", player->owner ? "" : "approx ",
					player->owner ? civ : round(civ, 10));
			if (mil)
				pr("with %s%d mil ", player->owner ? "" : "approx ",
					player->owner ? mil : round(mil, 10));
			pr("@ %s\n", xyas(x, y, player->cnum));
#ifdef HIDDEN
                        setcont(player->cnum, sect.sct_own, FOUND_LOOK);
#endif /* HIDDEN */
			prsync(player->cnum, &sect, EDV_LOOK);
		}
	}
	if (changed)
		writemap(player->cnum);
	return RET_OK;
}

static
look_ship(lookship)
	register struct shpstr *lookship;
{
	register struct shpstr *sp;
	register struct mchrstr *smcp;
	register struct mchrstr *tmcp;
	extern	int	ship_max_interdiction_range;
	struct	sctstr sect;
	int	range;
	int	vrange;
	int	i;
	int	dist;

	range = (int) techfact(lookship->shp_tech,
		(double) mchr[lookship->shp_type].m_vrnge);
	range = range * (lookship->shp_effic / 100.0);
	smcp = &mchr[lookship->shp_type];
	if (smcp->m_flags & M_SUB)
		range = min(range, 1);
	for (i=0; sp = getshipp(i); i++) {
		if (sp->shp_own == player->cnum || sp->shp_own == 0)
			continue;
		dist = mapdist(sp->shp_x, sp->shp_y,
			lookship->shp_x, lookship->shp_y);
		if (dist > ship_max_interdiction_range)
			continue;
		tmcp = &mchr[sp->shp_type];
		if (smcp->m_flags & M_SUB)
			vrange = (int)(mchr[sp->shp_type].m_visib * range/30.0);
		else
			vrange = (int)(mchr[sp->shp_type].m_visib * range/20.0);
		getsect(sp->shp_x, sp->shp_y, &sect);
		if (sect.sct_type != SCT_WATER)
			vrange = max(1, vrange);
		if (dist > vrange)
			continue;
		if (smcp->m_flags & M_SUB) {
			if (tmcp->m_flags & M_SONAR && dist < 2) {
				if(sp->shp_own != 0)
				wu(0, sp->shp_own,
				   "%s detected surfacing noises in %s.\n",
				   prship(sp),
				   xyas(lookship->shp_x, lookship->shp_y,
					sp->shp_own));
			}
			if (dist == 0 && (tmcp->m_flags & M_SUB) == 0)
				if(sp->shp_own != 0)
				wu(0, sp->shp_own,
				"Periscope spotted in %s by %s\n",
				   xyas(lookship->shp_x, lookship->shp_y,
					sp->shp_own),
				   prship(sp));
		}
		/* subs at sea only seen by sonar */
		if (tmcp->m_flags & M_SUB && sect.sct_type == SCT_WATER)
			continue;
		pr("%s (#%d) %s @ %s\n",
		   cname(sp->shp_own), sp->shp_own, prship(sp),
		   xyas(sp->shp_x, sp->shp_y, player->cnum));
		prsync(player->cnum, sp, EDV_COAS);
	}
}

static	void look_land();

llook()
{
	register int i;
	struct	nstr_item ni;
	struct	lndstr myland;
	struct	sctstr sect;
	int	x, y;
	int	civ;
	int	mil;
	u_char	bitmap[WORLD_X*WORLD_Y/8];
	int	changed = 0;

	if (!snxtitem(&ni, EF_LAND, player->argp[1]))
		return RET_SYN;
	bzero((s_char *)bitmap, sizeof (bitmap));
	while (nxtitem(&ni, (s_char *)&myland)) {
		if (!player->owner)
			continue;
		if (myland.lnd_ship >= 0)
			continue;
		look_land(&myland);
		for (i = 0; i <= 6; i++) {
			x = diroff[i][0] + myland.lnd_x;
			y = diroff[i][1] + myland.lnd_y;
			if (getbit(x, y, bitmap))
				continue;
			setbit(x, y, bitmap);
			getsect(x, y, &sect);
			if (sect.sct_type == SCT_WATER)
				continue;
			if (player->owner)
				pr("Your ");
			else
				pr("%s (#%d) ", cname(sect.sct_own),
					sect.sct_own);
			pr(dchr[sect.sct_type].d_name);
			changed += map_set(player->cnum, x, y,
				dchr[sect.sct_type].d_mnem, 0);
			pr(" %d%% efficient ", player->owner ? sect.sct_effic :
				round((int)sect.sct_effic, 10));
			civ = getvar(V_CIVIL, (s_char *)&sect, EF_SECTOR);
			mil = getvar(V_MILIT, (s_char *)&sect, EF_SECTOR);
			if (civ)
				pr("with %s%d civ ", player->owner ? "" :
					"approx ",
					player->owner ? civ : round(civ, 10));
			if (mil)
				pr("with %s%d mil ", player->owner ? "" :
					"approx ",
					player->owner ? mil : round(mil, 10));
			pr("@ %s\n", xyas(x, y, player->cnum));
#ifdef HIDDEN
                        setcont(player->cnum, sect.sct_own, FOUND_LOOK);
#endif /* HIDDEN */
			prsync(player->cnum, &sect, EDV_LOOK);
		}
	}
	if (changed)
		writemap(player->cnum);
	return RET_OK;
}

static void
look_land(lookland)
	register struct lndstr *lookland;
{
	register struct plnstr *pp;
	register struct lndstr *lp;
	double	drange;
	int	range;
	int	vrange;
	int	i;
	int	dist;
	double	techfact();

	drange = techfact(lookland->lnd_tech,
		(double) lchr[lookland->lnd_type].l_spy);
	drange = (drange * ((double)lookland->lnd_effic / 100.0));
	range = ldround(drange,1);

	if (range == 0)
		return;

	for (i=0; lp = getlandp(i); i++) {
		if (lp->lnd_own == player->cnum || lp->lnd_own == 0)
			continue;
		vrange = ldround((double)((lchr[lp->lnd_type].l_vis
				* range)/20.0),1);
		dist = mapdist(lp->lnd_x, lp->lnd_y,
			lookland->lnd_x, lookland->lnd_y);
		if (dist > vrange)
			continue;

		pr("%s (#%d) %s @ %s\n",
		   cname(lp->lnd_own), lp->lnd_own,
		   prland(lp),
		   xyas(lp->lnd_x, lp->lnd_y, player->cnum));
		prsync(player->cnum, lp, EDV_COAS);
	}
	for (i=0; pp = getplanep(i); i++) {
		if (pp->pln_own == player->cnum || pp->pln_own == 0)
			continue;
		if (pp->pln_ship >= 0)
			continue;
		vrange = ldround((double)((10* range)/20.0),1);
		dist = mapdist(pp->pln_x, pp->pln_y,
			lookland->lnd_x, lookland->lnd_y);
		if (dist > vrange)
			continue;

		pr("%s (#%d) %s @ %s\n",
			cname(pp->pln_own), pp->pln_own,
			prplane(pp),
			xyas(pp->pln_x, pp->pln_y, player->cnum));
		prsync(player->cnum, pp, EDV_COAS);
	}
}
