[Add] Enemies are now propperly parsed.

[Add] Chance for pirate to come and rampage.
[Fix] Actually got that buffer overflow in ai.
This commit is contained in:
Allanis 2013-02-09 22:06:02 +00:00
parent 9d57f0ddfc
commit d1c02773bf
11 changed files with 283 additions and 81 deletions

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Fleets>
<fleet name="Pirate">
<fleet name="Enemy Test">
<ai>test</ai>
<faction>Independent</faction>
<pilots>
<pilot chance='100'>Pirate</pilot>
<pilot chance='100'>Enemy Test</pilot>
</pilots>
</fleet>
<fleet name="Merchant Ship">
@ -24,4 +24,11 @@
<pilot chance='60'>Merchant Ship</pilot>
</pilots>
</fleet>
<fleet name="Pirate">
<ai>pirate</ai>
<faction>Pirate</faction>
<pilots>
<pilot chance='100'>Merchant Ship</pilot>
</pilots>
</fleet>
</Fleets>

View File

@ -26,7 +26,7 @@
<outfit quantity='3'>laser</outfit>
</outfits>
</ship>
<ship name="Pirate">
<ship name="Enemy Test">
<GFX>ship1</GFX>
<class>1</class>
<movement>

View File

@ -14,12 +14,13 @@
<planet>KonoSphere</planet>
</planets>
<fleets>
<fleet chance="100">Merchant Ship</fleet>
<fleet chance="100">Enemy Test</fleet>
<fleet chance="60">Pirate</fleet>
<fleet chance="60">Merchant Ship</fleet>
<fleet chance="50">Merchant Ship</fleet>
<fleet chance="40">Merchant Ship</fleet>
<fleet chance="50">Pirate</fleet>
<fleet chance="40">Pirate</fleet>
<fleet chance="50">Sml Merchant Convoy</fleet>
<fleet chance="40">Sml Merchant Convoy</fleet>
</fleets>
</ssys>
<ssys name="KonoSys">

View File

@ -4,7 +4,7 @@ control_rate = 2
-- Required "control" function.
function control()
if taskname() == "none" then
local planet = getrndplanet()
planet = getrndplanet()
pushtask(0, "go", planet)
end
end
@ -13,13 +13,13 @@ end
function attacked(attacker)
if taskname() ~= "runaway" then
-- Let's have some messages.
if attacker == player then
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!")
end
num = rng(0,3)
if num == 0 then msg = "Mayday! We are under attack!"
elseif num == 1 then msg = "Requesting assistance! Some scoundral is attacking us!"
elseif num == 2 then msg = "Merchant vessle under attack here! HALP!"
end
if msg then broadcast(msg) end
-- So bravely run away!
pushtask(0, "runaway", attacker)
end
@ -27,17 +27,17 @@ end
-- Runs away.
function runaway()
local target = gettargetid()
local dir = face(target, 1)
target = gettargetid()
dir = face(target, 1)
accel()
end
-- Fly to the target.
function go()
local target = gettarget()
local dir = face(target)
local dist = getdist(target)
local bdist = minbrakedist()
target = gettarget()
dir = face(target)
dist = getdist(target)
bdist = minbrakedist()
if dir < 10 and dist > bdist then
accel()
elseif dir < 10 and dist < bdist then

71
scripts/ai/pirate.lua Normal file
View File

@ -0,0 +1,71 @@
--Required control rate.
control_rate = 2
-- Required "control" function.
function control()
if taskname() ~= "attack" then
enemy = getenemy()
if enemy ~= -1 then
pushtask(0, "attack", enemy)
else
pushtask(0, "fly")
end
end
end
-- Required "attacked" function
function attacked(attacker)
task = taskname()
if task ~= "attack" and task ~= "runaway" then
taunt()
pushtask(0, "attack", attacker)
elseif task == "attack" then
if gettargetid() ~= attacker then
pushtask(0, "attack", attacker)
end
end
end
function taunt()
num = rng(0,4)
if num == 0 then msg = "How dare you attack me?!"
elseif num == 1 then msg = "Aha! You think you can beat ME?!"
elseif num == 2 then msg = "JUST! DIE!"
elseif num == 3 then msg = "Ohh, You're not going to enjoy this!"
end
if msg then comm(attacker, msg) end
end
-- Run away.
function runaway()
target = gettargerid()
dir = face(target, 1)
accel()
end
-- Attack.
function attack()
target = gettargetid()
dir = face(target)
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()
target = 0
dir = face(target)
dist = getdist(getpos(target))
if dir < 10 and dist > 300 then
accel()
end
end

