From b4e325a9fe4724a7a4028f3d54c6a6f2f81a4810 Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Thu, 25 Jul 2013 17:23:05 +0100
Subject: [PATCH] [Change] Removed alliance deal, now each faction states it's
 own allies/enemies.

---
 dat/faction.xml | 143 ++++++++++++++++++++-----
 dat/mission.xml |  14 +--
 src/faction.c   | 277 ++++++++++--------------------------------------
 src/faction.h   |   8 --
 src/mission.c   |  14 +--
 src/space.c     |   5 +-
 6 files changed, 182 insertions(+), 279 deletions(-)

diff --git a/dat/faction.xml b/dat/faction.xml
index 0c21aa4..f766fbd 100644
--- a/dat/faction.xml
+++ b/dat/faction.xml
@@ -2,49 +2,142 @@
 <Factions>
 <faction name="Independent">
 <player>0</player>
+<allies>
+<ally>Militia</ally>
+<ally>Merchant</ally>
+</allies>
+<enemies>
+<enemy>Pirate</enemy>
+<enemy>Collective</enemy>
+<enemy>Unknown1</enemy>
+<enemy>Unknown2</enemy>
+<enemy>Collective</enemy>
+</enemies>
 </faction>
 <faction name="Merchant">
 <player>0</player>
+<allies>
+<ally>Militia</ally>
+<ally>Independent</ally>
+<ally>Empire</ally>
+<ally>Unknown6</ally>
+</allies>
+<enemies>
+<enemy>Pirate</enemy>
+<enemy>Unknown2</enemy>
+<enemy>Unknown1</enemy>
+<enemy>Collective</enemy>
+</enemies>
 </faction>
 <faction name="Pirate">
 <player>-20</player>
+<enemies>
+<enemy>Empire</enemy>
+<enemy>Unknown3</enemy>
+<enemy>Unknown4</enemy>
+<enemy>Unknown1</enemy>
+<enemy>Unknown5</enemy>
+<enemy>Collective</enemy>
+<enemy>Unknown6</enemy>
+</enemies>
 </faction>
 <faction name="Militia">
 <player>0</player>
+<allies>
+<ally>Independent</ally>
+<ally>Merchant</ally>
+</allies>
+<enemies>
+<enemy>Pirate</enemy>
+<enemy>Collective</enemy>
+<enemy>Unknown2</enemy>
+</enemies>
 </faction>
 <faction name="Empire">
 <player>0</player>
+<allies>
+<ally>Unknown6</ally>
+<ally>Merchant</ally>
+</allies>
+<enemies>
+<enemy>Pirate</enemy>
+<enemy>Unknown2</enemy>
+<enemy>Unknown1</enemy>
+<enemy>Collective</enemy>
+</enemies>
 </faction>
 <faction name="Collective">
 <player>-100</player>
+<enemies>
+<enemy>Empire</enemy>
+<enemy>Unknown3</enemy>
+<enemy>Unknown4</enemy>
+<enemy>Unknown1</enemy>
+<enemy>Unknown5</enemy>
+<enemy>Unknown6</enemy>
+<enemy>Pirate</enemy>
+<enemy>Unknown2</enemy>
+</enemies>
 </faction>
-<Alliances>
-<alliance name="Neutral">
-<ally>Independent</ally>
-<ally>Merchant</ally>
-<ally>Militia</ally>
-</alliance>
-<alliance name="Empire United">
+<faction name="Unknown3">
+<player>0</player>
+<enemies>
+<enemy>Pirate</enemy>
+<enemy>Collective</enemy>
+<enemy>Unknown1</enemy>
+</enemies>
+</faction>
+<faction name="Unknown2">
+<player>-10</player>
+<enemies>
+<enemy>Empire</enemy>
+<enemy>Unknown4</enemy>
+<enemy>Unknown1</enemy>
+<enemy>Unknown5</enemy>
+<enemy>Collective</enemy>
+<enemy>Unknown6</enemy>
+</enemies>
+</faction>
+<faction name="Unknown4">
+<player>0</player>
+<enemies>
+<enemy>Pirate</enemy>
+<enemy>Collective</enemy>
+<enemy>Unknown1</enemy>
+</enemies>
+</faction>
+<faction name="Unknown1">
+<player>-80</player>
+<enemies>
+<enemy>Empire</enemy>
+<enemy>Unknown3</enemy>
+<enemy>Unknown4</enemy>
+<enemy>Unknown5</enemy>
+<enemy>Unknown6</enemy>
+<enemy>Pirate</enemy>
+<enemy>Unknown2</enemy>
+<enemy>Collective</enemy>
+</enemies>
+</faction>
+<faction name="Unknown5">
+<player>0</player>
+<enemies>
+<enemy>Pirate</enemy>
+<enemy>Collective</enemy>
+<enemy>Unknown1</enemy>
+</enemies>
+</faction>
+<faction name="Unknown6">
+<player>0</player>
+<allies>
 <ally>Empire</ally>
 <ally>Merchant</ally>
