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

View File

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

View File

@ -14,12 +14,13 @@
<planet>KonoSphere</planet> <planet>KonoSphere</planet>
</planets> </planets>
<fleets> <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="60">Merchant Ship</fleet>
<fleet chance="50">Merchant Ship</fleet> <fleet chance="50">Merchant Ship</fleet>
<fleet chance="40">Merchant Ship</fleet> <fleet chance="40">Merchant Ship</fleet>
<fleet chance="50">Pirate</fleet> <fleet chance="50">Sml Merchant Convoy</fleet>
<fleet chance="40">Pirate</fleet> <fleet chance="40">Sml Merchant Convoy</fleet>
</fleets> </fleets>
</ssys> </ssys>
<ssys name="KonoSys"> <ssys name="KonoSys">

View File

@ -4,7 +4,7 @@ control_rate = 2
-- Required "control" function. -- Required "control" function.
function control() function control()
if taskname() == "none" then if taskname() == "none" then
local planet = getrndplanet() planet = getrndplanet()
pushtask(0, "go", planet) pushtask(0, "go", planet)
end end
end end
@ -13,13 +13,13 @@ end
function attacked(attacker) 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 num = rng(0,3)
local msg = rng(0,4) if num == 0 then msg = "Mayday! We are under attack!"
if msg == 0 then say("ARGH! Please don't hurt me.") elseif num == 1 then msg = "Requesting assistance! Some scoundral is attacking us!"
elseif msg == 1 then say("HEY! We are simply a merchant vessle.") elseif num == 2 then msg = "Merchant vessle under attack here! HALP!"
elseif msg == 2 then say("LEAVE! ME! ALONE!")
end
end end
if msg then broadcast(msg) end
-- So bravely run away! -- So bravely run away!
pushtask(0, "runaway", attacker) pushtask(0, "runaway", attacker)
end end
@ -27,17 +27,17 @@ end
-- Runs away. -- Runs away.
function runaway() function runaway()
local target = gettargetid() target = gettargetid()
local dir = face(target, 1) dir = face(target, 1)
accel() accel()
end end
-- Fly to the target. -- Fly to the target.
function go() function go()
local target = gettarget() target = gettarget()
local dir = face(target) dir = face(target)
local dist = getdist(target) dist = getdist(target)
local bdist = minbrakedist() bdist = minbrakedist()
if dir < 10 and dist > bdist then if dir < 10 and dist > bdist then
accel() accel()
elseif dir < 10 and dist < bdist then 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. -- Required "attacked" function.
function attacked(attacker) function attacked(attacker)
if taskname() ~= "attack" and task ~= "runaway" then task = taskname()
if task ~= "attack" and task ~= "runaway" then
-- Let's have some taunts. -- Let's have some taunts.
if attacker == player then num = rng(0,4)
local msg = rng(0,4) if num == 0 then msg = "You will never kill me!"
if msg == 0 then say("You will never kill me!") elseif num == 1 then msg = "DIE!"
elseif msg == 1 then say("DIE!") elseif num == 2 then msg = "You won't survive!"
elseif msg == 2 then say("You won't survive!") elseif num == 3 then msg = "I hate you!"
elseif msg == 3 then say("I hate you!")
end
end end
if msg then comm(attacker, msg) end
pushtask(0, "attack", attacker) pushtask(0, "attack", attacker)
end end
end end
-- Runs away. -- Runs away.
function runaway() function runaway()
local target = gettargetid() target = gettargetid()
local dir = face(target, 1) dir = face(target, 1)
accel() accel()
end end
-- Attack -- Attack
function attack() function attack()
local target = gettargetid() target = gettargetid()
local dir = face(target) dir = face(target)
local dist = getdist(getpos(target)) dist = getdist(getpos(target))
if parmor() < 70 then if parmor() < 70 then
poptask() poptask()
@ -49,9 +50,9 @@ end
-- Fly to the player. -- Fly to the player.
function fly() function fly()
local target = 0 target = 0
local dir = face(target) dir = face(target)
local dist = getdist(getpos(target)) dist = getdist(getpos(target))
if dir < 10 and dist > 300 then if dir < 10 and dist > 300 then
accel() accel()
end end

View File

@ -68,6 +68,10 @@ static int nprofiles = 0;
// Current AI Lua interpreter. // Current AI Lua interpreter.
static lua_State* L = NULL; 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_minbrakedist(lua_State* L); // Minimal breaking distance.
static int ai_accel(lua_State* L); // Accelerate. 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) 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_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) static int ai_rng(lua_State* L); // rng(number, number)
// Current pilot "thinking" and assorted variables. // Current pilot "thinking" and assorted variables.
@ -211,7 +216,8 @@ static int ai_loadProfile(char* filename) {
lua_register(L, "timeup", ai_timeup); 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, "comm", ai_comm);
lua_register(L, "broadcast", ai_broadcast);
lua_register(L, "rng", ai_rng); lua_register(L, "rng", ai_rng);
@ -583,7 +589,17 @@ static int ai_shoot(lua_State* L) {
// Get the nearest enemy. // Get the nearest enemy.
static int ai_getenemy(lua_State* L) { 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; return 1;
} }
@ -623,11 +639,21 @@ static int ai_createvect(lua_State* L) {
} }
// Have the pilot say something to player. // 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); MIN_ARGS(1);
if(lua_isstring(L, 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; return 0;
} }

View File

