diff --git a/scripts/ai/test.lua b/scripts/ai/test.lua
index c22a7af..7b36389 100644
--- a/scripts/ai/test.lua
+++ b/scripts/ai/test.lua
@@ -12,7 +12,7 @@ function attack()
   dir = face(target)
   dist = getdist(getpos(target))
   if dir < 10 and dist > 100 then
-    accel(dist/100-1)
+    accel()
   elseif dir < 10 and dist < 100 then
     shoot()
   end
diff --git a/src/faction.c b/src/faction.c
new file mode 100644
index 0000000..3c91d2e
--- /dev/null
+++ b/src/faction.c
@@ -0,0 +1,103 @@
+#include <malloc.h>
+#include <string.h>
+#include <libxml/parser.h>
+
+#include "main.h"
+#include "log.h"
+#include "pack.h"
+#include "faction.h"
+
+#define XML_NODE_START 1
+#define XML_NODE_TEXT  3
+
+#define XML_FACTION_ID  "Factions" // XML section id.
+#define XML_FACTION_TAG "faction"
+
+#define FACTION_DATA "../dat/faction.xml"
+
+Faction* faction_stack = NULL;
+int nfactions = 0;
+
+static Faction* faction_parse(xmlNodePtr parent);
+
+// Return the faction of name "name".
+Faction* get_faction(const char* name) {
+  int i;
+  for(i = 0; i < nfactions; i++)
+    if(strcmp(faction_stack[i].name, name)==0)
+      break;
+  
+  if(i != nfactions)
+    return faction_stack+i;
+
+  return NULL;
+}
+
+// Return 1 if Faction a and b are enemies.
+int areEnemies(Faction* a, Faction* b) {
+  int i = 0;
+  while(a->enemies[i] != NULL && b != a->enemies[i]) i++;
+
+  if(a->enemies[i] == NULL) return 0;
+  return 1;
+}
+
+// Return 1 if Faction a and b are allies.
+int areAllies(Faction* a, Faction* b) {
+  int i = 0;
+  while(a->allies[i] != NULL && b != a->allies[i]) i++;
+
+  if(a->allies[i] == NULL) return 0;
+  return 1;
+}
+
+static Faction* faction_parse(xmlNodePtr parent) {
+  Faction* tmp = CALLOC_L(Faction);
+  tmp->name = (char*)xmlGetProp(parent, (xmlChar*)"name");
+  return tmp;
+}
+
+int factions_load(void) {
+  uint32_t bufsize;
+  char* buf = pack_readfile(DATA, FACTION_DATA, &bufsize);
+
+  xmlNodePtr node;
+  xmlDocPtr doc = xmlParseMemory(buf, bufsize);
+
+  Faction* tmp = NULL;
+
+  node = doc->xmlChildrenNode; // Ships node.
+  if(strcmp((char*)node->name, XML_FACTION_ID)) {
+    ERR("Malformed "FACTION_DATA" file: missing root element '"XML_FACTION_ID"'");
+    return -1;
+  }
+
+  node = node->xmlChildrenNode; // First ship node.
+  if(node == NULL) {
+    ERR("Malformed "FACTION_DATA" file: does not contain elements");
+    return -1;
+  }
+
+  do {
+    if(node->type == XML_NODE_START && strcmp((char*)node->name, XML_FACTION_TAG) == 0) {
+      tmp = faction_parse(node);
+      faction_stack = realloc(faction_stack, sizeof(Faction)*(++nfactions));
+      memcpy(faction_stack+nfactions-1, tmp, sizeof(Faction));
+      free(tmp);
+    }
+  } while((node = node->next));
+
+  xmlFreeDoc(doc);
+  free(buf);
+  xmlCleanupParser();
+
+  DEBUG("Loaded %d factions", nfactions);
+
+  return 0;
+}
+
+void factions_free(void) {
+  free(faction_stack);
+  nfactions = 0;
+}
+
diff --git a/src/faction.h b/src/faction.h
new file mode 100644
index 0000000..c0ff002
--- /dev/null
+++ b/src/faction.h
@@ -0,0 +1,17 @@
+#pragma once
+
+typedef struct Faction {
+  char* name;
+
+  struct Faction** enemies;
+  struct Faction** allies;
+} Faction;
+
+Faction* get_faction(const char* name);
+
+int areEnemies(Faction* a, Faction* b);
+int areAllies(Faction* a, Faction* b);
+
+int factions_load(void);
+void factions_free(void);
+
diff --git a/src/main.c b/src/main.c
index 985c8df..2679f6d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -20,6 +20,7 @@
 #include "outfit.h"
 #include "pack.h"
 #include "weapon.h"
+#include "faction.h"
 #include "pilot.h"
 
 #define APPNAME         "Lephisto"
@@ -245,6 +246,7 @@ int main(int argc, char** argv) {
   gui_init(); // Init the GUI crap.
 
   // Data loading.
+  factions_load();
   outfit_load();
   ships_load();
   space_load();
@@ -282,6 +284,7 @@ int main(int argc, char** argv) {
   gui_free();     // Free up the gui.
   ships_free();
   outfit_free();
+  factions_free();
 
   gl_freeFont(NULL);