#ifndef lint
static char *RCSid = "$Header: /u/dhay/stan/kent/update/RCS/ship.c,v 1.2 91/03/19 17:57:38 dhay Exp Locker: dhay $";
#endif

/*
 * ship.c
 *
 * do "production" for ships -- make more efficient,
 * charge for military, etc.
 *
 * from PSL Empire, 1985
 * and Dave Pare, 1986
 */

#include "misc.h"
#include "var.h"
#include "sect.h"
#include "nat.h"
#include "ship.h"
#include "var.h"
#include "news.h"
#include "file.h"
#include "product.h"

#ifdef BUDGET
prod_ship(etus,natnum,build)
	int	etus;
	int	natnum;
	int	build;	/* build = 1, maintain = 0 */
#else
int
prod_ship(etus)
	int	etus;
#endif /* BUDGET */
{
	register struct shpstr *sp;
	struct	natstr *np;
	int	n;
	extern	long sea_money[MAXNOC];
	int	start_money;

	for (n=0; sp = getshipp(n); n++) {
		if (sp->shp_own == 0)
			continue;
#ifdef BUDGET
		if (sp->shp_own != natnum)
			continue;
#endif /* BUDGET */
		np = getnatp(sp->shp_own);
		start_money = np->nat_money;
#ifdef BUDGET
		upd_ship(sp, n, etus, np, build);
#else
		upd_ship(sp, n, etus, np);
#endif /* BUDGET */
#ifdef BUDGET
		if (build) /* make sure to only autonav once */
#endif /* BUDGET */
#ifdef	AUTONAV
		nav_ship(sp, n, np);		/* autonav the ship */
#endif	AUTONAV
		sea_money[sp->shp_own] += np->nat_money - start_money;
	}
#ifdef BUDGET
	if (build) /* make sure to only sail once */
#endif /* BUDGET */
#ifdef	SAIL
	sail_ship();
#endif	SAIL
}

#ifdef BUDGET
upd_ship(sp, shipno, etus, np, build)
#else
upd_ship(sp, shipno, etus, np)
#endif /* BUDGET */
	register struct shpstr *sp;
	int	shipno;
	register int etus;
	struct	natstr *np;
#ifdef BUDGET
	int	build; /* build = 1, maintain = 0 */
#endif /* BUDGET */
{
	extern	long pops[];
	extern  double money_mil;
	struct	sctstr *sectp;
	struct	mchrstr *mp;
	int	vec[I_MAX+1];
	int	cvec[I_MAX+1];
	int	oil_gained;
	int	max_oil;
	int	max_food;
	struct	pchrstr *product;
	char	*resource;
	int	n;
#ifdef BUDGET
	int	mult;
	extern	double money_ship;
#endif /* BUDGET */

	mp = &mchr[sp->shp_type];
	getvec(VT_ITEM, vec, (char *)sp, EF_SHIP);
#ifdef BUDGET
if (build == 1){
	if (np->nat_priorities[PRI_SBUILD] == 0)
		return;
#endif /* BUDGET */
	if (sp->shp_effic < 20 || !shiprepair(sp, vec, np, etus)) {
		sp->shp_own = 0;
		return;
	}
#ifdef BUDGET
}else{
	mult = 1;
	if (np->nat_level[NAT_TLEV] < sp->shp_tech * 0.85)
		mult = 2;
	np->nat_money += (int) (mult * etus *
		dmin(0.0, money_ship * mp->m_cost));
#endif /* BUDGET */

	if (mp->m_flags & M_OIL) {
		/*
		 * take care of oil production
		 */
		sectp = getsectp(sp->shp_x, sp->shp_y);
		oil_gained = roundavg((vec[I_CIVIL] * etus / 10000.0)
			* sectp->sct_oil);
		vec[I_OIL] += oil_gained;
		max_oil = vl_find(V_OIL, mp->m_vtype, mp->m_vamt, MAXMCHV);
		if (vec[I_OIL] > max_oil)
			vec[I_OIL] = max_oil;
		product = &pchr[P_OIL];
		if (product->p_nrdep != 0 && oil_gained > 0) {
			resource = ((char *) sectp) + product->p_nrndx;
			*resource -=
				roundavg(oil_gained * product->p_nrdep / 100.0);
		}
	} else if (mp->m_flags & M_FOOD) {
		sectp = getsectp(sp->shp_x, sp->shp_y);
#ifdef NEWFISH
		vec[I_FOOD] += ((vec[I_CIVIL] * etus) / 1000.0)
#else
		vec[I_FOOD] += ((vec[I_CIVIL] * etus) / 10000.0)
#endif /* NEWFISH */
			* sectp->sct_fertil;
	}
	np->nat_money += (int) (etus * vec[I_MILIT] * money_mil);
	if ((n = feed_people(vec, etus)) > 0) {
#ifdef	SHIPNAMES
		wu(0, sp->shp_own, fmt("%d starved on %s %s(#%d)\n",
			n, mp->m_name, sp->shp_name, shipno));
#else
		wu(0, sp->shp_own, fmt("%d starved on %s #%d\n",
			n, mp->m_name, shipno));
#endif	SHIPNAMES
		if (n > 10)
			nreport(sp->shp_own, N_DIE_FAMINE, 0, 1);
	}
	max_food = vl_find(V_FOOD, mp->m_vtype, mp->m_vamt, MAXMCHV);
	if (vec[I_FOOD] > max_food)
		vec[I_FOOD] = max_food;
	/*
	 * do plague stuff.  plague can't break out on ships,
	 * but it can still kill people.
	 */
	getvec(VT_COND, cvec, (char *)sp, EF_SHIP);
	if (cvec[C_PSTAGE] > 0) {
		n = plague_people(np, vec, cvec, etus);
		switch (n) {
		case PLG_DYING:
			wu(0, sp->shp_own,
#ifdef	SHIPNAMES
				fmt("PLAGUE deaths reported on %s %s(#%d)\n",
				mp->m_name, sp->shp_name, sp->shp_uid));
#else
				fmt("PLAGUE deaths reported on %s #%d\n",
				mp->m_name, sp->shp_uid));
#endif	SHIPNAMES
			nreport(sp->shp_own, N_DIE_PLAGUE, 0, 1);
			break;
		case PLG_EXPOSED:
#ifdef	SHIPNAMES
			wu(0, sp->shp_own, fmt("%s %s(#%d) battling PLAGUE\n",
				mp->m_name, sp->shp_name, sp->shp_uid));
#else
			wu(0, sp->shp_own, fmt("%s #%d battling PLAGUE\n",
				mp->m_name, sp->shp_uid));
#endif	SHIPNAMES
			break;
		case PLG_INCUBATE:
			if (n == cvec[C_PSTAGE])
				break;
#ifdef	SHIPNAMES
			wu(0, sp->shp_own, fmt("Outbreak of PLAGUE on %s %s(#%d)!\n",
				mp->m_name, sp->shp_name, sp->shp_uid));
#else
			wu(0, sp->shp_own, fmt("Outbreak of PLAGUE on %s #%d!\n",
				mp->m_name, sp->shp_uid));
#endif	SHIPNAMES
			nreport(sp->shp_own, N_OUT_PLAGUE, 0, 1);
			break;
		default:
			break;
		}
		putvec(VT_COND, cvec, (char *)sp, EF_SHIP);
	}
	putvec(VT_ITEM, vec, (char *)sp, EF_SHIP);
	pops[sp->shp_own] += vec[I_CIVIL];
#ifdef BUDGET
}
#endif /* BUDGET */
}

