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

/*
 * expl.c
 *
 * takeover unoccupied sectors
 *
 * Jeff Wallace, 1989
 */

#include "misc.h"
#include "player.h"
#include "var.h"
#include "sect.h"
#include "xy.h"
#include "nsc.h"
#include "item.h"
#include "file.h"
#include "deity.h"
#include "nat.h"
#include "optlist.h"


static	int explore_map();

expl()
{
	register int amount;
	struct	sctstr orig, sect;
	struct	sctstr endsect;
	struct	sctstr start;
	struct	sctstr chksect;
	double	weight;
	int     mcost, dam;
	int     infected;
	int     vtype;
	int     amt_src;
	int     amt_dst;
	struct	ichrstr *ip;
	int     work;
	int     loyal;
	int     own, mob;
	int	justtook;
	coord	x, y;
	s_char	*p;
	int	n;
	int	left;
	s_char	buf[1024];
	s_char	prompt[128];

	if ((ip = whatitem(player->argp[1], "explore with what? (civ/mil) ")) == 0)
		return RET_SYN;
	vtype = ip->i_vtype;
	if ((vtype != V_CIVIL) && (vtype != V_MILIT)) {
		pr("You can only explore with civs and mil.\n");
		return RET_FAIL;
	}
	if ((p = getstarg(player->argp[2], "from sector : ", buf)) == 0)
		return RET_SYN;
	if (!sarg_xy(p, &x, &y))
		return RET_SYN;
	if (!getsect(x, y, &sect) || !player->owner) {
		pr("Not yours\n");
		return RET_FAIL;
	}
	bcopy(&sect,&orig,sizeof(struct sctstr));
	infected = getvar(V_PTIME, (s_char *)&sect, EF_SECTOR) == PLG_INFECT;
	if ((amt_src = getvar(vtype, (s_char *)&sect, EF_SECTOR)) <= 0) {
		pr("No %s in %s\n", ip->i_name, 
			xyas(sect.sct_x, sect.sct_y, player->cnum));
		return RET_SYN;
	}
	own = sect.sct_own;
	mob = (int)sect.sct_mobil;
	if (vtype == V_CIVIL && sect.sct_oldown != own) {
		pr("You can't explore with conquered populace!\n");
		return RET_SYN;
	}
	if (mob <= 0) {
		pr("No mobility in %s\n",
			xyas(sect.sct_x, sect.sct_y, player->cnum));
		return RET_SYN;
	}
	if (vtype == V_CIVIL) {
		work = sect.sct_work;
		if (work != 100)
			pr("Warning: civil unrest\n");
		loyal = sect.sct_loyal;
	} else if (vtype == V_MILIT) {
		work = 100;
		loyal = 0;
	}
	sprintf(prompt, "Number of %s to explore with? (max %d) ",
		ip->i_name, amt_src);
	amount = onearg(player->argp[3], prompt);
	if (amount > amt_src) {
		amount = amt_src;
		pr("Only exploring with %d.\n", amount);
	}
	if (would_abandon(&sect,vtype,amount)){
		s_char	y_or_n[80], *ppp;

		ppp = (s_char *)0;
		while (!ppp || ((*ppp != 'y') && (*ppp != 'n'))){
			bzero(y_or_n,80);
			if (ppp && (*ppp != 'y') && (*ppp != 'n'))
				pr("Answer y or n!\n");

			sprintf(prompt,
				"Do you really want to abandon %s [yn]? ",
				xyas(sect.sct_x, sect.sct_y, player->cnum));
			ppp = getstarg(y_or_n, prompt, buf);
			if (player->aborted){
				pr("Explore aborted.\n");
				return RET_OK;
			}
			if (ppp && isupper(*ppp))
				*ppp=tolower(*ppp);
		}
		if (*ppp != 'y'){
			pr("Explore cancelled.\n");
			return RET_FAIL;
		}
	}
	if (amount <= 0)
		return RET_SYN;
	weight = amount * ip->i_lbs;
	/* remove commodities from source sector */
	getsect(x, y, &start);
	amt_src = getvar(vtype, (s_char *)&start, EF_SECTOR);
	amt_src -= amount;
	if (amt_src < 0) {
		pr("%s in %s are gone!\n", ip->i_name, 
			xyas(start.sct_x, start.sct_y, player->cnum));
		return RET_OK;
	}
	putvar(vtype, amt_src, (s_char *)&start, EF_SECTOR);
	putsect(&start);
	/*
	 * Now parse the path and return ending sector.
	 */
	dam = 1;
	mcost = move_ground((s_char *)ip, &sect, &endsect,
		(double)sect.sct_mobil, weight, player->argp[4], 
		explore_map, 1, &dam);

	if (dam) {
		left = effdamage(amount, dam);
		if (left < amount) {
			if (left) {
				pr("%d of the %s you were exploring with were destroyed!\nOnly %d %s made it to %s\n",
				   amount - left,
				   ip->i_name,
				   left,
				   ip->i_name,
				   xyas(endsect.sct_x, endsect.sct_y, player->cnum));			   
			} else {
				pr("All of the %s you were exploring with were destroyed!\n",ip->i_name);
			}
			amount = left;
		}
	}
	if (mcost > 0)
		pr("Total movement cost = %d",mcost);
	else
		pr("No mobility used");

	if (mcost < 0) {
		pr("\nExplore aborted");
		getsect(start.sct_x,start.sct_y,&sect);
		sect.sct_mobil = (u_char)mob;
	}else{
		/* Charge mobility */
		getsect(sect.sct_x, sect.sct_y, &sect);
		n = sect.sct_mobil - mcost;
		if (n < 0)
			n = 0;
		sect.sct_mobil = (u_char)n;
		pr(", %d mob left in %s", sect.sct_mobil,
			xyas(sect.sct_x,sect.sct_y,player->cnum));
		putsect(&sect);
		getsect(endsect.sct_x, endsect.sct_y, &sect);
	}
	pr("\n");
	justtook = 0;

	/*
	 *	Check for a multitude of problems
	 */
	getsect(endsect.sct_x, endsect.sct_y, &chksect);
	if(chksect.sct_type == '.') {
		pr("Bridge disappeared!\n");
		return RET_FAIL;
	}
	if(!player->god && chksect.sct_own && chksect.sct_own != player->cnum
		&& chksect.sct_type != SCT_SANCT) {
		if ((chksect.sct_x == orig.sct_x) &&
			(chksect.sct_y == orig.sct_y)){
			pr("Someone captured the sector you started from!\n");
			pr("You exploring people die of disappointment!\n");
			return RET_FAIL;
		}else{
			pr("Somebody beat you there!\n");
			/* Send them xback home */
			getsect(start.sct_x,start.sct_y,&sect);
			sect.sct_own = own;
		}
	}

	if (!player->god && !player->owner && sect.sct_type != SCT_SANCT) {
		(void) takeover(&sect, player->cnum);
		justtook = 1;
		sect.sct_oldown = own;
		sect.sct_work = work;
		sect.sct_loyal = loyal;
	}
	if (vtype == V_CIVIL && sect.sct_oldown != player->cnum) {
		pr("Your civilians don't want to stay!\n");
		getsect(start.sct_x,start.sct_y,&sect);
		sect.sct_own = own;
	}
	amt_dst = getvar(vtype, (s_char *)&sect, EF_SECTOR);
	if (32767 - amt_dst < amount) {
		amount = 32767 - amt_dst;
		pr("Only %d can be left there.\n", amount);
		if (amount <= 0)
			getsect(start.sct_x,start.sct_y,&sect);
	}
	if (putvar(vtype, amount + amt_dst, (s_char *)&sect, EF_SECTOR) < 0) {
		pr("No more room in %s.\n", 
			xyas(sect.sct_x, sect.sct_y, player->cnum));
		return RET_OK;
	}
	/*
	 * Now add commodities to destination sector,
	 * along with plague that came along for the ride.
	 * Takeover unowned sectors if not deity.
	 */
	if (!player->god && sect.sct_type != SCT_SANCT && justtook) {
		pr("Sector %s is now yours.\n", 
			xyas(sect.sct_x, sect.sct_y, player->cnum));
		sect.sct_mobil = 0;
	}
	if (infected && getvar(V_PTIME, (s_char *)&sect, EF_SECTOR) == 0)
		putvar(V_PTIME, PLG_EXPOSED, (s_char *)&sect, EF_SECTOR);
	if (vtype == V_CIVIL) {
		if (opt_NEW_WORK) {
			sect.sct_loyal =( (amt_dst * sect.sct_loyal) + 
					 (amount * loyal) ) / (amt_dst+amount);
			sect.sct_work =( (amt_dst * sect.sct_work) + 
					(amount * work) ) / (amt_dst+amount);
		} else {	/* ! NEW_WORK */

			/* It only takes one bad apple... */
			if (sect.sct_loyal < loyal)
				sect.sct_loyal = loyal;
			if (sect.sct_work > work)
				sect.sct_work = work;
		} /* end NEW_WORK */
	}
	putsect(&sect);
	return RET_OK;
}

/*ARGSUSED*/
static
explore_map(what, curx, cury, arg)
	s_char	*what;
	coord	curx, cury;
	s_char	*arg;
{
	struct	nstr_sect ns;
	struct	natstr *np;
	struct	sctstr sect;
	coord	rel_x, rel_y;
	s_char	range[128];
	s_char	view[7];
	int	i;
	int	changed = 0;

	np = getnatp(player->cnum);
	rel_x = xrel(np, curx);
	rel_y = yrel(np, cury);
	sprintf(range, "%d:%d,%d:%d", rel_x-2, rel_x+2, rel_y-1, rel_y+1);
	if (!snxtsct(&ns, range))
		return RET_FAIL;
	i = 0;
	while (i < 7 && nxtsct(&ns, &sect)) {
		view[i] = dchr[sect.sct_type].d_mnem;
		switch (sect.sct_type) {
		case SCT_WATER:
		case SCT_RURAL:
		case SCT_MOUNT:
		case SCT_WASTE:
			break;
		default:
			if (sect.sct_own != player->cnum && !player->god)
				view[i] = '?';
			break;
		}
		changed += map_set(player->cnum, ns.x, ns.y, view[i], 0);
		i++;
	}
	if (changed)
		writemap(player->cnum);
	if (!getsect(curx, cury, &sect))
		return RET_FAIL;
	pr("    %c %c         min gold fert  oil uran\n", view[0], view[1]);
	pr("   %c %c %c        %3d %4d %4d %4d %4d\n",
		view[2], view[3], view[4],
		sect.sct_min, sect.sct_gmin, sect.sct_fertil, sect.sct_oil,
		sect.sct_uran);
	pr("    %c %c\n", view[5], view[6]);
	return RET_OK;
}
