/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2012, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2021, 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-2012
+ * Markus Armbruster, 2004-2021
*/
#include <config.h>
+#include "chance.h"
#include "empobj.h"
-#include "file.h"
#include "item.h"
#include "land.h"
#include "map.h"
#include "nsc.h"
#include "nuke.h"
#include "optlist.h"
+#include "plague.h"
#include "plane.h"
#include "player.h"
#include "prototypes.h"
/*
* Get planes and escorts argument.
- * Read planes into *NI_BOMB, and (optional) escorts into *NI_ESC.
- * If INPUT_BOMB is not empty, use it, else prompt for more input.
- * Same for INPUT_ESC.
- * If we got a plane argument, initialize *NI_BOMB and *NI_ESC, and
+ * Read planes into *@ni_bomb, and (optional) escorts into *@ni_esc.
+ * If @input_bomb is not empty, use it, else prompt for more input.
+ * Same for @input_esc.
+ * If we got a plane argument, initialize *@ni_bomb and *@ni_esc, and
* return 0.
- * Else return -1 (*NI_BOMB and *NI_ESC may be modified).
+ * Else return -1 (*@ni_bomb and *@ni_esc may be modified).
*/
int
get_planes(struct nstr_item *ni_bomb, struct nstr_item *ni_esc,
/*
* Get assembly point argument.
- * If INPUT is not empty, use it, else prompt for more input using PROMPT.
- * If this yields a valid assembly point, read it into *AP_SECT and
- * return AP_SECT.
+ * If @input is not empty, use it.
+ * Else prompt for more input using @prompt.
+ * If this yields a valid assembly point, read it into *@ap_sect and
+ * return @ap_sect.
* Else complain and return NULL.
- * *AP_SECT and BUF[1024] may be modified in either case.
+ * *@ap_sect and @buf[1024] may be modified in either case.
*/
struct sctstr *
get_assembly_point(char *input, struct sctstr *ap_sect, char *buf)
/* over own or allied ship is fine */
snxtitem_xy(&ni, EF_SHIP, x, y);
while (nxtitem(&ni, &ship)) {
- if (ship.shp_effic < SHIP_MINEFF || ship.shp_own == 0)
+ if (!ship.shp_own)
continue;
if (relations_with(ship.shp_own, player->cnum) == ALLIED)
return ap_sect;
}
/*
- * Find out whether planes can fly one-way to X,Y.
+ * 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
+ * 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_where_to_land(coord x, coord y,
union empobj_storage *target, int *flagsp)
{
+ /* Keep conditions for landing consistent with pln_airbase_ok() */
int nships;
int cno;
int fl;
pr("Nowhere to land at sector %s!\n", xyas(x, y, player->cnum));
return -1;
}
+ /* clear to land at sector */
if (target->sect.sct_type == SCT_MOUNT) {
- pr("Nowhere to land at sector %s!\n", xyas(x, y, player->cnum));
- return -1;
+ *flagsp |= P_K;
}
- /* clear to land at sector */
if (target->sect.sct_type != SCT_AIRPT || target->sect.sct_effic < 60)
*flagsp |= P_V;
return 0;
cname(player->cnum), prplane(&plp->plane),
prship(&ship));
}
+ if (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->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);
if (amt > 0) {
getsect(tx, ty, §);
if (sect.sct_type != SCT_WATER) {
- pr("Your seamines have no effect here.\n");
+ pr("Your sea mines have no effect here.\n");
return;
}
sect.sct_mines = MIN(sect.sct_mines + amt, MINES_MAX);
}
/*
- * Has PP's type capabilities satisfying WANTFLAGS and NOWANTFLAGS?
+ * Has @pp's type capabilities satisfying @wantflags and @nowantflags?
* A plane type is capable unless
- * - it lacks all of the P_B, P_T in WANTFLAGS, or
- * - it lacks all of the P_F, P_ESC in WANTFLAGS, or
- * - it lacks all of the P_E, P_L, P_K in WANTFLAGS, or
- * - it lacks any of the other capabilities in WANTFLAGS, or
- * - it has any of the capabilities in NOWANTFLAGS.
+ * - it lacks all of the P_B, P_T in @wantflags, or
+ * - it lacks all of the P_F, P_ESC in @wantflags, or
+ * - it lacks all of the P_E, P_L, P_K in @wantflags, or
+ * - it lacks any of the other capabilities in @wantflags, or
+ * - it has any of the capabilities in @nowantflags.
*/
int
pln_capable(struct plnstr *pp, int wantflags, int nowantflags)
}
/*
- * Return union of capabilities of planes in LIST.
+ * Return union of capabilities of planes in @list.
*/
int
pln_caps(struct emp_qelem *list)
}
/*
- * Find plane types that can operate from carrier SP.
- * If MSL find missile types, else non-missile types.
+ * Find plane types that can operate from carrier @sp.
+ * If @msl find missile types, else non-missile types.
* Return a combination of P_L, P_K, P_E.
- * It's zero if SP can't support air operations due to its type or
+ * It's zero if @sp can't support air operations due to its type or
* state (low efficiency).
*/
int
return res;
}
+/*
+ * Can @pp operate out its sector?
+ * If @oneway, consider only takeoff, else takeoff and landing.
+ * If @noisy, report to current player when it can't.
+ */
int
pln_airbase_ok(struct plnstr *pp, int oneway, int noisy)
{
+ /* Keep conditions for landing consistent with pln_where_to_land() */
struct shpstr ship;
struct lndstr land;
struct sctstr sect;
return 0;
} else {
- /* sector: needs to be own or allied, efficient airfield */
+ /* sector: needs to be own or allied, efficient, suitable type */
if (!getsect(pp->pln_x, pp->pln_y, §)) {
CANT_REACH();
return 0;
}
+ /* mountain requires helo or missile */
+ if (sect.sct_type == SCT_MOUNT && !(pcp->pl_flags & (P_K | P_M))) {
+ if (noisy)
+ pr("(note) %s is in a mountain and can't take off\n",
+ prplane(pp));
+ return 0;
+ }
if (relations_with(sect.sct_own, pp->pln_own) != ALLIED) {
if (noisy)
continue;
if (opt_MARKET) {
if (ontradingblock(EF_PLANE, &plane)) {
- pr("plane #%d inelligible - it's for sale.\n",
+ pr("plane #%d ineligible - it's for sale.\n",
plane.pln_uid);
continue;
}
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;
}
case 'e': /* escort */
load = 0;
break;
- case 'i': /* missile interception */
- if (CANT_HAPPEN(!(pcp->pl_flags & P_M)
- || !(pcp->pl_flags & (P_N | P_O))))
- break;
- if (load)
- itype = I_SHELL;
- break;
default:
CANT_REACH();
load = 0;
needed = 0;
else {
pr("%s can't fly this mission"
- " while it is carrying a nuclear weapon",
+ " while it is carrying a nuclear weapon\n",
prplane(pp));
return -1;
}
/* We should do more, like make sure it's really
a carrier, etc. but for now just make sure it's
not sunk. */
- if (ship.shp_effic < SHIP_MINEFF) {
+ if (!ship.shp_own) {
mpr(pp->pln_own,
"Ship #%d has been sunk, plane #%d has nowhere to land, and\n"
"splashes into the sea.\n",
}
/*
- * 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
+ * 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.
*/
static int
}
/*
- * 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.
+ * 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
}
/*
- * Can PP be loaded on a ship of SP's type?
+ * Can @pp be loaded on a ship of @sp's type?
*/
int
could_be_on_ship(struct plnstr *pp, struct shpstr *sp)
}
int
-pln_damage(struct plnstr *pp, char type, int noisy)
+pln_damage(struct plnstr *pp, char type, char *noisy)
{
struct plchrstr *pcp = plchr + pp->pln_type;
int load, i, hitroll, aim, len;
aim = 100 - aim;
}
- len = 0;
+ len = noisy ? snprintf(buf, sizeof(buf), "%s", noisy) : 0;
while (i--) {
+ if (noisy) {
+ if (len > 75) {
+ mpr(pp->pln_own, "%s\n", buf);
+ len = 0;
+ }
+ }
dam += roll(6);
hitroll = roll(100);
if (hitroll >= 90) {
len += sprintf(buf + len, "blam");
}
if (noisy) {
- if (len > 75) {
- mpr(pp->pln_own, "%s\n", buf);
- len = 0;
- }
if (i)
len += sprintf(buf + len, "-");
}
}
/*
- * Set PP's tech to TLEV along with everything else that depends on it.
+ * Set @pp's tech to @tlev along with everything else that depends on it.
*/
void
pln_set_tech(struct plnstr *pp, int tlev)