#ifndef lint
static char *RCSid = "$Header: /u/dhay/bemp/kent/update/RCS/nav_ship.c,v 1.1 91/03/28 00:36:05 dhay Exp Locker: dhay $";
#endif

/*
 * nav_util.c
 *
 * Utilities for autonav and sail.
 *
 */

#include "misc.h"

#ifdef	AUTONAV
#define WANT_THIS
#endif	AUTONAV

#ifdef	SAIL
#undef WANT_THIS
#define WANT_THIS
#endif	SAIL

#ifdef	WANT_THIS

#include <ctype.h>
#include "var.h"
#include "ship.h"
#include "sect.h"
#include "news.h"
#include "xy.h"
#include "nsc.h"
#include "nat.h"
#include "path.h"
#include "deity.h"
#include "file.h"


 /* return codes from check_nav */
#define CN_LANDLOCKED	(1)
#define CN_CONSTRUCTION	(2)
#define CN_ERROR	(-1)
#define CN_NAVIGABLE	(0)


/* Format a ship name */
char *
nav_nameship(sp, mcp)
        register struct shpstr *sp;
	register struct mchrstr *mcp;
{
	static char buf[100];

#ifdef	SHIPNAMES
	sprintf(buf, "%s %s(#%d)", mcp->m_name, sp->shp_name, sp->shp_uid);
#else
	sprintf(buf, "%s #%d", mcp->m_name, sp->shp_uid);
#endif	SHIPNAMES
	return(buf);
}


int 
check_nav(sect)
	struct	sctstr *sect;
{
	extern struct dchrstr dchr[];

	switch (dchr[sect->sct_type].d_flg & 03) {
	case NAVOK:
		break;

	case NAV_02:
		if (sect->sct_effic < 2)
			return CN_CONSTRUCTION;
		break;
	case NAV_60:
		if (sect->sct_effic < 60)
			return CN_CONSTRUCTION;
		break;
	default:
		return CN_LANDLOCKED;
	}
	return CN_NAVIGABLE;
}

int
nav_chkdir(dir_char, min_dir, max_dir)
        char    dir_char;
        int     min_dir;
        int     max_dir;
{
        register int i;

        for (i = min_dir; i <= max_dir; i++)
                if (dir_char == dirch[i])
                        return i;
        return -1;
}

double
techfact(level, mult)
        int     level;
        double  mult;
{
        return mult * ((50.0 + level) / (200.0 + level));
}

static int
snxtsct_dist(np, cx, cy, dist)
	register struct nstr_sect *np;
	coord	cx, cy;
	int	dist;
{
	bzero(np, sizeof(*np));
	xydist_range(cx, cy, dist, &np->range);
	np->cx = cx;
	np->cy = cy;
	np->ncond = 0;
	np->dist = dist;
	np->type = NS_DIST;
	np->read = ef_read;
	np->x = np->range.lx - 1;
	np->y = np->range.ly;
	np->dx = -1;
	np->dy = 0;
	xysize_range(&np->range);
	ef_zapcache(EF_SECTOR);
}

static int
xysize_range(rp)
	register struct range *rp;
{
	if (rp->lx >= rp->hx)
		rp->width = WORLD_X + rp->hx - rp->lx;
	else
		rp->width = rp->hx - rp->lx;
	if (rp->ly >= rp->hy)
		rp->height = WORLD_Y + rp->hy - rp->ly;
	else
		rp->height = rp->hy - rp->ly;
}

static int
xydist_range(x, y, dist, rp)
	coord	x;
	coord	y;
	int	dist;
	struct	range *rp;
{
	rp->lx = xnorm((coord)(x - 2 * dist));
	rp->hx = xnorm((coord)(x + 2 * dist) + 1);
	rp->ly = ynorm((coord)(y - dist));
	rp->hy = ynorm((coord)(y + dist) + 1);
	rp->height = 0;
	rp->width = 0;
}


static struct sctstr *
nxtsctp(np)
	register struct nstr_sect *np;
{
	while (1) {
		np->dx++;
		np->x++;
		if (np->x >= WORLD_X)
			np->x = 0;
		if (np->dx >= np->range.width) {
			np->dx = 0;
			np->x = np->range.lx;
			np->dy++;
			if (np->dy >= np->range.height)
				return (struct sctstr *)0;
			np->y++;
			if (np->y >= WORLD_Y)
				np->y = 0;
		}
		if ((np->y + np->x) & 01)
			continue;
		if (np->type == NS_DIST) {
			np->curdist = mapdist(np->x, np->y, np->cx, np->cy);
			if (np->curdist > np->dist)
				continue;
		}
		return(getsectp(np->x, np->y));
	}
	/*NOTREACHED*/
}

int
nav_shiprad(sp, cx, cy)
	struct shpstr *sp;
	int	cx, cy;
{
	int	range;
	struct	sctstr *sectp;
	struct	nstr_sect ns;

	range = (int) techfact(sp->shp_tech,
			(double) mchr[sp->shp_type].m_vrnge);
	range = (int) (range * (sp->shp_effic / 100.0));
	/* JNP 12/15/89  radar always can see at least 1 distant */
	if (range < 1) range = 1;
	snxtsct_dist(&ns, cx, cy, range);
	while ((sectp=nxtsctp(&ns))) {
		if (sectp->sct_own == sp->shp_own ||
		    (sectp->sct_type <= SCT_RURAL && sectp->sct_type != SCT_SANCT)
		    || ns.curdist <= range/3 || ns.curdist == 1)
			setbigmap(ns.x, ns.y, dchr[sectp->sct_type].d_mnem);
		else
			setbigmap(ns.x, ns.y, '?');
	}
}
#endif	WANT_THIS
