/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak,
- * Ken Stevens, Steve McClure
+ * Copyright (C) 1986-2020, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Ken Stevens, Steve McClure, Markus Armbruster
*
- * This program is free software; you can redistribute it and/or modify
+ * Empire is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ---
*
* ---
*
* cargo.c: Cargo lists
- *
+ *
* Known contributors to this file:
- * Markus Armbruster, 2008
+ * Markus Armbruster, 2009
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
-#include "file.h"
+#include <string.h>
#include "unit.h"
struct clink {
- short next;
- short head[EF_NUKE - EF_PLANE + 1];
+ int next;
+ int head[EF_NUKE - EF_PLANE + 1];
};
/*
* Cargo lists
*
* Persistent game state encodes "who carries what" by storing the
- * carrier uid in the cargo. Cargo lists augment that: they store
+ * carrier UID in the cargo. Cargo lists augment that: they store
* lists of cargo for each carrier.
*
* clink[TYPE] points to an array of cargo list links. The array has
* EF_NUKE. Other slots of clink[] and nclink[] are unused and remain
* zero.
*
- * clink[TYPE][UID].next is the uid of the next unit of the same type
+ * clink[TYPE][UID].next is the UID of the next unit of the same type
* in the same carrier, -1 if none.
*
- * clink[TYPE][UID].head[CARGO-EF_PLANE] is the uid of the first unit
+ * clink[TYPE][UID].head[CARGO-EF_PLANE] is the UID of the first unit
* of type CARGO carried by this unit, -1 if none. The next unit, if
* any, is clink[CARGO][clink[TYPE][UID].head[CARGO-EF_PLANE]].next,
* and so forth.
* cargo lists know nothing about that.
*/
static struct clink *clink[EF_NUKE + 1];
-static short nclink[EF_NUKE + 1];
+static int nclink[EF_NUKE + 1];
/*
- * Return pointer to CL's cargo list head for file type TYPE.
+ * Return pointer to @cl's cargo list head for file type @type.
*/
-static short *
+static int *
clink_headp(struct clink *cl, int type)
{
- static short dummy;
+ static int dummy;
if (CANT_HAPPEN(type < EF_PLANE || type > EF_NUKE)) {
dummy = -1;
}
/*
- * Initialize cargo list link CL to empty.
+ * Initialize cargo list link @cl to empty.
*/
static void
clink_init(struct clink *cl)
}
/*
- * Check whether *UIDP is a valid uid for file type TYPE.
+ * Check whether *@uidp is a valid UID for file type @type.
*/
static void
-clink_check1(short *uidp, int type)
+clink_check1(int *uidp, int type)
{
if (CANT_HAPPEN(*uidp >= nclink[type]))
*uidp = -1;
}
/*
- * Check validity of cargo lists for file type TYPE.
+ * Check validity of cargo lists for file type @type.
*/
static void
clink_check(int type)
}
/*
- * Add to CL's cargo list for type TYPE the uid UID.
- * UID must not be on any cargo list already.
+ * Add to @cl's cargo list for type @type the UID @uid.
+ * @uid must not be on any cargo list already.
*/
static void
clink_add(struct clink *cl, int type, int uid)
{
- short *head = clink_headp(cl, type);
+ int *head = clink_headp(cl, type);
if (CANT_HAPPEN(type < 0 || type > EF_NUKE
|| uid < 0 || uid >= nclink[type]))
}
/*
- * Remove from CL's cargo list for type TYPE the uid UID.
- * UID must be on that cargo list.
+ * Remove from @cl's cargo list for type @type the UID @uid.
+ * @uid must be on that cargo list.
*/
static void
clink_rem(struct clink *cl, int type, int uid)
{
- short *head = clink_headp(cl, type);
+ int *head = clink_headp(cl, type);
struct clink *linkv;
int n;
- short *p;
+ int *p;
if (CANT_HAPPEN(type < 0 || type > EF_NUKE))
return;
}
/*
- * Update cargo lists for a change of CARGO's carrier.
- * Carrier is of type TYPE, and changes from uid OLD to NEW.
- * Negative uids mean no carrier.
+ * Update cargo lists for a change of @cargo's carrier.
+ * Carrier is of type @type, and changes from UID @old to @new.
+ * Negative UIDs mean no carrier.
*/
void
unit_carrier_change(struct empobj *cargo, int type, int old, int new)
{
if (CANT_HAPPEN(type < 0 || type > EF_NUKE))
return;
- if (old >= 0)
+ if (old >= 0 && !CANT_HAPPEN(old >= nclink[type]))
clink_rem(&clink[type][old], cargo->ef_type, cargo->uid);
- if (new >= 0)
+ if (new >= 0 && !CANT_HAPPEN(new >= nclink[type]))
clink_add(&clink[type][new], cargo->ef_type, cargo->uid);
}
/*
- * Update cargo lists for a change of PP's carrier.
- * Carrier is of type TYPE, and changes from uid OLD to NEW.
- * Negative uids mean no carrier.
+ * Update cargo lists for a change of @pp's carrier.
+ * Carrier is of type @type, and changes from UID @old to @new.
+ * Negative UIDs mean no carrier.
*/
void
pln_carrier_change(struct plnstr *pp, int type, int old, int new)
}
/*
- * Update cargo lists for a change of LP's carrier.
- * Carrier is of type TYPE, and changes from uid OLD to NEW.
- * Negative uids mean no carrier.
+ * Update cargo lists for a change of @lp's carrier.
+ * Carrier is of type @type, and changes from UID @old to @new.
+ * Negative UIDs mean no carrier.
*/
void
lnd_carrier_change(struct lndstr *lp, int type, int old, int new)
}
/*
- * Update cargo lists for a change of NP's carrier.
- * Carrier is of type TYPE, and changes from uid OLD to NEW.
- * Negative uids mean no carrier.
+ * Update cargo lists for a change of @np's carrier.
+ * Carrier is of type @type, and changes from UID @old to @new.
+ * Negative UIDs mean no carrier.
*/
void
nuk_carrier_change(struct nukstr *np, int type, int old, int new)
struct lndstr *lp;
struct nukstr *np;
- for (i = EF_SHIP; i <= EF_NUKE; i++) {
- nclink[i] = 0;
+ memset(nclink, 0, sizeof(nclink));
+ for (i = EF_SHIP; i <= EF_NUKE; i++)
unit_onresize(i);
- }
for (i = 0; (pp = getplanep(i)); i++) {
- if (!pp->pln_own)
+ if (!pp->pln_own) {
+ if (CANT_HAPPEN(pp->pln_ship >= 0 || pp->pln_land >= 0))
+ pp->pln_ship = pp->pln_land = -1;
continue;
+ }
if (CANT_HAPPEN(pp->pln_ship >= 0 && pp->pln_land >= 0))
pp->pln_land = -1;
pln_carrier_change(pp, EF_SHIP, -1, pp->pln_ship);
pln_carrier_change(pp, EF_LAND, -1, pp->pln_land);
}
for (i = 0; (lp = getlandp(i)); i++) {
- if (!lp->lnd_own)
+ if (!lp->lnd_own) {
+ if (CANT_HAPPEN(lp->lnd_ship >= 0 || lp->lnd_land >= 0))
+ lp->lnd_ship = lp->lnd_land = -1;
continue;
+ }
if (CANT_HAPPEN(lp->lnd_ship >= 0 && lp->lnd_land >= 0))
lp->lnd_land = -1;
lnd_carrier_change(lp, EF_SHIP, -1, lp->lnd_ship);
lnd_carrier_change(lp, EF_LAND, -1, lp->lnd_land);
}
for (i = 0; (np = getnukep(i)); i++) {
- if (!np->nuk_own)
+ if (!np->nuk_own) {
+ if (CANT_HAPPEN(np->nuk_plane >= 0))
+ np->nuk_plane = -1;
continue;
+ }
nuk_carrier_change(np, EF_PLANE, -1, np->nuk_plane);
}
}
/*
- * Resize clink[TYPE] to match ef_nelem(TYPE).
+ * Resize clink[@type] to match ef_nelem(@type).
* Return 0 on success, -1 on error.
* This is the struct empfile onresize callback for units.
*/
-int
+void
unit_onresize(int type)
{
int n, i;
struct clink *cl;
if (CANT_HAPPEN(type < EF_SHIP || type > EF_NUKE))
- return -1;
+ return;
n = ef_nelem(type);
cl = realloc(clink[type], n * sizeof(*clink[type]));
clink_init(&cl[i]);
clink[type] = cl;
nclink[type] = n;
- clink_check(type);
- return 0;
+ if (ef_flags(type) & EFF_MEM)
+ clink_check(type);
}
/*
- * Find first unit on a carrier's cargo list for file type CARGO_TYPE.
- * Search carrier UID of type TYPE.
- * Return first unit's uid, or -1 if the carrier isn't carrying such
+ * Find first unit on a carrier's cargo list for file type @cargo_type.
+ * Search carrier @uid of type @type.
+ * Return first unit's UID, or -1 if the carrier isn't carrying such
* units.
*/
int
unit_cargo_first(int type, int uid, int cargo_type)
{
- short *headp;
+ int *headp;
if (CANT_HAPPEN(type < EF_SHIP || type > EF_NUKE))
return -1;
}
/*
- * Find the next unit on a cargo list for file type CARGO_TYPE.
- * Get the unit after CARGO_UID.
- * Return its uid, or -1 if there are no more on this list.
+ * Find the next unit on a cargo list for file type @cargo_type.
+ * Get the unit after @cargo_uid.
+ * Return its UID, or -1 if there are no more on this list.
*/
int
unit_cargo_next(int cargo_type, int cargo_uid)
}
/*
- * If SP carries planes, return the uid of the first one, else -1.
+ * If @sp carries planes, return the UID of the first one, else -1.
*/
int
pln_first_on_ship(struct shpstr *sp)
}
/*
- * If LP carries planes, return the uid of the first one, else -1.
+ * If @lp carries planes, return the UID of the first one, else -1.
*/
int
pln_first_on_land(struct lndstr *lp)
}
/*
- * Find the next plane on the same carrier as plane#UID.
- * Return its uid, or -1 if there are no more.
+ * Find the next plane on the same carrier as plane#@uid.
+ * Return its UID, or -1 if there are no more.
*/
int
pln_next_on_unit(int uid)
}
/*
- * If SP carries land units, return the uid of the first one, else -1.
+ * If @sp carries land units, return the UID of the first one, else -1.
*/
int
lnd_first_on_ship(struct shpstr *sp)
}
/*
- * If SP carries land units, return the uid of the first one, else -1.
+ * If @lp carries land units, return the UID of the first one, else -1.
*/
int
lnd_first_on_land(struct lndstr *lp)
}
/*
- * Find the next land unit on the same carrier as land#UID.
- * Return its uid, or -1 if there are no more.
+ * Find the next land unit on the same carrier as land#@uid.
+ * Return its UID, or -1 if there are no more.
*/
int
lnd_next_on_unit(int uid)
}
/*
- * If PP carries a nuke, return its uid, else -1.
+ * If @pp carries a nuke, return its UID, else -1.
*/
int
nuk_on_plane(struct plnstr *pp)
}
/*
- * Return length of a carrier's cargo list for file type CARGO_TYPE.
+ * Return length of a carrier's cargo list for file type @cargo_type.
+ * Use carrier @uid of type @type.
*/
int
unit_cargo_count(int type, int uid, int cargo_type)
}
/*
- * Return number of land units loaded on SP.
+ * Return number of land units loaded on @sp.
*/
int
shp_nland(struct shpstr *sp)
}
/*
- * Return number of land units loaded on LP.
+ * Return number of land units loaded on @lp.
*/
int
lnd_nland(struct lndstr *lp)