-</alliance>
-</Alliances>
-<Enemies>
+</allies>
 <enemies>
-<enemy type="faction">Collective</enemy>
-<enemy type="alliance">Neutral</enemy>
+<enemy>Unknown1</enemy>
+<enemy>Pirate</enemy>
+<enemy>Unknown2</enemy>
+<enemy>Collective</enemy>
 </enemies>
-<enemies>
-<enemy type="faction">Collective</enemy>
-<enemy type="alliance">Empire United</enemy>
-</enemies>
-<enemies>
-<enemy type="alliance">Neutral</enemy>
-<enemy type="faction">Pirate</enemy>
-</enemies>
-<enemies>
-<enemy type="alliance">Empire United</enemy>
-<enemy type="faction">Pirate</enemy>
-</enemies>
-</Enemies>
+</faction>
 </Factions>
diff --git a/dat/mission.xml b/dat/mission.xml
index 7c11e76..ad1ce1f 100644
--- a/dat/mission.xml
+++ b/dat/mission.xml
@@ -13,8 +13,9 @@
 <avail>
 <chance>960</chance>
 <location>Computer</location>
-<alliance>Neutral</alliance>
-<alliance>Empire United</alliance>
+<faction>Independent</faction>
+<faction>Empire</faction>
+<faction>Unkown6</faction>
 </avail>
 </mission>
 <mission name="Empire Recruitment">
@@ -25,8 +26,7 @@
 <avail>
 <chance>80</chance>
 <location>Bar</location>
-<alliance>Empire United</alliance>
-<alliance>Neutral</alliance>
+<faction>Empire</faction>
 </avail>
 </mission>
 <mission name="Empire Shipping">
@@ -35,8 +35,8 @@
 <cond>var.peek("es_cargo") == true</cond>
 <chance>350</chance>
 <location>Computer</location>
-<alliance>Empire United</alliance>
-<alliance>Neutral</alliance>
+<faction>Empire</faction>
+<faction>Unkown6</faction>
 </avail>
 </mission>
 <mission name="Empire Scouting">
@@ -48,7 +48,7 @@
 <req>es_cargo</req>
 <chance>70</chance>
 <location>Bar</location>
-<alliance>Empire United</alliance>
+<faction>Empire</faction>
 </avail>
 </mission>
 </Missions>
diff --git a/src/faction.c b/src/faction.c
index 3c784f0..952d5b6 100644
--- a/src/faction.c
+++ b/src/faction.c
@@ -9,17 +9,11 @@
 
 #define XML_FACTION_ID    "Factions" /* XML section id. */
 #define XML_FACTION_TAG   "faction"
-#define XML_ALLIANCE_ID   "Alliances"
-#define XML_ALLIANCE_TAG  "alliance"
-#define XML_ENEMIES_ID    "Enemies"
-#define XML_ENEMIES_TAG   "enemies"
 
 #define FACTION_DATA "../dat/faction.xml"
 
 #define PLAYER_ALLY   70 /* Above this, player is considered ally. */
 
