AI/lua: Command 'lua wesnoth.debug_ai(2).ai' gives now access to ai-table
This commit is contained in:
parent
5301eedbe6
commit
f9a231f09d
6 changed files with 105 additions and 74 deletions
|
@ -1,6 +1,8 @@
|
|||
Version 1.11.4+dev:
|
||||
* AI:
|
||||
* Recruiting in Micro and Experimental AIs: allow more terrain codes for castles/keeps
|
||||
* Improved/Added: Command 'lua wesnoth.debug_ai([side]).ai' will now give access to the
|
||||
ai-table of [side].
|
||||
* Campaigns:
|
||||
* Legend of Wesmere:
|
||||
* Scenario 05: Elvish Horse Archers can now carry the treasure
|
||||
|
|
|
@ -234,7 +234,7 @@ private:
|
|||
*/
|
||||
engine_lua::engine_lua( readonly_context &context, const config &cfg )
|
||||
: engine(context,cfg)
|
||||
, code_(cfg["code"])
|
||||
, code_(get_engine_code(cfg))
|
||||
, lua_ai_context_(resources::lua_kernel->create_lua_ai_context(
|
||||
get_engine_code(cfg).c_str(), this))
|
||||
{
|
||||
|
@ -269,7 +269,7 @@ void engine_lua::push_ai_table()
|
|||
{
|
||||
if (game_config::debug)
|
||||
{
|
||||
lua_ai_context_->load();
|
||||
lua_ai_context_->load_and_inject_ai_table(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -815,6 +815,76 @@ 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 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 },
|
||||
{ "get_new_enemy_dst_src", &cfun_ai_get_enemy_dstsrc },
|
||||
{ "get_new_enemy_src_dst", &cfun_ai_get_enemy_srcdst },
|
||||
{ "recalculate_move_maps", &cfun_ai_recalculate_move_maps },
|
||||
{ "recalculate_enemy_move_maps", &cfun_ai_recalculate_move_maps_enemy },
|
||||
// End of move maps
|
||||
// Goals and targets
|
||||
{ "get_targets", &cfun_ai_get_targets },
|
||||
// End of G & T
|
||||
// Aspects
|
||||
{ "get_aggression", &cfun_ai_get_aggression },
|
||||
{ "get_avoid", &cfun_ai_get_avoid },
|
||||
{ "get_attack_depth", &cfun_ai_get_attack_depth },
|
||||
{ "get_attacks", &cfun_ai_get_attacks },
|
||||
{ "get_caution", &cfun_ai_get_caution },
|
||||
{ "get_grouping", &cfun_ai_get_grouping },
|
||||
{ "get_leader_aggression", &cfun_ai_get_leader_aggression },
|
||||
{ "get_leader_goal", &cfun_ai_get_leader_goal },
|
||||
{ "get_leader_ignores_keep", &cfun_ai_get_leader_ignores_keep },
|
||||
{ "get_leader_value", &cfun_ai_get_leader_value },
|
||||
{ "get_number_of_possible_recruits_to_force_recruit", &cfun_ai_get_number_of_possible_recruits_to_force_recruit },
|
||||
{ "get_passive_leader", &cfun_ai_get_passive_leader },
|
||||
{ "get_passive_leader_shares_keep", &cfun_ai_get_passive_leader_shares_keep },
|
||||
{ "get_recruitment_ignore_bad_combat", &cfun_ai_get_recruitment_ignore_bad_combat },
|
||||
{ "get_recruitment_ignore_bad_movement", &cfun_ai_get_recruitment_ignore_bad_movement },
|
||||
{ "get_recruitment_pattern", &cfun_ai_get_recruitment_pattern },
|
||||
{ "get_scout_village_targeting", &cfun_ai_get_scout_village_targeting },
|
||||
{ "get_simple_targeting", &cfun_ai_get_simple_targeting },
|
||||
{ "get_support_villages", &cfun_ai_get_support_villages },
|
||||
{ "get_village_value", &cfun_ai_get_village_value },
|
||||
{ "get_villages_per_scout", &cfun_ai_get_villages_per_scout },
|
||||
// End of aspects
|
||||
// Validation/cache functions
|
||||
{ "is_dst_src_valid", &cfun_ai_is_dst_src_valid },
|
||||
{ "is_enemy_dst_src_valid", &cfun_ai_is_dst_src_enemy_valid },
|
||||
{ "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 },
|
||||
{ "suitable_keep", &cfun_ai_get_suitable_keep },
|
||||
{ "check_recall", &cfun_ai_check_recall },
|
||||
{ "check_move", &cfun_ai_check_move },
|
||||
{ "check_stopunit", &cfun_ai_check_stopunit },
|
||||
{ "check_attack", &cfun_ai_check_attack },
|
||||
{ "check_recruit", &cfun_ai_check_recruit },
|
||||
//{ "",},
|
||||
//{ "",},
|
||||
{ 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);
|
||||
}
|
||||
}
|
||||
|
||||
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]
|
||||
|
@ -827,76 +897,7 @@ lua_ai_context* lua_ai_context::create(lua_State *L, char const *code, ai::engin
|
|||
return NULL;
|
||||
}
|
||||
//push data table here
|
||||
lua_newtable(L);// stack size is 2 [ -1: new table, -2: ai as string ]
|
||||
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 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 },
|
||||
{ "get_new_enemy_dst_src", &cfun_ai_get_enemy_dstsrc },
|
||||
{ "get_new_enemy_src_dst", &cfun_ai_get_enemy_srcdst },
|
||||
{ "recalculate_move_maps", &cfun_ai_recalculate_move_maps },
|
||||
{ "recalculate_enemy_move_maps",&cfun_ai_recalculate_move_maps_enemy },
|
||||
// End of move maps
|
||||
// Goals and targets
|
||||
{ "get_targets", &cfun_ai_get_targets },
|
||||
// End of G & T
|
||||
// Aspects
|
||||
{ "get_aggression", &cfun_ai_get_aggression },
|
||||
{ "get_avoid", &cfun_ai_get_avoid },
|
||||
{ "get_attack_depth", &cfun_ai_get_attack_depth },
|
||||
{ "get_attacks", &cfun_ai_get_attacks },
|
||||
{ "get_caution", &cfun_ai_get_caution },
|
||||
{ "get_grouping", &cfun_ai_get_grouping },
|
||||
{ "get_leader_aggression", &cfun_ai_get_leader_aggression },
|
||||
{ "get_leader_goal", &cfun_ai_get_leader_goal },
|
||||
{ "get_leader_ignores_keep", &cfun_ai_get_leader_ignores_keep},
|
||||
{ "get_leader_value", &cfun_ai_get_leader_value },
|
||||
{ "get_number_of_possible_recruits_to_force_recruit", &cfun_ai_get_number_of_possible_recruits_to_force_recruit},
|
||||
{ "get_passive_leader", &cfun_ai_get_passive_leader },
|
||||
{ "get_passive_leader_shares_keep", &cfun_ai_get_passive_leader_shares_keep},
|
||||
{ "get_recruitment_ignore_bad_combat", &cfun_ai_get_recruitment_ignore_bad_combat},
|
||||
{ "get_recruitment_ignore_bad_movement", &cfun_ai_get_recruitment_ignore_bad_movement},
|
||||
{ "get_recruitment_pattern", &cfun_ai_get_recruitment_pattern },
|
||||
{ "get_scout_village_targeting", &cfun_ai_get_scout_village_targeting },
|
||||
{ "get_simple_targeting", &cfun_ai_get_simple_targeting },
|
||||
{ "get_support_villages", &cfun_ai_get_support_villages },
|
||||
{ "get_village_value", &cfun_ai_get_village_value },
|
||||
{ "get_villages_per_scout", &cfun_ai_get_villages_per_scout },
|
||||
// End of aspects
|
||||
// Validation/cache functions
|
||||
{ "is_dst_src_valid", &cfun_ai_is_dst_src_valid },
|
||||
{ "is_enemy_dst_src_valid", &cfun_ai_is_dst_src_enemy_valid },
|
||||
{ "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 },
|
||||
{ "suitable_keep", &cfun_ai_get_suitable_keep },
|
||||
{ "check_recall", &cfun_ai_check_recall },
|
||||
{ "check_move", &cfun_ai_check_move },
|
||||
{ "check_stopunit", &cfun_ai_check_stopunit },
|
||||
{ "check_attack", &cfun_ai_check_attack },
|
||||
{ "check_recruit", &cfun_ai_check_recruit },
|
||||
//{ "",},
|
||||
//{ "",},
|
||||
{ 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);
|
||||
}
|
||||
generate_and_push_ai_table(L, engine);
|
||||
|
||||
//compile the ai as a closure
|
||||
if (!luaW_pcall(L, 1, 1, true)) {
|
||||
|
@ -948,6 +949,13 @@ void lua_ai_context::load()
|
|||
lua_remove(L,-2);
|
||||
}
|
||||
|
||||
void lua_ai_context::load_and_inject_ai_table(ai::engine_lua* engine)
|
||||
{
|
||||
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]
|
||||
}
|
||||
|
||||
lua_ai_context::~lua_ai_context()
|
||||
{
|
||||
// Remove the ai context from the registry, so that it can be collected.
|
||||
|
|
|
@ -51,6 +51,7 @@ public:
|
|||
{
|
||||
}
|
||||
void load();
|
||||
void load_and_inject_ai_table(engine_lua* engine);
|
||||
void get_persistent_data(config &) const;
|
||||
void set_persistent_data(const config &);
|
||||
static void init(lua_State *L);
|
||||
|
|
|
@ -286,6 +286,11 @@ component* holder::get_component(component *root, const std::string &path) {
|
|||
|
||||
if (root == NULL) // Return root component(ai_)
|
||||
{
|
||||
if (!this->ai_) {
|
||||
this->init(this->side_);
|
||||
}
|
||||
assert(this->ai_);
|
||||
|
||||
return &*this->ai_;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,9 @@
|
|||
#include "ai/lua/core.hpp"
|
||||
#include "version.hpp"
|
||||
#include "gui/widgets/clickable.hpp"
|
||||
#include "ai/contexts.hpp"
|
||||
#include "ai/configuration.hpp"
|
||||
#include "ai/composite/ai.hpp"
|
||||
#ifdef GUI2_EXPERIMENTAL_LISTBOX
|
||||
#include "gui/widgets/list.hpp"
|
||||
#else
|
||||
|
@ -3608,8 +3611,20 @@ static int intf_debug_ai(lua_State *L)
|
|||
|
||||
if (lua_engine == NULL)
|
||||
{
|
||||
lua_createtable(L, 0, 0);
|
||||
return 1;
|
||||
//no lua engine is defined for this side.
|
||||
//so set up a dummy engine
|
||||
|
||||
ai::ai_composite * ai_ptr = dynamic_cast<ai::ai_composite *>(c);
|
||||
ai::ai_context& ai_context = ai_ptr->get_ai_context();
|
||||
config cfg = ai::configuration::get_default_ai_parameters();
|
||||
|
||||
lua_engine = new ai::engine_lua(ai_context, cfg);
|
||||
LOG_LUA << "Created new dummy lua-engine for debug_ai(). \n";
|
||||
|
||||
//and add the dummy engine as a component
|
||||
//to the manager, so we could use it later
|
||||
cfg.add_child("engine", lua_engine->to_config());
|
||||
ai::component_manager::add_component(c, "engine[]", cfg);
|
||||
}
|
||||
|
||||
lua_engine->push_ai_table(); // stack: [-1: ai_context]
|
||||
|
|
Loading…
Add table
Reference in a new issue