From 9fae81c3896ffdc4a75e642dad03355cb40e5ff7 Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Thu, 14 Feb 2013 14:25:32 +0000
Subject: [PATCH] [Fix] AI's landing, it's still not as good as I wish however.
 [Add] A few more xml macros and cleaned up a little code to use them.

---
 dat/outfit.xml |  4 ++--
 src/ai.c       |  2 +-
 src/outfit.c   | 58 +++++++++++++++++++++-----------------------------
 src/outfit.h   | 26 +++++++++++-----------
 src/pilot.c    | 40 ++++++++++++++++++++++------------
 src/space.c    |  3 +++
 src/space.h    |  1 +
 src/xml.h      |  9 ++++++--
 8 files changed, 77 insertions(+), 66 deletions(-)

diff --git a/dat/outfit.xml b/dat/outfit.xml
index 8604419..7323505 100644
--- a/dat/outfit.xml
+++ b/dat/outfit.xml
@@ -7,8 +7,8 @@
       <mass>1</mass>
 		</general>
     <specific type = "1">
-      <sound>laser.wav</sound>
-      <gfx>lasergreen.png</gfx>
+      <sound>laser</sound>
+      <gfx>lasergreen</gfx>
       <delay>500</delay>
       <speed>550</speed>
       <range>300</range>
