LuaAI: the need to define an engine is now deprecated.
All CAs can be store in external .lua files. If the scenario config lacks an [engine] tag for the Lua AI engine, but still tries to use CA with engine=lua, a dummy engine will be automatically generated, providing the needed functionality
This commit is contained in:
parent
a46252cbdb
commit
b207a1b1ca
8 changed files with 312 additions and 9 deletions
|
@ -38,6 +38,7 @@
|
|||
{ai/scenarios/scenario-AI_Arena_small.cfg}
|
||||
{ai/scenarios/scenario-test_move_to_targets.cfg}
|
||||
{ai/scenarios/scenario-lua-ai.cfg}
|
||||
{ai/scenarios/scenario-no_engine.cfg}
|
||||
#endif
|
||||
|
||||
[textdomain]
|
||||
|
|
16
data/ai/lua/dummy_engine_lua.lua
Normal file
16
data/ai/lua/dummy_engine_lua.lua
Normal file
|
@ -0,0 +1,16 @@
|
|||
--! #textdomain wesnoth
|
||||
|
||||
return {
|
||||
get_ai = function(ai)
|
||||
local my_ai = { }
|
||||
local ai_stdlib = wesnoth.require('ai/lua/stdlib.lua')
|
||||
ai_stdlib.init(ai, true)
|
||||
|
||||
-- compulsory for the external CA's
|
||||
function my_ai:get_ai()
|
||||
return ai
|
||||
end
|
||||
|
||||
return my_ai
|
||||
end
|
||||
}
|
16
data/ai/lua/extCAexample.lua
Normal file
16
data/ai/lua/extCAexample.lua
Normal file
|
@ -0,0 +1,16 @@
|
|||
--! #textdomain wesnoth
|
||||
|
||||
example_ca = {}
|
||||
|
||||
function example_ca:eval(ai)
|
||||
wesnoth.message("External eval says hi!")
|
||||
|
||||
return 10000
|
||||
end
|
||||
|
||||
function example_ca:exec(ai)
|
||||
wesnoth.message("External CA exec attacks!")
|
||||
ai.attack(2, 12, 3, 12, 1, 1) -- showcasing the presence of the AI table
|
||||
end
|
||||
|
||||
return example_ca
|
|
@ -245,7 +245,7 @@ Gs^Fp , Gs^Fp , Wwf , Wwf , Mm , Rd
|
|||
engine=lua
|
||||
code = << return 0.23 >>
|
||||
[/aspect]
|
||||
[engine]
|
||||
[engine]
|
||||
name="lua"
|
||||
code= <<
|
||||
--! ==============================================================
|
||||
|
@ -319,7 +319,7 @@ function my_ai:do_moves()
|
|||
end
|
||||
|
||||
-- compulsory for the external CA's
|
||||
function my_ai:ai()
|
||||
function my_ai:get_ai()
|
||||
return ai
|
||||
end
|
||||
|
||||
|
|
261
data/ai/scenarios/scenario-no_engine.cfg
Normal file
261
data/ai/scenarios/scenario-no_engine.cfg
Normal file
|
@ -0,0 +1,261 @@
|
|||
#textdomain wesnoth
|
||||
# @file data/scenario-luaai.cfg
|
||||
|
||||
[test]
|
||||
name="Test scenario for Lua AI with no Lua engine defined"
|
||||
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 , Gg^Efm , 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 , Gg^Efm , Gg^Efm
|
||||
Wwf , Wwf , Hh , Gg^Efm , 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 , Gg^Efm , Wwf , Wwf , Wwf
|
||||
Gg^Efm , Gg^Efm , 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 , Gg^Efm , 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_no_engine
|
||||
|
||||
{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]
|
||||
|
||||
|
||||
[event]
|
||||
name=side 2 turn 1
|
||||
first_time_only=yes
|
||||
{MODIFY_AI_DELETE_CANDIDATE_ACTION 2 ca_loop firstca}
|
||||
[/event]
|
||||
|
||||
[event]
|
||||
name=side 2 turn 1
|
||||
[modify_side]
|
||||
side=2
|
||||
[ai]
|
||||
[avoid]
|
||||
x,y=1,11
|
||||
[/avoid]
|
||||
|
||||
[leader_goal]
|
||||
x,y=2,12
|
||||
[/leader_goal]
|
||||
[/ai]
|
||||
[/modify_side]
|
||||
|
||||
#{MODIFY_UNIT side=1 moves 0}
|
||||
[/event]
|
||||
|
||||
[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"
|
||||
name="Bilbo"
|
||||
[/unit]
|
||||
[unit]
|
||||
x,y=3,8
|
||||
type="Walking Corpse"
|
||||
name="Sally"
|
||||
[/unit]
|
||||
|
||||
[unit]
|
||||
x,y=16,5
|
||||
type="Wolf Rider"
|
||||
name="Rark"
|
||||
[/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
|
||||
[goal]
|
||||
name=protect_location
|
||||
value=5
|
||||
protect_radius=16
|
||||
[criteria] #NOTE: this is a SLF, because we're protecting a location
|
||||
x,y=42,20
|
||||
[/criteria]
|
||||
[/goal]
|
||||
|
||||
[goal]
|
||||
name=lua_goal
|
||||
value=6
|
||||
engine=lua
|
||||
code = <<
|
||||
local t = {}
|
||||
t[1] = {["value"]=2.3, ["type"]=3, ["loc"]={["x"]=5, ["y"]=6}}
|
||||
t[2] = {["value"]=2.4, ["type"]=4, ["loc"]={["x"]=4, ["y"]=16}}
|
||||
return t
|
||||
>>
|
||||
[/goal]
|
||||
[aspect]
|
||||
id=aggression
|
||||
engine=lua
|
||||
code = << return 0.23 >>
|
||||
[/aspect]
|
||||
[stage]
|
||||
name=testing_ai_default::candidate_action_evaluation_loop
|
||||
id=ca_loop
|
||||
[candidate_action]
|
||||
engine=lua
|
||||
name=external
|
||||
location="ai/lua/extCAexample.lua"
|
||||
[/candidate_action]
|
||||
[/stage]
|
||||
[/ai]
|
||||
[/side]
|
||||
[/test]
|
||||
|
||||
# vim: tabstop=4: shiftwidth=4: expandtab: softtabstop=4: autoindent:
|
|
@ -157,7 +157,7 @@ public:
|
|||
virtual engine_ptr get_new_instance( readonly_context &ai, const std::string& name ){
|
||||
config cfg;
|
||||
cfg["name"] = name;
|
||||
cfg["engine"] = "cpp";
|
||||
cfg["engine"] = "cpp"; // @Crab: what is the purpose of this line(neph)
|
||||
return engine_ptr(new ENGINE(ai,cfg));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -149,10 +149,10 @@ public:
|
|||
private:
|
||||
std::string location_;
|
||||
|
||||
void generate_code(std::string& eval, std::string& exec) {
|
||||
void generate_code(std::string& eval, std::string& exec) {
|
||||
std::string code = "wesnoth.require(\"" + location_ + "\")";
|
||||
eval = "return " + code + ".eval((...):ai())";
|
||||
exec = code + ".exec((...):ai())";
|
||||
eval = "return " + code + ":eval((...):get_ai())";
|
||||
exec = code + ":exec((...):get_ai())";
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -235,20 +235,27 @@ engine_lua::engine_lua( readonly_context &context, const config &cfg )
|
|||
: engine(context,cfg)
|
||||
, code_(cfg["code"])
|
||||
, lua_ai_context_(resources::lua_kernel->create_lua_ai_context(
|
||||
cfg["code"].str().c_str(), this))
|
||||
get_engine_code(cfg).c_str(), this))
|
||||
{
|
||||
name_ = "lua";
|
||||
|
||||
config data(cfg.child_or_empty("data"));
|
||||
lua_ai_context_->set_persistent_data(data);
|
||||
}
|
||||
|
||||
std::string engine_lua::get_engine_code(const config &cfg) const
|
||||
{
|
||||
if (cfg.has_attribute("code")) {
|
||||
return cfg["code"].str();
|
||||
}
|
||||
// If there is no engine defined we create a dummy engine
|
||||
std::string code = "local ai = ... local m_ai = wesnoth.require(\"ai/lua/dummy_engine_lua.lua\") return m_ai.get_ai(ai)";
|
||||
return code;
|
||||
}
|
||||
|
||||
engine_lua::~engine_lua()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void engine_lua::do_parse_candidate_action_from_config( rca_context &context, const config &cfg, std::back_insert_iterator<std::vector< candidate_action_ptr > > b ){
|
||||
if (!cfg) {
|
||||
return;
|
||||
|
|
|
@ -77,6 +77,8 @@ private:
|
|||
|
||||
//There is one lua engine per AI. So, it can hold state
|
||||
boost::shared_ptr<lua_ai_context> lua_ai_context_;
|
||||
|
||||
std::string get_engine_code(const config&) const;
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue