#ifndef lint
static char *RCSid = "$Header: assa.c,v 1.18 89/11/28 11:25:48 mr-frog Exp $";
#endif /* not lint */

/*
 * assa.c
 *
 * hit the beaches!
 *
 * from PSL Empire, 1985
 */

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

static	lostship();

assa()
{
	extern	char *argp[];
	extern	int btused;
	register int troops;
	struct	sctstr sect;
	struct	sctstr from;
	struct	shpstr ship;
	coord	x, y;
	coord	shx, shy;
	int	shnu;
	natid	own;
	int	sdef;
	int	fdef;
	int	a_mil;
	int	s_mil;
	int	a_dead;
	int	d_dead;
	int	defenders;
	double	def;
	int	taken;
	double	odds;
	double	food;
	int	vec[I_MAX+1];
	int	pvec[I_MAX+1];
	int	svec[I_MAX+1];
	char	*p;
	float	food_per_trooper;
#ifdef SLOW_WAR
        int     rel;
        struct natstr   *natp;
#endif /* SLOW_WAR */
#ifdef BETTERARMOR
	struct	mchrstr *mcp;
#endif /* BETTERARMOR */
#ifdef SNEAK_ATTACK
	char	y_or_n[80], *ppp=(char *)0;
#endif /* SNEAK_ATTACK */

	if (!(p = getstarg(argp[1], "Sector :  ")) ||
	    !sarg_xy(p, &x, &y) || !getsect(x, y, &sect))
		return RET_SYN;
	shnu = onearg(argp[2],
		fmt("Assault sector %s from ship #", xyas(x,y,cnum)));
	if (shnu < 0) {
		pr("You may only assault from one ship!\n");
		return RET_SYN;
	}
	if (!getship(shnu, &ship) || ship.shp_own != cnum) {
		pr("Not your ship.\n");
		return RET_FAIL;
	}
	shx = ship.shp_x;
	shy = ship.shp_y;
	if (mapdist(shx, shy, x, y) > 1) {
		pr("You'll have to get there first...\n");
		return RET_FAIL;
	}
	own = sect.sct_own;
#ifndef OWNASSAULT
	if (own == cnum) {
		pr("That's your own sector!\n");
		return RET_FAIL;
	}
#endif /* OWNASSAULT */
#ifdef SLOW_WAR
        natp = getnatp(cnum);
        rel = getrel(natp,own);
#ifdef OWNASSAULT
	if (own != cnum)
#endif /* OWNASSAULT */
#ifdef SNEAK_ATTACK
        if ((rel != AT_WAR) && (own) && (sect.sct_oldown != cnum) &&
	    (rel != SITZKRIEG) && (rel != MOBILIZATION)) {
		pr("You're not at war with them!\n");
		while (!ppp || ((*ppp != 'y') && (*ppp != 'n'))){
			bzero(y_or_n,80);
			if (ppp && (*ppp != 'y') && (*ppp != 'n'))
				pr("Answer y or n!\n");

			ppp=getstarg(y_or_n,fmt("Do you really want to sneak attack [yn]? "));
			if (isupper(*ppp))
				*ppp=tolower(*ppp);
		}
		if (*ppp != 'y'){
			pr("Sneak attack cancelled!\n");
			return RET_FAIL;
		}
	}

        if ((rel != AT_WAR) && (own) && (sect.sct_oldown != cnum) &&
	    ((rel == SITZKRIEG) || (rel == MOBILIZATION))) {
#else
        if ((rel != AT_WAR) && (own) && (sect.sct_oldown != cnum)){
#endif /* SNEAK_ATTACK */
                pr("You're not at war with them!\n");
                return RET_FAIL;
        }
#endif /* SLOW_WAR */
	if (sect.sct_type <= SCT_WASTE) {
		pr("Don't bother...\n");
		return RET_FAIL;
	}
	getvec(VT_ITEM, vec, (char *)&ship, EF_SHIP);
	if ((a_mil = vec[I_MILIT]) == 0) {
		pr(fmt("No military on ship #%d", shnu));
		return RET_FAIL;
	}
	if ((x != shx || y != shy) &&
	    (!getsect(shx, shy, &from) || from.sct_type != SCT_WATER)) {
		pr("Your ship can not attack that far inland!\n");
		return RET_FAIL;
	}
	if (own && !trechk(cnum, own, LANATT))
		return RET_FAIL;
	if(!getsect(x, y, &sect))
		return RET_FAIL;
	getvec(VT_ITEM, svec, (char *)&sect, EF_SECTOR);
	s_mil = svec[I_MILIT];
	pr(fmt("Sector %s is a %d%% %s with approx. %d military.\n",
		xyas(x, y, cnum), round((int)sect.sct_effic, 10),
		dchr[sect.sct_type].d_name,
		round(s_mil, 10)));
#ifdef OWNASSAULT
	if (own != cnum){
#endif /* OWNASSAULT */
	if (s_mil && !(mchr[ship.shp_type].m_flags & M_LAND))
		a_mil /= 10;
#ifdef SEMILAND
	if (s_mil && (mchr[ship.shp_type].m_flags & M_SEMILAND)){
		a_mil *= 10;
		a_mil /= 4;
	}
#endif /* SEMILAND */
#ifdef OWNASSAULT
	}
#endif /* OWNASSAULT */
	troops = onearg(argp[3],fmt("Number of troops in assault? (max %d) ",
		a_mil));
	troops = min(troops, a_mil);
	if (troops <= 0)
		return RET_FAIL;

	if (!getship(shnu, &ship) || ship.shp_own != cnum) {
		pr("Your ship has been lost!\n");
		return RET_FAIL;
	}

	if(!getsect(x, y, &sect))
		return RET_FAIL;
	getvec(VT_ITEM, svec, (char *)&sect, EF_SECTOR);
	/*
	 * NOTE: need getcom here
	 */
	food = vec[I_FOOD];
	taken = (int) (food * troops / (vec[I_MILIT] + vec[I_CIVIL]) + 0.5);
	if ((taken == food) && taken)
		taken -= 1;
	vec[I_MILIT] -= troops;
	vec[I_FOOD] -= taken;
	putvec(VT_ITEM, vec, (char *)&ship, EF_SHIP);
	food_per_trooper = (float) taken / troops;
#ifdef OWNASSAULT
	if (own != cnum){
#endif /* OWNASSAULT */
	def = (dchr[sect.sct_type].d_dstr / 2.0 - 1.0) *
		(sect.sct_effic / 100.0) + 1.0;
	odds = (double) troops / (s_mil * def * 2 + troops);
	pr(fmt("Your success odds are %.1f%%\n", odds * 100.0));
	sdef = seadef(ship.shp_type);
	fdef = fortdef(&sect, sdef, shx, shy);
	if (fdef > 0) {
#ifdef BETTERARMOR
		mcp = &mchr[ship.shp_type];
		fdef = ((float)fdef*(63.0/(float)mcp->m_armor));
#endif /* BETTERARMOR */
		shipdamage(&ship, fdef);
		putship(shnu, &ship);
		if (ship.shp_own == 0) {
			lostship(x, y, cnum, own, ship);
			return RET_OK;
		}
		troops = ((100 - fdef) * troops) / 100.0 + 0.5;
		odds = (double) troops / (s_mil * 2 + troops);
		pr(fmt("Your success odds are now %.1f%%\n", odds * 100.0));
	}
	fdef = defdef(own, sdef, shx, shy);
#ifdef BETTERARMOR
	mcp = &mchr[ship.shp_type];
	fdef = ((float)fdef*(63.0/(float)mcp->m_armor));
#endif /* BETTERARMOR */
	if (fdef > 0) {
#ifdef MERC
		if(own != 0)
#endif
		wu(0, own, 
#ifdef	SHIPNAMES
			fmt("Fortress(es) defending %s did %d%% damage to %s %s(#%d)",
			xyas(sect.sct_x, sect.sct_y, own), fdef,
			mchr[ship.shp_type].m_name, ship.shp_name, shnu));
#else
			fmt("Fortress(es) defending %s did %d%% damage to %s #%d",
			xyas(sect.sct_x, sect.sct_y, own), fdef,
			mchr[ship.shp_type].m_name, shnu));
#endif	SHIPNAMES
		shipdamage(&ship, fdef);
		putship(shnu, &ship);
		if (ship.shp_own == 0) {
			lostship(x, y, cnum, own, ship);
			return RET_OK;
		}
		troops = ((100 - fdef) * troops) / 100.0 + 0.5;
		odds = (double) troops / (s_mil * 2 + troops);
		pr(fmt("Your success odds are now %.1f%%\n", odds * 100.0));
	}
	fdef = shipdef(own, sdef, shx, shy);
#ifdef BETTERARMOR
	mcp = &mchr[ship.shp_type];
	fdef = ((float)fdef*(63.0/(float)mcp->m_armor));
#endif /* BETTERARMOR */
	if (fdef > 0) {
#ifdef MERC
		if(own != 0)
#endif
#ifdef	SHIPNAMES
		wu(0, own, fmt("Return fire did %d%% damage to %s %s(#%d)",
			fdef, mchr[ship.shp_type].m_name, ship.shp_name, shnu));
#else
		wu(0, own, fmt("Return fire did %d%% damage to %s #%d",
			fdef, mchr[ship.shp_type].m_name, shnu));
#endif	SHIPNAMES
		shipdamage(&ship, fdef);
		putship(shnu, &ship);
		if (ship.shp_own == 0) {
			lostship(x, y, cnum, own, ship);
			return RET_OK;
		}
		troops = ((100 - fdef) * troops) / 100.0 + 0.5;
		odds = (double) troops / (s_mil * 2 + troops);
		pr(fmt("Your success odds are now %.1f%%\n", odds * 100.0));
	}
	if (troops == 0) {
		lostship(x,y,cnum,own,ship);
		return RET_OK;
	}
	defenders = s_mil;
	a_dead = d_dead = 0;
	while (defenders > 0) {
		if (troops <= 0)
			break;
		if (chance(odds) == 0) {
			pr("@");
			a_dead++;
			troops--;
		} else {
			pr("!");
			d_dead++;
			defenders--;
		}
	}
	if (own != 0)
#ifdef MERC
		if(own != 0)
#endif
		wu(0, own,
#ifdef	SHIPNAMES
	        fmt("%s (#%d) assaulted %s%s from %s %s(#%d); yours %d, theirs %d\n",
		    cname(cnum), cnum, troops ? "(and took) " : " ",
		    xyas(x, y, own), mchr[ship.shp_type].m_name,
		    ship.shp_name, ship.shp_uid, d_dead, a_dead));
#else
	        fmt("%s (#%d) assaulted %s%s from %s #%d; yours %d, theirs %d\n",
		    cname(cnum), cnum, troops ? "(and took) " : " ",
		    xyas(x, y, own), mchr[ship.shp_type].m_name,
		    ship.shp_uid, d_dead, a_dead));
#endif	SHIPNAMES
#ifdef OWNASSAULT
	}
