Add support for AI candidate actions written in lua.

patch LuaW_pcall to support LUA_MULTRET. Patch #1558 by Darkas.
This commit is contained in:
Iurii Chernyi 2010-03-23 21:04:50 +00:00
parent 19428efb5e
commit f2b8b94d0b
6 changed files with 79 additions and 12 deletions

View file

@ -2,6 +2,7 @@ Version 1.7.15+svn:
* AI:
* Fixed bug #14247: Make formula AI behave correctly if the side has only 1
potential recruit.
* Added support for candidate actions written in lua.
* Campaigns:
* Legend of Wesmere:
* Fixed bug #15631: Scenario 3: arrival of Kalenz failed

View file

@ -205,11 +205,32 @@ local my_ai = { }
local ai_stdlib = wesnoth.require('ai/lua/stdlib.lua');
ai_stdlib.init(ai)
function my_ai:execute()
ai.say_hello()
function my_ai:stage_hello()
wesnoth.message('hello from stage!')
end
function my_ai:candidate_action_evaluation_hello()
wesnoth.message('hello from candidate action evaluation!')
return 42, {test=123}
end
function my_ai:candidate_action_execution_hello(cfg)
wesnoth.message('hello from candidate action execution!')
wesnoth.message('test value is ' .. cfg.test)
self:do_moves()
end
function my_ai:candidate_action_evaluation_hello2()
wesnoth.message('hello from second candidate action evaluation!')
return 99
end
function my_ai:candidate_action_execution_hello2()
wesnoth.message('hello from second candidate action execution!')
self:do_moves()
end
function my_ai:do_moves()
my_leader = wesnoth.get_units({canrecruit = true, side = ai.side})[1]
--! move (partial move)
@ -237,9 +258,24 @@ return my_ai
--! ==============================================================
>>
[/engine]
[stage]
name=testing_ai_default::candidate_action_evaluation_loop
[candidate_action]
engine=lua
name=first
evaluation="return (...):candidate_action_evaluation_hello()"
execution="local ai, cfg = ...; ai:candidate_action_execution_hello(cfg)"
[/candidate_action]
[candidate_action]
engine=lua
name=second
evaluation="return (...):candidate_action_evaluation_hello2()"
execution="(...):candidate_action_execution_hello2()"
[/candidate_action]
[/stage]
[stage]
engine="lua"
code= "(...):execute()"
code= "(...):stage_hello()"
[/stage]
[/ai]
[/side]

View file

@ -799,6 +799,9 @@
[entry]
name = "Alesis Novik"
[/entry]
[entry]
name = "André Knispel"
[/entry]
[entry]
name = "Andrea Palmatè (afxgroup)"
[/entry]

View file

@ -55,7 +55,7 @@ public:
{
serialized_evaluation_state_ = config();
if (evaluation_action_handler_) {
evaluation_action_handler_->handle(serialized_evaluation_state_);
evaluation_action_handler_->handle(serialized_evaluation_state_, true);
} else {
return BAD_SCORE;
}

View file

@ -364,6 +364,8 @@ static bool luaW_pcall(lua_State *L
lua_rawget(L, LUA_REGISTRYINDEX);
lua_insert(L, -2 - nArgs);
int error_handler_index = lua_gettop(L) - nArgs - 1;
// Call the function.
int res = lua_pcall(L, nArgs, nRets, -2 - nArgs);
if (res)
@ -382,7 +384,13 @@ static bool luaW_pcall(lua_State *L
}
// Remove the error handler.
lua_remove(L, -1 - nRets);
if(nRets == LUA_MULTRET) {
lua_remove(L, error_handler_index);
} else {
lua_remove(L, -1 - nRets);
}
return true;
}
@ -2735,19 +2743,38 @@ lua_ai_context::~lua_ai_context()
lua_pop(L, 1);
}
/**
* handling of config in-out parameter will be done later
*/
void lua_ai_action_handler::handle(config &/*cfg*/)
void lua_ai_action_handler::handle(config &cfg, bool configOut)
{
int initial_top = lua_gettop(L);//get the old stack size
// Load the user function from the registry.
lua_pushlightuserdata(L, (void *)&aisKey);//stack size is now 1 [-1: ais_table key]
lua_rawget(L, LUA_REGISTRYINDEX);//stack size is still 1 [-1: ais_table]
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]
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]
luaW_pcall(L, 1, 0, true);
if (!configOut)
{
lua_newtable(L);//stack size is 3 [-1: table -2: ai_context -3: ai_action]
table_of_wml_config(L, cfg);//the new table now contains the config
luaW_pcall(L, 2, LUA_MULTRET, true);
}
else if (lua_gettop(L) > initial_top)
{
if (luaW_pcall(L, 1, LUA_MULTRET, true)) {
int score = lua_tonumber(L, initial_top + 1);//get score
if (lua_gettop(L) >= initial_top + 2) {//check if we also have config
luaW_toconfig(L, initial_top + 2, cfg);//get config
}
cfg["score"] = str_cast(score);//write score to the config
}
}
lua_settop(L, initial_top);//empty stack
}
lua_ai_action_handler::~lua_ai_action_handler()

View file

@ -51,7 +51,7 @@ public:
{
}
~lua_ai_action_handler();
void handle(config &);
void handle(config &, bool configOut = false);
};