-#define ALLIANCE_OFFSET 27182 /* Special offset for alliances. */
-
 typedef struct Faction_ {
   char* name;
 
@@ -35,24 +29,12 @@ typedef struct Faction_ {
 } Faction;
 
 static Faction* faction_stack = NULL;
-static int nfactions = 0;
-
-/* Save alliance. */
-typedef struct Alliance_ {
-  char* name;
-  int* factions;
-  int nfactions;
-} Alliance;
-
-/* Stack of alliances. */
-static Alliance* alliances = NULL;
-static int nalliances = 0;
+static int faction_nstack = 0;
 
 /* Static. */
+static int faction_isFaction(int f);
 static Faction* faction_parse(xmlNodePtr parent);
-static void alliance_parse(xmlNodePtr parent);
-static void enemies_parse(xmlNodePtr parent);
-static Alliance* alliance_get(char* name);
+static void faction_parseSocial(xmlNodePtr parent);
 /* Extern. */
 int pfaction_save(xmlTextWriterPtr writer);
 int pfaction_load(xmlNodePtr parent);
@@ -60,47 +42,23 @@ int pfaction_load(xmlNodePtr parent);
 /* Return the faction of name "name". */
 int faction_get(const char* name) {
   int i;
-  for(i = 0; i < nfactions; i++)
+  for(i = 0; i < faction_nstack; i++)
     if(strcmp(faction_stack[i].name, name)==0)
       break;
 
-  if(i != nfactions)
+  if(i != faction_nstack)
     return i;
 
   DEBUG("Faction '%s' not found in stack.", name);
   return -1;
 }
 
-/* Return the id of an alliance. */
-int faction_getAlliance(char* name) {
-  int i;
-  for(i = 0; i < nalliances; i++)
-    if(strcmp(alliances[i].name, name)==0)
-      break;
-
-  if(i != nalliances)
-    return ALLIANCE_OFFSET + i;
-  DEBUG("Alliance '%s' not found in stack.", name);
-  return -1;
-}
-
+/* Return the faction's name. */
 char* faction_name(int f) {
   return faction_stack[f].name;
 }
 
-/* Return the alliance of name 'name'. */
-static Alliance* alliance_get(char* name) {
-  int i;
-  for(i = 0; i < nalliances; i++)
-    if(strcmp(alliances[i].name, name)==0)
-      break;
-
-  if(i != nalliances)
-    return alliances+i;
-
-  return NULL;
-}
-
+/* Modify the player's standing with a faction. */
 void faction_modPlayer(int f, int mod) {
   if(faction_isFaction(f)) {
     faction_stack[f].player += mod;
@@ -264,41 +222,9 @@ int areAllies(int a, int b) {
   return 0;
 }
 
-/* Is faction f part of alliance a? */
-int faction_ofAlliance(int f, int a) {
-  int i;
-  Alliance* aa;
-
-  if(!faction_isFaction(f)) {
-    DEBUG("faction_ofAlliance: invalid alliance '%d'", f);
-    return 0;  
-  }
-  
-  if(!faction_isAlliance(a)) {
-    DEBUG("faction_ofAlliance: invalid alliance '%d'", a);
-    return 0;
-  }
-
-  aa = &alliances[a-ALLIANCE_OFFSET];
-
-  for(i = 0; i < aa->nfactions; i++)
-    if(aa->factions[i] == f)
-      return 1;
-
-  return 0;
-}
-
-/* Return true if a s an alliance. */
-int faction_isAlliance(int a) {
-  if((a < ALLIANCE_OFFSET) || (a >= ALLIANCE_OFFSET + nalliances))
-    return 0;
-
-  return 1;
-}
-
 /* Return true if f is a faction. */
-int faction_isFaction(int f) {
-  if((f < 0) || (f >= nfactions))
+static int faction_isFaction(int f) {
+  if((f < 0) || (f >= faction_nstack))
     return 0;
   return 1;
 }
@@ -311,7 +237,7 @@ static Faction* faction_parse(xmlNodePtr parent) {
 
   tmp = CALLOC_L(Faction);
 
-  tmp->name = (char*)xmlGetProp(parent, (xmlChar*)"name");
+  tmp->name = xml_nodeProp(parent, "name");
   if(tmp->name == NULL)
     WARN("Faction from "FACTION_DATA" has invalid or no name");
 
@@ -329,143 +255,51 @@ static Faction* faction_parse(xmlNodePtr parent) {
   return tmp;
 }
 
-/* We set allies/enemies here, in the faction_stack. */
-static void alliance_parse(xmlNodePtr parent) {
-  Alliance* a;
-  int* i, j, n, m;
-  Faction* ft;
+static void faction_parseSocial(xmlNodePtr parent) {
   xmlNodePtr node, cur;
+  char* buf;
+  Faction* base;
+  int mod;
+
+  buf = xml_nodeProp(parent, "name");
+  base = &faction_stack[faction_get(buf)];
+  free(buf);
 
   node = parent->xmlChildrenNode;
-
   do {
-    if((node->type == XML_NODE_START) && (strcmp((char*)node->name,
-                                                 XML_ALLIANCE_TAG)==0)) {
-      /* Allocate a new alliance. */
-      alliances = realloc(alliances, sizeof(Alliance)*(++nalliances));
-      alliances[nalliances-1].name = (char*)xmlGetProp(node,(xmlChar*)"name");
-      alliances[nalliances-1].factions = NULL;
-      alliances[nalliances-1].nfactions = 0;
-
-      /* Parse the current alliance's allies. */
+    if(xml_isNode(node, "allies")) {
       cur = node->xmlChildrenNode;
       do {
-        if(strcmp((char*)cur->name, "ally")==0) {
-          /* Add the faction (and pointers to make things simple). */
-          a = alliances + nalliances-1;
-          i = &a->nfactions;
-          (*i)++;
-
-          /* Load the faction. */
-          a->factions = realloc(a->factions, (*i)*sizeof(int));
-          a->factions[(*i)-1] = faction_get((char*)cur->children->content);
-
-          if(a->factions[(*i)-1] == -1)
-            WARN("Faction '%s' in alliance '%s' does not exist in "FACTION_DATA,
-                 (char*)cur->children->content, a->name);
+        if(xml_isNode(cur, "ally")) {
+          mod = faction_get(xml_get(cur));
+          base->nallies++;
+          base->allies = realloc(base->allies, sizeof(int)*base->nallies);
+          base->allies[base->nallies-1] = mod;
         }
-      } while((cur = cur->next));
-
-      /* Set the crap needed by faction_stack. */
-      for(j = 0; j < (*i); j++) {
-        ft = &faction_stack[a->factions[j]];
-        ft->nallies += (*i)-1;
-        ft->allies = realloc(ft->allies, (ft->nallies)*sizeof(int));
-        for(n = 0, m = 0; n < (*i); n++, m++) {
-          /* Add as ally for all factions exept self. */
-          if(n == j) m--;
-          else if(n != j)
-            ft->allies[ft->nallies-(*i)+1+m] = a->factions[n];
-        }
-      }
+      } while(xml_nextNode(cur));
     }
-  } while((node = node->next));
-}
-
-static void enemies_parse(xmlNodePtr parent) {
-  xmlNodePtr node, cur;
-  int** f;
-  Faction* ft;
-  Alliance* a;
-  int i, *j, n, m, x, y, z, e;
-  char* type;
-
-  node = parent->xmlChildrenNode;
-
-  do {
-    if((node->type == XML_NODE_START)
-       && (strcmp((char*)node->name, XML_ENEMIES_TAG)==0)) {
-      i = 0;
-      f = NULL;
-      j = NULL;
 
+    /* Grab the enemies. */
+    if(xml_isNode(node, "enemies")) {
       cur = node->xmlChildrenNode;
       do {
-        if(strcmp((char*)cur->name,"enemy")==0) {
-          type = (char*)xmlGetProp(cur, (xmlChar*)"type");
-
-          i++;
-          j = realloc(j, sizeof(int)*i);
-          f = realloc(f, sizeof(int*)*i);
-
-          if(strcmp(type, "alliance")==0) {
-            /* Enemy thing is an alliance. */
-            a = alliance_get((char*)cur->children->content);
-            if(a == NULL)
-              WARN("Alliance %s not found in stack",
-                   (char*)cur->children->content);
-            j[i-1] = a->nfactions;
-            f[i-1] = a->factions;
-          }
-          else if(strcmp(type,"faction")==0) {
-            /* Enemy thing is only a faction. */
-            j[i-1] = 1;
-            f[i-1] = malloc(sizeof(int));
-            f[i-1][0] = faction_get((char*)cur->children->content);
-            if(f[i-1][0] == -1)
-              WARN("Faction %s not found in stack",
-                   (char*)cur->children->content);
-          }
-          free(type);
+        if(xml_isNode(cur, "enemy")) {
+          mod = faction_get(xml_get(cur));
+          base->nenemies++;
+          base->enemies = realloc(base->enemies, sizeof(int)*base->nenemies);
+          base->enemies[base->nenemies-1] = mod;
         }
-      } while((cur = cur->next));
-      /* Now actually parse and load up the enemies. */
-      for(n = 0; n < i; n++) {        /* Unsinged int. */
-        for(m = 0; m < j[n]; m++) {   /* Unsigned int. */
-          /* Faction. */
-          /* Add all the faction enemies to nenemies and alloc. */
-          for(e = 0, x = 0; x < i; x++)
-            if(x != n) e += j[x]; /* Store the total enemies. */
-          /* Now allocate the memory. */
-          ft = &faction_stack[f[n][m]];
-          ft->nenemies += e;
-          ft->enemies = realloc(ft->enemies, sizeof(int)*ft->nenemies);
-
-          /* Add the actualy enemies. */
-          for(x = 0, z = 0; x < i; x++)
-            if(x != n)
-              /* Make sure it's not from the same group. */
-              if(x != n)
-                for(y = 0; y < j[x]; y++, z++)
-                  ft->enemies[ft->nenemies-e+z] = f[x][y];
-        }
-      }
-      /* Free al the temp memory. */
-      for(x = 0; x < i; x++)
-        if(j[x]==1) free(f[x]); /* Free the single malloced factions. */
-      free(f); /* Free the rest. */
-      free(j);
+      } while(xml_nextNode(cur));
     }
-  } while((node = node->next));
+  } while(xml_nextNode(node));
 }
 
-
 /* Load all the factions. */
 int factions_load(void) {
   uint32_t bufsize;
   char* buf = pack_readfile(DATA, FACTION_DATA, &bufsize);
 
-  xmlNodePtr node;
+  xmlNodePtr factions, node;
   xmlDocPtr doc = xmlParseMemory(buf, bufsize);
 
   Faction* tmp = NULL;
@@ -476,8 +310,8 @@ int factions_load(void) {
     return -1;
   }
 
-  node = node->xmlChildrenNode; /* First faction node. */
-  if(node == NULL) {
+  factions = node->xmlChildrenNode; /* First faction node. */
+  if(factions == NULL) {
     ERR("Malformed "FACTION_DATA" file: does not contain elements");
     return -1;
   }
@@ -487,50 +321,47 @@ int factions_load(void) {
   faction_stack[0].name     = strdup("Player");
   faction_stack[0].nallies  = 0;
   faction_stack[0].nenemies = 0;
-  nfactions++;
+  faction_nstack++;
 
+  /* First pass. */
+  node = factions;
   do {
     if(xml_isNode(node, XML_FACTION_TAG)) {
       tmp = faction_parse(node);
-      faction_stack = realloc(faction_stack, sizeof(Faction)*(++nfactions));
-      memcpy(faction_stack + nfactions - 1, tmp, sizeof(Faction));
+      faction_stack = realloc(faction_stack, sizeof(Faction)*(++faction_nstack));
+      memcpy(faction_stack + faction_nstack - 1, tmp, sizeof(Faction));
       free(tmp);
     }
-    else if(xml_isNode(node, XML_ALLIANCE_ID))
-      alliance_parse(node);
-    else if(xml_isNode(node, XML_ENEMIES_ID))
-      enemies_parse(node);
-  } while((node = node->next));
+  } while(xml_nextNode(node));
+
+  /* Second pass - Set allies and enemies. */
+  node = factions;
+  do {
+    if (xml_isNode(node,XML_FACTION_TAG))
+      faction_parseSocial(node);
+  } while (xml_nextNode(node));
 
   xmlFreeDoc(doc);
   free(buf);
   xmlCleanupParser();
 
-  DEBUG("Loaded %d Faction%s", nfactions, (nfactions==1) ?"": "s");
+  DEBUG("Loaded %d Faction%s", faction_nstack, (faction_nstack==1) ?"": "s");
 
   return 0;
 }
 
 void factions_free(void) {
   int i;
-  /* Free alliances. */
-  for(i = 0; i < nalliances; i++) {
-    free(alliances[i].name);
-    free(alliances[i].factions);
-  }
-  free(alliances);
-  alliances = NULL;
-  nalliances = 0;
 
   /* Free factions. */
-  for(i = 0; i < nfactions; i++) {
+  for(i = 0; i < faction_nstack; i++) {
     free(faction_stack[i].name);
     if(faction_stack[i].nallies > 0)  free(faction_stack[i].allies);
     if(faction_stack[i].nenemies > 0) free(faction_stack[i].enemies);
   }
   free(faction_stack);
   faction_stack = NULL;
-  nfactions = 0;
+  faction_nstack = 0;
 }
 
 int pfaction_save(xmlTextWriterPtr writer) {
@@ -539,7 +370,7 @@ int pfaction_save(xmlTextWriterPtr writer) {
   xmlw_startElem(writer, "factions");
 
   /* Player is faction 0. */
-  for(i = 1; i < nfactions; i++) {
+  for(i = 1; i < faction_nstack; i++) {
     xmlw_startElem(writer, "faction");
 
     xmlw_attr(writer, "name", "%s", faction_stack[i].name);
diff --git a/src/faction.h b/src/faction.h
index 626fb5d..7241350 100644
--- a/src/faction.h
+++ b/src/faction.h
@@ -4,7 +4,6 @@
 
 /* Get stuff. */
 int faction_get(const char* name);
-int faction_getAlliance(char* name);
 char* faction_name(int f);
 
 /* Player stuff. */
@@ -16,13 +15,6 @@ char* faction_getStanding(int mod);
 int areEnemies(int a, int b);
 int areAllies(int a, int b);
 
-/* Faction + Alliance. */
-int faction_ofAlliance(int f, int a);
-
-/* Check. */
-int faction_isAlliance(int a);
-int faction_isFaction(int f);
-
 /* Load/Free. */
 int factions_load(void);
 void factions_free(void);
diff --git a/src/mission.c b/src/mission.c
index 6868812..43fa2f2 100644
--- a/src/mission.c
+++ b/src/mission.c
@@ -342,13 +342,9 @@ static void mission_freeData(MissionData* mission) {
 static int mission_matchFaction(MissionData* misn, int faction) {
   int i;
 
-  for(i = 0; i < misn->avail.nfactions; i++) {
-    if(faction_isFaction(misn->avail.factions[i]) &&
-        (faction == misn->avail.factions[i]))
+  for(i = 0; i < misn->avail.nfactions; i++)
+    if(faction == misn->avail.factions[i])
       return 1;
-    else if(faction_ofAlliance(faction, misn->avail.factions[i]))
-      return 1;
-  }
   return 0;
 }
 
@@ -436,12 +432,6 @@ static MissionData* mission_parse(const xmlNodePtr parent) {
           tmp->avail.planet = strdup(xml_get(cur));
         else if(xml_isNode(cur, "system"))
           tmp->avail.system = strdup(xml_get(cur));
-        else if(xml_isNode(cur, "alliance")) {
-          tmp->avail.factions = realloc(tmp->avail.factions,
-              sizeof(int) * ++tmp->avail.nfactions);
-          tmp->avail.factions[tmp->avail.nfactions-1] = 
-              faction_getAlliance(xml_get(cur));
-        }
         else if(xml_isNode(cur, "faction")) {
           tmp->avail.factions = realloc(tmp->avail.factions,
               sizeof(int) * ++tmp->avail.nfactions);
diff --git a/src/space.c b/src/space.c
index c4dc118..cc5064a 100644
--- a/src/space.c
+++ b/src/space.c
@@ -227,10 +227,7 @@ char** space_getFactionPlanet(int* nplanets, int* factions, int nfactions) {
     for(j = 0; j < systems_stack[i].nplanets; j++) {
       planet = &systems_stack[i].planets[j];
       for(k = 0; k < nfactions; k++)
-        if((faction_isFaction(factions[k]) &&
-              (planet->faction == factions[k])) ||
-            (faction_isAlliance(factions[k]) &&
-             faction_ofAlliance(planet->faction, factions[k]))) {
+        if(planet->faction == factions[k]) {
           ntmp++;
           if(ntmp > mtmp) {
             mtmp += 25;