#endif /* OWNASSAULT */
	if (troops > 0) {
#ifdef OWNASSAULT
		if (own == cnum){
			pr(fmt("\nYou reinforce sector %s with %d troops\n",
				xyas(x,y,cnum), troops));
			svec[I_MILIT] += troops;
			svec[I_FOOD] += roundavg(troops * food_per_trooper);
		}else{
#endif /* OWNASSAULT */
#ifdef SNEAK_ATTACK
                if (rel != AT_WAR && own) {
                        pr(fmt("Your sneak attack was successful\n"));
                        pr(fmt("But it will cost you $5000\n"));
                        pr(fmt("War has been declared!!!!\n"));
                        wu(0,own,
                           fmt("Country %s (#%d) has Sneak Attacked!!\n",
                               cname(cnum),cnum)); 
                        wu(0,own,
                           fmt("Country %s (#%d) has Declared WAR on you!!\n",
                               cname(cnum),cnum)); 
                        dolcost += 5000;
                        rel = MOBILIZATION;
                        nreport(cnum, N_DECL_WAR, own, 1);
                        setrel(cnum,own,rel);
                }
#endif /* SNEAK_ATTACK */
		pr(fmt("\nYou have taken sector %s\n", xyas(x,y,cnum)));
		nreport(cnum, N_WON_SECT, own, 1);
		troops = takeover(&sect, troops);
		sect.sct_mobil = 0;
		svec[I_MILIT] = troops;
		svec[I_FOOD] += roundavg(troops * food_per_trooper);
		if (sect.sct_type == SCT_CAPIT)
			caploss(&sect, own,
				"which happens to be %s's capital!\n");
#ifdef OWNASSAULT
		}
#endif /* OWNASSAULT */
	} else {
#ifdef OWNASSAULT
		if (own != cnum){
#endif /* OWNASSAULT */
		pr("\nYou have been defeated!\n");
		nreport(cnum, N_SCT_LOSE, own, 1);
#ifdef SNEAK_ATTACK
                if (rel != AT_WAR && own) {
                        pr(fmt("Your sneak attack was unsuccessful\n"));
                        pr(fmt("But it will cost you $5000\n"));
                        pr(fmt("War has been declared!!!!\n"));
                        wu(0,own,
                           fmt("Country %s (#%d) has Sneak Attacked!!\n",
                               cname(cnum),cnum)); 
                        wu(0,own,
                           fmt("Country %s (#%d) has Declared WAR on you!!\n",
                               cname(cnum),cnum)); 
                        dolcost += 5000;
                        rel = MOBILIZATION;
                        nreport(cnum, N_DECL_WAR, own, 1);
                        setrel(cnum,own,rel);
                }
#endif /* SNEAK_ATTACK */
		svec[I_MILIT] = defenders;
#ifdef OWNASSAULT
		}
#endif /* OWNASSAULT */
	}
	putvec(VT_ITEM, svec, (char *)&sect, EF_SECTOR);
	/* You've touched 'em -- give 'em plague if even you've lost! */
	getvec(VT_COND, vec, (char *)&ship, EF_SHIP);
	if (vec[C_PSTAGE] == PLG_INFECT) {
		getvec(VT_COND, pvec, (char *)&sect, EF_SECTOR);
		if (pvec[C_PSTAGE] == PLG_HEALTHY) {
			pvec[C_PSTAGE] = PLG_EXPOSED;
			putvec(VT_COND, pvec, (char *)&sect, EF_SECTOR);
		}
	}
	putsect(&sect);
	putship(shnu, &ship);
#ifdef OWNASSAULT
	if (own != cnum){
#endif /* OWNASSAULT */
	pr(fmt("Casualties :\nYours... %3d\nTheirs.. %3d\n", a_dead, d_dead));
	btused += (int) ((d_dead + a_dead) * 0.15 + 0.5);
#ifdef OWNASSAULT
	}
#endif /* OWNASSAULT */
	return RET_OK;
}

static
lostship(x, y, ctrynum, own, ship)
	coord	x;
	coord	y;
	natid	ctrynum;
	natid	own;
	struct	shpstr ship;
{
	char	*p;

#ifdef	SHIPNAMES
	p = fmt("%s (#%d) assaulted %s from %s %s(#%d)",cname(ctrynum), ctrynum,
		xyas(x, y, own), mchr[ship.shp_type].m_name, ship.shp_name,
		ship.shp_uid);
#else
	p = fmt("%s (#%d) assaulted %s from %s #%d", cname(ctrynum), ctrynum,
		xyas(x, y, own), mchr[ship.shp_type].m_name, ship.shp_uid);
#endif	SHIPNAMES
#ifdef MERC
	if(own != 0)
#endif
	wu(0, own, p);
	nreport(ctrynum, N_ASSAULT_LOSE, own, 1);
}

