#ifndef lint
static char *RCSid = "$Header: /usr/brule/guest/empire/empire/emprcs/lib/update/mobility.c,v 2.1 1995/07/27 20:50:10 empire Exp $";
#endif

/*
 * mobility.c
 *
 * Add mobility to each of the items which accumlate mobility.
 * 
 * Dave Pare, 1986
 */

#include "misc.h"
#include "var.h"
#include "sect.h"
#include "ship.h"
#include "land.h"
#include "plane.h"
#include "nat.h"
#include "file.h"
#include "optlist.h"

mob_sect(etus)
	register int etus;
{
	extern	float sect_mob_scale;
	extern	int sect_mob_max;
	register struct sctstr *sp;
	register int value;
	register int n;

	for (n=0; sp = getsectid(n); n++) {
		if (sp->sct_own == 0)
			continue;
		if (sp->sct_type == SCT_SANCT)
			continue;
		value = sp->sct_mobil + ((float)etus * sect_mob_scale);
		if (value > sect_mob_max)
			value = sect_mob_max;
		sp->sct_mobil = value;
	}
}

mob_ship(etus)
	register int etus;
{
	extern	int ship_mob_max;
	extern	float ship_mob_scale;
	int	newfuel=0;
	register struct shpstr *sp;
	register int value;
	register int n;
	int	can_add,have_fuel_for,total_add;
	double	d;
	extern	int fuel_mult;

	for (n=0; sp = getshipp(n); n++) {
		if (sp->shp_own == 0)
			continue;

		if (opt_FUEL == 0) { /* only a bit to do ... */
			value = sp->shp_mobil + ((float)etus * ship_mob_scale);
			if (value > ship_mob_max)
				value = ship_mob_max;
			sp->shp_mobil = value;
			continue; /* so we ship the FUEL stuff */
		}

		/* opt_FUEL in force */
		if (mchr[sp->shp_type].m_fuelu == 0) {
			value = sp->shp_mobil + ((float)etus * ship_mob_scale);
			if (value > ship_mob_max)
				value = ship_mob_max;
			sp->shp_mobil = value;
		} else {
			can_add = ship_mob_max - sp->shp_mobil;
			if (can_add > ((float)etus*ship_mob_scale))
				can_add = ((float)etus*ship_mob_scale);
			have_fuel_for = ldround((((double)sp->shp_fuel /
						  (double)mchr[sp->shp_type].m_fuelu)*
						 (double)fuel_mult),1);
	
			if (can_add > have_fuel_for){
				int	need;
				need = can_add - have_fuel_for;
				d = (double)need;
				d *= (double)mchr[sp->shp_type].m_fuelu;
				d /= (double)fuel_mult;
				d /= 5.0;
				if ((d-(int)d) > 0.0)
					d++;
				need = (int)d;
				newfuel = supply_commod(sp->shp_own,sp->shp_x,
							sp->shp_y,I_PETROL,need);
				sp->shp_fuel += newfuel * 5;
			}

			have_fuel_for = ldround((((double)sp->shp_fuel /
						  (double)mchr[sp->shp_type].m_fuelu)*
						 (double)fuel_mult),1);

			if (can_add > have_fuel_for){
				int	need;
				need = can_add - have_fuel_for;
				d = (double)need;
				d *= (double)mchr[sp->shp_type].m_fuelu;
				d /= (double)fuel_mult;
				d /= 50.0;
				if ((d-(int)d) > 0.0)
					d++;
				need = (int)d;
				newfuel = supply_commod(sp->shp_own,sp->shp_x,
							sp->shp_y,I_OIL,need);
				sp->shp_fuel += newfuel * 50;
			}

			have_fuel_for = ldround((((double)sp->shp_fuel /
						  (double)mchr[sp->shp_type].m_fuelu)*
						 (double)fuel_mult),1);

			if (can_add > have_fuel_for)
				total_add = have_fuel_for;
			else
				total_add = can_add;
			d = (double)total_add;
			d *= (double)mchr[sp->shp_type].m_fuelu;
			d /= (double)fuel_mult;
			sp->shp_fuel -= ldround(d,1);
			sp->shp_fuel = min(sp->shp_fuel,
					   mchr[sp->shp_type].m_fuelc);
			sp->shp_mobil += total_add;
		}
	}
}

