mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-18 17:03:25 +00:00
Add ai.aspects table which provides access to all aspects
The advantage of this over the get_* functions is that it will automatically update whenever new aspects are added. It doesn't support the deprecated recruitement aspect.
This commit is contained in:
parent
f8f5557eb0
commit
6972d5170f
@ -22,6 +22,7 @@
|
||||
#include <cstring>
|
||||
|
||||
#include "core.hpp"
|
||||
#include "ai/composite/aspect.hpp"
|
||||
#include "scripting/game_lua_kernel.hpp"
|
||||
#include "scripting/lua_api.hpp"
|
||||
#include "scripting/push_check.hpp"
|
||||
@ -130,6 +131,16 @@ static ai::readonly_context &get_readonly_context(lua_State *L)
|
||||
return get_engine(L).get_readonly_context();
|
||||
}
|
||||
|
||||
static void push_location_key(lua_State* L, const map_location& loc)
|
||||
{
|
||||
// This should be factored out. The same function is defined in data/lua/location_set.lua
|
||||
// At this point, it is not clear, where this(hashing) function can be placed
|
||||
// Implemented it this way, to test the new version of the data structure
|
||||
// as requested from the users of LuaAI <Nephro>
|
||||
int hashed_index = (loc.x + 1) * 16384 + (loc.y + 1) + 2000;
|
||||
lua_pushinteger(L, hashed_index);
|
||||
}
|
||||
|
||||
static int transform_ai_action(lua_State *L, ai::action_result_ptr action_result)
|
||||
{
|
||||
lua_newtable(L);
|
||||
@ -732,15 +743,7 @@ static void push_move_map(lua_State *L, const move_map& m)
|
||||
do
|
||||
{
|
||||
map_location key = it->first;
|
||||
|
||||
//push_map_location(L, key); // deprecated
|
||||
|
||||
// This should be factored out. The same function is defined in data/lua/location_set.lua
|
||||
// At this point, it is not clear, where this(hashing) function can be placed
|
||||
// Implemented it this way, to test the new version of the data structure
|
||||
// as requested from the users of LuaAI <Nephro>
|
||||
int hashed_index = (key.x + 1) * 16384 + (key.y + 1) + 2000;
|
||||
lua_pushinteger(L, hashed_index);
|
||||
push_location_key(L, key);
|
||||
|
||||
lua_createtable(L, 0, 0);
|
||||
|
||||
@ -833,6 +836,70 @@ static int cfun_ai_recalculate_move_maps_enemy(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
typesafe_aspect<T>* try_aspect_as(aspect_ptr p)
|
||||
{
|
||||
return boost::dynamic_pointer_cast<typesafe_aspect<T> >(p).get();
|
||||
}
|
||||
|
||||
static int impl_ai_aspect_get(lua_State* L)
|
||||
{
|
||||
const aspect_map& aspects = get_engine(L).get_readonly_context().get_aspects();
|
||||
aspect_map::const_iterator iter = aspects.find(luaL_checkstring(L, 2));
|
||||
if(iter == aspects.end()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// For attacks, just fall back to existing function
|
||||
if(iter->first == "attacks") {
|
||||
lua_pushlightuserdata(L, &get_engine(L));
|
||||
lua_pushcclosure(L, &cfun_ai_get_attacks, 1);
|
||||
lua_call(L, 0, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef std::vector<std::string> string_list;
|
||||
if(typesafe_aspect<bool>* aspect = try_aspect_as<bool>(iter->second)) {
|
||||
lua_pushboolean(L, aspect->get());
|
||||
} else if(typesafe_aspect<int>* aspect = try_aspect_as<int>(iter->second)) {
|
||||
lua_pushinteger(L, aspect->get());
|
||||
} else if(typesafe_aspect<double>* aspect = try_aspect_as<double>(iter->second)) {
|
||||
lua_pushnumber(L, aspect->get());
|
||||
} else if(typesafe_aspect<config>* aspect = try_aspect_as<config>(iter->second)) {
|
||||
luaW_pushconfig(L, aspect->get());
|
||||
} else if(typesafe_aspect<string_list>* aspect = try_aspect_as<string_list>(iter->second)) {
|
||||
lua_push(L, aspect->get());
|
||||
} else if(typesafe_aspect<terrain_filter>* aspect = try_aspect_as<terrain_filter>(iter->second)) {
|
||||
std::set<map_location> result;
|
||||
aspect->get().get_locations(result);
|
||||
lua_push(L, result);
|
||||
} else if(typesafe_aspect<attacks_vector>* aspect = try_aspect_as<attacks_vector>(iter->second)) {
|
||||
// This case is caught separately above, but should the get_* aspect functions ever be
|
||||
// deprecated, this is the place to move the code of cfun_ai_get_attacks to.
|
||||
(void) aspect;
|
||||
} else if(typesafe_aspect<unit_advancements_aspect>* aspect = try_aspect_as<unit_advancements_aspect>(iter->second)) {
|
||||
const unit_advancements_aspect& val = aspect->get();
|
||||
int my_side = luaW_getglobal(L, "ai", "side", NULL) - 1;
|
||||
lua_newtable(L);
|
||||
for (unit_map::const_iterator u = resources::units->begin(); u != resources::units->end(); ++u) {
|
||||
if (!u.valid() || u->side() != my_side) {
|
||||
continue;
|
||||
}
|
||||
push_location_key(L, u->get_location());
|
||||
lua_push(L, val.get_advancements(u));
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int impl_ai_aspect_set(lua_State*)
|
||||
{
|
||||
return 0; // The aspects table is read-only
|
||||
}
|
||||
|
||||
static int impl_ai_get(lua_State* L)
|
||||
{
|
||||
if(!lua_isstring(L,2)) {
|
||||
@ -844,6 +911,17 @@ static int impl_ai_get(lua_State* L)
|
||||
lua_pushinteger(L, engine.get_readonly_context().get_side());
|
||||
return 1;
|
||||
}
|
||||
if(m == "aspects") {
|
||||
lua_newtable(L); // [-1: Aspects table]
|
||||
lua_newtable(L); // [-1: Aspects metatable -2: Aspects table]
|
||||
lua_pushlightuserdata(L, &engine); // [-1: Engine -2: Aspects mt -3: Aspects table]
|
||||
lua_pushcclosure(L, &impl_ai_aspect_get, 1); // [-1: Metafunction -2: Aspects mt -3: Aspects table]
|
||||
lua_setfield(L, -2, "__index"); // [-1: Aspects metatable -2: Aspects table]
|
||||
lua_pushcfunction(L, &impl_ai_aspect_set); // [-1: Metafunction -2: Aspects mt -3: Aspects table]
|
||||
lua_setfield(L, -2, "__newindex"); // [-1: Aspects metatable -2: Aspects table]
|
||||
lua_setmetatable(L, -2); // [-1: Aspects table]
|
||||
return 1;
|
||||
}
|
||||
static luaL_Reg const callbacks[] = {
|
||||
// Move maps
|
||||
{ "get_new_dst_src", &cfun_ai_get_dstsrc },
|
||||
|
Loading…
x
Reference in New Issue
Block a user