diff --git a/bin/ai_test.lua b/bin/ai_test.lua
new file mode 100644
index 0000000..4a9cbd3
--- /dev/null
+++ b/bin/ai_test.lua
@@ -0,0 +1,4 @@
+function control(pilot)
+ accel(1)
+end
+
diff --git a/dat/ship.xml b/dat/ship.xml
index f9ed5f2..e657d1c 100644
--- a/dat/ship.xml
+++ b/dat/ship.xml
@@ -5,7 +5,7 @@
1
400
- 960
+ 360
360
diff --git a/src/ai.c b/src/ai.c
index b19aed7..944b73a 100644
--- a/src/ai.c
+++ b/src/ai.c
@@ -6,6 +6,7 @@
#include "def.h"
#include "log.h"
#include "pilot.h"
+#include "physics.h"
#include "ai.h"
// == AI ======================================================
@@ -21,23 +22,45 @@
// (task).
// ============================================================
+// Call the AI function with name f.
+#define AI_LCALL(f) (lua_getglobal(L, f), lua_call(L, 0, 0))
+
+static int ai_minbrakedist(lua_State* L); // Minimal breaking distance.
+static int ai_accel(lua_State* L); // Accelerate.
// Basic task.
// name : Tasks name (Lua function.)
// target : Target, this will depend on the task itself.
typedef struct {
char* name;
- void* target;
+ union {
+ void* target;
+ unsigned int ID;
+ };
} Task;
// Global Lua interpreter.
static lua_State* L = NULL;
+// Current pilot "thinking" and assorted variables.
+static Pilot* cur_pilot = NULL;
+static double pilot_acc = 0.;
+static double pilot_turn = 0.;
+
int ai_init(void) {
L = luaL_newstate();
if(L == NULL)
return -1;
+ // Register C funstions in Lua.
+ lua_register(L, "minbrakedist", ai_minbrakedist);
+ lua_register(L, "accel", ai_accel);
+
+ if(luaL_dofile(L, "ai_test.lua") != 0) {
+ WARN("Unable to load AI file: %s", "ai_test.lua");
+ return -1;
+ }
+
return 0;
}
@@ -47,8 +70,43 @@ void ai_exit(void) {
// Heart of hearts of the ai!! Brains of the pilot.
void ai_think(Pilot* pilot) {
+ cur_pilot = pilot; // Set current pilot being processed.
+ pilot_acc = pilot_turn = 0.; // Clean up some variables.
if(pilot->action == NULL) {
// Idle git!
+ AI_LCALL("control");
}
+
+ cur_pilot->solid->dir_vel = 0.;
+ if(pilot_turn)
+ cur_pilot->solid->dir_vel -= cur_pilot->ship->turn * pilot_turn;
+ vect_pset(&cur_pilot->solid->force, cur_pilot->ship->thrust * pilot_acc, cur_pilot->solid->dir);
+}
+
+// ========================================================
+// C functions to call from Lua.
+// -----------------------------
+// Get the minimum braking distance.
+//
+// Braking vel ==> v*t = 0.5 a * t^2 => t = 2*v / a
+// Add turn around time (to initial velocity) :
+// ==> 180.*360./cur_pilot->ship->turn
+// Add it to general euler equation x = v*t + 0.5 * a * t^2
+// Have fun.
+// ========================================================
+static int ai_minbrakedist(lua_State* L) {
+ double time = 2. * VMOD(cur_pilot->solid->vel) /
+ (cur_pilot->ship->thrust / cur_pilot->solid->mass);
+
+ double dist = VMOD(cur_pilot->solid->vel) * (time + 0.5 * (180. * 360. / cur_pilot->ship->turn)) -
+ 0.5 * (cur_pilot->ship->thrust / cur_pilot->solid->mass)*time*time;
+
+ lua_pushnumber(L, dist); // return
+ return 1;
+}
+
+static int ai_accel(lua_State* L) {
+ pilot_acc = (lua_isnumber(L, 1)) ? (double)lua_tonumber(L, 1) : 1.;
+ return 0;
}
diff --git a/src/main.c b/src/main.c
index abb5b25..fa30dd3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -239,12 +239,12 @@ int main(int argc, char** argv) {
// | Text and GUI.
// ========================================================
static void update_all(void) {
- double dt = (double)(SDL_GetTicks() - time) / 1000.0;
+ double dt = (double)(SDL_GetTicks() - time) / 1000.;
time = SDL_GetTicks();
if(dt > MINIMUM_FPS) {
Vec2 pos;
- vect_cinit(&pos, 10., (double)(gl_screen.h-40));
+ vect_cset(&pos, 10., (double)(gl_screen.h-40));
gl_print(NULL, &pos, "FPS is really low! Skipping frames.");
SDL_GL_SwapBuffers();
return;
@@ -273,7 +273,7 @@ static void display_fps(const double dt) {
fps_dt = fps_cur = 0.;
}
Vec2 pos;
- vect_cinit(&pos, 10., (double)(gl_screen.h-20));
+ vect_cset(&pos, 10., (double)(gl_screen.h-20));
gl_print(NULL, &pos, "%3.2f", fps);
}
diff --git a/src/physics.c b/src/physics.c
index 7bc523d..f0a0fa8 100644
--- a/src/physics.c
+++ b/src/physics.c
@@ -8,16 +8,33 @@
#define M_PI 3.14159265358979323846f
#endif
-// Init cartesian vector.
-void vect_cinit(Vec2* v, double x, double y) {
+// Set the vector value using cartesian coords.
+void vect_cset(Vec2* v, double x, double y) {
+ v->x = x;
+ v->y = y;
v->mod = MOD(x,y);
v->angle = ANGLE(x, y);
}
-// Init polarized vector
-void vect_pinit(Vec2* v, double mod, double angle) {
+// Set the vector value using polar coords.
+void vect_pset(Vec2* v, double mod, double angle) {
v->mod = mod;
v->angle = angle;
+ v->x = v->mod*cos(v->angle);
+ v->y = v->mod*sin(v->angle);
+}
+
+// Copy vector source to destination.
+void vectcpy(Vec2* dest, const Vec2* src) {
+ dest->x = src->x;
+ dest->y = src->y;
+ dest->mod = src->mod;
+ dest->angle = src->angle;
+}
+
+// Null a vector.
+void vectnull(Vec2* v) {
+ v->x = v->y = v->mod = v->angle = 0.;
}
// ==Update method.========================================
@@ -124,14 +141,12 @@ static void rk4_update(Solid* obj, const double dt) {
py += ty;
vy += ay*h;
}
- obj->vel.mod = MOD(vx, vy);
- obj->vel.angle = ANGLE(vx, vy);
+ vect_cset(&obj->vel, vx, vy);
} else {
px += dt*vx;
py += dt*vy;
}
- obj->pos.mod = MOD(px, py);
- obj->pos.angle = ANGLE(px, py);
+ vect_cset(&obj->pos, px, py);
}
// Initialize a new solid.
@@ -141,18 +156,13 @@ void solid_init(Solid* dest, const double mass, const Vec2* vel, const Vec2* pos
dest->force.mod = 0;
dest->dir = 0;
- if(vel == NULL)
- vect_cinit(&dest->vel, 0., 0.);
- else
- vect_pinit(&dest->vel, vel->mod, vel->angle);
-
- if(pos == NULL)
- vect_cinit(&dest->pos, 0., 0.);
- else
- vect_pinit(&dest->pos, pos->mod, pos->angle);
+ if(vel == NULL) vectnull(&dest->vel);
+ else vectcpy(&dest->vel, vel);
+
+ if(pos == NULL) vectnull(&dest->pos);
+ else vectcpy(&dest->pos, pos);
dest->update = rk4_update;
- //dest->update = simple_update;
}
// Create a new solid.
diff --git a/src/physics.h b/src/physics.h
index a674dfb..a939652 100644
--- a/src/physics.h
+++ b/src/physics.h
@@ -16,8 +16,10 @@ typedef struct {
} Vec2;
// Vector manupulation.
-void vect_cinit(Vec2* v, double x, double y);
-void vect_pinit(Vec2* v, double mod, double angle);
+void vect_cset(Vec2* v, double x, double y);
+void vect_pset(Vec2* v, double mod, double angle);
+void vectcpy(Vec2* dest, const Vec2* src);
+void vectnull(Vec2* v);
// Describe any solid in 2D space.
struct Solid {
diff --git a/src/pilot.c b/src/pilot.c
index 5440ff3..d7077b0 100644
--- a/src/pilot.c
+++ b/src/pilot.c
@@ -56,7 +56,7 @@ static void pilot_update(Pilot* pilot, const double dt) {
if(VMOD(pilot->solid->vel) > pilot->ship->speed) {
// Should not go faster.
- VMOD(pilot->solid->vel) = pilot->ship->speed;
+ vect_pset(&pilot->solid->vel, pilot->ship->speed, VANGLE(pilot->solid->vel));
}
pilot_render(pilot);
diff --git a/src/player.c b/src/player.c
index 56a2841..6ec1aac 100644
--- a/src/player.c
+++ b/src/player.c
@@ -29,8 +29,7 @@ void player_think(Pilot* player, const double dt) {
if(player_turn)
player->solid->dir_vel -= player->ship->turn * player_turn;
- player->solid->force.angle = player->solid->dir;
- player->solid->force.mod = player->ship->thrust * player_acc;
+ vect_pset(&player->solid->force, player->ship->thrust * player_acc, player->solid->dir);
}
// Initialization/exit functions (does not assign keys).