diff --git a/dat/fleetgroup.xml b/dat/fleetgroup.xml
new file mode 100644
index 0000000..541efc7
--- /dev/null
+++ b/dat/fleetgroup.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FleetGroups>
+ <fleetgroup name="Goddard Prescence">
+  <fleet chance="50">Goddard Goddard</fleet>
+  <fleet chance="50">Goddard Goddard</fleet>
+ </fleetgroup>
+ <fleetgroup name="Trader Light Prescence">
+  <fleet chance="50">Trader Llama</fleet>
+  <fleet chance="40">Trader Llama</fleet>
+  <fleet chance="40">Trader Koala</fleet>
+  <fleet chance="30">Trader Koala</fleet>
+  <fleet chance="30">Trader Mule</fleet>
+ </fleetgroup>
+ <fleetgroup name="Trader Medium Prescence">
+  <fleet chance="70">Trader Llama</fleet>
+  <fleet chance="60">Trader Llama</fleet>
+  <fleet chance="60">Trader Koala</fleet>
+  <fleet chance="50">Trader Koala</fleet>
+  <fleet chance="50">Trader Mule</fleet>
+  <fleet chance="40">Trader Mule</fleet>
+  <fleet chance="30">Sml Trader Convoy</fleet>
+ </fleetgroup>
+ <fleetgroup name="Trader Heavy Prescence">
+  <fleet chance="80">Trader Llama</fleet>
+  <fleet chance="70">Trader Llama</fleet>
+  <fleet chance="60">Trader Llama</fleet>
+  <fleet chance="70">Trader Koala</fleet>
+  <fleet chance="60">Trader Koala</fleet>
+  <fleet chance="50">Trader Koala</fleet>
+  <fleet chance="60">Trader Mule</fleet>
+  <fleet chance="50">Trader Mule</fleet>
+  <fleet chance="40">Trader Mule</fleet>
+  <fleet chance="40">Sml Trader Convoy</fleet>
+  <fleet chance="30">Sml Trader Convoy</fleet>
+ </fleetgroup>
+ <fleetgroup name="Pirate Light Prescence">
+  <fleet chance="50">Pirate Hyena</fleet>
+  <fleet chance="40">Pirate Vendetta</fleet>
+  <fleet chance="30">Pirate Ancestor</fleet>
+  <fleet chance="20">Pirate Hyena Pack</fleet>
+  <fleet chance="5" >Pirate Admonisher</fleet>
+ </fleetgroup>
+ <fleetgroup name="Pirate Medium Prescence">
+  <fleet chance="50">Pirate Hyena</fleet>
+  <fleet chance="60">Pirate Vendetta</fleet>
+  <fleet chance="50">Pirate Ancestor</fleet>
+  <fleet chance="30">Pirate Hyena Pack</fleet>
+  <fleet chance="20">Pirate Admonisher</fleet>
+ </fleetgroup>
+ <fleetgroup name="Pirate Heavy Prescence">
+  <fleet chance="80">Pirate Hyena</fleet>
+  <fleet chance="50">Pirate Hyena</fleet>
+  <fleet chance="80">Pirate Vendetta</fleet>
+  <fleet chance="60">Pirate Vendetta</fleet>
+  <fleet chance="70">Pirate Ancestor</fleet>
+  <fleet chance="50">Pirate Ancestor</fleet>
+  <fleet chance="50">Pirate Hyena Pack</fleet>
+  <fleet chance="40">Pirate Admonisher</fleet>
+ </fleetgroup>
+ <fleetgroup name="Empire Patrol Prescence">
+  <fleet chance="70">Empire Pacifier</fleet>
+  <fleet chance="20">Empire Pacifier</fleet>
+ </fleetgroup>
+ <fleetgroup name="Empire Light Prescence">
+  <fleet chance="50">Empire Lancelot</fleet>
+  <fleet chance="30">Empire Admonisher</fleet>
+  <fleet chance="10">Empire Pacifier</fleet>
+ </fleetgroup>
+ <fleetgroup name="Empire Medium Prescence">
+  <fleet chance="60">Empire Lancelot</fleet>
+  <fleet chance="30">Empire Lancelot</fleet>
+  <fleet chance="45">Empire Admonisher</fleet>
+  <fleet chance="25">Empire Pacifier</fleet>
+ </fleetgroup>
+ <fleetgroup name="Empire Heavy Prescence">
+  <fleet chance="80">Empire Lancelot</fleet>
+  <fleet chance="70">Empire Lancelot</fleet>
+  <fleet chance="60">Empire Admonisher</fleet>
+  <fleet chance="50">Empire Admonisher</fleet>
+  <fleet chance="40">Empire Pacifier</fleet>
+  <fleet chance="30">Empire Pacifier</fleet>
+  <fleet chance="50">Empire Sml Defense</fleet>
+ </fleetgroup>
+ <fleetgroup name="Collective Light Prescence">
+  <fleet chance="80">Collective Drone</fleet>
+  <fleet chance="40">Collective Drone</fleet>
+  <fleet chance="20">Collective Sml Swarm</fleet>
+ </fleetgroup>
+ <fleetgroup name="Collective Medium Prescence">
+  <fleet chance="80">Collective Drone</fleet>
+  <fleet chance="60">Collective Drone</fleet>
+  <fleet chance="40">Collective Drone</fleet>
+  <fleet chance="40">Collective Sml Swarm</fleet>
+  <fleet chance="20">Collective Sml Swarm</fleet>
+ </fleetgroup>
+ <fleetgroup name="Dvaered Light Prescence">
+  <fleet chance="70">Dvaered Vendetta</fleet>
+  <fleet chance="20">Dvaered Vendetta</fleet>
+  <fleet chance="40">Dvaered Ancestor</fleet>
+ </fleetgroup>
+ <fleetgroup name="Dvaered Medium Prescence">
+  <fleet chance="70">Dvaered Vendetta</fleet>
+  <fleet chance="50">Dvaered Vendetta</fleet>
+  <fleet chance="60">Dvaered Ancestor</fleet>
+  <fleet chance="40">Dvaered Ancestor</fleet>
+  <fleet chance="5" >Dvaered Goddard</fleet>
+ </fleetgroup>
+ <fleetgroup name="Dvaered Heavy Prescence">
+  <fleet chance="80">Dvaered Vendetta</fleet>
+  <fleet chance="60">Dvaered Vendetta</fleet>
+  <fleet chance="40">Dvaered Vendetta</fleet>
+  <fleet chance="60">Dvaered Ancestor</fleet>
+  <fleet chance="40">Dvaered Ancestor</fleet>
+  <fleet chance="15">Dvaered Goddard</fleet>
+  <fleet chance="30">Dvaered Sml Force</fleet>
+ </fleetgroup>
+ <fleetgroup name="FLF Light Guerrilla">
+  <fleet chance="20">FLF Vendetta</fleet>
+  <fleet chance="10">FLF Pacifier</fleet>
+  <fleet chance="5" >FLF Sml Force</fleet>
+ </fleetgroup>
+ <fleetgroup name="FLF Medium Guerrilla">
+  <fleet chance="30">FLF Vendetta</fleet>
+  <fleet chance="20">FLF Pacifier</fleet>
+  <fleet chance="15">FLF Sml Force</fleet>
+  <fleet chance="5" >FLF Med Force</fleet>
+ </fleetgroup>
+</FleetGroups>
diff --git a/src/fleet.c b/src/fleet.c
index cd20e76..575bfd0 100644
--- a/src/fleet.c
+++ b/src/fleet.c
@@ -1,33 +1,24 @@
 /**
- * @file pilot.c
+ * @file fleet.c
  *
- * @brief Handles the pilot stuff.
+ * @brief Handles the fleet stuff.
  */
 
