#ifndef lint
static char *RCSid = "$Header: /u/dhay/stan/kent/player/commands/RCS/orde.c,v 1.1 91/03/27 22:42:09 dhay Exp Locker: dhay $";
#endif

/*
 * orde.c
 *
 * turn on/off autonavigation
 *
 * from PSL Empire, 1985
 */

#include <ctype.h>
#include "misc.h"
#ifdef	AUTONAV
#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"
#include "item.h"



/*
**  Command syntax:
**
**  ORDER <ship>				  Show orders
**  ORDER <ship> e[ta]                            Show time info
**  ORDER <ship> c[ancel]			  Cancel orders
**  ORDER <ship> s[top]				  Suspend orders
**  ORDER <ship> r[esume]			  Resume orders
**  ORDER <ship> <coord>			  Goto dest
**  ORDER <ship> <coord0> <com0>		  Goto dest, get cargo
**  ORDER <ship> <coord0> <com0> <coord1>	  Goto dest, get cargo, return
**  ORDER <ship> <coord0> <com0> <coord1> <com1>  Set roundtrip trade route
**
** New syntax:
**  qorder <ship>
**  order <ship> eta
**  order <ship> cancel
*/

orde()
{
	extern char *argp[];
	extern	int  aborted;
	int	nships=0;
	int	diffeachship = 0;
	int	orders;
	struct nstr_item nb;
	struct shpstr ship;
	struct ichrstr *ip;
	coord	p0x, p0y, p1x, p1y;
	int	c0, c1;
	char	*p;
	char	buf[128];

	if (!snxtitem(&nb, EF_SHIP, argp[1])) return RET_SYN;
	while (!aborted && nxtitem(&nb, (char *)(&ship))) {
		if (!owner || ship.shp_own == 0)
			continue;
		if (ship.shp_type < 0 || ship.shp_type > shp_maxno) {
			pr(fmt("bad ship type %d (#%d)\n",
				ship.shp_type, nb.cur));
			continue;
		}
#ifdef SAIL
		if (*ship.shp_path) {
			if (!diffeachship)
				pr(fmt("Ship #%d has a \"sail\" path!\n",
					ship.shp_uid));
			continue;
		}
#endif

		sprintf(buf, "Ship #%d, declare, cancel, suspend, resume? ",
				ship.shp_uid);
		p = getstarg(argp[2], buf);
		if (aborted || !p)
			return RET_FAIL;
		if (!*p)
			if (!diffeachship) {
				return RET_FAIL;
			} else
				continue;

		switch (*p) {
		default:
			pr("Bad order type!\n");
			return RET_SYN;
		case 'c':
			ship.shp_autonav &= ~(AN_AUTONAV+AN_STANDBY+AN_LOADING);
			break;
		case 's':
			ship.shp_autonav |= AN_STANDBY;
			break;
		case 'r':
			ship.shp_autonav &= ~AN_STANDBY;
			break;
		case 'd':
			orders = 0;
			c0 = c1 = ' ';

			/* Need location */
			if ((p=getstarg(argp[3],"Destination? "))==0 || *p==0)
				return RET_SYN;
			if (!sarg_xy(p, &p0x, &p0y))
				return RET_SYN;
			p1x = p0x;
			p1y = p0y;

			/* Look for first pickup item */
			ip = whatitem(argp[4], "Pickup? ");
			if (!ip) {
				orders = ORDER_P;
			} else {
				c0 = ip->i_mnem;
			}
			if (!orders) {
				p = getstarg(argp[5], "Second dest? ");
				if (!p || !*p) {
					orders = ORDER_PC;
				} else {
					if (!sarg_xy(p, &p1x, &p1y))
						return RET_SYN;
				}
			}
			if (!orders) {
				ip = whatitem(argp[6], "2nd Pickup? ");
				if (!ip) {
					orders = ORDER_PCP;
				} else {
					c1 = ip->i_mnem;
					orders = ORDER_PCPC;
				}
			}

			/*
			 *  Set new destination and trade type fields.
			 */

			ship.shp_trdtype[0] = c0;
			ship.shp_trdtype[1] = c1;
			ship.shp_destx[1] = p1x;
			ship.shp_desty[1] = p1y;
			ship.shp_destx[0] = p0x;
			ship.shp_desty[0] = p0y;

			ship.shp_autonav &= ~(AN_STANDBY+AN_SAILDIR+AN_LOADING);
			ship.shp_autonav |= AN_AUTONAV;

			/*
			 *  Set loading flag if ship is already in one
			 *  of the specified harbors and a cargo has been
			 *  specified.
			 */

			if ( ((ship.shp_x == ship.shp_destx[0])
				&& (ship.shp_y == ship.shp_desty[0])
				&& (ship.shp_trdtype[0] != ' '))
			    || ((ship.shp_x == ship.shp_desty[1])
				&& (ship.shp_y == ship.shp_desty[1])
				&& (ship.shp_trdtype[1] != ' ')) )
			    ship.shp_autonav |= AN_LOADING;

			/*
			**  Write ship back to database, then give it
			**  a kick down the autonav route if necessary.
			*/


		}
		putship(ship.shp_uid, &ship);
		nships++;
	}
	return RET_OK;
}

