[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!
|
||||
// ================
|
||||
@ -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
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.
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
|
53
src/ai.c
53
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);
|
||||
|
3
src/ai.h
3
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.
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user