summaryrefslogtreecommitdiff
path: root/src/uqm/supermelee/meleesetup.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/uqm/supermelee/meleesetup.c')
-rw-r--r--src/uqm/supermelee/meleesetup.c440
1 files changed, 440 insertions, 0 deletions
diff --git a/src/uqm/supermelee/meleesetup.c b/src/uqm/supermelee/meleesetup.c
new file mode 100644
index 0000000..a45f172
--- /dev/null
+++ b/src/uqm/supermelee/meleesetup.c
@@ -0,0 +1,440 @@
+/*
+ * This program 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * 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.
+ */
+
+#define MELEESETUP_INTERNAL
+#include "port.h"
+#include "meleesetup.h"
+
+#include "../master.h"
+#include "libs/log.h"
+
+
+///////////////////////////////////////////////////////////////////////////
+
+// Temporary
+const size_t MeleeTeam_serialSize = MELEE_FLEET_SIZE +
+ sizeof (((MeleeTeam*)0)->name);
+
+void
+MeleeTeam_init (MeleeTeam *team)
+{
+ FleetShipIndex slotI;
+
+ for (slotI = 0; slotI < MELEE_FLEET_SIZE; slotI++)
+ team->ships[slotI] = MELEE_NONE;
+
+ team->name[0] = '\0';
+}
+
+void
+MeleeTeam_uninit (MeleeTeam *team)
+{
+ (void) team;
+}
+
+MeleeTeam *
+MeleeTeam_new (void)
+{
+ MeleeTeam *result = HMalloc (sizeof (MeleeTeam));
+ MeleeTeam_init (result);
+ return result;
+}
+
+void
+MeleeTeam_delete (MeleeTeam *team)
+{
+ MeleeTeam_uninit (team);
+ HFree (team);
+}
+
+int
+MeleeTeam_serialize (const MeleeTeam *team, uio_Stream *stream)
+{
+ FleetShipIndex slotI;
+
+ for (slotI = 0; slotI < MELEE_FLEET_SIZE; slotI++) {
+ if (uio_putc ((int) team->ships[slotI], stream) == EOF)
+ return -1;
+ }
+ if (uio_fwrite ((const char *) team->name, sizeof team->name, 1,
+ stream) != 1)
+ return -1;
+
+ return 0;
+}
+
+int
+MeleeTeam_deserialize (MeleeTeam *team, uio_Stream *stream)
+{
+ FleetShipIndex slotI;
+
+ // Sanity check on the ships.
+ for (slotI = 0; slotI < MELEE_FLEET_SIZE; slotI++)
+ {
+ int ship = uio_getc (stream);
+ if (ship == EOF)
+ goto err;
+ team->ships[slotI] = (MeleeShip) ship;
+
+ if (team->ships[slotI] == MELEE_NONE)
+ continue;
+
+ if (team->ships[slotI] >= NUM_MELEE_SHIPS)
+ {
+ log_add (log_Warning, "Invalid ship type in loaded team (index "
+ "%d, ship type is %d, max valid is %d).",
+ slotI, team->ships[slotI], NUM_MELEE_SHIPS - 1);
+ team->ships[slotI] = MELEE_NONE;
+ }
+ }
+
+ if (uio_fread (team->name, sizeof team->name, 1, stream) != 1)
+ goto err;
+
+ team->name[MAX_TEAM_CHARS] = '\0';
+
+ return 0;
+
+err:
+ MeleeTeam_delete(team);
+ return -1;
+}
+
+// XXX: move this to elsewhere?
+COUNT
+MeleeTeam_getValue (const MeleeTeam *team)
+{
+ COUNT total = 0;
+ FleetShipIndex slotI;
+
+ for (slotI = 0; slotI < MELEE_FLEET_SIZE; slotI++)
+ {
+ MeleeShip ship = team->ships[slotI];
+ COUNT shipValue = GetShipValue (ship);
+ if (shipValue == (COUNT)~0)
+ {
+ // Invalid ship.
+ continue;
+ }
+ total += shipValue;
+ }
+
+ return total;
+}
+
+MeleeShip
+MeleeTeam_getShip (const MeleeTeam *team, FleetShipIndex slotNr)
+{
+ return team->ships[slotNr];
+}
+
+void
+MeleeTeam_setShip (MeleeTeam *team, FleetShipIndex slotNr, MeleeShip ship)
+{
+ team->ships[slotNr] = ship;
+}
+
+const MeleeShip *
+MeleeTeam_getFleet (const MeleeTeam *team)
+{
+ return team->ships;
+}
+
+const char *
+MeleeTeam_getTeamName (const MeleeTeam *team)
+{
+ return team->name;
+}
+
+// Returns true iff the state has actually changed.
+void
+MeleeTeam_setName (MeleeTeam *team, const char *name)
+{
+ strncpy (team->name, name, sizeof team->name - 1);
+ team->name[sizeof team->name - 1] = '\0';
+}
+
+void
+MeleeTeam_copy (MeleeTeam *copy, const MeleeTeam *original)
+{
+ *copy = *original;
+}
+
+#if 0
+bool
+MeleeTeam_isEqual (const MeleeTeam *team1, const MeleeTeam *team2)
+{
+ const MeleeShip *fleet1;
+ const MeleeShip *fleet2;
+ FleetShipIndex slotI;
+
+ if (strcmp (team1->name, team2->name) != 0)
+ return false;
+
+ fleet1 = team1->ships;
+ fleet2 = team2->ships;
+
+ for (slotI = 0; slotI < MELEE_FLEET_SIZE; slotI++)
+ {
+ if (fleet1[slotI] != fleet2[slotI])
+ return false;
+ }
+
+ return true;
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+
+#ifdef NETPLAY
+static void
+MeleeSetup_initSentTeam (MeleeSetup *setup, size_t teamNr)
+{
+ MeleeTeam *team = &setup->sentTeams[teamNr];
+ FleetShipIndex slotI;
+
+ for (slotI = 0; slotI < MELEE_FLEET_SIZE; slotI++)
+ MeleeTeam_setShip (team, slotI, MELEE_UNSET);
+
+ setup->haveSentTeamName[teamNr] = false;
+#ifdef DEBUG
+ // The actual team name should be irrelevant if haveSentTeamName is
+ // set to false. In a debug build, we set it to invalid, so that
+ // it is more likely that it will be noticed if it is ever used.
+ MeleeTeam_setName (team, "<INVALID>");
+#endif /* DEBUG */
+}
+#endif /* NETPLAY */
+
+MeleeSetup *
+MeleeSetup_new (void)
+{
+ size_t teamI;
+ MeleeSetup *result = HMalloc (sizeof (MeleeSetup));
+ if (result == NULL)
+ return NULL;
+
+ for (teamI = 0; teamI < NUM_SIDES; teamI++)
+ {
+ MeleeTeam_init (&result->teams[teamI]);
+ result->fleetValue[teamI] = 0;
+#ifdef NETPLAY
+ MeleeSetup_initSentTeam (result, teamI);
+#endif /* NETPLAY */
+ }
+ return result;
+}
+
+void
+MeleeSetup_delete (MeleeSetup *setup)
+{
+ HFree (setup);
+}
+
+#ifdef NETPLAY
+void
+MeleeSetup_resetSentTeams (MeleeSetup *setup)
+{
+ size_t teamI;
+
+ for (teamI = 0; teamI < NUM_SIDES; teamI++)
+ MeleeSetup_initSentTeam (setup, teamI);
+}
+#endif /* NETPLAY */
+
+// Returns true iff the state has actually changed.
+bool
+MeleeSetup_setShip (MeleeSetup *setup, size_t teamNr, FleetShipIndex slotNr,
+ MeleeShip ship)
+{
+ MeleeTeam *team = &setup->teams[teamNr];
+ MeleeShip oldShip = MeleeTeam_getShip (team, slotNr);
+
+ if (ship == oldShip)
+ return false;
+
+ if (oldShip != MELEE_NONE)
+ setup->fleetValue[teamNr] -= GetShipCostFromIndex (oldShip);
+
+ MeleeTeam_setShip (team, slotNr, ship);
+
+ if (ship != MELEE_NONE)
+ setup->fleetValue[teamNr] += GetShipCostFromIndex (ship);
+
+ return true;
+}
+
+MeleeShip
+MeleeSetup_getShip (const MeleeSetup *setup, size_t teamNr,
+ FleetShipIndex slotNr)
+{
+ return MeleeTeam_getShip (&setup->teams[teamNr], slotNr);
+}
+
+const MeleeShip *
+MeleeSetup_getFleet (const MeleeSetup *setup, size_t teamNr)
+{
+ return MeleeTeam_getFleet (&setup->teams[teamNr]);
+}
+
+// Returns true iff the state has actually changed.
+bool
+MeleeSetup_setTeamName (MeleeSetup *setup, size_t teamNr,
+ const char *name)
+{
+ MeleeTeam *team = &setup->teams[teamNr];
+ const char *oldName = MeleeTeam_getTeamName (team);
+
+ if (strcmp (oldName, name) == 0)
+ return false;
+
+ MeleeTeam_setName (team, name);
+ return true;
+}
+
+// NB. This function returns a pointer to a static buffer, which is
+// overwritten by calls to MeleeSetup_setTeamName().
+const char *
+MeleeSetup_getTeamName (const MeleeSetup *setup, size_t teamNr)
+{
+ return MeleeTeam_getTeamName (&setup->teams[teamNr]);
+}
+
+COUNT
+MeleeSetup_getFleetValue (const MeleeSetup *setup, size_t teamNr)
+{
+ return setup->fleetValue[teamNr];
+}
+
+int
+MeleeSetup_deserializeTeam (MeleeSetup *setup, size_t teamNr,
+ uio_Stream *stream)
+{
+ MeleeTeam *team = &setup->teams[teamNr];
+ int ret = MeleeTeam_deserialize (team, stream);
+ if (ret == 0)
+ setup->fleetValue[teamNr] = MeleeTeam_getValue (team);
+ return ret;
+}
+
+int
+MeleeSetup_serializeTeam (const MeleeSetup *setup, size_t teamNr,
+ uio_Stream *stream)
+{
+ const MeleeTeam *team = &setup->teams[teamNr];
+ return MeleeTeam_serialize (team, stream);
+}
+
+#ifdef NETPLAY
+MeleeShip
+MeleeSetup_getSentShip (const MeleeSetup *setup, size_t teamNr,
+ FleetShipIndex slotNr)
+{
+ return MeleeTeam_getShip (&setup->sentTeams[teamNr], slotNr);
+}
+
+// Returns NULL if there is no team name set. This is not the same
+// as when an empty (zero-length) team name is set.
+// NB. This function returns a pointer to a static buffer, which is
+// overwritten by calls to MeleeSetup_setSentTeamName().
+const char *
+MeleeSetup_getSentTeamName (const MeleeSetup *setup, size_t teamNr)
+{
+ if (!setup->haveSentTeamName[teamNr])
+ return NULL;
+
+ return MeleeTeam_getTeamName (&setup->sentTeams[teamNr]);
+}
+
+// Returns true iff the state has actually changed.
+bool
+MeleeSetup_setSentShip (MeleeSetup *setup, size_t teamNr,
+ FleetShipIndex slotNr, MeleeShip ship)
+{
+ MeleeTeam *team = &setup->sentTeams[teamNr];
+ MeleeShip oldShip = MeleeTeam_getShip (team, slotNr);
+
+ if (ship == oldShip)
+ return false;
+
+ MeleeTeam_setShip (team, slotNr, ship);
+ return true;
+}
+
+// Returns true iff the state has actually changed.
+// 'name' can be NULL to indicate that no team name set. This is not the same
+// as when an empty (zero-length) team name is set.
+bool
+MeleeSetup_setSentTeamName (MeleeSetup *setup, size_t teamNr,
+ const char *name)
+{
+ bool haveSentName = setup->haveSentTeamName[teamNr];
+
+ if (name == NULL)
+ {
+ if (!haveSentName)
+ {
+ // Had not sent a team name, and still haven't.
+ return false;
+ }
+
+#ifdef DEBUG
+ {
+ // The actual team name should be irrelevant if haveSentTeamName
+ // is set to false. In a debug build, we set it to invalid, so
+ // that it is more likely that it will be noticed if it is ever
+ // used.
+ MeleeTeam *team = &setup->sentTeams[teamNr];
+ MeleeTeam_setName (team, "<INVALID>");
+ }
+#endif
+ }
+ else
+ {
+ MeleeTeam *team = &setup->sentTeams[teamNr];
+
+ if (haveSentName)
+ {
+ // Have sent a team name. Check whether it has actually changed.
+ const char *oldName = MeleeTeam_getTeamName (team);
+ if (strcmp (oldName, name) == 0)
+ return false; // Team name has not changed.
+ }
+
+ MeleeTeam_setName (team, name);
+ }
+
+ setup->haveSentTeamName[teamNr] = (name != NULL);
+
+ return true;
+}
+
+#if 0
+bool
+MeleeSetup_isTeamSent (MeleeSetup *setup, size_t teamNr)
+{
+ MeleeTeam *localTeam = &setup->teams[teamNr];
+ MeleeTeam *sentTeam = &setup->sentTeams[teamNr];
+
+ return MeleeTeam_isEqual (localTeam, sentTeam);
+}
+#endif
+
+#endif /* NETPLAY */
+
+///////////////////////////////////////////////////////////////////////////
+
+