Lua AI: redesign, simplified usage, added lua_ai test scenario
This commit is contained in:
parent
5f6c1f8001
commit
f9b0fdb1f5
8 changed files with 459 additions and 121 deletions
|
@ -34,6 +34,7 @@
|
|||
{scenario-leaders.cfg}
|
||||
{ai/scenarios/scenario-AI_Arena_small.cfg}
|
||||
{ai/scenarios/scenario-test_move_to_targets.cfg}
|
||||
{ai/scenarios/scenario-lua-ai.cfg}
|
||||
#endif
|
||||
|
||||
[textdomain]
|
||||
|
|
|
@ -5,11 +5,44 @@
|
|||
version=10710
|
||||
[engine]
|
||||
name="lua"
|
||||
code="side = ... local ai = wesnoth.dofile('ai/lua/simple_ai.lua') return ai"
|
||||
code= <<
|
||||
local data = ...
|
||||
local ai = { side = data._side() }
|
||||
|
||||
--! do a full move from FROM to TO. Unit's movement points are set to 0 after a move
|
||||
|
||||
--! recruit a UNIT_NAME on LOC
|
||||
function ai:recruit(UNIT_NAME,LOC)
|
||||
ai:_recruit(UNIT_NAME,LOC.x,LOC.y)
|
||||
end
|
||||
|
||||
--! recall a UNIT_ID at LOC
|
||||
function ai:recall(UNIT_ID,LOC)
|
||||
ai:_recall(UNIT_ID,LOC.x,LOC.y)
|
||||
end
|
||||
|
||||
--! stop a unit at LOC - remove MOVES and/or remove ATTACK
|
||||
function ai:stop(LOC,MOVES,ATTACKS)
|
||||
ai:_stop(LOC.x,LOC.y,MOVES,ATTACKS)
|
||||
end
|
||||
|
||||
--! implementation
|
||||
function ai:execute()
|
||||
print(self.side)
|
||||
my_leader = wesnoth.get_units( {canrecruit="yes", side=self.side})[1]
|
||||
self:recruit("Spearman",{x=15, y=3})
|
||||
self:_move_full(my_leader,{x=11, y=4})
|
||||
self:_attack({x=11,y=4},{x=11, y=5},1)
|
||||
end
|
||||
|
||||
|
||||
|
||||
return ai;
|
||||
>>
|
||||
[/engine]
|
||||
[stage]
|
||||
engine="lua"
|
||||
code= "(...):play_turn()"
|
||||
code= "(...):execute()"
|
||||
[/stage]
|
||||
[/ai]
|
||||
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
local ai = { side = side }
|
||||
|
||||
--! do a full move from FROM to TO. Unit's movement points are set to 0 after a move
|
||||
function ai:move_full(FROM,TO)
|
||||
wesnoth.ai_execute_move(self.side,FROM.x,FROM.y,TO.x,TO.y,1)
|
||||
end
|
||||
|
||||
--! do a partial move from FROM to TO.
|
||||
function ai:move(FROM,TO)
|
||||
wesnoth.ai_execute_move(self.side,FROM.x,FROM.y,TO.x,TO.y,0)
|
||||
end
|
||||
|
||||
--! do a simple attack using aggression 0.5 and choosing best weapon
|
||||
function ai:attack_simple(ATT,DEF)
|
||||
wesnoth.ai_execute_attack(self.side,ATT.x,ATT.y,DEF.x,DEF.y,-1,0.5)
|
||||
end
|
||||
|
||||
--! recruit a UNIT_NAME on LOC
|
||||
function ai:recruit(UNIT_NAME,LOC)
|
||||
wesnoth.ai_execute_recruit(self.side,UNIT_NAME,LOC.x,LOC.y)
|
||||
end
|
||||
|
||||
--! recall a UNIT_ID at LOC
|
||||
function ai:recall(UNIT_ID,LOC)
|
||||
wesnoth.ai_execute_recall(self.side,UNIT_ID,LOC.x,LOC.y)
|
||||
end
|
||||
|
||||
--! stop a unit at LOC - remove MOVES and/or remove ATTACK
|
||||
function ai:stop(LOC,MOVES,ATTACKS)
|
||||
wesnoth.ai_execute_stopunit(self.side,LOC.x,LOC.y,MOVES,ATTACKS)
|
||||
end
|
||||
|
||||
return ai
|
|
@ -1,9 +0,0 @@
|
|||
local ai = wesnoth.dofile('ai/lua/ai.lua')
|
||||
|
||||
function ai:play_turn()
|
||||
--! only a few thousands lines have to be added here to complete the ai
|
||||
my_leader = wesnoth.get_units( {canrecruit="yes", side=self.side})[1]
|
||||
self:move_full(my_leader,{x=11, y=4})
|
||||
end
|
||||
|
||||
return ai
|
17
data/ai/lua/stdlib.lua
Normal file
17
data/ai/lua/stdlib.lua
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
return {
|
||||
|
||||
init = function(ai,data)
|
||||
|
||||
--! ===========================
|
||||
--! all functions here should start with an underscore to indicate that they come from wesnoth core
|
||||
|
||||
--! say hello to player via a message
|
||||
function ai:_say_hello()
|
||||
wesnoth.message(string.format("Hello from Lua AI which controls side %d! It's turn %d.", self.side, wesnoth.current.turn ))
|
||||
end
|
||||
|
||||
--! ===========================
|
||||
end
|
||||
}
|
||||
|
244
data/ai/scenarios/scenario-lua-ai.cfg
Normal file
244
data/ai/scenarios/scenario-lua-ai.cfg
Normal file
|
@ -0,0 +1,244 @@
|
|||
#textdomain wesnoth
|
||||
# @file data/scenario-luaai.cfg
|
||||
|
||||
[test]
|
||||
name="Test scenario for Lua AI"
|
||||
map_data=" border_size=1
|
||||
usage=map
|
||||
|
||||
Hh , Hh , Gg , Wwf , Wwf , Gs^Fp , Mm , Hh , Gg , Gs^Fp , Gg , Hh , Gg , Mm , Hh , Mm , Wwf , Wwf , Hh , Gs^Fp , Hh , Mm , Mm
|
||||
Hh , Hh , Gg^Ve , Wwf , Wwf , Gs^Fp , Mm , Hh , Gg , Gs^Fp , Gg , Hh , Gg , Mm , Hh , Mm , Wwf , Wwf , Hh , Gs^Fp , Hh , Mm , Mm
|
||||
Wwf , Wwf , Wwf , Wwf , Gg , Wwf , Wwf , Hh , Gg , Gg , Wwf , Ch , Wwf , Gs^Fp , Wwf , Wwf , Re , Re , Hh , Mm , Wwf , Mm , Mm
|
||||
Mm , Mm , Wwf , Gs^Fp , Gg^Vh , Wwf , Gg , Gg , Wwf , Wwf , Wwf , 1 Kh , Ch , Wwf , Re , Re , Rd , Rd , Wwf , Wwf , Gs^Fp , Wwf , Wwf
|
||||
Wwf , Wwf , Mm , Wwf , Gs^Fp , Wwf , Wwf , Wwf , Gg^Vh , Gg , Wwf , Ch , Wwf , Ch , Rd , Rd , Wwf , Wwf , Gg^Vh , Gs^Fp , Re^Gvs , Hh , Hh
|
||||
Hh , Hh , Wwf , Gs^Fp , Wwf , Wwf , Gg , Gg , Gg , Gg , Wwf , Ch , Gg , Wwf , Wwf , Wwf , Mm , Gs^Fp , Re , Re^Gvs , Gg^Wm , Re^Gvs , Re^Gvs
|
||||
Wwf , Wwf , Mm , Wwf , Hh , Gs^Fp , Rd , Rd , Gg , Gg , Wwf , Wwf , Gs^Fp , Gg , Hh , Gg , Re , Re , Rd , Rd , Gg , Hh , Hh
|
||||
Hh , Hh , Gs^Fp , Gg , Gg , Rd , Gg , Gg , Wwf , Wwf , Gs^Fp , Wwf , Gs^Fp , Mm , Re , Re , Rd , Rd , Gg , Ggf , Mm , Gs^Fp , Gs^Fp
|
||||
Gs^Fp , Gs^Fp , Gg , Gg , Wwf , Gg , Wwf , Wwf , Mm , Hh , Wwf , Wwf , Re , Re , Rd , Rd , Rd , Gg , Gs^Fp , Gs^Fp , Gs^Fp , Hh , Hh
|
||||
Hh , Hh , Wwf , Wwf , Hh , Wwf , Gg , Gg , Gg , Gg , Wwf , Re , Re , Rd , Gg , Gg , Gg , Gg^Vh , Hh , Gg , Wwf , Ggf , Ggf
|
||||
Wwf , Wwf , Hh , Ggf , Gs^Fp , Hh^Vhh , Gg , Gg , Gg , Ss^Vhs , Hh , Ww , Gs^Fp , Gg , Gs^Fp , Hh , Wwf , Wwf , Wwf , Wwf , Gg , Wwf , Wwf
|
||||
Hh , Hh , Gg , Gg , Re , Gg , Re , Re , Gg , Ss , Gs^Fp , Ww , Hh , Mm , Ww , Wwf , Gg , Gg , Ds , Gg , Gg , Gs^Fp , Gs^Fp
|
||||
Gs^Fp , Gs^Fp , Gg , Rd , Rd , Re , Rd , Re , Hh , Mm , Wwf , Ww , Ww , Ww , Gg , Gg , Hh , Gs^Fp , Rd , Rd , Hh , Gg , Gg
|
||||
Rd , Rd , Gs^Fp , Hh , Rd , Rd , Gs^Fp , Re , Gg , Gg , Wwf , Gg , Wwf , Gg , Gg , Re , Gs^Fp , Hh , Rd , Mm , Gs^Fp , Rd , Rd
|
||||
Rd , Rd , Hh , Mm , Rd , Hh , Hh , Re , Gg , Gg , Ww , Gg , Wwf , Gg , Hh , Re , Rd , Rd , Rd , Hh , Gg , Rd , Rd
|
||||
Gg , Gg , Gg , Rd , Ds , Gs^Fp , Gg , Gg , Ww , Ww , Hh , Ww , Gs^Fp , Mm , Gg , Re , Re , Re , Re , Rd , Gg , Gs^Fp , Gs^Fp
|
||||
Gs^Fp , Gs^Fp , Gg , Gg , Wwf , Gg , Wwf , Wwf , Gs^Fp , Mm , Gs^Fp , Ww , Hh , Ss , Gg , Re , Gg , Gg , Gs^Fp , Gg , Hh , Hh , Hh
|
||||
Wwf , Wwf , Wwf , Wwf , Hh , Wwf , Gg , Hh , Gg , Gg , Re , Ww , Wwf , Ss^Vhs , Gg , Gg , Gg , Hh^Vhh , Hh , Ggf , Wwf , Wwf , Wwf
|
||||
Ggf , Ggf , Gs^Fp , Gg , Gs^Fp , Gg^Vh , Rd , Gg , Rd , Rd , Re , Re , Wwf , Gg , Mm , Gg , Wwf , Wwf , Wwf , Wwf , Gg , Mm , Mm
|
||||
Hh , Hh , Mm , Gs^Fp , Gg , Gg , Rd , Rd , Re , Re , Gs^Fp , Wwf , Gs^Fp , Hh , Wwf , Wwf , Gg , Gg , Gg , Gg , Gs^Fp , Gs^Fp , Gs^Fp
|
||||
Gs^Fp , Gs^Fp , Gg , Ggf , Rd , Rd , Re , Re , Hh , Mm , Gg , Wwf , Wwf , Wwf , Gg , Gg , Rd , Rd , Hh , Gg , Mm , Hh , Hh
|
||||
Hh , Hh , Gg^Wm , Rd , Re , Re , Mm , Gg , Wwf , Wwf , Wwf , Ch , Gg , Gg , Gg , Rd , Gg , Gs^Fp , Wwf , Wwf , Wwf , Wwf , Wwf
|
||||
Re^Gvs , Re^Gvs , Re^Gvs , Re^Gvs , Gg^Vh , Gs^Fp , Wwf , Wwf , Rd , Ch , Ch , Ch , Gg , Gg , Gg^Vh , Gg , Wwf , Wwf , Gs^Fp , Gs^Fp , Gg^Ve , Gg , Gg
|
||||
Hh , Hh , Gs^Fp , Gs^Fp , Wwf , Wwf , Rd , Rd , Re , Re , Wwf , 2 Kh , Wwf , Gg , Wwf , Wwf , Gg , Wwf , Wwf , Wwf , Wwf , Gs^Fp , Gs^Fp
|
||||
Gs^Fp , Gs^Fp , Wwf , Wwf , Mm , Rd , Gs^Fp , Hh , Wwf , Wwf , Gg , Ch , Gg , Wwf , Hh , Gg , Wwf , Wwf , Gg^Vh , Gg , Wwf , Mm , Mm
|
||||
Gs^Fp , Gs^Fp , Wwf , Wwf , Mm , Rd , Gs^Fp , Wwf , Wwf , Gg , Gg , Gg , Gg , Gg , Hh , Gg , Wwf , Wwf , Gg , Gg , Wwf , Mm , Mm
|
||||
"
|
||||
|
||||
turns=90
|
||||
id=lua_ai
|
||||
|
||||
{DEFAULT_SCHEDULE}
|
||||
|
||||
[label]
|
||||
x,y=16,5
|
||||
text="Patrol waypoint 1"
|
||||
[/label]
|
||||
|
||||
[label]
|
||||
x,y=16,15
|
||||
text="Patrol waypoint 2"
|
||||
[/label]
|
||||
|
||||
[label]
|
||||
x,y=3,14
|
||||
text="Formula priorities test"
|
||||
[/label]
|
||||
|
||||
[label]
|
||||
x,y=2,12
|
||||
text="first"
|
||||
[/label]
|
||||
|
||||
[label]
|
||||
x,y=3,11
|
||||
text="second"
|
||||
[/label]
|
||||
|
||||
[label]
|
||||
x,y=3,13
|
||||
text="third"
|
||||
[/label]
|
||||
|
||||
[label]
|
||||
x,y=8,5
|
||||
text="Location guarded (range = 3)"
|
||||
[/label]
|
||||
|
||||
[side]
|
||||
type=Dwarvish Steelclad
|
||||
id=side_1_leader
|
||||
side=1
|
||||
canrecruit=yes
|
||||
recruit=Dwarvish Guardsman,Dwarvish Fighter,Dwarvish Thunderer,Thief,Poacher,Footpad
|
||||
gold=100
|
||||
controller=human
|
||||
[unit]
|
||||
x,y=10,8
|
||||
type="Elvish Archer"
|
||||
hitpoints=1
|
||||
generate_name=yes
|
||||
[/unit]
|
||||
|
||||
[unit]
|
||||
x,y=3,12
|
||||
type="Elvish Fighter"
|
||||
random_traits=no
|
||||
generate_name=yes
|
||||
[modifications]
|
||||
[trait]
|
||||
id=move
|
||||
[effect]
|
||||
apply_to=movement
|
||||
set=0
|
||||
[/effect]
|
||||
[/trait]
|
||||
[trait]
|
||||
id=hp
|
||||
[effect]
|
||||
apply_to=hitpoints
|
||||
increase_total=120
|
||||
[/effect]
|
||||
[/trait]
|
||||
[/modifications]
|
||||
[/unit]
|
||||
[/side]
|
||||
|
||||
[side]
|
||||
#controller=human
|
||||
name=LuaAI
|
||||
type=Dark Sorcerer
|
||||
side=2
|
||||
canrecruit=yes
|
||||
recruit=Skeleton,Skeleton Archer,Walking Corpse,Ghost,Vampire Bat,Dark Adept,Ghoul
|
||||
gold=100
|
||||
shroud=yes
|
||||
|
||||
[unit]
|
||||
placement=recall
|
||||
type="Skeletal Dragon"
|
||||
id="Kiressh"
|
||||
name="Kiressh"
|
||||
[/unit]
|
||||
|
||||
[unit]
|
||||
x,y=8,5
|
||||
type="Orcish Archer"
|
||||
generate_name=yes
|
||||
[/unit]
|
||||
[unit]
|
||||
x,y=3,8
|
||||
type="Walking Corpse"
|
||||
generate_name=yes
|
||||
[/unit]
|
||||
|
||||
[unit]
|
||||
x,y=16,5
|
||||
type="Wolf Rider"
|
||||
generate_name=yes
|
||||
[/unit]
|
||||
|
||||
[unit]
|
||||
x,y=3,11
|
||||
type="Goblin Spearman"
|
||||
generate_name=yes
|
||||
[/unit]
|
||||
|
||||
[unit]
|
||||
x,y=3,13
|
||||
type="Goblin Spearman"
|
||||
generate_name=yes
|
||||
[/unit]
|
||||
|
||||
[unit]
|
||||
x,y=2,12
|
||||
type="Goblin Spearman"
|
||||
generate_name=yes
|
||||
[/unit]
|
||||
|
||||
[unit]
|
||||
x,y=7,20
|
||||
type="Silver Mage"
|
||||
generate_name=yes
|
||||
[/unit]
|
||||
|
||||
[unit]
|
||||
x,y=6,20
|
||||
type="Ghost"
|
||||
generate_name=yes
|
||||
[/unit]
|
||||
[unit]
|
||||
x,y=15,22
|
||||
type="Ghost"
|
||||
generate_name=yes
|
||||
[/unit]
|
||||
[unit]
|
||||
x,y=12,19
|
||||
type="Ghost"
|
||||
generate_name=yes
|
||||
[/unit]
|
||||
[unit]
|
||||
x,y=10,6
|
||||
type="Lich"
|
||||
experience=149
|
||||
generate_name=yes
|
||||
[/unit]
|
||||
|
||||
[ai]
|
||||
version=10710
|
||||
[engine]
|
||||
name="lua"
|
||||
code= <<
|
||||
--! ==============================================================
|
||||
local data = ...
|
||||
local ai = { side = data._side() }
|
||||
|
||||
local ai_stdlib = wesnoth.require('ai/lua/stdlib.lua');
|
||||
ai_stdlib.init(ai,data);
|
||||
|
||||
function ai:execute()
|
||||
self:_say_hello();
|
||||
my_leader = wesnoth.get_units( {canrecruit="yes", side=self.side})[1]
|
||||
--! move (partial move)
|
||||
self:_move(my_leader,{x=13, y=22})
|
||||
--! full move. note that the my_leader still can be used altrough x and y are now different.
|
||||
self:_move_full(my_leader,{x=11, y=23})
|
||||
dummy_target = {x=3,y=12}
|
||||
--! attack with auto weapon/aggression
|
||||
self:_attack({x=2,y=12},dummy_target)
|
||||
--! attack with weapon selected
|
||||
self:_attack({x=3,y=11},dummy_target,1)
|
||||
--! attack with different aggression
|
||||
self:_attack({x=3,y=13},dummy_target,-1,1)
|
||||
if wesnoth.current.turn==1 then
|
||||
--! recruit on specific location
|
||||
self:_recruit("Vampire Bat",{x=10, y=22})
|
||||
--! recruit on any suitable location
|
||||
self:_recruit("Skeleton")
|
||||
--! recall on any suitable location.
|
||||
self:_recall("Kiressh")
|
||||
end
|
||||
end
|
||||
|
||||
return ai
|
||||
--! ==============================================================
|
||||
>>
|
||||
[/engine]
|
||||
[stage]
|
||||
engine="lua"
|
||||
code= "(...):execute()"
|
||||
[/stage]
|
||||
[/ai]
|
||||
[/side]
|
||||
[/test]
|
||||
|
||||
# vim: tabstop=4: shiftwidth=4: expandtab: softtabstop=4: autoindent:
|
|
@ -1846,72 +1846,6 @@ static int intf_float_label(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//start of ai_ functions
|
||||
static int intf_ai_execute_move(lua_State *L)
|
||||
{
|
||||
int side = lua_tointeger(L, 1);
|
||||
map_location from;
|
||||
from.x = lua_tointeger(L, 2) - 1;
|
||||
from.y = lua_tointeger(L, 3) - 1;
|
||||
map_location to;
|
||||
to.x = lua_tointeger(L, 4) - 1;
|
||||
to.y = lua_tointeger(L, 5) - 1;
|
||||
bool remove_movement = lua_toboolean(L, 6);
|
||||
ai::actions::execute_move_action(side,true,from,to,remove_movement);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intf_ai_execute_attack(lua_State *L)
|
||||
{
|
||||
int side = lua_tointeger(L, 1);
|
||||
map_location attacker;
|
||||
attacker.x = lua_tointeger(L, 2) - 1;
|
||||
attacker.y = lua_tointeger(L, 3) - 1;
|
||||
map_location defender;
|
||||
defender.x = lua_tointeger(L, 4) - 1;
|
||||
defender.y = lua_tointeger(L, 5) - 1;
|
||||
int attacker_weapon = lua_tointeger(L, 6);
|
||||
double aggression = lua_tonumber(L, 7);
|
||||
ai::actions::execute_attack_action(side,true,attacker,defender,attacker_weapon,aggression);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intf_ai_execute_stopunit(lua_State *L)
|
||||
{
|
||||
int side = lua_tointeger(L, 1);
|
||||
map_location loc;
|
||||
loc.x = lua_tointeger(L, 2) - 1;
|
||||
loc.y = lua_tointeger(L, 3) - 1;
|
||||
bool remove_movement = lua_toboolean(L, 4);
|
||||
bool remove_attacks = lua_toboolean(L, 5);
|
||||
ai::actions::execute_stopunit_action(side,true,loc,remove_movement,remove_attacks);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intf_ai_execute_recruit(lua_State *L)
|
||||
{
|
||||
int side = lua_tointeger(L, 1);
|
||||
const char* unit_name = lua_tostring(L,2);
|
||||
map_location where;
|
||||
where.x = lua_tointeger(L, 3) - 1;
|
||||
where.y = lua_tointeger(L, 4) - 1;
|
||||
ai::actions::execute_recruit_action(side,true,std::string(unit_name),where);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int intf_ai_execute_recall(lua_State *L)
|
||||
{
|
||||
int side = lua_tointeger(L, 1);
|
||||
const char* unit_id = lua_tostring(L,2);
|
||||
map_location where;
|
||||
where.x = lua_tointeger(L, 3) - 1;
|
||||
where.y = lua_tointeger(L, 4) - 1;
|
||||
ai::actions::execute_recall_action(side,true,std::string(unit_id),where);
|
||||
return 0;
|
||||
}
|
||||
//end of ai_ functions
|
||||
|
||||
LuaKernel::LuaKernel()
|
||||
: mState(luaL_newstate())
|
||||
{
|
||||
|
@ -1935,11 +1869,6 @@ LuaKernel::LuaKernel()
|
|||
|
||||
// Put some callback functions in the scripting environment.
|
||||
static luaL_reg const callbacks[] = {
|
||||
{ "ai_execute_move", &intf_ai_execute_move },
|
||||
{ "ai_execute_attack", &intf_ai_execute_attack },
|
||||
{ "ai_execute_stopunit", &intf_ai_execute_stopunit },
|
||||
{ "ai_execute_recruit", &intf_ai_execute_recruit },
|
||||
{ "ai_execute_recall", &intf_ai_execute_recall },
|
||||
{ "dofile", &intf_dofile },
|
||||
{ "fire", &intf_fire },
|
||||
{ "fire_event", &lua_fire_event },
|
||||
|
@ -2207,6 +2136,134 @@ bool LuaKernel::execute(char const *prog, int nArgs, int nRets)
|
|||
|
||||
|
||||
// ai support stuff
|
||||
static int transform_ai_action(lua_State *L, ai::action_result_ptr action_result)
|
||||
{
|
||||
lua_newtable(L);
|
||||
lua_pushboolean(L,action_result->is_ok());
|
||||
lua_setfield(L, -2, "ok");
|
||||
lua_pushboolean(L,action_result->is_gamestate_changed());
|
||||
lua_setfield(L, -2, "gamestate_changed");
|
||||
lua_pushinteger(L,action_result->get_status());
|
||||
lua_setfield(L, -2, "status");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static map_location to_map_location(lua_State *L, int index)
|
||||
{
|
||||
map_location loc;
|
||||
|
||||
if (!lua_isnoneornil(L,index)) {
|
||||
lua_getfield(L,index,"x");
|
||||
loc.x = luaL_checkint(L, -1) - 1;
|
||||
lua_pop(L,1);
|
||||
|
||||
lua_getfield(L,index,"y");
|
||||
loc.y = luaL_checkint(L, -1) - 1;
|
||||
lua_pop(L,1);
|
||||
}
|
||||
|
||||
return loc;
|
||||
}
|
||||
|
||||
static int impl_ai_execute_move(lua_State *L, bool remove_movement)
|
||||
{
|
||||
int side = lua_tointeger(L,lua_upvalueindex(1));
|
||||
map_location from = to_map_location(L,2);
|
||||
map_location to = to_map_location(L,3);
|
||||
ai::move_result_ptr move_result = ai::actions::execute_move_action(side,true,from,to,remove_movement);
|
||||
return transform_ai_action(L,move_result);
|
||||
}
|
||||
|
||||
|
||||
static int impl_ai_execute_move_full(lua_State *L)
|
||||
{
|
||||
return impl_ai_execute_move(L,true);
|
||||
}
|
||||
|
||||
|
||||
static int impl_ai_execute_move_partial(lua_State *L)
|
||||
{
|
||||
return impl_ai_execute_move(L,false);
|
||||
}
|
||||
|
||||
|
||||
static int impl_ai_execute_attack(lua_State *L)
|
||||
{
|
||||
int side = lua_tointeger(L,lua_upvalueindex(1));
|
||||
map_location attacker = to_map_location(L,2);
|
||||
map_location defender = to_map_location(L,3);
|
||||
|
||||
int attacker_weapon = -1;//-1 means 'select what is best'
|
||||
double aggression = 0.5;//TODO: replace with side agression
|
||||
|
||||
if (!lua_isnoneornil(L, 5)) {
|
||||
aggression = luaL_checknumber(L, 5);
|
||||
}
|
||||
|
||||
if (!lua_isnoneornil(L, 4)) {
|
||||
attacker_weapon = luaL_checkint(L, 4);
|
||||
}
|
||||
|
||||
ai::attack_result_ptr attack_result = ai::actions::execute_attack_action(side,true,attacker,defender,attacker_weapon,aggression);
|
||||
return transform_ai_action(L,attack_result);
|
||||
}
|
||||
|
||||
|
||||
static int impl_ai_execute_stopunit_select(lua_State *L, bool remove_movement, bool remove_attacks)
|
||||
{
|
||||
int side = lua_tointeger(L,lua_upvalueindex(1));
|
||||
map_location loc = to_map_location(L,2);
|
||||
|
||||
ai::stopunit_result_ptr stopunit_result = ai::actions::execute_stopunit_action(side,true,loc,remove_movement,remove_attacks);
|
||||
return transform_ai_action(L,stopunit_result);
|
||||
}
|
||||
|
||||
|
||||
static int impl_ai_execute_stopunit_moves(lua_State *L)
|
||||
{
|
||||
return impl_ai_execute_stopunit_select(L,true,false);
|
||||
}
|
||||
|
||||
static int impl_ai_execute_stopunit_attacks(lua_State *L)
|
||||
{
|
||||
return impl_ai_execute_stopunit_select(L,false,true);
|
||||
}
|
||||
|
||||
static int impl_ai_execute_stopunit_all(lua_State *L)
|
||||
{
|
||||
return impl_ai_execute_stopunit_select(L,true,true);
|
||||
}
|
||||
|
||||
|
||||
static int impl_ai_execute_recruit(lua_State *L)
|
||||
{
|
||||
int side = lua_tointeger(L,lua_upvalueindex(1));
|
||||
const char* unit_name = luaL_checkstring(L,2);
|
||||
map_location where = to_map_location(L,3);
|
||||
|
||||
ai::recruit_result_ptr recruit_result = ai::actions::execute_recruit_action(side,true,std::string(unit_name),where);
|
||||
return transform_ai_action(L,recruit_result);
|
||||
}
|
||||
|
||||
|
||||
static int impl_ai_execute_recall(lua_State *L)
|
||||
{
|
||||
int side = lua_tointeger(L,lua_upvalueindex(1));
|
||||
const char* unit_id = luaL_checkstring(L,2);
|
||||
map_location where = to_map_location(L,3);
|
||||
|
||||
ai::recall_result_ptr recall_result = ai::actions::execute_recall_action(side,true,std::string(unit_id),where);
|
||||
return transform_ai_action(L,recall_result);
|
||||
}
|
||||
|
||||
static int impl_ai_side(lua_State *L)
|
||||
{
|
||||
int side = lua_tointeger(L,lua_upvalueindex(1));
|
||||
lua_pushinteger(L,side);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
lua_ai_context* LuaKernel::create_ai_context(char const *code, int side)
|
||||
{
|
||||
lua_State *L = mState;
|
||||
|
@ -2219,9 +2276,37 @@ lua_ai_context* LuaKernel::create_ai_context(char const *code, int side)
|
|||
lua_pop(L, 2);//return with stack size 0 []
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//push data table here
|
||||
lua_newtable(L);//stack size is 2 [-1: ai_context -2: new table]
|
||||
lua_pushinteger(L,side);
|
||||
luaW_pcall(L, 1, 1, true);//compile the ai
|
||||
lua_pushcclosure(L,&impl_ai_side,1);
|
||||
lua_setfield(L, -2, "_side");
|
||||
luaW_pcall(L, 1, 1, true);//compile the ai as a closure
|
||||
lua_pushinteger(L,side);
|
||||
lua_pushcclosure(L,&impl_ai_execute_move_partial,1);
|
||||
lua_setfield(L, -2, "_move");
|
||||
lua_pushinteger(L,side);
|
||||
lua_pushcclosure(L,&impl_ai_execute_move_full,1);
|
||||
lua_setfield(L, -2, "_move_full");
|
||||
lua_pushinteger(L,side);
|
||||
lua_pushcclosure(L,&impl_ai_execute_attack,1);
|
||||
lua_setfield(L, -2, "_attack");
|
||||
lua_pushinteger(L,side);
|
||||
lua_pushcclosure(L,&impl_ai_execute_stopunit_moves,1);
|
||||
lua_setfield(L, -2, "_stopunit_moves");
|
||||
lua_pushinteger(L,side);
|
||||
lua_pushcclosure(L,&impl_ai_execute_stopunit_attacks,1);
|
||||
lua_setfield(L, -2, "_stopunit_attacks");
|
||||
lua_pushinteger(L,side);
|
||||
lua_pushcclosure(L,&impl_ai_execute_stopunit_all,1);
|
||||
lua_setfield(L, -2, "_stopunit_all");
|
||||
lua_pushinteger(L,side);
|
||||
lua_pushcclosure(L,&impl_ai_execute_recall,1);
|
||||
lua_setfield(L, -2, "_recall");
|
||||
lua_pushinteger(L,side);
|
||||
lua_pushcclosure(L,&impl_ai_execute_recruit,1);
|
||||
lua_setfield(L, -2, "_recruit");
|
||||
|
||||
// Retrieve the ai elements table from the registry.
|
||||
lua_pushlightuserdata(L, (void *)&aisKey);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX); //stack size is now 2 [-1: ais_table -2: f]
|
||||
|
@ -2231,7 +2316,7 @@ lua_ai_context* LuaKernel::create_ai_context(char const *code, int side)
|
|||
lua_rawseti(L, -2, length_ai + 1);// ais_table[length+1]=ai_context. stack size is now 2 [-1: ais_table -2: ai_context]
|
||||
lua_remove(L, -1);//stack size is now 1 [-1: ai_context]
|
||||
lua_remove(L, -1);//stack size is now 0 []
|
||||
return new lua_ai_context(L, length_ai + 1);
|
||||
return new lua_ai_context(L, length_ai + 1, side);
|
||||
}
|
||||
|
||||
lua_ai_action_handler* LuaKernel::create_ai_action_handler(char const *code, lua_ai_context &context)
|
||||
|
@ -2262,7 +2347,6 @@ lua_ai_action_handler* LuaKernel::create_ai_action_handler(char const *code, lua
|
|||
}
|
||||
|
||||
|
||||
//will be moved to separate file
|
||||
void lua_ai_context::load()
|
||||
{
|
||||
lua_pushlightuserdata(L, (void *)&aisKey);//stack size is now 1 [-1: ais_table key]
|
||||
|
@ -2295,7 +2379,7 @@ void lua_ai_action_handler::handle(config &/*cfg*/)
|
|||
lua_rawgeti(L, -1, num_);//stack size is 2 [-1: ai_action -2: ais_table]
|
||||
lua_remove(L,-2);//stack size is 1 [-1: ai_action]
|
||||
//load the lua ai context as a parameter
|
||||
context_.load();//stack size is 2 [-1: ai_context -2: ai_action]
|
||||
context_.load();//stack size is 2 [-1: ai_context -2: ai_action]
|
||||
luaW_pcall(L, 1, 0, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,8 +27,9 @@ class lua_ai_context
|
|||
private:
|
||||
lua_State *L;
|
||||
int num_;
|
||||
int side_;
|
||||
public:
|
||||
lua_ai_context(lua_State *l, int num) : L(l), num_(num)
|
||||
lua_ai_context(lua_State *l, int num, int side) : L(l), num_(num), side_(side)
|
||||
{
|
||||
}
|
||||
~lua_ai_context();
|
||||
|
|
Loading…
Add table
Reference in a new issue