+#include "fleet.h"
+
 #include <string.h>
 #include <math.h>
 #include <stdlib.h>
 #include <limits.h>
 
 #include "lxml.h"
-
 #include "lephisto.h"
 #include "log.h"
-#include "weapon.h"
-#include "ldata.h"
-#include "spfx.h"
-#include "rng.h"
-#include "hook.h"
-#include "map.h"
-#include "explosion.h"
-#include "escort.h"
-#include "music.h"
 #include "pilot.h"
+#include "ldata.h"
 
-#define XML_ID    "Fleets"  /**< XML document identifier. */
-#define XML_FLEET "fleet"   /**< XML individual fleet identifier. */
-
-#define FLEET_DATA  "../dat/fleet.xml" /**< Where to find fleet data. */
+#define FLEET_DATA      "../dat/fleet.xml" /**< Where to find fleet data. */
+#define FLEETGROUP_DATA "../dat/fleetgroup.xml" /**< Where to find fleetgroup. */
 
 #define CHUNK_SIZE  32  /**< Size to allocate memory by. */
 
@@ -35,6 +26,13 @@
 static Fleet* fleet_stack = NULL; /**< Fleet stack. */
 static int nfleets = 0; /**< Number of fleets. */
 
+/* Stack of fleetgroups. */
+static FleetGroup* fleetgroup_stack = NULL; /**< FleetGroup stack. */
+static int nfleetgroups = 0; /**< Number of fleetgroups. */
+
+static int fleet_parse(Fleet* tmp, const xmlNodePtr parent);
+static int fleet_parseGroup(FleetGroup* fltgrp, xmlNodePtr parent);
+
 /**
  * @brief Grabs a fleet out of the stack.
  *    @param name Name of the fleet to match.
@@ -47,7 +45,21 @@ Fleet* fleet_get(const char* name) {
     if(strcmp(fleet_stack[i].name, name)==0)
       return &fleet_stack[i];
 
-  WARN("Fleet '%s' not found in stack", name);
+  return NULL;
+}
+
+/**
+ * @brief Grab a fleetgroup out of the stack.
+ *    @param name Name of the fleetgroup to match.
+ *    @return The fleetgroup matching name or NULL if not found.
+ */
+FleetGroup* fleet_getGroup(const char* name) {
+  int i;
+
+  for(i = 0; i < nfleetgroups; i++)
+    if(strcmp(fleetgroup_stack[i].name, name)==0)
+      return &fleetgroup_stack[i];
+
   return NULL;
 }
 
