[Add] About time I added timer support for AI.
[Fix] Buffer overflow in AI.
This commit is contained in:
parent
eac16dacdd
commit
9d57f0ddfc
@ -1,3 +1,10 @@
|
|||||||
|
// ================
|
||||||
|
// CONSTANTS!
|
||||||
|
// ================
|
||||||
|
|
||||||
|
number player
|
||||||
|
-- players pilot id.
|
||||||
|
|
||||||
// ================
|
// ================
|
||||||
// TASKS!
|
// TASKS!
|
||||||
// ================
|
// ================
|
||||||
@ -124,6 +131,20 @@ shoot([number weapon])
|
|||||||
getenemy()
|
getenemy()
|
||||||
-- return the id of the nearest enemy.
|
-- 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!
|
// MISC!
|
||||||
|
59
scripts/ai/basic.lua
Normal file
59
scripts/ai/basic.lua
Normal 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
|
||||||
|
|
@ -4,7 +4,8 @@ control_rate = 2
|
|||||||
-- Required "control" function.
|
-- Required "control" function.
|
||||||
function control()
|
function control()
|
||||||
if taskname() == "none" then
|
if taskname() == "none" then
|
||||||
pushtask(0, "fly")
|
local planet = getrndplanet()
|
||||||
|
pushtask(0, "go", planet)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -13,7 +14,7 @@ function attacked(attacker)
|
|||||||
if taskname() ~= "runaway" then
|
if taskname() ~= "runaway" then
|
||||||
-- Let's have some messages.
|
-- Let's have some messages.
|
||||||
if attacker == player then
|
if attacker == player then
|
||||||
msg = rng(0,4)
|
local msg = rng(0,4)
|
||||||
if msg == 0 then say("ARGH! Please don't hurt me.")
|
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 == 1 then say("HEY! We are simply a merchant vessle.")
|
||||||
elseif msg == 2 then say("LEAVE! ME! ALONE!")
|
elseif msg == 2 then say("LEAVE! ME! ALONE!")
|
||||||
@ -26,18 +27,39 @@ end
|
|||||||
|
|
||||||
-- Runs away.
|
-- Runs away.
|
||||||
function runaway()
|
function runaway()
|
||||||
target = gettargetid()
|
local target = gettargetid()
|
||||||
dir = face(target, 1)
|
local dir = face(target, 1)
|
||||||
accel()
|
accel()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Fly to the player.
|
-- Fly to the target.
|
||||||
function fly()
|
function go()
|
||||||
target = 0
|
local target = gettarget()
|
||||||
dir = face(target)
|
local dir = face(target)
|
||||||
dist = getdist(getpos(target))
|
local dist = getdist(target)
|
||||||
if dir < 10 and dist > 300 then
|
local bdist = minbrakedist()
|
||||||
|
if dir < 10 and dist > bdist then
|
||||||
accel()
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ function attacked(attacker)
|
|||||||
if taskname() ~= "attack" and task ~= "runaway" then
|
if taskname() ~= "attack" and task ~= "runaway" then
|
||||||
-- Let's have some taunts.
|
-- Let's have some taunts.
|
||||||
if attacker == player then
|
if attacker == player then
|
||||||
msg = rng(0,4)
|
local msg = rng(0,4)
|
||||||
if msg == 0 then say("You will never kill me!")
|
if msg == 0 then say("You will never kill me!")
|
||||||
elseif msg == 1 then say("DIE!")
|
elseif msg == 1 then say("DIE!")
|
||||||
elseif msg == 2 then say("You won't survive!")
|
elseif msg == 2 then say("You won't survive!")
|
||||||
@ -26,16 +26,16 @@ end
|
|||||||
|
|
||||||
-- Runs away.
|
-- Runs away.
|
||||||
function runaway()
|
function runaway()
|
||||||
target = gettargetid()
|
local target = gettargetid()
|
||||||
dir = face(target, 1)
|
local dir = face(target, 1)
|
||||||
accel()
|
accel()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Attack
|
-- Attack
|
||||||
function attack()
|
function attack()
|
||||||
target = gettargetid()
|
local target = gettargetid()
|
||||||
dir = face(target)
|
local dir = face(target)
|
||||||
dist = getdist(getpos(target))
|
local dist = getdist(getpos(target))
|
||||||
|
|
||||||
if parmor() < 70 then
|
if parmor() < 70 then
|
||||||
poptask()
|
poptask()
|
||||||
@ -49,9 +49,9 @@ end
|
|||||||
|
|
||||||
-- Fly to the player.
|
-- Fly to the player.
|
||||||
function fly()
|
function fly()
|
||||||
target = 0
|
local target = 0
|
||||||
dir = face(target)
|
local dir = face(target)
|
||||||
dist = getdist(getpos(target))
|
local dist = getdist(getpos(target))
|
||||||
if dir < 10 and dist > 300 then
|
if dir < 10 and dist > 300 then
|
||||||
accel()
|
accel()
|
||||||
end
|
end
|
||||||
|
53
src/ai.c
53
src/ai.c
@ -47,13 +47,15 @@
|
|||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
// Call the AI function with name f.
|
// Call the AI function with name f.
|
||||||
#define AI_LCALL(f) (lua_getglobal(L, f), lua_pcall(L, 0, 0, 0))
|
#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 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.
|
// Don't run the function if (n) params aren't passed.
|
||||||
#define MIN_ARGS(n) if(lua_gettop(L) < n) return 0
|
#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
|
#define MIN_VEL_ERR 2.5
|
||||||
|
|
||||||
// file info.
|
// file info.
|
||||||
@ -104,6 +106,9 @@ static int ai_getrndplanet(lua_State* L); // pointer getrndplanet()
|
|||||||
// Combat.
|
// Combat.
|
||||||
static int ai_shoot(lua_State* L); // shoot(number) number = 1,2,3.
|
static int ai_shoot(lua_State* L); // shoot(number) number = 1,2,3.
|
||||||
static int ai_getenemy(lua_State* L); // number getenemy().
|
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.
|
// Misc.
|
||||||
static int ai_createvect(lua_State* L); // createvect(number, number)
|
static int ai_createvect(lua_State* L); // createvect(number, number)
|
||||||
static int ai_say(lua_State* L); // say(string)
|
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.
|
// Init an IA_Profile and add it to the stack.
|
||||||
static int ai_loadProfile(char* filename) {
|
static int ai_loadProfile(char* filename) {
|
||||||
char* buf;
|
char* buf = NULL;
|
||||||
|
uint32_t bufsize = 0;
|
||||||
|
|
||||||
profiles = realloc(profiles, sizeof(AI_Profile)*(++nprofiles));
|
profiles = realloc(profiles, sizeof(AI_Profile)*(++nprofiles));
|
||||||
profiles[nprofiles-1].name = strndup(filename+strlen(AI_PREFIX),
|
profiles[nprofiles-1].name = strndup(filename+strlen(AI_PREFIX),
|
||||||
@ -168,7 +174,7 @@ static int ai_loadProfile(char* filename) {
|
|||||||
//luaL_openlibs(L);
|
//luaL_openlibs(L);
|
||||||
|
|
||||||
// Constants.
|
// Constants.
|
||||||
lua_regnumber("player", PLAYER_ID); // Player id.
|
lua_regnumber(L, "player", PLAYER_ID); // Player id.
|
||||||
|
|
||||||
// Register C funstions in Lua.
|
// Register C funstions in Lua.
|
||||||
// Tasks.
|
// Tasks.
|
||||||
@ -200,14 +206,18 @@ static int ai_loadProfile(char* filename) {
|
|||||||
// Combat.
|
// Combat.
|
||||||
lua_register(L, "shoot", ai_shoot);
|
lua_register(L, "shoot", ai_shoot);
|
||||||
lua_register(L, "getenemy", ai_getenemy);
|
lua_register(L, "getenemy", ai_getenemy);
|
||||||
|
// Timers.
|
||||||
|
lua_register(L, "settimer", ai_settimer);
|
||||||
|
lua_register(L, "timeup", ai_timeup);
|
||||||
// Misc.
|
// Misc.
|
||||||
lua_register(L, "createvect", ai_createvect);
|
lua_register(L, "createvect", ai_createvect);
|
||||||
lua_register(L, "say", ai_say);
|
lua_register(L, "say", ai_say);
|
||||||
lua_register(L, "rng", ai_rng);
|
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("loading AI file: %s", filename);
|
||||||
ERR("%s", lua_tostring(L, -1));
|
ERR("%s", lua_tostring(L, -1));
|
||||||
WARN("Most likely Lua file has improper syntax, please check it.");
|
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
|
// Clean up global AI
|
||||||
void ai_exit(void) {
|
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.
|
// Heart of hearts of the ai!! Brains of the pilot.
|
||||||
@ -572,6 +587,28 @@ static int ai_getenemy(lua_State* L) {
|
|||||||
return 1;
|
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.
|
// Create a vector.
|
||||||
static int ai_createvect(lua_State* L) {
|
static int ai_createvect(lua_State* L) {
|
||||||
MIN_ARGS(2);
|
MIN_ARGS(2);
|
||||||
|
3
src/ai.h
3
src/ai.h
@ -1,6 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
|
// Max number of AI timers.
|
||||||
|
#define MAX_AI_TIMERS 2
|
||||||
|
|
||||||
typedef enum { TYPE_NULL, TYPE_INT, TYPE_PTR } TaskData;
|
typedef enum { TYPE_NULL, TYPE_INT, TYPE_PTR } TaskData;
|
||||||
|
|
||||||
// Basic task.
|
// Basic task.
|
||||||
|
@ -42,6 +42,9 @@ Faction* faction_get(const char* name) {
|
|||||||
// Return 1 if Faction a and b are enemies.
|
// Return 1 if Faction a and b are enemies.
|
||||||
int areEnemies(Faction* a, Faction* b) {
|
int areEnemies(Faction* a, Faction* b) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
if(a == b) return 0;
|
||||||
|
|
||||||
for(i = 0; i < a->nenemies; i++)
|
for(i = 0; i < a->nenemies; i++)
|
||||||
if(a->enemies[i] == b)
|
if(a->enemies[i] == b)
|
||||||
return 1;
|
return 1;
|
||||||
@ -55,6 +58,9 @@ int areEnemies(Faction* a, Faction* b) {
|
|||||||
// Return 1 if Faction a and b are allies.
|
// Return 1 if Faction a and b are allies.
|
||||||
int areAllies(Faction* a, Faction* b) {
|
int areAllies(Faction* a, Faction* b) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
if(a == b) return 0;
|
||||||
|
|
||||||
for(i = 0; i < a->nallies; i++)
|
for(i = 0; i < a->nallies; i++)
|
||||||
if(a->allies[i] == b)
|
if(a->allies[i] == b)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -53,6 +53,7 @@ typedef struct Pilot {
|
|||||||
// AI.
|
// AI.
|
||||||
AI_Profile* ai; // Ai personality profile.
|
AI_Profile* ai; // Ai personality profile.
|
||||||
unsigned int tcontrol; // Timer for control tick.
|
unsigned int tcontrol; // Timer for control tick.
|
||||||
|
unsigned int timer[MAX_AI_TIMERS]; // Timers for AI.
|
||||||
Task* task; // Current action.
|
Task* task; // Current action.
|
||||||
} Pilot;
|
} Pilot;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user