/*
 * idea is: a sector full of workers can fix up eight
 * battleships +8 % eff each etu.  This will cost around
 * 8 * 8 * $40 = $2560!
 */
int
shiprepair(ship, vec, np, etus)
	register struct shpstr *ship;
	int	*vec;
	struct	natstr *np;
	int	etus;
{
	extern	int ship_grow_scale;
	extern	double money_ship;
	register int delta;
	struct	sctstr *sp;
	struct	mchrstr *mp;
	int	wf;
	int	left;
	int	avail;
	int	w_p_eff;
	int	mult;
#ifdef ALLYHARBORWORK
	int	rel;
#endif /* ALLYHARBORWORK */

	mp = &mchr[ship->shp_type];
	sp = getsectp(ship->shp_x, ship->shp_y);
	mult = 1;
	if (np->nat_level[NAT_TLEV] < ship->shp_tech * 0.85)
		mult = 2;
#ifndef BUDGET
	np->nat_money += (int) (mult * etus *
		dmin(0.0, money_ship * mp->m_cost));
#endif /* BUDGET */
	if (ship->shp_effic == 100) {
		/* ship is ok; no repairs needed */
		return 1;
	}
	if ((sp->sct_own != ship->shp_own) && (sp->sct_own != 0)) {
#ifdef ALLYHARBORWORK
		rel=getrel(getnatp(sp->sct_own),ship->shp_own);

		if (rel != ALLIED)
			return 1;
#else
		/* not our harbor -> shore leave; no eff gain */
		return 1;
#endif /* ALLYHARBORWORK */
	}
	left = 100 - ship->shp_effic;
	wf = 0;
	/* only military can work on a military boat */
	if (mp->m_glim > 0)
		wf = etus * vec[I_MILIT]/2;
	else
		wf = etus * (vec[I_CIVIL]/2 + vec[I_MILIT]/5);
	if (sp->sct_type != SCT_HARBR)
		wf /= 3;
	avail = wf + sp->sct_avail * 100;
	w_p_eff = 20 + (mp->m_lcm + 2 * mp->m_hcm);
	delta = roundavg((double)avail/w_p_eff);
	if (delta <= 0)
		return 1;
	if (delta > etus*ship_grow_scale)
		delta = etus*ship_grow_scale;
	if (delta > left)
		delta = left;
	wf -= delta * w_p_eff;
	if (wf < 0) {
		/*
		 * I didn't use roundavg here, because I want to penalize
		 * the player with a large number of ships.
		 */
		avail = (sp->sct_avail * 100 + wf) / 100;
		if (avail < 0)
			avail = 0;
		sp->sct_avail = avail;
	}
	np->nat_money -= mult * mp->m_cost * delta / 100.0;
	ship->shp_effic += delta;
	return 1;
}
