[Add] About time I added timer support for AI.

[Fix] Buffer overflow in AI.
This commit is contained in:
Allanis 2013-02-09 18:58:50 +00:00
parent eac16dacdd
commit 9d57f0ddfc
8 changed files with 176 additions and 27 deletions

View File

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

59
scripts/ai/basic.lua Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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