diff --git a/data/ai/lua/dummy_engine_lua.lua b/data/ai/lua/dummy_engine_lua.lua index 49092cc13f7f..bec8d483a9a2 100644 --- a/data/ai/lua/dummy_engine_lua.lua +++ b/data/ai/lua/dummy_engine_lua.lua @@ -2,21 +2,9 @@ -- This is the engine used by the Lua AI when no engine is -- defined specifically in the [side] tag -return { - get_ai = function(ai) - local my_ai = {} +-- This provides a cache level for the move map functions, +-- making them a bit easier to use +local ai_stdlib = wesnoth.require('ai/lua/stdlib.lua') +ai_stdlib.init(ai) - local ai_stdlib = wesnoth.require('ai/lua/stdlib.lua') - ai_stdlib.init(ai) - - -- Make the ai table available to the eval/exec functions - function my_ai:get_ai() - return ai - end - - -- Make the persistent data table available to the eval/exec functions - my_ai.data = {} - - return my_ai - end -} +-- No special state is returned by the default engine diff --git a/src/ai/composite/aspect.cpp b/src/ai/composite/aspect.cpp index 14073ab63e2a..e4de2c2971c8 100644 --- a/src/ai/composite/aspect.cpp +++ b/src/ai/composite/aspect.cpp @@ -148,4 +148,15 @@ known_aspect::~known_aspect() { } +std::string lua_aspect_visitor::quote_string(const std::string& s) +{ + if (s.find_first_of('"') == std::string::npos) { + return '"' + s + '"'; + } else if (s.find_first_of("'") == std::string::npos) { + return "'" + s + "'"; + } else { + return "[=====[" + s + "]=====]"; + } +} + } //end of namespace ai diff --git a/src/ai/composite/aspect.hpp b/src/ai/composite/aspect.hpp index b46f7b95a00c..ba558cea3a84 100644 --- a/src/ai/composite/aspect.hpp +++ b/src/ai/composite/aspect.hpp @@ -26,6 +26,7 @@ #include "scripting/game_lua_kernel.hpp" #include "log.hpp" +#include "util.hpp" #include #include @@ -394,6 +395,18 @@ class standard_aspect : public typesafe_aspect { std::string turns_; }; + +class lua_aspect_visitor : public boost::static_visitor { + static std::string quote_string(const std::string& s); +public: + std::string operator()(bool b) const {return b ? "true" : "false";} + std::string operator()(int i) const {return quote_string(str_cast(i));} + std::string operator()(unsigned long long i) const {return quote_string(str_cast(i));} + std::string operator()(double i) const {return quote_string(str_cast(i));} + std::string operator()(const std::string& s) const {return quote_string(s);} + std::string operator()(const t_string& s) const {return quote_string(s.str());} + std::string operator()(boost::blank) const {return "nil";} +}; template class lua_aspect : public typesafe_aspect @@ -401,50 +414,44 @@ class lua_aspect : public typesafe_aspect public: lua_aspect(readonly_context &context, const config &cfg, const std::string &id, boost::shared_ptr& l_ctx) : typesafe_aspect(context, cfg, id) - , handler_(), code_() + , handler_(), code_(), params_(cfg.child_or_empty("args")) { - std::string value; if (cfg.has_attribute("value")) { - value = cfg["value"].str(); - if (value == "yes") /** @todo for Nephro or Crab: get rid of this workaround */ - { - value = "true"; - } - value = "return " + value; + code_ = "return " + cfg["value"].apply_visitor(lua_aspect_visitor()); } else if (cfg.has_attribute("code")) { - value = cfg["code"].str(); + code_ = cfg["code"].str(); } else { // error return; } - code_ = value; - handler_ = boost::shared_ptr(resources::lua_kernel->create_lua_ai_action_handler(value.c_str(), *l_ctx)); + handler_ = boost::shared_ptr(resources::lua_kernel->create_lua_ai_action_handler(code_.c_str(), *l_ctx)); } void recalculate() const { this->valid_lua_ = true; - boost::shared_ptr< lua_object > l_obj = boost::shared_ptr< lua_object >(new lua_object()); - config c = config(); - handler_->handle(c, true, l_obj); - this->value_lua_ = l_obj; + handler_->handle(params_, true, this->value_lua_); } config to_config() const { config cfg = aspect::to_config(); cfg["code"] = code_; + if (!params_.empty()) { + cfg.add_child("args", params_); + } return cfg; } private: boost::shared_ptr handler_; std::string code_; + const config params_; }; diff --git a/src/ai/composite/engine_lua.cpp b/src/ai/composite/engine_lua.cpp index 77d4c0f1f5ed..4132f3688848 100644 --- a/src/ai/composite/engine_lua.cpp +++ b/src/ai/composite/engine_lua.cpp @@ -56,7 +56,7 @@ class lua_candidate_action_wrapper_base : public candidate_action { public: lua_candidate_action_wrapper_base( rca_context &context, const config &cfg) - : candidate_action(context, cfg),evaluation_action_handler_(),execution_action_handler_(),serialized_evaluation_state_() + : candidate_action(context, cfg),evaluation_action_handler_(),execution_action_handler_(),serialized_evaluation_state_(cfg.child_or_empty("args")) { // do nothing } @@ -65,8 +65,6 @@ class lua_candidate_action_wrapper_base : public candidate_action { virtual double evaluate() { - serialized_evaluation_state_ = config(); - lua_int_obj l_obj = lua_int_obj(new lua_object()); if (evaluation_action_handler_) { @@ -82,15 +80,15 @@ class lua_candidate_action_wrapper_base : public candidate_action { virtual void execute() { - lua_int_obj l_obj = lua_int_obj(new lua_object()); if (execution_action_handler_) { - execution_action_handler_->handle(serialized_evaluation_state_, false, l_obj); + lua_object_ptr nil; + execution_action_handler_->handle(serialized_evaluation_state_, false, nil); } } virtual config to_config() const { config cfg = candidate_action::to_config(); - cfg.add_child("state",serialized_evaluation_state_); + cfg.add_child("args",serialized_evaluation_state_); return cfg; } @@ -155,9 +153,10 @@ class lua_candidate_action_wrapper_external : public lua_candidate_action_wrappe std::string exec_parms_; void generate_code(std::string& eval, std::string& exec) { - std::string code = "wesnoth.require(\"" + location_ + "\")"; - eval = "return " + code + ":evaluation((...):get_ai(), {" + eval_parms_ + "}, (...))"; - exec = code + ":execution((...):get_ai(), {" + exec_parms_ + "}, (...))"; + std::string preamble = "local params, data, state = ...\n"; + std::string load = "wesnoth.require(\"" + location_ + "\")"; + eval = preamble + "return " + load + ":evaluation(ai, {" + eval_parms_ + "}, {data = data})"; + exec = preamble + load + ":execution(ai, {" + exec_parms_ + "}, {data = data})"; } }; @@ -197,7 +196,7 @@ class lua_sticky_candidate_action_wrapper : public lua_candidate_action_wrapper class lua_stage_wrapper : public stage { public: lua_stage_wrapper( ai_context &context, const config &cfg, lua_ai_context &lua_ai_ctx ) - : stage(context,cfg),action_handler_(),code_(cfg["code"]),serialized_evaluation_state_(cfg.child_or_empty("state")) + : stage(context,cfg),action_handler_(),code_(cfg["code"]),serialized_evaluation_state_(cfg.child_or_empty("args")) { action_handler_ = boost::shared_ptr(resources::lua_kernel->create_lua_ai_action_handler(code_.c_str(),lua_ai_ctx)); } @@ -209,10 +208,10 @@ class lua_stage_wrapper : public stage { virtual bool do_play_stage() { gamestate_observer gs_o; - lua_int_obj l_obj = lua_int_obj(new lua_object()); if (action_handler_) { - action_handler_->handle(serialized_evaluation_state_, false, l_obj); + lua_object_ptr nil; + action_handler_->handle(serialized_evaluation_state_, false, nil); } return gs_o.is_gamestate_changed(); @@ -222,7 +221,7 @@ class lua_stage_wrapper : public stage { { config cfg = stage::to_config(); cfg["code"] = code_; - cfg.add_child("state",serialized_evaluation_state_); + cfg.add_child("args",serialized_evaluation_state_); return cfg; } private: @@ -244,9 +243,12 @@ engine_lua::engine_lua( readonly_context &context, const config &cfg ) { name_ = "lua"; config data(cfg.child_or_empty("data")); + config args(cfg.child_or_empty("args")); if (lua_ai_context_) { // The context might be NULL if the config contains errors lua_ai_context_->set_persistent_data(data); + lua_ai_context_->set_arguments(args); + lua_ai_context_->update_state(); } } @@ -256,7 +258,7 @@ std::string engine_lua::get_engine_code(const config &cfg) const return cfg["code"].str(); } // If there is no engine defined we create a dummy engine - std::string code = "local ai = ... return wesnoth.require(\"ai/lua/dummy_engine_lua.lua\").get_ai(ai)"; + std::string code = "wesnoth.require(\"ai/lua/dummy_engine_lua.lua\")"; return code; } @@ -273,7 +275,7 @@ void engine_lua::push_ai_table() { if (game_config::debug) { - lua_ai_context_->load_and_inject_ai_table(this); + // TODO: Reimplement this somehow } } diff --git a/src/ai/composite/goal.cpp b/src/ai/composite/goal.cpp index 5da4662fb692..4e46e89a406a 100644 --- a/src/ai/composite/goal.cpp +++ b/src/ai/composite/goal.cpp @@ -350,7 +350,7 @@ void lua_goal::add_targets(std::back_insert_iterator< std::vector< target > > ta { boost::shared_ptr< lua_object< std::vector < target > > > l_obj = boost::shared_ptr< lua_object< std::vector < target > > >(new lua_object< std::vector < target > >()); - config c = config(); + config c(cfg_.child_or_empty("args")); handler_->handle(c, true, l_obj); try { std::vector < target > targets = *(l_obj->get()); diff --git a/src/ai/lua/core.cpp b/src/ai/lua/core.cpp index 3503bcf96376..31ea207a2b6b 100644 --- a/src/ai/lua/core.cpp +++ b/src/ai/lua/core.cpp @@ -63,6 +63,34 @@ void lua_ai_context::init(lua_State *L) lua_rawset(L, LUA_REGISTRYINDEX); } +void lua_ai_context::get_arguments(config &cfg) const +{ + int top = lua_gettop(L); + + lua_pushlightuserdata(L, static_cast(const_cast(&aisKey))); + lua_rawget(L, LUA_REGISTRYINDEX); + lua_rawgeti(L, -1, num_); + + lua_getfield(L, -1, "args"); + luaW_toconfig(L, -1, cfg); + + lua_settop(L, top); +} + +void lua_ai_context::set_arguments(const config &cfg) +{ + int top = lua_gettop(L); + + lua_pushlightuserdata(L, static_cast(const_cast(&aisKey))); + lua_rawget(L, LUA_REGISTRYINDEX); + lua_rawgeti(L, -1, num_); + + luaW_pushconfig(L, cfg); + lua_setfield(L, -2, "args"); + + lua_settop(L, top); +} + void lua_ai_context::get_persistent_data(config &cfg) const { int top = lua_gettop(L); @@ -84,20 +112,13 @@ void lua_ai_context::set_persistent_data(const config &cfg) lua_pushlightuserdata(L, static_cast(const_cast(&aisKey))); lua_rawget(L, LUA_REGISTRYINDEX); lua_rawgeti(L, -1, num_); - - if(lua_isnoneornil(L, -1)) { - // Just in case the self table wasn't initialized. - lua_pop(L, 1); - lua_newtable(L); - lua_rawseti(L, -2, num_); - lua_rawgeti(L, -1, num_); - } luaW_pushconfig(L, cfg); lua_setfield(L, -2, "data"); lua_settop(L, top); } + static ai::engine_lua &get_engine(lua_State *L) { return *(static_cast( @@ -812,13 +833,18 @@ static int cfun_ai_recalculate_move_maps_enemy(lua_State *L) return 1; } -static void generate_and_push_ai_table(lua_State* L, ai::engine_lua* engine) { - //push data table here - lua_newtable(L); - lua_pushinteger(L, engine->get_readonly_context().get_side()); - lua_setfield(L, -2, "side"); //stack size is 2 [- 1: new table; -2 ai as string] +static int impl_ai_get(lua_State* L) +{ + if(!lua_isstring(L,2)) { + return 0; + } + ai::engine_lua& engine = get_engine(L); + std::string m = lua_tostring(L,2); + if(m == "side") { + lua_pushinteger(L, engine.get_readonly_context().get_side()); + return 1; + } static luaL_Reg const callbacks[] = { - { "attack", &cfun_ai_execute_attack }, // Move maps { "get_new_dst_src", &cfun_ai_get_dstsrc }, { "get_new_src_dst", &cfun_ai_get_srcdst }, @@ -859,14 +885,6 @@ static void generate_and_push_ai_table(lua_State* L, ai::engine_lua* engine) { { "is_src_dst_valid", &cfun_ai_is_src_dst_valid }, { "is_enemy_src_dst_valid", &cfun_ai_is_src_dst_enemy_valid }, // End of validation functions - { "move", &cfun_ai_execute_move_partial }, - { "move_full", &cfun_ai_execute_move_full }, - { "recall", &cfun_ai_execute_recall }, - { "recruit", &cfun_ai_execute_recruit }, - { "stopunit_all", &cfun_ai_execute_stopunit_all }, - { "stopunit_attacks", &cfun_ai_execute_stopunit_attacks }, - { "stopunit_moves", &cfun_ai_execute_stopunit_moves }, - { "synced_command", &cfun_ai_execute_synced_command }, { "suitable_keep", &cfun_ai_get_suitable_keep }, { "check_recall", &cfun_ai_check_recall }, { "check_move", &cfun_ai_check_move }, @@ -878,16 +896,73 @@ static void generate_and_push_ai_table(lua_State* L, ai::engine_lua* engine) { //{ "",}, { NULL, NULL } }; for (const luaL_Reg* p = callbacks; p->name; ++p) { - lua_pushlightuserdata(L, engine); - lua_pushcclosure(L, p->func, 1); - lua_setfield(L, -2, p->name); + if(m == p->name) { + lua_pushlightuserdata(L, &engine); // [-1: engine ...] + lua_pushcclosure(L, p->func, 1); // [-1: function ...] + // Store the function so that __index doesn't need to be called next time + lua_pushstring(L, p->name); // [-1: name -2: function ...] + lua_pushvalue(L, -2); // [-1: function -2: name -3: function ...] + lua_rawset(L, 1); // [-1: function ...] + return 1; + } + } + lua_pushstring(L, "read_only"); + lua_rawget(L, 1); + bool read_only = lua_toboolean(L, -1); + lua_pop(L, 1); + if(read_only) { + return 0; } + static luaL_Reg const mutating_callbacks[] = { + { "attack", &cfun_ai_execute_attack }, + { "move", &cfun_ai_execute_move_partial }, + { "move_full", &cfun_ai_execute_move_full }, + { "recall", &cfun_ai_execute_recall }, + { "recruit", &cfun_ai_execute_recruit }, + { "stopunit_all", &cfun_ai_execute_stopunit_all }, + { "stopunit_attacks", &cfun_ai_execute_stopunit_attacks }, + { "stopunit_moves", &cfun_ai_execute_stopunit_moves }, + { "synced_command", &cfun_ai_execute_synced_command }, + { NULL, NULL } }; + for (const luaL_Reg* p = mutating_callbacks; p->name; ++p) { + if(m == p->name) { + lua_pushlightuserdata(L, &engine); + lua_pushcclosure(L, p->func, 1); + return 1; + } + } + return 0; +} + +static void generate_and_push_ai_table(lua_State* L, ai::engine_lua* engine) { + //push data table here + lua_newtable(L); // [-1: ai table] + lua_newtable(L); // [-1: metatable -2: ai table] + lua_pushlightuserdata(L, engine); // [-1: engine -2: metatable -3: ai table] + lua_pushcclosure(L, &impl_ai_get, 1); // [-1: metafunc -2: metatable -3: ai table] + lua_setfield(L, -2, "__index"); // [-1: metatable -2: ai table] + lua_setmetatable(L, -2); // [-1: ai table] +} + +static size_t generate_and_push_ai_state(lua_State* L, ai::engine_lua* engine) +{ + // Retrieve the ai elements table from the registry. + lua_pushlightuserdata(L, static_cast(const_cast(&aisKey))); + lua_rawget(L, LUA_REGISTRYINDEX); // [-1: AIs registry table] + size_t length_ai = lua_rawlen(L, -1); // length of table + lua_newtable(L); // [-1: AI state table -2: AIs registry table] + generate_and_push_ai_table(L, engine); // [-1: AI routines -2: AI state -3: AIs registry] + lua_setfield(L, -2, "ai"); // [-1: AI state -2: AIs registry] + lua_pushvalue(L, -1); // [-1: AI state -2: AI state -3: AIs registry] + lua_rawseti(L, -3, length_ai + 1); // [-1: AI state -2: AIs registry] + lua_remove(L, -2); // [-1: AI state table] + return length_ai + 1; } lua_ai_context* lua_ai_context::create(lua_State *L, char const *code, ai::engine_lua *engine) { - int res_ai = luaL_loadstring(L, code);//stack size is now 1 [ -1: ai_context] - if (res_ai) + int res_ai = luaL_loadstring(L, code); // [-1: AI code] + if (res_ai != 0) { char const *m = lua_tostring(L, -1); @@ -896,22 +971,35 @@ lua_ai_context* lua_ai_context::create(lua_State *L, char const *code, ai::engin return NULL; } //push data table here - generate_and_push_ai_table(L, engine); + size_t idx = generate_and_push_ai_state(L, engine); // [-1: AI state -2: AI code] + lua_pushvalue(L, -2); // [-1: AI code -2: AI state -3: AI code] + lua_setfield(L, -2, "update_state"); // [-1: AI state -2: AI code] + lua_pushlightuserdata(L, engine); + lua_setfield(L, -2, "engine"); // [-1: AI state -2: AI code] + lua_pop(L, 2); + return new lua_ai_context(L, idx, engine->get_readonly_context().get_side()); +} - //compile the ai as a closure - if (!luaW_pcall(L, 1, 1, true)) { - return NULL;//return with stack size 0 [] +void lua_ai_context::update_state() +{ + lua_ai_load ctx(*this, true); // [-1: AI state table] + + // Load the AI code and arguments + lua_getfield(L, -1, "update_state"); // [-1: AI code -2: AI state] + lua_getfield(L, -2, "args"); // [-1: Arguments -2: AI code -3: AI state] + lua_getfield(L, -3, "data"); // [-1: Persistent data -2: Arguments -3: AI code -4: AI state] + + // Call the function + if (!luaW_pcall(L, 2, 1, true)) { // [-1: Result -2: AI state] + lua_pop(L, 2); // (The result in this case is an error message.) + return; // return with stack size 0 [] } - - // Retrieve the ai elements table from the registry. - lua_pushlightuserdata(L, static_cast(const_cast(&aisKey))); - lua_rawget(L, LUA_REGISTRYINDEX); //stack size is now 2 [-1: ais_table -2: f] - // Push the function in the table so that it is not collected. - size_t length_ai = lua_rawlen(L, -1);//length of ais_table - lua_pushvalue(L, -2); //stack size is now 3: [-1: ai_context -2: ais_table -3: ai_context] - 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_pop(L, 2); - return new lua_ai_context(L, length_ai + 1, engine->get_readonly_context().get_side()); + + // Store the state for use by components + lua_setfield(L, -2, "state"); // [-1: AI state] + + // And return with empty stack. + lua_pop(L, 1); } lua_ai_action_handler* lua_ai_action_handler::create(lua_State *L, char const *code, lua_ai_context &context) @@ -925,7 +1013,6 @@ lua_ai_action_handler* lua_ai_action_handler::create(lua_State *L, char const *c return NULL; } - // Retrieve the ai elements table from the registry. lua_pushlightuserdata(L, static_cast(const_cast(&aisKey))); lua_rawget(L, LUA_REGISTRYINDEX); //stack size is now 2 [-1: ais_table -2: f] @@ -940,19 +1027,26 @@ lua_ai_action_handler* lua_ai_action_handler::create(lua_State *L, char const *c } -void lua_ai_context::load() +lua_ai_load::lua_ai_load(lua_ai_context& ctx, bool read_only) : L(ctx.L) { - lua_pushlightuserdata(L, static_cast(const_cast(&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_context -2: ais_table] - lua_remove(L,-2); + lua_pushlightuserdata(L, static_cast(const_cast(&aisKey))); // [-1: key] + lua_rawget(L, LUA_REGISTRYINDEX); // [-1: AI registry] + lua_rawgeti(L, -1, ctx.num_); // [-1: AI state -2: AI registry] + lua_remove(L,-2); // [-1: AI state] + + // Load the AI functions table into global scope + lua_getfield(L, -1, "ai"); // [-1: AI functions -2: AI state] + lua_pushstring(L, "read_only"); // [-1: key -2: AI functions -3: AI state] + lua_pushboolean(L, read_only); // [-1: value -2: key -3: AI functions -4: AI state] + lua_rawset(L, -3); // [-1: AI functions -2: AI state] + lua_setglobal(L, "ai"); // [-1: AI state] } -void lua_ai_context::load_and_inject_ai_table(ai::engine_lua* engine) +lua_ai_load::~lua_ai_load() { - load(); //stack size is 1 [-1: ai_context] - generate_and_push_ai_table(L, engine); //stack size is 2 [-1: ai_table -2: ai_context] - lua_setfield(L, -2, "ai"); //stack size is 1 [-1: ai_context] + // Remove the AI functions from the global scope + lua_pushnil(L); + lua_setglobal(L, "ai"); } lua_ai_context::~lua_ai_context() @@ -965,26 +1059,28 @@ lua_ai_context::~lua_ai_context() lua_pop(L, 1); } -void lua_ai_action_handler::handle(config &cfg, bool configOut, lua_object_ptr l_obj) +void lua_ai_action_handler::handle(const config &cfg, bool read_only, lua_object_ptr l_obj) { int initial_top = lua_gettop(L);//get the old stack size + + // Load the context + lua_ai_load ctx(context_, read_only); // [-1: AI state table] // Load the user function from the registry. - lua_pushlightuserdata(L, static_cast(const_cast(&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] - //load the lua ai context as a parameter - context_.load();//stack size is 2 [-1: ai_context -2: ai_action] - - if (!configOut) - { - luaW_pushconfig(L, cfg); - luaW_pcall(L, 2, 0, true); - } - else if (luaW_pcall(L, 1, 5, true)) // @note for Crab: how much nrets should we actually have here - { // there were 2 initially, but aspects like recruitment pattern - l_obj->store(L, initial_top + 1); // return a lot of results + lua_pushlightuserdata(L, static_cast(const_cast(&aisKey))); // [-1: key -2: AI state] + lua_rawget(L, LUA_REGISTRYINDEX); // [-1: AI registry -2: AI state] + lua_rawgeti(L, -1, num_); // [-1: AI action -2: AI registry -3: AI state] + lua_remove(L, -2); // [-1: AI action -2: AI state] + + // Load the arguments + luaW_pushconfig(L, cfg); // [-1: parameters -2: AI action -3: AI state] + lua_getfield(L, -3, "data"); // [-1: data -2: parameters -3: action -4: state] + lua_getfield(L, -4, "state"); + + // Call the function + luaW_pcall(L, 3, l_obj ? 1 : 0, true); + if (l_obj) { + l_obj->store(L, initial_top + 1); } lua_settop(L, initial_top);//empty stack diff --git a/src/ai/lua/core.hpp b/src/ai/lua/core.hpp index 3d4bb2dd007e..7f4505d2e1b1 100644 --- a/src/ai/lua/core.hpp +++ b/src/ai/lua/core.hpp @@ -44,20 +44,23 @@ class lua_ai_context static lua_ai_context* create(lua_State *L, char const *code, engine_lua *engine); public: ~lua_ai_context(); - lua_ai_context() - : L(NULL) - , num_(0) - , side_(0) - { - } - void load(); - void load_and_inject_ai_table(engine_lua* engine); + void update_state(); void get_persistent_data(config &) const; void set_persistent_data(const config &); + void get_arguments(config &) const; + void set_arguments(const config &); static void init(lua_State *L); friend class ::game_lua_kernel; + friend class lua_ai_load; }; +class lua_ai_load +{ + lua_State* L; +public: + lua_ai_load(lua_ai_context& ctx, bool read_only); + ~lua_ai_load(); +}; /** * Proxy class for calling AI action handlers defined in Lua. @@ -74,7 +77,7 @@ class lua_ai_action_handler static lua_ai_action_handler* create(lua_State *L, char const *code, lua_ai_context &context); public: ~lua_ai_action_handler(); - void handle(config &, bool configOut, lua_object_ptr); + void handle(const config &cfg, bool read_only, lua_object_ptr l_obj); friend class ::game_lua_kernel; }; diff --git a/src/ai/lua/lua_object.hpp b/src/ai/lua/lua_object.hpp index c32b894561eb..cfddf4b5a89c 100644 --- a/src/ai/lua/lua_object.hpp +++ b/src/ai/lua/lua_object.hpp @@ -135,11 +135,10 @@ inline boost::shared_ptr lua_object::to_type(lua_State *L, int n template <> inline boost::shared_ptr lua_object::to_type(lua_State *L, int n) { - // To Crab_: Is this part ok? I tested it, works fine boost::shared_ptr cfg = boost::shared_ptr(new config()); boost::shared_ptr vcfg = boost::shared_ptr(new vconfig(*cfg)); luaW_tovconfig(L, n, *vcfg); - boost::shared_ptr tf = boost::shared_ptr(new terrain_filter(*vcfg, resources::filter_con)); + boost::shared_ptr tf(new terrain_filter(*vcfg, resources::filter_con)); return tf; }