[Add] Initial AI support with Lua

This commit is contained in:
Allanis 2013-02-03 00:37:42 +00:00
parent 05e83fdcd6
commit 57dc51fb91
8 changed files with 101 additions and 28 deletions

4
bin/ai_test.lua Normal file
View File

@ -0,0 +1,4 @@
function control(pilot)
accel(1)
end

View File

@ -5,7 +5,7 @@
<class>1</class>
<movement>
<thrust>400</thrust>
<turn>960</turn>
<turn>360</turn>
<speed>360</speed>
</movement>
<health>

View File

@ -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;
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;
}

View File

@ -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);
}

View File

@ -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(vel == NULL) vectnull(&dest->vel);
else vectcpy(&dest->vel, vel);
if(pos == NULL)
vect_cinit(&dest->pos, 0., 0.);
else
vect_pinit(&dest->pos, pos->mod, pos->angle);
if(pos == NULL) vectnull(&dest->pos);
else vectcpy(&dest->pos, pos);
dest->update = rk4_update;
//dest->update = simple_update;
}
// Create a new solid.

View File

@ -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 {

View File

@ -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);

View File

@ -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).