/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2011, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
* Ken Stevens, Steve McClure, Markus Armbruster
*
* Empire is free software: you can redistribute it and/or modify
* Dave Pare, 1986
* Ken Stevens, 1995
* Steve McClure, 1998-2000
- * Markus Armbruster, 2004-2010
+ * Markus Armbruster, 2004-2012
*/
#include <config.h>
+#include "chance.h"
+#include "empobj.h"
#include "file.h"
#include "item.h"
#include "land.h"
-#include "lost.h"
#include "map.h"
#include "misc.h"
#include "nat.h"
#include "nsc.h"
#include "nuke.h"
#include "optlist.h"
-#include "path.h"
+#include "plague.h"
#include "plane.h"
#include "player.h"
#include "prototypes.h"
#include "ship.h"
#include "xy.h"
-static int fit_plane_on_ship(struct plnstr *, struct shpstr *);
+static int ship_can_carry(struct shpstr *, int, int, int, int);
+static int inc_shp_nplane(struct plnstr *, int *, int *, int *);
/*
* Get planes and escorts argument.
return NULL;
}
+/*
+ * Find out whether planes can fly one-way to X,Y.
+ * Offer the player any carriers there. If he chooses one, read it
+ * into TARGET->ship. Else read the target sector into TARGET->sect.
+ * If planes can land there, set required plane flags in *FLAGSP, and
+ * return 0. Else return -1.
+ */
int
-pln_onewaymission(struct sctstr *target, int *shipno, int *flagp)
+pln_where_to_land(coord x, coord y,
+ union empobj_storage *target, int *flagsp)
{
int nships;
int cno;
- int flags, fl;
- struct shpstr ship;
+ int fl;
char buf[1024];
char *p;
- flags = *flagp;
-
/* offer carriers */
- nships = carriersatxy(target->sct_x, target->sct_y, player->cnum);
+ nships = carriersatxy(x, y, player->cnum);
if (nships) {
for (;;) {
p = getstring("Carrier #? ", buf);
if (!*p)
break;
cno = atoi(p);
- if (cno < 0
- || !getship(cno, &ship)
+ if (!getship(cno, &target->ship)
|| (!player->owner
- && (relations_with(ship.shp_own, player->cnum)
+ && (relations_with(target->ship.shp_own, player->cnum)
!= ALLIED))) {
pr("Not yours\n");
continue;
}
- if (ship.shp_x != target->sct_x || ship.shp_y != target->sct_y) {
- pr("Ship #%d not in %s\n", cno,
- xyas(target->sct_x, target->sct_y, player->cnum));
+ if (target->ship.shp_x != x || target->ship.shp_y != y) {
+ pr("Ship #%d not in %s\n", cno, xyas(x, y, player->cnum));
continue;
}
- fl = carrier_planes(&ship, 0);
+ fl = carrier_planes(&target->ship, 0);
if (fl == 0) {
- pr("Can't land on %s.\n", prship(&ship));
+ pr("Can't land on %s.\n", prship(&target->ship));
continue;
}
/* clear to land on ship#CNO */
pr("landing on carrier %d\n", cno);
- flags |= fl;
- *shipno = cno;
- *flagp = flags;
+ *flagsp |= fl;
return 0;
}
}
/* try to land at sector */
- if (relations_with(target->sct_own, player->cnum) != ALLIED) {
- pr("Nowhere to land at sector %s!\n",
- xyas(target->sct_x, target->sct_y, player->cnum));
+ getsect(x, y, &target->sect);
+ if (relations_with(target->sect.sct_own, player->cnum) != ALLIED) {
+ pr("Nowhere to land at sector %s!\n", xyas(x, y, player->cnum));
return -1;
}
- if (target->sct_type == SCT_MOUNT) {
- pr("Nowhere to land at sector %s!\n",
- xyas(target->sct_x, target->sct_y, player->cnum));
+ if (target->sect.sct_type == SCT_MOUNT) {
+ pr("Nowhere to land at sector %s!\n", xyas(x, y, player->cnum));
return -1;
}
- if (target->sct_type != SCT_AIRPT || target->sct_effic < 60)
- flags |= P_V;
-
/* clear to land at sector */
- *shipno = -1;
- *flagp = flags;
+ if (target->sect.sct_type != SCT_AIRPT || target->sect.sct_effic < 60)
+ *flagsp |= P_V;
return 0;
}
int
-pln_oneway_to_carrier_ok(struct emp_qelem *bomb_list,
- struct emp_qelem *esc_list, int cno)
+pln_can_land_on_carrier(struct emp_qelem *bomb_list,
+ struct emp_qelem *esc_list,
+ struct shpstr *sp)
+
{
+ int n, nch, nxl, nmsl;
struct emp_qelem *list, *qp;
struct plist *plp;
- struct shpstr ship;
- if (cno < 0 || !getship(cno, &ship))
- return 0;
+ n = shp_nplane(sp, &nch, &nxl, &nmsl);
/* for both lists */
for (list = bomb_list;
list = list == bomb_list ? esc_list : NULL) {
for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
plp = (struct plist *)qp;
- if (plp->plane.pln_ship == ship.shp_uid)
+ if (plp->plane.pln_ship == sp->shp_uid)
continue;
- if (!fit_plane_on_ship(&plp->plane, &ship))
+ n++;
+ if (!inc_shp_nplane(&plp->plane, &nch, &nxl, &nmsl))
return 0;
}
}
- return 1;
+ return ship_can_carry(sp, n, nch, nxl, nmsl);
}
void
for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
plp = (struct plist *)qp;
if (cno >= 0) {
- if (!could_be_on_ship(&plp->plane, &ship, 0, 0, 0, 0))
+ if (!could_be_on_ship(&plp->plane, &ship))
pr("\t%s cannot land on ship #%d! %s aborts!\n",
prplane(&plp->plane), cno, prplane(&plp->plane));
else if (!put_plane_on_ship(&plp->plane, &ship))
cname(player->cnum), prplane(&plp->plane),
prship(&ship));
}
+ if (plp->pcp->pl_crew && plp->pstage == PLG_INFECT
+ && ship.shp_pstage == PLG_HEALTHY)
+ ship.shp_pstage = PLG_EXPOSED;
}
} else {
plp->plane.pln_x = tx;
cname(player->cnum),
prplane(&plp->plane), xyas(tx, ty, sect.sct_own));
}
+ if (plp->pcp->pl_crew && plp->pstage == PLG_INFECT
+ && sect.sct_pstage == PLG_HEALTHY)
+ sect.sct_pstage = PLG_EXPOSED;
plp->plane.pln_ship = cno;
}
}
struct shpstr ship;
int there;
int max;
+ int pstage;
if (!ip)
return;
- amt = 0;
- for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
- plp = (struct plist *)qp;
- amt += plp->load;
- }
if (cno < 0) {
getsect(tx, ty, §);
if (!sect.sct_own) {
}
there = sect.sct_item[ip->i_uid];
max = ITEM_MAX;
+ pstage = sect.sct_pstage;
} else {
getship(cno, &ship);
there = ship.shp_item[ip->i_uid];
max = mchr[ship.shp_type].m_item[ip->i_uid];
+ pstage = ship.shp_pstage;
}
+
+ amt = 0;
+ for (qp = list->q_forw; qp != list; qp = qp->q_forw) {
+ plp = (struct plist *)qp;
+ amt += plp->load;
+ if (plp->load
+ && plp->pstage == PLG_INFECT && pstage == PLG_HEALTHY)
+ pstage = PLG_EXPOSED;
+ }
+
there += amt;
if (there > max) {
pr("%d excess %s discarded\n", there - max, ip->i_name);
pr("%d %s landed safely", amt, ip->i_name);
if (cno < 0) {
sect.sct_item[ip->i_uid] = there;
+ sect.sct_pstage = pstage;
if (sect.sct_own != player->cnum)
wu(0, sect.sct_own, "%s planes drop %d %s in %s\n",
cname(player->cnum), amt, ip->i_name,
putsect(§);
} else {
ship.shp_item[ip->i_uid] = there;
+ ship.shp_pstage = pstage;
if (ship.shp_own != player->cnum)
wu(0, ship.shp_own, "%s planes land %d %s on carrier %d\n",
cname(player->cnum), amt, ip->i_name, ship.shp_uid);
putplane(plane.pln_uid, &plane);
plp = malloc(sizeof(struct plist));
plp->load = 0;
+ plp->pstage = PLG_HEALTHY;
plp->pcp = pcp;
plp->plane = plane;
emp_insque(&plp->queue, list);
pcp = plp->pcp;
if (pp->pln_ship >= 0) {
getship(pp->pln_ship, &ship);
+ plp->pstage = ship.shp_pstage;
item = ship.shp_item;
own = ship.shp_own;
} else if (pp->pln_land >= 0) {
getland(pp->pln_land, &land);
+ plp->pstage = land.lnd_pstage;
item = land.lnd_item;
own = land.lnd_own;
} else {
getsect(pp->pln_x, pp->pln_y, §);
+ plp->pstage = sect.sct_pstage;
item = sect.sct_item;
own = sect.sct_oldown;
}
}
/*
- * Can PP be loaded on a ship of SP's type?
- * Assume that it already carries N planes, of which NCH are choppers,
- * NXL xlight, NMSL light missiles, and the rest are light fixed-wing
+ * Can a carrier of SP's type carry this load of planes?
+ * The load consists of N planes, of which NCH are choppers, NXL
+ * xlight, NMSL light missiles, and the rest are light fixed-wing
* planes.
*/
-int
-could_be_on_ship(struct plnstr *pp, struct shpstr *sp,
- int n, int nch, int nxl, int nmsl)
+static int
+ship_can_carry(struct shpstr *sp, int n, int nch, int nxl, int nmsl)
{
- struct plchrstr *pcp = &plchr[pp->pln_type];
struct mchrstr *mcp = &mchr[sp->shp_type];
- int nfw;
-
- if (pcp->pl_flags & P_K)
- nch++;
- else if (pcp->pl_flags & P_E)
- nxl++;
- else if (!(pcp->pl_flags & P_L))
- return 0;
- else if (pcp->pl_flags & P_M)
- nmsl++;
- n++;
- nfw = n - nch - nxl - nmsl;
+ int nfw = n - nch - nxl - nmsl;
if (nch > mcp->m_nchoppers) /* overflow into fixed-wing slots */
nfw += nch - mcp->m_nchoppers;
}
/*
- * Fit a plane of PP's type on ship SP.
- * Updating the plane accordingly is the caller's job.
- * Return whether it fits.
+ * Increment carrier plane counters for PP.
+ * If it's a chopper, increment *NCH.
+ * Else, if it's x-light, increment *NXL.
+ * Else, if it's a light missile, increment *MSL.
+ * Return non-zero if it's a chopper, x-light or light.
*/
static int
-fit_plane_on_ship(struct plnstr *pp, struct shpstr *sp)
+inc_shp_nplane(struct plnstr *pp, int *nch, int *nxl, int *nmsl)
{
- int n, nch, nxl, nmsl;
+ struct plchrstr *pcp = &plchr[pp->pln_type];
- n = shp_nplane(sp, &nch, &nxl, &nmsl);
- return could_be_on_ship(pp, sp, n, nch, nxl, nmsl);
+ if (pcp->pl_flags & P_K)
+ (*nch)++;
+ else if (pcp->pl_flags & P_E)
+ (*nxl)++;
+ else if (!(pcp->pl_flags & P_L))
+ return 0;
+ else if (pcp->pl_flags & P_M)
+ (*nmsl)++;
+ return 1;
+}
+
+/*
+ * Can PP be loaded on a ship of SP's type?
+ */
+int
+could_be_on_ship(struct plnstr *pp, struct shpstr *sp)
+{
+ int nch = 0, nxl = 0, nmsl = 0;
+
+ if (!inc_shp_nplane(pp, &nch, &nxl, &nmsl))
+ return 0;
+ return ship_can_carry(sp, 1, nch, nxl, nmsl);
}
int
put_plane_on_ship(struct plnstr *plane, struct shpstr *ship)
{
+ int n, nch, nxl, nmsl;
+
if (plane->pln_ship == ship->shp_uid)
return 1; /* Already on ship */
- if (!fit_plane_on_ship(plane, ship))
- return 0;
+ n = shp_nplane(ship, &nch, &nxl, &nmsl);
+ if (!inc_shp_nplane(plane, &nch, &nxl, &nmsl))
+ return 0; /* not a carrier plane */
+ if (!ship_can_carry(ship, n + 1, nch, nxl, nmsl))
+ return 0; /* no space */
plane->pln_x = ship->shp_x;
plane->pln_y = ship->shp_y;
return 1;
}
-/*
- * Fit a plane of PP's type on land unit LP.
- * Updating the plane accordingly is the caller's job.
- * Return whether it fits.
- */
-static int
-fit_plane_on_land(struct plnstr *pp, struct lndstr *lp)
-{
- struct plchrstr *pcp = plchr + pp->pln_type;
- struct lchrstr *lcp = lchr + lp->lnd_type;
-
- return (pcp->pl_flags & P_E) && lnd_nxlight(lp) < lcp->l_nxlight;
-}
-
int
put_plane_on_land(struct plnstr *plane, struct lndstr *land)
{
if (plane->pln_land == land->lnd_uid)
return 1; /* Already on unit */
-
- if (!fit_plane_on_land(plane, land))
+ if (!(plchr[plane->pln_type].pl_flags & P_E))
+ return 0;
+ if (lnd_nxlight(land) >= lchr[land->lnd_type].l_nxlight)
return 0;
plane->pln_x = land->lnd_x;