static int
eta_calc(sp, path, len, nupdates)
	struct shpstr *sp;
	char *path;
	int *len, *nupdates;
	
{
	extern int etu_per_update;
	extern int ship_mob_scale;
	struct mchrstr *mcp;
	double mobcost, mobil;
	int	i;

	i = strlen(path);
	*len = i;
	*nupdates = 1;

	mcp = &mchr[sp->shp_type];
	mobcost = sp->shp_effic * 0.01 * mcp->m_speed;
	mobcost = 480.0 / (mobcost + techfact(sp->shp_tech, mobcost));
	mobil = sp->shp_mobil;
	while (i) {
		if (mobil > 0) {
			mobil -= mobcost;
			i--;
		} else {
			mobil += (ship_mob_scale * etu_per_update);
			(*nupdates)++;
		}
	}
}

qorde()
{
	int	nships=0;
	int	len, updates;
	char	*c;
	struct nstr_item nb;
	struct shpstr ship;
        extern  char *argp[];

	if (!snxtitem(&nb, EF_SHIP, argp[1])) return RET_SYN;
	while (nxtitem(&nb, (char *)(&ship))) {
		if (!owner || ship.shp_own==0)
		    continue;
		if (ship.shp_type < 0 || ship.shp_type > shp_maxno) {
			pr(fmt("bad ship type %d (#%d)\n",
				ship.shp_type, nb.cur));
			continue;
		}
#ifdef SAIL
		if ((ship.shp_autonav & AN_AUTONAV) || (ship.shp_path[0])){
#else
		if (ship.shp_autonav & AN_AUTONAV){
#endif /* SAIL */
			if (!nships) { /* 1st ship, print banner */
				if (god) pr("own ");
				pr("shp#     ship type       x,y   flt  ");
				pr("dest1 pick dest2  pick dist eta\n");
			}
		}

		/* Basic ship description */
#ifdef SAIL
		if ((ship.shp_autonav & AN_AUTONAV) || (ship.shp_path[0])){
#else
		if (ship.shp_autonav & AN_AUTONAV){
#endif /* SAIL */
			nships++;
			if (god) pr(fmt("%3d ", ship.shp_own));
			pr(fmt("%4d", nb.cur));
			pr(fmt(" %-16.16s", mchr[ship.shp_type].m_name));
			pr(fmt(" %s",xyfmt("%4d,%-4d", ship.shp_x, ship.shp_y,
				cnum)));
			pr(fmt(" %1c", ship.shp_fleet));
		}
#ifdef SAIL
		if (ship.shp_path[0]) {
			pr("  Has a \"sail\" path\n");
		} else
#endif
		if (ship.shp_autonav & AN_AUTONAV){
			/* Destination 1 */
			pr(fmt(" %s",xyfmt("%4d,%-4d", ship.shp_destx[0],
				       ship.shp_desty[0], cnum)));

			pr(fmt(" %c", ship.shp_trdtype[0]));

			/* Destination 2 */
			if (   (ship.shp_destx[1]!=ship.shp_destx[0])
			    || (ship.shp_desty[1]!=ship.shp_desty[0]) ) {
				pr(fmt(" %s",xyfmt("%4d,%-4d",ship.shp_destx[1],
					ship.shp_desty[1], cnum)));
				pr(fmt(" %1c ", ship.shp_trdtype[1]));
			} else pr("            ");
			if (ship.shp_autonav & AN_STANDBY) {
				pr(" suspended\n");
			} else if (ship.shp_autonav & AN_LOADING) {
				pr(" loading\n");
			} else {
				/* ETA calculation */
				c = (char *)bestpath(ship.shp_x, ship.shp_y,
					ship.shp_destx[0], ship.shp_desty[0],
					".= ");
				if (!c || !*c) {
					pr("no route possible\n");
				} else if (*c == 'h') {
					pr("has arrived\n");
				} else if (*c == '?') {
					pr("route too long\n");
				} else {
					/* distance to destination */
					eta_calc(&ship, c, &len, &updates);
					pr(fmt(" %3d %3d\n", len, updates));
				}
			}
		}
#ifdef	SHIPNAMES
#ifdef SAIL
		if ((ship.shp_autonav & AN_AUTONAV) || (ship.shp_path[0])){
#else
		if (ship.shp_autonav & AN_AUTONAV){
#endif /* SAIL */
			if (ship.shp_name[0] != 0) {
				if (god)
					pr("    ");
				pr(fmt("       %s\n",ship.shp_name));
			}
		}
#endif	SHIPNAMES
	}
	if (!nships) {
		pr(fmt("%s: No ships(s)\n", ((argp[1]) ? argp[1] : "")));
		return RET_FAIL;
	} else
		pr(fmt("%d ships(s)\n", nships));
	return RET_OK;
}
#endif	AUTONAV