diff --git a/src/ai.c b/src/ai.c
index 751c834..f43a299 100644
--- a/src/ai.c
+++ b/src/ai.c
@@ -491,7 +491,7 @@ static int ai_minbrakedist(lua_State* L) {
   double time = VMOD(cur_pilot->solid->vel) /
         (cur_pilot->ship->thrust / cur_pilot->solid->mass);
 
-  double dist = VMOD(cur_pilot->solid->vel) * (time + cur_pilot->ship->turn/180.) -
+  double dist = VMOD(cur_pilot->solid->vel) * (time + 180./cur_pilot->ship->turn) -
         0.5 * (cur_pilot->ship->thrust / cur_pilot->solid->mass)*time*time;
 
   lua_pushnumber(L, dist); // return
diff --git a/src/outfit.c b/src/outfit.c
index e733b75..3f6b2f8 100644
--- a/src/outfit.c
+++ b/src/outfit.c
@@ -81,27 +81,20 @@ static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent) {
 
   do {
     // Load all the things.
-    if(strcmp((char*)node->name, "speed")==0)
-      tmp->speed = (double)atoi((char*)node->children->content);
-    else if(strcmp((char*)node->name, "delay")==0)
-      tmp->delay = atoi((char*)node->children->content);
-    else if(strcmp((char*)node->name, "range")==0)
-      tmp->range = atof((char*) node->children->content);
-    else if(strcmp((char*)node->name, "accuracy")==0)
-      tmp->accuracy = atof((char*)node->children->content);
-    else if(strcmp((char*)node->name, "gfx")==0) {
-      snprintf(str, strlen((char*)node->children->content)+sizeof(OUTFIT_GFX),
-            OUTFIT_GFX"%s", (char*)node->children->content);
+    if(xml_isNode(node, "speed")) tmp->speed = xml_getFloat(node);
+    else if(xml_isNode(node, "delay")) tmp->delay = xml_getInt(node);
+    else if(xml_isNode(node, "range")) tmp->range = xml_getFloat(node);
+    else if(xml_isNode(node, "accuracy")) tmp->accuracy = xml_getFloat(node);
+    else if(xml_isNode(node, "gfx")) {
+      snprintf(str, strlen(xml_get(node))+sizeof(OUTFIT_GFX)+4, OUTFIT_GFX"%s.png", xml_get(node));
       tmp->gfx_space = gl_newSprite(str, 6, 6);
     }
-    if(strcmp((char*)node->name, "damage")==0) {
+    else if(xml_isNode(node, "damage")) {
       cur = node->children;
-      while((cur = cur->next)) {
-        if(strcmp((char*)cur->name, "armor")==0)
-          tmp->damage_armor = atof((char*)cur->children->content);
-        else if(strcmp((char*)cur->name, "shield")==0)
-          tmp->damage_shield = atof((char*)cur->children->content);
-      }
+      do {
+        if(xml_isNode(cur, "armor")) tmp->damage_armor = xml_getFloat(cur);
+        else if(xml_isNode(cur, "shield")) tmp->damage_shield = xml_getFloat(cur);
+      } while((cur = cur->next));
     }
   } while((node = node->next));
 #define MELEMENT(o,s) if((o) == 0) WARN("Outfit '%s' missing '"s"' element", tmp->name)
@@ -119,31 +112,28 @@ static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent) {
 static Outfit* outfit_parse(const xmlNodePtr parent) {
   Outfit* tmp = CALLOC_L(Outfit);
   xmlNodePtr cur, node;
-  xmlChar* prop;
+  char* prop;
 
-  tmp->name = (char*)xmlGetProp(parent, (xmlChar*)"name"); // Already mallocs.
+  tmp->name = xml_nodeProp(parent, "name"); // Already malloced.
   if(tmp->name == NULL) WARN("Outfit in "OUTFIT_DATA" has invalid or no name");
 
   node = parent->xmlChildrenNode;
   do {
     // Load all the things.
-    if(strcmp((char*)node->name, "general")==0) {
+    if(xml_isNode(node, "general")) {
       cur = node->children;
-      while((cur = cur->next)) {
-        if(strcmp((char*)cur->name, "max")==0)
-          tmp->max = atoi((char*)cur->children->content);
-        else if(strcmp((char*)cur->name, "tech")==0)
-          tmp->tech = atoi((char*)cur->children->content);
-        else if(strcmp((char*)cur->name, "mass")== 0)
-          tmp->mass = atoi((char*)cur->children->content);
-      }
+      do {
+        if(xml_isNode(cur, "max")) tmp->max = xml_getInt(cur);
+        else if(xml_isNode(cur, "tech")) tmp->tech = xml_getInt(cur);
+        else if(xml_isNode(cur, "mass")) tmp->mass = xml_getInt(cur);
+      } while((cur = cur->next));
     }
-    else if(strcmp((char*)node->name, "specific")==0) {
+    else if(xml_isNode(node, "specific")) {
       // Has to be processed seperately.
-      prop = xmlGetProp(node,(xmlChar*)"type");
+      prop = xml_nodeProp(node, "type");
       if(prop == NULL)
         ERR("Outfit '%s' element 'specific' missing property 'type'", tmp->name);
-      tmp->type = atoi((char*)prop);
+      tmp->type = atoi(prop);
       free(prop);
       switch(tmp->type) {
         case OUTFIT_TYPE_NULL:
@@ -180,7 +170,7 @@ int outfit_load(void) {
   xmlDocPtr doc = xmlParseMemory(buf, bufsize);
 
   node = doc->xmlChildrenNode;
-  if(strcmp((char*)node->name, XML_OUTFIT_ID)) {
+  if(!xml_isNode(node, XML_OUTFIT_ID)) {
     ERR("Malformed "OUTFIT_DATA" file: missing root element '"XML_OUTFIT_ID"'");
     return -1;
   }
@@ -192,7 +182,7 @@ int outfit_load(void) {
   }
 
   do {
-    if(node->type == XML_NODE_START && strcmp((char*)node->name, XML_OUTFIT_TAG)==0) {
+    if(xml_isNode(node,  XML_OUTFIT_TAG)) {
       tmp = outfit_parse(node);
       outfit_stack = realloc(outfit_stack, sizeof(Outfit)*(++outfits));
       memcpy(outfit_stack+outfits-1, tmp, sizeof(Outfit));
diff --git a/src/outfit.h b/src/outfit.h
index 235f674..18d41f9 100644
--- a/src/outfit.h
+++ b/src/outfit.h
@@ -6,19 +6,19 @@
 
 // Outfit types.
 typedef enum {
-  OUTFIT_TYPE_NULL = 0,
-  OUTFIT_TYPE_BOLT,
-  OUTFIT_TYPE_BEAM,
-  OUTFIT_TYPE_MISSILE_DUMB,
-  OUTFIT_TYPE_MISSILE_DUMB_AMMO,
-  OUTFIT_TYPE_MISSILE_SEEK,
-  OUTFIT_TYPE_MISSILE_SEEK_AMMO,
-  OUTFIT_TYPE_MISSILE_SEEK_SMART,
-  OUTFIT_TYPE_MISSILE_SEEK_SMART_AMMO,
-  OUTFIT_TYPE_MISSILE_SWARM,
-  OUTFIT_TYPE_MISSILE_SWARM_AMMO,
-  OUTFIT_TYPE_MISSILE_SWARM_SMART,
-  OUTFIT_TYPE_MISSILE_SWARM_SMART_AMMO
+  OUTFIT_TYPE_NULL                      = 0,
+  OUTFIT_TYPE_BOLT                      = 1,
+  OUTFIT_TYPE_BEAM                      = 2,
+  OUTFIT_TYPE_MISSILE_DUMB              = 3,
+  OUTFIT_TYPE_MISSILE_DUMB_AMMO         = 4,
+  OUTFIT_TYPE_MISSILE_SEEK              = 5,
+  OUTFIT_TYPE_MISSILE_SEEK_AMMO         = 6,
+  OUTFIT_TYPE_MISSILE_SEEK_SMART        = 7,
+  OUTFIT_TYPE_MISSILE_SEEK_SMART_AMMO   = 8,
+  OUTFIT_TYPE_MISSILE_SWARM             = 9,
+  OUTFIT_TYPE_MISSILE_SWARM_AMMO        = 10,
+  OUTFIT_TYPE_MISSILE_SWARM_SMART       = 11,
+  OUTFIT_TYPE_MISSILE_SWARM_SMART_AMMO  = 12
 } OutfitType;
 
 // An outfit depends a lot on the type.
diff --git a/src/pilot.c b/src/pilot.c
index a5b8e9e..a371f52 100644
--- a/src/pilot.c
+++ b/src/pilot.c
@@ -40,15 +40,19 @@ static Fleet* fleet_parse(const xmlNodePtr parent);
 
 // Get the next pilot based on id.
 unsigned int pilot_getNext(const unsigned int id) {
-  // Regular search.
-  int i;
-  for(i = 0; i < pilots; i++)
-    if(pilot_stack[i]->id == id)
-      break;
+  // Dichotmical search.
+  int l, m, h;
+  l = 0;
+  h = pilots-1;
+  while(l <= h) {
+    m = (l+h)/2;
+    if(pilot_stack[m]->id > id) h = m-1;
+    else if(pilot_stack[m]->id < id) l = m+1;
+    else break;
+  }
 
-  if(i == pilots-1) return PLAYER_ID;
-
-  return pilot_stack[i+1]->id;
+  if(m == (pilots-1)) return PLAYER_ID;
+  else return pilot_stack[m+1]->id;
 }
 
 // Get the nearest enemy to the pilot -- Tamir's (insightful) request.
@@ -87,6 +91,7 @@ unsigned pilot_getHostile(void) {
 // Pull a pilot out of the pilot_stack based on id.
 Pilot* pilot_get(const unsigned int id) {
   // Regular search.
+#if 0
   int i;
   for(i = 0; i < pilots; i++)
     if(pilot_stack[i]->id == id)
@@ -94,13 +99,20 @@ Pilot* pilot_get(const unsigned int id) {
   return NULL;
 
   if(id == 0) return player;
-#if 0
-  // Dichotomical search.
-  int i, n;
-  for(i = 0, n = pilots/2; n > 0; n /= 2)
-    i += (pilot_stack[i+n]->id > id) ? 0 : n;
-  return (pilot_stack[i]->id == id) ? pilot_stack[i] : NULL;
 #endif
+  if(id == PLAYER_ID) return player; // Special case player.
+
+  // Dichotomical search.
+  int l, m, h;
+  l = 0;
+  h = pilots-1;
+  while(l <= h) {
+    m = (l+h)/2;
+    if(pilot_stack[m]->id > id) h = m-1;
+    else if(pilot_stack[m]->id < id) l = m+1;
+    else return pilot_stack[m];
+  }
+  return NULL;
 }
 
 // Mkay, this is how we shoot. Listen up.
diff --git a/src/space.c b/src/space.c
index 19380e4..0403cd8 100644
--- a/src/space.c
+++ b/src/space.c
@@ -152,6 +152,9 @@ int space_hyperspace(Pilot* p) {
     if(d < MIN_HYPERSPACE_DIST)
       return (int)(MIN_HYPERSPACE_DIST - d);
   }
+  // Too fast.
+  if(VMOD(p->solid->vel) > MAX_HYPERSPACE_VEL) return -1;
+
   // TODO: All hyperspace worky work.
   if(p == player) {
     // Player crap.
diff --git a/src/space.h b/src/space.h
index 86fd2c1..c1d2b12 100644
--- a/src/space.h
+++ b/src/space.h
@@ -4,6 +4,7 @@
 #include "pilot.h"
 
 #define MIN_HYPERSPACE_DIST 1500
+#define MAX_HYPERSPACE_VEL  3
 
 // Planet types. I didn't take them from Star Trek, I promise.
 typedef enum {
diff --git a/src/xml.h b/src/xml.h
index 053300e..1d918f9 100644
--- a/src/xml.h
+++ b/src/xml.h
@@ -6,8 +6,13 @@
 #define XML_NODE_TEXT   3
 
 // Check if node n is of name s.
-#define xml_isNode(n,s) ((n)->type == XML_NODE_START) && \
-      (strcmp((char*)(n)->name, s)==0)
+#define xml_isNode(n,s) (((n)->type == XML_NODE_START) && \
+      (strcmp((char*)(n)->name, s)==0))
 
+// Get the property s of node n. This mallocs.
 #define xml_nodeProp(n,s) (char*)xmlGetProp(n, (xmlChar*)s)
 
+#define xml_get(n)      (char*)(n)->children->content
+#define xml_getInt(n)   atoi((char*)(n)->children->content)
+#define xml_getFloat(n) atof((char*)(n)->children->content)
+