From 9d57f0ddfcfaa1594cfcacb8423aa61aae26e7bf Mon Sep 17 00:00:00 2001 From: Allanis Date: Sat, 9 Feb 2013 18:58:50 +0000 Subject: [PATCH] [Add] About time I added timer support for AI. [Fix] Buffer overflow in AI. --- scripts/ai/API | 21 +++++++++++++++ scripts/ai/basic.lua | 59 +++++++++++++++++++++++++++++++++++++++++ scripts/ai/merchant.lua | 42 ++++++++++++++++++++++------- scripts/ai/test.lua | 18 ++++++------- src/ai.c | 53 ++++++++++++++++++++++++++++++------ src/ai.h | 3 +++ src/faction.c | 6 +++++ src/pilot.h | 1 + 8 files changed, 176 insertions(+), 27 deletions(-) create mode 100644 scripts/ai/basic.lua diff --git a/scripts/ai/API b/scripts/ai/API index dd88df5..c074910 100644 --- a/scripts/ai/API +++ b/scripts/ai/API @@ -1,3 +1,10 @@ +// ================ +// CONSTANTS! +// ================ + +number player + -- players pilot id. + // ================ // TASKS! // ================ @@ -124,6 +131,20 @@ shoot([number weapon]) getenemy() -- return the id of the nearest enemy. +// ================ +// TIMERS! +// ================ + +settimer(number t, number delay) + -- Set timer t to wait for delay ms. + -- t - Timer to set. + -- delay - Delay time in ms to wait. + -- return nil. + +timeup(number t) + -- Return true if time is up for timer t. + -- t - timer to check. + -- return boolean true if timer t is up. // ================ // MISC! diff --git a/scripts/ai/basic.lua b/scripts/ai/basic.lua new file mode 100644 index 0000000..0f96661 --- /dev/null +++ b/scripts/ai/basic.lua @@ -0,0 +1,59 @@ +-- Required control rate. +control_rate = 2 + +-- Required "control" function. +function control() + if taskname() == "none" then + pushtask(0, "fly") + end +end + +-- Required "attacked" function. +function attacked(attacker) + if taskname() ~= "attack" and task ~= "runaway" then + -- Let's have some taunts. + if attacker == player then + local msg = rng(0,4) + if msg == 0 then say("You will never kill me!") + elseif msg == 1 then say("DIE!") + elseif msg == 2 then say("You won't survive!") + elseif msg == 3 then say("I hate you!") + end + end + pushtask(0, "attack", attacker) + end +end + +-- Runs away. +function runaway() + local target = gettargetid() + local dir = face(target, 1) + accel() +end + +-- Attack +function attack() + local target = gettargetid() + local dir = face(target) + local dist = getdist(getpos(target)) + + if parmor() < 70 then + poptask() + pushtask(0, "runaway", target) + elseif dir < 10 and dist > 300 then + accel() + elseif dir < 10 and dist < 300 then + shoot() + end +end + +-- Fly to the player. +function fly() + local target = 0 + local dir = face(target) + local dist = getdist(getpos(target)) + if dir < 10 and dist > 300 then + accel() + end +end + diff --git a/scripts/ai/merchant.lua b/scripts/ai/merchant.lua index 59bea4a..d070991 100644 --- a/scripts/ai/merchant.lua +++ b/scripts/ai/merchant.lua @@ -4,7 +4,8 @@ control_rate = 2 -- Required "control" function. function control() if taskname() == "none" then - pushtask(0, "fly") + local planet = getrndplanet() + pushtask(0, "go", planet) end end @@ -13,7 +14,7 @@ function attacked(attacker) if taskname() ~= "runaway" then -- Let's have some messages. if attacker == player then - msg = rng(0,4) + local msg = rng(0,4) if msg == 0 then say("ARGH! Please don't hurt me.") elseif msg == 1 then say("HEY! We are simply a merchant vessle.") elseif msg == 2 then say("LEAVE! ME! ALONE!") @@ -26,18 +27,39 @@ end -- Runs away. function runaway() - target = gettargetid() - dir = face(target, 1) + local target = gettargetid() + local dir = face(target, 1) accel() end --- Fly to the player. -function fly() - target = 0 - dir = face(target) - dist = getdist(getpos(target)) - if dir < 10 and dist > 300 then +-- Fly to the target. +function go() + local target = gettarget() + local dir = face(target) + local dist = getdist(target) + local bdist = minbrakedist() + if dir < 10 and dist > bdist then accel() + elseif dir < 10 and dist < bdist then + poptask() + pushtask(0, "stop") + end +end + +-- Backthrust. +function stop() + brake() + if isstopped() then + poptask() + settimer(0, rng(3000, 5000)) + pushtask(0, "land") + end +end + +--Waits. +function land() + if timeup(0) then + pushtask(0, "runaway", player) end end diff --git a/scripts/ai/test.lua b/scripts/ai/test.lua index 38ec016..0f96661 100644 --- a/scripts/ai/test.lua +++ b/scripts/ai/test.lua @@ -13,7 +13,7 @@ function attacked(attacker) if taskname() ~= "attack" and task ~= "runaway" then -- Let's have some taunts. if attacker == player then - msg = rng(0,4) + local msg = rng(0,4) if msg == 0 then say("You will never kill me!") elseif msg == 1 then say("DIE!") elseif msg == 2 then say("You won't survive!") @@ -26,16 +26,16 @@ end -- Runs away. function runaway() - target = gettargetid() - dir = face(target, 1) + local target = gettargetid() + local dir = face(target, 1) accel() end -- Attack function attack() - target = gettargetid() - dir = face(target) - dist = getdist(getpos(target)) + local target = gettargetid() + local dir = face(target) + local dist = getdist(getpos(target)) if parmor() < 70 then poptask() @@ -49,9 +49,9 @@ end -- Fly to the player. function fly() - target = 0 - dir = face(target) - dist = getdist(getpos(target)) + local target = 0 + local dir = face(target) + local dist = getdist(getpos(target)) if dir < 10 and dist > 300 then accel() end diff --git a/src/ai.c b/src/ai.c index b75baf9..108da4a 100644 --- a/src/ai.c +++ b/src/ai.c @@ -47,13 +47,15 @@ // ============================================================ // Call the AI function with name f. -#define AI_LCALL(f) (lua_getglobal(L, f), lua_pcall(L, 0, 0, 0)) -#define lua_regnumber(s,n) (lua_pushnumber(L,n), lua_setglobal(L,s)) +#define AI_LCALL(f) (lua_getglobal(L, f), lua_pcall(L, 0, 0, 0)) +#define lua_regnumber(l,s,n) (lua_pushnumber(l,n), lua_setglobal(l,s)) +#define luaL_dobuffer(L,b,n,s) (luaL_loadbuffer(L,b,n,s) || lua_pcall(L, 0, LUA_MULTRET, 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_DIR_ERR 5.0*M_PI/180. +#define MAX_DIR_ERR 2.5*M_PI/180. #define MIN_VEL_ERR 2.5 // file info. @@ -104,6 +106,9 @@ static int ai_getrndplanet(lua_State* L); // pointer getrndplanet() // Combat. static int ai_shoot(lua_State* L); // shoot(number) number = 1,2,3. static int ai_getenemy(lua_State* L); // number getenemy(). +// Timers. +static int ai_settimer(lua_State* L); // settimer(number, number) +static int ai_timeup(lua_State* L); // bool timeup(number) // Misc. static int ai_createvect(lua_State* L); // createvect(number, number) static int ai_say(lua_State* L); // say(string) @@ -149,7 +154,8 @@ int ai_init(void) { // Init an IA_Profile and add it to the stack. static int ai_loadProfile(char* filename) { - char* buf; + char* buf = NULL; + uint32_t bufsize = 0; profiles = realloc(profiles, sizeof(AI_Profile)*(++nprofiles)); profiles[nprofiles-1].name = strndup(filename+strlen(AI_PREFIX), @@ -168,7 +174,7 @@ static int ai_loadProfile(char* filename) { //luaL_openlibs(L); // Constants. - lua_regnumber("player", PLAYER_ID); // Player id. + lua_regnumber(L, "player", PLAYER_ID); // Player id. // Register C funstions in Lua. // Tasks. @@ -200,14 +206,18 @@ static int ai_loadProfile(char* filename) { // Combat. lua_register(L, "shoot", ai_shoot); lua_register(L, "getenemy", ai_getenemy); + // Timers. + lua_register(L, "settimer", ai_settimer); + lua_register(L, "timeup", ai_timeup); // Misc. lua_register(L, "createvect", ai_createvect); lua_register(L, "say", ai_say); lua_register(L, "rng", ai_rng); - buf = pack_readfile(DATA, filename, NULL); - if(luaL_dostring(L, buf) != 0) { + // Now load the file, since all the functions have been previously loaded. + buf = pack_readfile(DATA, filename, &bufsize); + if(luaL_dobuffer(L, buf, bufsize, filename) != 0) { ERR("loading AI file: %s", filename); ERR("%s", lua_tostring(L, -1)); WARN("Most likely Lua file has improper syntax, please check it."); @@ -234,7 +244,12 @@ AI_Profile* ai_getProfile(char* name) { // Clean up global AI void ai_exit(void) { - lua_close(L); + int i; + for(i = 0; i < nprofiles; i++) { + free(profiles[i].name); + lua_close(profiles[i].L); + } + free(profiles); } // Heart of hearts of the ai!! Brains of the pilot. @@ -572,6 +587,28 @@ static int ai_getenemy(lua_State* L) { return 1; } +// Set the timer. +static int ai_settimer(lua_State* L) { + MIN_ARGS(2); + + int n; // Get the timer. + if(lua_isnumber(L, 1)) n = lua_tonumber(L,1); + + cur_pilot->timer[n] = (lua_isnumber(L,2)) ? lua_tonumber(L,2) + SDL_GetTicks() : 0; + return 0; +} + +// Check the timer. +static int ai_timeup(lua_State* L) { + MIN_ARGS(1); + + int n; // Get the timer. + if(lua_isnumber(L,1)) n = lua_tonumber(L,1); + + lua_pushboolean(L, cur_pilot->timer[n] < SDL_GetTicks()); + return 1; +} + // Create a vector. static int ai_createvect(lua_State* L) { MIN_ARGS(2); diff --git a/src/ai.h b/src/ai.h index 2796363..b4467e4 100644 --- a/src/ai.h +++ b/src/ai.h @@ -1,6 +1,9 @@ #pragma once #include "lua.h" +// Max number of AI timers. +#define MAX_AI_TIMERS 2 + typedef enum { TYPE_NULL, TYPE_INT, TYPE_PTR } TaskData; // Basic task. diff --git a/src/faction.c b/src/faction.c index b775d52..7079123 100644 --- a/src/faction.c +++ b/src/faction.c @@ -42,6 +42,9 @@ Faction* faction_get(const char* name) { // Return 1 if Faction a and b are enemies. int areEnemies(Faction* a, Faction* b) { int i = 0; + + if(a == b) return 0; + for(i = 0; i < a->nenemies; i++) if(a->enemies[i] == b) return 1; @@ -55,6 +58,9 @@ int areEnemies(Faction* a, Faction* b) { // Return 1 if Faction a and b are allies. int areAllies(Faction* a, Faction* b) { int i = 0; + + if(a == b) return 0; + for(i = 0; i < a->nallies; i++) if(a->allies[i] == b) return 1; diff --git a/src/pilot.h b/src/pilot.h index c26af71..097cbf9 100644 --- a/src/pilot.h +++ b/src/pilot.h @@ -53,6 +53,7 @@ typedef struct Pilot { // AI. AI_Profile* ai; // Ai personality profile. unsigned int tcontrol; // Timer for control tick. + unsigned int timer[MAX_AI_TIMERS]; // Timers for AI. Task* task; // Current action. } Pilot;