View File

@ -10,32 +10,33 @@ end
-- Required "attacked" function.
function attacked(attacker)
if taskname() ~= "attack" and task ~= "runaway" then
task = taskname()
if task ~= "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
num = rng(0,4)
if num == 0 then msg = "You will never kill me!"
elseif num == 1 then msg = "DIE!"
elseif num == 2 then msg = "You won't survive!"
elseif num == 3 then msg = "I hate you!"
end
if msg then comm(attacker, msg) end
pushtask(0, "attack", attacker)
end
end
-- Runs away.
function runaway()
local target = gettargetid()
local dir = face(target, 1)
target = gettargetid()
dir = face(target, 1)
accel()
end
-- Attack
function attack()
local target = gettargetid()
local dir = face(target)
local dist = getdist(getpos(target))
target = gettargetid()
dir = face(target)
dist = getdist(getpos(target))
if parmor() < 70 then
poptask()
@ -49,9 +50,9 @@ end
-- Fly to the player.
function fly()
local target = 0
local dir = face(target)
local dist = getdist(getpos(target))
target = 0
dir = face(target)
dist = getdist(getpos(target))
if dir < 10 and dist > 300 then
accel()
end

View File

@ -68,6 +68,10 @@ static int nprofiles = 0;
// Current AI Lua interpreter.
static lua_State* L = NULL;
// Extern pilot hacks.
extern Pilot** pilot_stack;
extern int pilots;
static int ai_minbrakedist(lua_State* L); // Minimal breaking distance.
static int ai_accel(lua_State* L); // Accelerate.
@ -111,7 +115,8 @@ 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)
static int ai_comm(lua_State* L); // comm(string)
static int ai_broadcast(lua_State* L); // broadcast(string)
static int ai_rng(lua_State* L); // rng(number, number)
// Current pilot "thinking" and assorted variables.
@ -211,7 +216,8 @@ static int ai_loadProfile(char* filename) {
lua_register(L, "timeup", ai_timeup);
// Misc.
lua_register(L, "createvect", ai_createvect);
lua_register(L, "say", ai_say);
lua_register(L, "comm", ai_comm);
lua_register(L, "broadcast", ai_broadcast);
lua_register(L, "rng", ai_rng);
@ -583,7 +589,17 @@ static int ai_shoot(lua_State* L) {
// Get the nearest enemy.
static int ai_getenemy(lua_State* L) {
lua_pushnumber(L,1);
int i, p;
double d, td;
for(p = -1, i = 0; i < pilots; i++)
if(areEnemies(cur_pilot->faction, pilot_stack[i]->faction)) {
td = vect_dist(&pilot_stack[i]->solid->pos, &cur_pilot->solid->pos);
if((p == -1) || (td < d)) {
d = td;
p = pilot_stack[i]->id;
}
}
lua_pushnumber(L,p);
return 1;
}
@ -623,11 +639,21 @@ static int ai_createvect(lua_State* L) {
}
// Have the pilot say something to player.
static int ai_say(lua_State* L) {
static int ai_comm(lua_State* L) {
MIN_ARGS(2);
if(lua_isnumber(L,1) && (lua_tonumber(L,1)==PLAYER_ID) && lua_isstring(L,2))
player_message("Comm: %s> \"%s\"", cur_pilot->name, lua_tostring(L,2));
return 0;
}
// Broadcasts to the entire area.
static int ai_broadcast(lua_State* L) {
MIN_ARGS(1);
if(lua_isstring(L, 1))
player_message("Comm: %s> \"%s\"", cur_pilot->name, lua_tostring(L, 1));
player_message("Broadcast: %s> \"%s\"", cur_pilot->name, lua_tostring(L, 1));
return 0;
}

View File

@ -22,9 +22,21 @@
Faction* faction_stack = NULL;
int nfactions = 0;
// Save alliance.
typedef struct {
char* name;
Faction** factions;
int nfactions;
} Alliance;
// Stack of alliances.
static Alliance* alliances = NULL;
static int nalliances = 0;
static Faction* faction_parse(xmlNodePtr parent);
static void alliance_parse(xmlNodePtr parent);
static void enemies_parse(xmlNodePtr parent);
static Alliance* alliance_get(char* name);
// Return the faction of name "name".
Faction* faction_get(const char* name) {
@ -39,6 +51,19 @@ Faction* faction_get(const char* name) {
return NULL;
}
// Return the alliance of name 'name'.
static Alliance* alliance_get(char* name) {
int i;
for(i = 0; i < nalliances; i++)
if(strcmp(alliances[i].name, name)==0)
break;
if(i != nalliances)
return alliances+i;
return NULL;
}
// Return 1 if Faction a and b are enemies.
int areEnemies(Faction* a, Faction* b) {
int i = 0;
@ -82,67 +107,127 @@ static Faction* faction_parse(xmlNodePtr parent) {
// We set allies/enemies here, in the faction_stack.
static void alliance_parse(xmlNodePtr parent) {
Faction** f = NULL;
int i, j, n, m;
i = 0;
char* name = NULL;
Alliance* a;
int* i, j, n, m;
xmlNodePtr node, cur;
node = parent->xmlChildrenNode;
do {
if(node->type == XML_NODE_START) {
if(strcmp((char*)node->name, XML_ALLIANCE_TAG)==0) {
name = (char*)xmlGetProp(node, (xmlChar*)"name");
if((node->type == XML_NODE_START) && (strcmp((char*)node->name, XML_ALLIANCE_TAG)==0)) {
// Allocate a new alliance.
alliances = realloc(alliances, sizeof(Alliance)*(++nalliances));
alliances[nalliances-1].name = (char*)xmlGetProp(node,(xmlChar*)"name");
alliances[nalliances-1].factions = NULL;
alliances[nalliances-1].nfactions = 0;
// Parse the current alliance's allies.
cur = node->xmlChildrenNode;
do {
if(strcmp((char*)cur->name, "ally")==0) {
f = realloc(f, (++i)*sizeof(Faction*));
f[i-1] = faction_get((char*)cur->children->content);
if(f[i-1] == NULL)
WARN("Faction %s in alliance %s does not exist in "FACTION_DATA,
(char*)cur->children->content, name);
}
}while((cur = cur->next));
// Parse the current alliance's allies.
cur = node->xmlChildrenNode;
do {
if(strcmp((char*)cur->name, "ally")==0) {
// Add the faction (and pointers to make things simple).
a = alliances + nalliances-1;
i = &a->nfactions;
(*i)++;
// Load the faction.
a->factions = realloc(a->factions, (*i)*sizeof(Faction*));
a->factions[(*i)-1] = faction_get((char*)cur->children->content);
if(a->factions[(*i)-1] == NULL)
WARN("Faction %s in alliance %s does not exist in "FACTION_DATA,
(char*)cur->children->content, a->name);
}
} while((cur = cur->next));
// Set the crap needed by faction_stack.
for(j = 0; j < i; j++) {
f[j]->nallies += i-1;
f[j]->allies = realloc(f[j]->allies, f[j]->nallies*sizeof(Faction*));
for(n = 0, m = 0; n < i; n++, m++) {
for(j = 0; j < (*i); j++) {
a->factions[j]->nallies += (*i)-1;
a->factions[j]->allies = realloc(a->factions[j]->allies, a->factions[j]->nallies*sizeof(Faction*));
for(n = 0, m = 0; n < (*i); n++, m++) {
// Add as ally for all factions exept self.
if(n == j) m--;
else if(n != j) f[j]->allies[f[j]->nallies-i+1+m] = f[n];
else if(n != j)
a->factions[j]->allies[a->factions[j]->nallies-(*i)+1+m] = a->factions[n];
}
}
// Free up some memory.
if(f) {
free(f);
f = NULL;
i = 0;
}
if(name) free(name);
}
}
} while((node = node->next));
}
static void enemies_parse(xmlNodePtr parent) {
xmlNodePtr node;
xmlNodePtr node, cur;
Faction*** f;
Alliance* a;
int i, *j, n, m, x, y, z, e;
char* type;
i = 0;
f = NULL;
j = NULL;
node = parent->xmlChildrenNode;
do {
if(node->type == XML_NODE_START) {
if(strcmp((char*)node->name, XML_ENEMIES_TAG)==0) {
if((node->type == XML_NODE_START) && (strcmp((char*)node->name, XML_ENEMIES_TAG)==0)) {
cur = node->xmlChildrenNode;
do {
if(strcmp((char*)cur->name,"enemy")==0) {
type = (char*)xmlGetProp(cur, (xmlChar*)"type");
}
i++;
j = realloc(j, sizeof(int)*i);
f = realloc(f, sizeof(Faction**)*i);
if(strcmp(type, "alliance")==0) {
// Enemy thing is an alliance.
a = alliance_get((char*)cur->children->content);
if(a == NULL)
WARN("Alliance %s not found in stack", (char*)cur->children->content);
j[i-1] = a->nfactions;
f[i-1] = a->factions;
}
else if(strcmp(type,"faction")==0) {
// Enemy thing is only a faction.
j[i-1] = 1;
f[i-1] = malloc(sizeof(Faction*));
f[i-1][0] = faction_get((char*)cur->children->content);
if(f[i-1][0] == NULL)
WARN("Faction %s not found in stack", (char*)cur->children->content);
}
free(type);
}
} while((cur = cur->next));
// Now actually parse and load up the enemies.
for(n = 0; n < i; n++) {
for(m = 0; m < j[n]; m++) {
// Faction.
// Add all the faction enemies to nenemies and alloc.
for(e = 0, x = 0; x < i; x++)
if(x != n) e += j[x]; // Store the total enemies.
// Now allocate the memory.
f[n][m]->nenemies += e;
f[n][m]->enemies = realloc(f[n][m]->enemies, sizeof(Faction*)*f[n][m]->nenemies);
// Add the actualy enemies.
for(x = 0, z = 0; x < i; x++)
if(x != n)
// Make sure it's not from the same group.
if(x != n)
for(y = 0; y < j[x]; y++, z++)
f[n][m]->enemies[f[n][m]->nenemies-e+z]=f[x][y];
}
}
// Free al the temp memory.
for(x = 0; x < i; x++)
if(j[x]==1) free(f[x]); // Free the single malloced factions.
free(f); // Free the rest.
free(j);
}
} while((node = node->next));
}
// Load all the factions.
int factions_load(void) {
uint32_t bufsize;
@ -184,19 +269,30 @@ int factions_load(void) {
free(buf);
xmlCleanupParser();
DEBUG("Loaded %d factions%c", nfactions, (nfactions==1)?' ':'s');
DEBUG("Loaded %d faction%c", nfactions, (nfactions==1)?' ':'s');
return 0;
}
void factions_free(void) {
int i;
// Free alliances.
for(i = 0; i < nalliances; i++) {
free(alliances[i].name);
free(alliances[i].factions);
}
free(alliances);
alliances = NULL;
nalliances = 0;
// Free factions.
for(i = 0; i < nfactions; i++) {
free(faction_stack[i].name);
if(faction_stack[i].nallies > 0) free(faction_stack[i].allies);
if(faction_stack[i].nenemies > 0) free(faction_stack[i].enemies);
}
free(faction_stack);
faction_stack = NULL;
nfactions = 0;
}

View File

@ -23,7 +23,7 @@
static unsigned int pilot_id = 0;
// Stack of pilots - yes, they come in stacks now.
Pilot** pilot_stack = NULL; // Not static, it is used in player.c and weapon.c
Pilot** pilot_stack = NULL; // Not static, it is used in player.c and weapon.c and ai.c
int pilots = 0;
extern Pilot* player;
@ -389,7 +389,7 @@ int fleet_load(void) {
free(buf);
xmlCleanupParser();
DEBUG("Loaded %d fleets%c", nfleets, (nfleets==1)?' ':'s');
DEBUG("Loaded %d fleet%c", nfleets, (nfleets==1)?' ':'s');
return 0;
}

View File

@ -312,7 +312,7 @@ int gui_init(void) {
VY(gui.pos_frame) + gui.gfx_frame->h - 10); // y.
// -- Bars.
gui.shield.w = gui.armor.w = gui.energy.w = 128;
gui.shield.w = gui.armor.w = gui.energy.w = 129;
gui.shield.h = gui.armor.h = gui.energy.h = 10;
vect_csetmin(&gui.pos_shield,
VX(gui.pos_frame) + 10, // x

View File

@ -355,7 +355,7 @@ static StarSystem* system_parse(const xmlNodePtr parent) {
MELEMENT(flags&FLAG_ASTEROIDSSET, "asteroids"); // Can be 0.
MELEMENT(flags&FLAG_INTEFERENCESET, "inteference");
#undef MELEMENT
DEBUG("Loaded Star System '%s' with %d Planets%s", tmp->name, tmp->nplanets, (tmp->nplanets > 1) ? "s" : "");
DEBUG("Loaded Star System '%s' with %d Planet%c", tmp->name, tmp->nplanets, (tmp->nplanets == 1) ? ' ' : 's');
return tmp;
}