@@ -136,29 +148,34 @@ static int fleet_parse(Fleet* tmp, const xmlNodePtr parent) {
  * @brief Loads all the fleets.
  *    @return 0 on success.
  */
-int fleet_load(void) {
+static int fleet_loadFleets(void) {
   int mem;
   uint32_t bufsize;
-  char* buf = ldata_read(FLEET_DATA, &bufsize);
 
+  char* buf;
   xmlNodePtr node;
-  xmlDocPtr doc = xmlParseMemory(buf, bufsize);
 
-  node = doc->xmlChildrenNode; /* Ships node. */
-  if(strcmp((char*)node->name, XML_ID)) {
-    ERR("Malformed "FLEET_DATA" file: missing root element '"XML_ID"'");
+  xmlDocPtr doc;
+
+  /* Load the data. */
+  buf = ldata_read(FLEET_DATA, &bufsize);
+  doc = xmlParseMemory(buf, bufsize);
+
+  node = doc->xmlChildrenNode; /* Fleets node. */
+  if(strcmp((char*)node->name, "Fleets")) {
+    ERR("Malformed "FLEET_DATA" file: missing root element 'Fleets'.");
     return -1;
   }
 
-  node = node->xmlChildrenNode; /* First ship node. */
+  node = node->xmlChildrenNode; /* First fleet node. */
   if(node == NULL) {
-    ERR("Malformed "FLEET_DATA" file: does not contain elements");
+    ERR("Malformed "FLEET_DATA" file: does not contain elements.");
     return -1;
   }
 
   mem = 0;
   do {
-    if(xml_isNode(node, XML_FLEET)) {
+    if(xml_isNode(node, "fleet")) {
       /* See if memory must grow. */
       nfleets++;
       if(nfleets > mem) {
@@ -177,7 +194,127 @@ int fleet_load(void) {
   xmlFreeDoc(doc);
   free(buf);
 
-  DEBUG("Loaded %d Fleets%s", nfleets, (nfleets == 1) ? "" : "s");
+  return 0;
+}
+
+/**
+ * @brief Parses a fleetgroup from an xml node.
+ *    @param fltgrp FleetGroup to fill with data from the xml node.
+ *    @param parent Node containing fleetgroup data.
+ *    @return 0 on success.
+ */
+static int fleet_parseGroup(FleetGroup* fltgrp, xmlNodePtr parent) {
+  int mem;
+  xmlNodePtr node;
+  Fleet* f;
+  char* buf;
+
+  /* Clear memory. */
+  memset(fltgrp, 0, sizeof(FleetGroup));
+
+  /* Get the name. */
+  xmlr_attr(parent, "name", fltgrp->name);
+
+  /* Load the fleetgroup data. */
+  node = parent->children;
+  mem = 0;
+  do {
+    if(xml_isNode(node, "fleet")) {
+      /* See if memory must grow. */
+      fltgrp->nfleets++;
+      if(fltgrp->nfleets > mem) {
+        mem += CHUNK_SIZE;
+        fltgrp->fleets = realloc(fltgrp->fleets, sizeof(Fleet*) * mem);
+        fltgrp->chance = realloc(fltgrp->chance, sizeof(int) * mem);
+      }
+
+      /* Add the fleet. */
+      f = fleet_get(xml_get(node));
+      if(f == NULL) {
+        WARN("Fleet '%s' in FleetGroup '%s' not found in stack.",
+            xml_get(node), fltgrp->name);
+        fltgrp->nfleets--;
+        continue;
+      }
+      fltgrp->fleets[fltgrp->nfleets-1] = f;
+
+      /* Get the chance. */
+      xmlr_attr(node, "chance", buf);
+      if(buf == NULL) {
+        WARN("Fleet '%s' in FleetGroup '%s' missing 'chance' attribute.",
+            xml_get(node), fltgrp->name);
+        fltgrp->chance[fltgrp->nfleets-1] = 0;
+        continue;
+      }
+      fltgrp->chance[fltgrp->nfleets-1] = CLAMP(0, 100, atoi(buf));
+    }
+  } while(xml_nextNode(node));
+
+  return 0;
+}
+
+/**
+ * @brief Load all the fleetgroups.
+ *    @return 0 on success.
+ */
+static int fleet_loadFleetGroups(void) {
+  int mem;
+  uint32_t bufsize;
+  char* buf;
+  xmlNodePtr node;
+  xmlDocPtr doc;
+
+  /* Create the document. */
+  buf = ldata_read(FLEETGROUP_DATA, &bufsize);
+  doc = xmlParseMemory(buf, bufsize);
+
+  node = doc->xmlChildrenNode; /* Fleetgroups node. */
+  if(strcmp((char*)node->name, "FleetGroups")) {
+    ERR("Malformed "FLEETGROUP_DATA" file: missing root element 'FleetGroups'");
+    return -1;
+  }
+
+  node = node->xmlChildrenNode; /* First fleetgroup node. */
+  if(node == NULL) {
+    ERR("Malformed "FLEETGROUP_DATA" file: does not contain elements");
+    return -1;
+  }
+
+  mem = 0;
+  do {
+    if(xml_isNode(node, "fleetgroup")) {
+      /* See if memory must grow. */
+      nfleetgroups++;
+      if(nfleets > mem) {
+        mem += CHUNK_SIZE;
+        fleetgroup_stack = realloc(fleetgroup_stack, sizeof(FleetGroup) * mem);
+      }
+
+      /* Load the fleetgroup. */
+      fleet_parseGroup(&fleetgroup_stack[nfleetgroups-1], node);
+    }
+  } while(xml_nextNode(node));
+
+  /* Shrink to minimum. */
+  fleet_stack = realloc(fleet_stack, sizeof(Fleet) * nfleets);
+
+  xmlFreeDoc(doc);
+  free(buf);
+
+  return 0;
+}
+
+/**
+ * @brief Load all the fleets and fleetgroups.
+ *    @return 0 on success.
+ */
+int fleet_load(void) {
+  if(fleet_loadFleets())
+    return -1;
+  if(fleet_loadFleetGroups())
+    return -1;
+
+  DEBUG("Loaded %d Fleet%s", nfleets, (nfleets==1) ? "" : "s");
 
   return 0;
 }
@@ -200,8 +337,20 @@ void fleet_free(void) {
       free(fleet_stack[i].ai);
     }
     free(fleet_stack);
-    fleet_stack = NULL;
   }
+  fleet_stack = NULL;
   nfleets = 0;
+
+  /* Free the fleetgroup stack. */
+  if(fleetgroup_stack != NULL) {
+    for(i = 0; i < nfleetgroups; i++) {
+      free(fleetgroup_stack[i].name);
+      free(fleetgroup_stack[i].fleets);
+      free(fleetgroup_stack[i].chance);
+    }
+    free(fleetgroup_stack);
+  }
+  fleetgroup_stack = NULL;
+  nfleetgroups = 0;
 }
 
diff --git a/src/fleet.h b/src/fleet.h
index 834981a..8da1b74 100644
--- a/src/fleet.h
+++ b/src/fleet.h
@@ -25,21 +25,36 @@ typedef struct FleetPilot_ {
  * mission triggers.
  *
  * @sa FleetPilot
+ * @sa FleetGroup
  */
 typedef struct Fleet_ {
-  char* name;   /**< Fleet name, used as the identifier. */
-  int faction;  /**< Faction of the fleet. */
-
-  char* ai;     /**< faction of the fleet. */
-
+  char* name;         /**< Fleet name, used as the identifier. */
+  int faction;        /**< Faction of the fleet. */
+  char* ai;           /**< faction of the fleet. */
   FleetPilot* pilots; /**< The pilots in the fleet. */
-  int npilots;  /**< Total number of pilots. */
+  int npilots;        /**< Total number of pilots. */
 } Fleet;
 
+/**
+ * @brief Represents a group of fleets.
+ *
+ * Used to simplify creation of star systems and easily synchonize all systems.
+ * with new ship additions.
+ *
+ * @sa Fleet
+ */
+typedef struct FleetGroup_ {
+  char* name;     /** Name of the fleetgroup, used as the identifier. */
+  Fleet** fleets; /**< List of fleets in the group. */
+  int* chance;    /**< Chance of each fleet in the group. */
+  int nfleets;    /**< Number of fleets in the group. */
+} FleetGroup;
+
 /*
  * Get fleet stuff.
  */
 Fleet* fleet_get(const char* name);
+FleetGroup* fleet_getGroup(const char* name);
 
 /*
  * Load / cleanup.
diff --git a/src/lephisto.h b/src/lephisto.h
index 92c778d..e8f5597 100644
--- a/src/lephisto.h
+++ b/src/lephisto.h
@@ -8,11 +8,12 @@
 
 #define APPNAME "Lephisto"    /**< Application name. */
 
-#define ABS(x)    (((x)<0)?-(x):(x))    /**< Return absulute value. */
-#define FABS(x)   (((x)<0.)?-(x):(x))   /**< Return float absolute value. */
+#define ABS(x)          (((x)<0)?-(x):(x))    /**< Return absulute value. */
+#define FABS(x)         (((x)<0.)?-(x):(x))   /**< Return float absolute value. */
 
-#define MAX(x,y)  (((x)>(y))?(x):(y))   /**< Return maximum. */
-#define MIN(x,y)  (((x)>(y))?(y):(x))   /**< Return minumum. */
+#define MAX(x,y)        (((x)>(y))?(x):(y))   /**< Return maximum. */
+#define MIN(x,y)        (((x)>(y))?(y):(x))   /**< Return minumum. */
+#define CLAMP(a, b, x)  ((x)<(a)?(a):((x)>(b)?(b):(x))) /**< Clamps x between a and b: a <= x <= b */
 
 #define pow2(x)   ((x)*(x))             /**< ^2 */
 
diff --git a/src/perlin.c b/src/perlin.c
index 5bd74c0..9de13bb 100644
--- a/src/perlin.c
+++ b/src/perlin.c
@@ -34,10 +34,6 @@
  * @brief Ponderates x between a and b.
  */
 #define LERP(a, b, x)   (a + x * (b - a))
-/**
- * @brief Clamps x between a and b: a <= x <= b.
- */
-#define CLAMP(a, b, x)  ((x) < (a) ? (a) : ((x) > (b) ? (b) : (x)))
 
 /**
  * @brief Structure used for generating noise.