mob_land(etus)
	register int etus;
{
	extern	int land_mob_max;
	extern	float land_mob_scale;
	int	newfuel=0;
	register struct lndstr *lp;
	register int value;
	register int n;
	int	can_add,have_fuel_for,total_add;
	double	d;
	extern	int fuel_mult;

	for (n=0; lp = getlandp(n); n++) {
		if (lp->lnd_own == 0)
			continue;

		/*
		 * Give damaged units a break. When at low
		 * efficiency, units can go to -100 mob when
		 * marching 1 step, making them slower than
		 * normal mil. This helps take the curse off.
		 */

		if (lp->lnd_mobil < 0)
			lp->lnd_mobil /= 2;

		if (opt_FUEL == 0) { /* just some bits and pieces */
			value = lp->lnd_mobil + ((float)etus * land_mob_scale);
			if (value > land_mob_max)
				value = land_mob_max;
			lp->lnd_mobil = value;
			continue; /* done! */
		}

		/* opt_FUEL in force ... */
		if (lchr[lp->lnd_type].l_fuelu == 0){
			value = lp->lnd_mobil + ((float)etus * land_mob_scale);
			if (value > land_mob_max)
				value = land_mob_max;
			lp->lnd_mobil = value;
		} else {
			can_add = land_mob_max - lp->lnd_mobil;

			if (can_add > ((float)etus*land_mob_scale))
				can_add = ((float)etus*land_mob_scale);

			have_fuel_for = (lp->lnd_fuel /
				lchr[lp->lnd_type].l_fuelu)*fuel_mult;
	
			if (can_add > have_fuel_for){
				int	need;
				need = can_add - have_fuel_for;
				d = (double)need;
				d *= (double)lchr[lp->lnd_type].l_fuelu;
				d /= (double)fuel_mult;
				d /= 5.0;
				if ((d-(int)d) > 0.0)
					d++;
				need = (int)d;
				newfuel = supply_commod(lp->lnd_own,lp->lnd_x,
					lp->lnd_y,I_PETROL,need);
				lp->lnd_fuel += newfuel * 5;
			}

			have_fuel_for = (lp->lnd_fuel /
				lchr[lp->lnd_type].l_fuelu)*fuel_mult;

			if (can_add > have_fuel_for){
				int	need;
				need = can_add - have_fuel_for;
				d = (double)need;
				d *= (double)lchr[lp->lnd_type].l_fuelu;
				d /= (double)fuel_mult;
				d /= 50.0;
				if ((d-(int)d) > 0.0)
					d++;
				need = (int)d;
				newfuel = supply_commod(lp->lnd_own,lp->lnd_x,
					lp->lnd_y,I_OIL,need);
				lp->lnd_fuel += newfuel * 50;
			}

			have_fuel_for = (lp->lnd_fuel /
				lchr[lp->lnd_type].l_fuelu)*fuel_mult;

			if (can_add > have_fuel_for){
				total_add = have_fuel_for;
			}
			else
				total_add = can_add;
			d = (double)total_add;
			d *= (double)lchr[lp->lnd_type].l_fuelu;
			d /= (double)fuel_mult;
			lp->lnd_fuel -= ldround(d,1);
			lp->lnd_fuel = min(lp->lnd_fuel,
				lchr[lp->lnd_type].l_fuelc);
			lp->lnd_mobil += total_add;
		}
	}
}

mob_plane(etus)
	register int etus;
{
	extern	int plane_mob_max;
	extern	float plane_mob_scale;
	register struct plnstr *pp;
	register int value;
	register int n;

	for (n=0; pp = getplanep(n); n++) {
		if (pp->pln_own == 0)
			continue;
		value = pp->pln_mobil + ((float)etus * plane_mob_scale);
		if (value > plane_mob_max)
			value = plane_mob_max;
		pp->pln_mobil = value;
	}
}
