From c10b1f24fb75bb27747e53e8f3d45db85ff7c29b Mon Sep 17 00:00:00 2001 From: Allanis Date: Mon, 4 Feb 2013 14:10:59 +0000 Subject: [PATCH] [Add] A few more AI(Lua) calls. [Add] A little more documentation for Lua. --- scripts/ai/API | 12 +++++++++ scripts/ai/test.lua | 25 ++++++------------ src/ai.c | 63 ++++++++++++++++++++++++++++++++++++++++++--- src/opengl.c | 2 +- src/pack.c | 2 +- src/player.c | 2 +- 6 files changed, 83 insertions(+), 23 deletions(-) diff --git a/scripts/ai/API b/scripts/ai/API index c698b5b..b4db7a1 100644 --- a/scripts/ai/API +++ b/scripts/ai/API @@ -46,6 +46,18 @@ minbrakedist() -- Returns the minimum required braking distance assuming all goes well. -- return number distance needed to brake. +// ================ +// BOOLEAN! +// ================ + +ismaxval() + -- Check if velocity is maximum. + -- return true if velocity is max, false otherwise. + +isstopped() + -- Check if we are stopped. + -- return true if stopped, false otherwise. + // ================ // MOVEMENT! // ================ diff --git a/scripts/ai/test.lua b/scripts/ai/test.lua index 03890ed..df11988 100644 --- a/scripts/ai/test.lua +++ b/scripts/ai/test.lua @@ -1,3 +1,11 @@ +-- Required control rate. +control_rate = 2 + +-- Required "control" function. +function control() + pusttask(0, "follow"); +end + function follow() target =1 dir = face(target) @@ -7,20 +15,3 @@ function follow() end end -function goto() - v = gettarget() - face(v) - - d = getdist(v) - if d < minbrakedist()*1.05 then - poptask() - else - accel(1) - end -end - -function control() - pushtask(0, "follow"); - --pushtask(0, "goto", createvect(1000, 0)); -end - diff --git a/src/ai.c b/src/ai.c index 3cb4fa6..982a841 100644 --- a/src/ai.c +++ b/src/ai.c @@ -13,6 +13,24 @@ #include "ai.h" // == AI ====================================================== +// +// -- Goal (Task) based AI with additional optimization. +// AI uses the goal (task) based AI approach with tasks scripted +// in lua. Additionally there is a task that is hardcoded and +// obligatory in any AI script. The 'control' task, whose only +// purpose is to assign tasks if there is none, and optimize +// or change tasks if there are. +// +// Eg.. Pilot A is attacking Pilot B. Pilot C then comes along +// the same system and is of the same faction as Pilot B. and +// therefor attacks Pilot A. Pilot A would keep fighting pilot +// B and until the control task comes in. Then the pilot could +// run if it deems fit that Pilot C and Pilot B together are +// both too strong for A. Or.. Attack C as it is an easy target +// to finish. +// Basically, there is many possibilities, and it's down to the +// Lua fanatics to decide what to do. +// // -- AI will follow basic tasks defined from Lua AI scripts. // -- If task is NULL, AI will run "control" task. // -- Task is continued every frame. @@ -26,11 +44,14 @@ // ============================================================ // Call the AI function with name f. -#define AI_LCALL(f) (lua_getglobal(L, f), lua_call(L, 0, 0)) +#define AI_LCALL(f) (lua_getglobal(L, f), lua_pcall(L, 0, 0, 0)) // Don't run the function if (n) params aren't passed. #define MIN_ARGS(n) if(lua_gettop(L) < n) return 0 +#define MAX_DIR_ERR 5.0*M_PI/180. +#define MIN_VEL_ERR 2.5 + static int ai_minbrakedist(lua_State* L); // Minimal breaking distance. static int ai_accel(lua_State* L); // Accelerate. @@ -47,10 +68,14 @@ static int ai_gettargetid(lua_State* L); // Number gettargetis() static int ai_getdistance(lua_State* L); // Number getdist(Vec2) static int ai_getpos(lua_State* L); // getpos(number/pilot) static int ai_minbrakedist(lua_State* L); // Number minbrakedist() +// Boolean expressions. +static int ai_ismaxvel(lua_State* L); // Boolean ismaxvel() +static int ai_isstopped(lua_State* L); // Boolean isstopped() // Movement. static int ai_accel(lua_State* L); // accel(number); nuimber <= 1. static int ai_turn(lua_State* L); // turn(number); abs(number) <= 1. static int ai_face(lua_State* L); // face(number/pointer) +static int ai_brake(lua_State* L); // Brake() // Misc. static int ai_createvect(lua_State* L); // createvect(number, number) @@ -70,30 +95,41 @@ void ai_destroy(Pilot* p) { // Init the AI stuff. Which is basically Lua. int ai_init(void) { L = luaL_newstate(); - if(L == NULL) + if(L == NULL) { + ERR("Unable to create a new Lua state"); return -1; + } // Open the standard Lua libraries. luaL_openlibs(L); // Register C funstions in Lua. + // Tasks. lua_register(L, "pushtask", ai_pushtask); lua_register(L, "poptask", ai_poptask); lua_register(L, "taskname", ai_taskname); + // Consult. lua_register(L, "gettarget", ai_gettarget); lua_register(L, "gettargetid", ai_gettargetid); lua_register(L, "getdist", ai_getdistance); lua_register(L, "getpos", ai_getpos); lua_register(L, "minbrakedist", ai_minbrakedist); + // Boolean. + lua_register(L, "ismaxvel", ai_ismaxvel); + lua_register(L, "isstopped", ai_isstopped); + // Movement. lua_register(L, "accel", ai_accel); lua_register(L, "turn", ai_turn); lua_register(L, "face", ai_face); + lua_register(L, "brake", ai_brake); + // Misc. lua_register(L, "createvect", ai_createvect); char* buf = pack_readfile(DATA, "../scripts/ai/test.lua", NULL); if(luaL_dostring(L, buf) != 0) { - WARN("Unable to load AI file: %s", "../scripts/ai/test.lua"); + ERR("loading AI file: %s", "../scripts/ai/test.lua"); + WARN("Most likely Lua file has improper syntax, please check it."); return -1; } @@ -247,6 +283,18 @@ static int ai_minbrakedist(lua_State* L) { return 1; } +// Are we at max velocity? +static int ai_ismaxvel(lua_State* L) { + lua_pushboolean(L, VMOD(cur_pilot->solid->vel) == cur_pilot->ship->speed); + return 1; +} + +// Have we stopped? +static int ai_isstopped(lua_State* L) { + lua_pushboolean(L, VMOD(cur_pilot->solid->vel) < MIN_VEL_ERR); + return 1; +} + // Accelerate the pilot based on a param. static int ai_accel(lua_State* L) { pilot_acc = (lua_gettop(L) > 1 && lua_isnumber(L, 1)) ? ABS((double)lua_tonumber(L, 1)) : 1.; @@ -283,6 +331,15 @@ static int ai_face(lua_State* L) { return 1; } +// This is generally good for coming to a halt. +static int ai_brake(lua_State* L) { + double diff = angle_diff(cur_pilot->solid->dir, VANGLE(cur_pilot->solid->vel)); + pilot_turn = 10*diff; + if(diff < MAX_DIR_ERR && VMOD(cur_pilot->solid->vel) > MIN_VEL_ERR) + pilot_acc = 1.; + return 0; +} + // Create a vector. static int ai_createvect(lua_State* L) { MIN_ARGS(2); diff --git a/src/opengl.c b/src/opengl.c index 132d11a..e80616e 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -52,7 +52,7 @@ static int SDL_VFlipSurface(SDL_Surface* surface) { Uint8* rowhi, *rowlo, *tmpbuf; int y; - tmpbuf = (Uint8*)malloc(surface->pitch); + tmpbuf = malloc(surface->pitch); if(tmpbuf == NULL) { WARN("Out of memory"); return -1; diff --git a/src/pack.c b/src/pack.c index d1760c2..0b66e61 100644 --- a/src/pack.c +++ b/src/pack.c @@ -165,7 +165,7 @@ int pack_files(const char* outfile, const char** infiles, const uint32_t nfiles) int pack_open(Packfile* file, const char* packfile, const char* filename) { int i, j; uint32_t nfiles; - char* buf = (char*)malloc(MAX_FILENAME); + char* buf = malloc(MAX_FILENAME); file->start = file->end = 0; diff --git a/src/player.c b/src/player.c index deaaf60..20a8f28 100644 --- a/src/player.c +++ b/src/player.c @@ -48,7 +48,7 @@ void input_init(void) { Keybind* tmp; int i; for(i = 0; keybindNames[i]; i++); // Get number of bindings. - player_input = (Keybind**)malloc(i*sizeof(Keybind*)); + player_input = malloc(i*sizeof(Keybind*)); // Create a null keybinding for each. for(i = 0; keybindNames[i]; i++) {