@ -22,9 +22,21 @@
Faction* faction_stack = NULL; Faction* faction_stack = NULL;
int nfactions = 0; 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 Faction* faction_parse(xmlNodePtr parent);
static void alliance_parse(xmlNodePtr parent); static void alliance_parse(xmlNodePtr parent);
static void enemies_parse(xmlNodePtr parent); static void enemies_parse(xmlNodePtr parent);
static Alliance* alliance_get(char* name);
// Return the faction of name "name". // Return the faction of name "name".
Faction* faction_get(const char* name) { Faction* faction_get(const char* name) {
@ -39,6 +51,19 @@ Faction* faction_get(const char* name) {
return NULL; 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. // 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;
@ -82,67 +107,127 @@ static Faction* faction_parse(xmlNodePtr parent) {
// We set allies/enemies here, in the faction_stack. // We set allies/enemies here, in the faction_stack.
static void alliance_parse(xmlNodePtr parent) { static void alliance_parse(xmlNodePtr parent) {
Faction** f = NULL; Alliance* a;
int i, j, n, m; int* i, j, n, m;
i = 0;
char* name = NULL;
xmlNodePtr node, cur; xmlNodePtr node, cur;
node = parent->xmlChildrenNode; node = parent->xmlChildrenNode;
do { do {
if(node->type == XML_NODE_START) { if((node->type == XML_NODE_START) && (strcmp((char*)node->name, XML_ALLIANCE_TAG)==0)) {
if(strcmp((char*)node->name, XML_ALLIANCE_TAG)==0) { // Allocate a new alliance.
name = (char*)xmlGetProp(node, (xmlChar*)"name"); 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) {
// Add the faction (and pointers to make things simple).
a = alliances + nalliances-1;
i = &a->nfactions;
(*i)++;
// Parse the current alliance's allies. // Load the faction.
cur = node->xmlChildrenNode; a->factions = realloc(a->factions, (*i)*sizeof(Faction*));
do { a->factions[(*i)-1] = faction_get((char*)cur->children->content);
if(strcmp((char*)cur->name, "ally")==0) {
f = realloc(f, (++i)*sizeof(Faction*)); if(a->factions[(*i)-1] == NULL)
f[i-1] = faction_get((char*)cur->children->content); WARN("Faction %s in alliance %s does not exist in "FACTION_DATA,
if(f[i-1] == NULL) (char*)cur->children->content, a->name);
WARN("Faction %s in alliance %s does not exist in "FACTION_DATA, }
(char*)cur->children->content, name); } while((cur = cur->next));
}
}while((cur = cur->next));
// Set the crap needed by faction_stack. // Set the crap needed by faction_stack.
for(j = 0; j < i; j++) { for(j = 0; j < (*i); j++) {
f[j]->nallies += i-1; a->factions[j]->nallies += (*i)-1;
f[j]->allies = realloc(f[j]->allies, f[j]->nallies*sizeof(Faction*)); a->factions[j]->allies = realloc(a->factions[j]->allies, a->factions[j]->nallies*sizeof(Faction*));
for(n = 0, m = 0; n < i; n++, m++) { for(n = 0, m = 0; n < (*i); n++, m++) {
// Add as ally for all factions exept self. // Add as ally for all factions exept self.
if(n == j) m--; 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)); } while((node = node->next));
} }
static void enemies_parse(xmlNodePtr parent) { 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; node = parent->xmlChildrenNode;
do { do {
if(node->type == XML_NODE_START) { if((node->type == XML_NODE_START) && (strcmp((char*)node->name, XML_ENEMIES_TAG)==0)) {
if(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)); } while((node = node->next));
} }
// Load all the factions. // Load all the factions.
int factions_load(void) { int factions_load(void) {
uint32_t bufsize; uint32_t bufsize;
@ -184,19 +269,30 @@ int factions_load(void) {
free(buf); free(buf);
xmlCleanupParser(); xmlCleanupParser();
DEBUG("Loaded %d factions%c", nfactions, (nfactions==1)?' ':'s'); DEBUG("Loaded %d faction%c", nfactions, (nfactions==1)?' ':'s');
return 0; return 0;
} }
void factions_free(void) { void factions_free(void) {
int i; 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++) { for(i = 0; i < nfactions; i++) {
free(faction_stack[i].name); free(faction_stack[i].name);
if(faction_stack[i].nallies > 0) free(faction_stack[i].allies); if(faction_stack[i].nallies > 0) free(faction_stack[i].allies);
if(faction_stack[i].nenemies > 0) free(faction_stack[i].enemies); if(faction_stack[i].nenemies > 0) free(faction_stack[i].enemies);
} }
free(faction_stack); free(faction_stack);
faction_stack = NULL;
nfactions = 0; nfactions = 0;
} }

View File

@ -23,7 +23,7 @@
static unsigned int pilot_id = 0; static unsigned int pilot_id = 0;
// Stack of pilots - yes, they come in stacks now. // 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; int pilots = 0;
extern Pilot* player; extern Pilot* player;
@ -389,7 +389,7 @@ int fleet_load(void) {
free(buf); free(buf);
xmlCleanupParser(); xmlCleanupParser();
DEBUG("Loaded %d fleets%c", nfleets, (nfleets==1)?' ':'s'); DEBUG("Loaded %d fleet%c", nfleets, (nfleets==1)?' ':'s');
return 0; return 0;
} }

View File

@ -312,7 +312,7 @@ int gui_init(void) {
VY(gui.pos_frame) + gui.gfx_frame->h - 10); // y. VY(gui.pos_frame) + gui.gfx_frame->h - 10); // y.
// -- Bars. // -- 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; gui.shield.h = gui.armor.h = gui.energy.h = 10;
vect_csetmin(&gui.pos_shield, vect_csetmin(&gui.pos_shield,
VX(gui.pos_frame) + 10, // x 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_ASTEROIDSSET, "asteroids"); // Can be 0.
MELEMENT(flags&FLAG_INTEFERENCESET, "inteference"); MELEMENT(flags&FLAG_INTEFERENCESET, "inteference");
#undef MELEMENT #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; return tmp;
} }