AI: convert leader related aspects to variants

This commit is contained in:
mattsc 2019-12-26 08:10:01 -08:00
parent ec7acef7e0
commit 34e3c9103f
9 changed files with 190 additions and 58 deletions

View file

@ -1063,11 +1063,9 @@ end
--------- Unit related helper functions ----------
function ai_helper.is_passive_leader(aspect_value, id)
if (aspect_value == 'yes') then return true end
if (aspect_value == 'no') then return false end
if (type(aspect_value) == 'boolean') then return aspect_value end
local aspect_ids = ai_helper.split(aspect_value)
for _,aspect_id in ipairs(aspect_ids) do
for _,aspect_id in ipairs(aspect_value) do
if (aspect_id == id) then
return true
end

View file

@ -112,7 +112,42 @@ public:
value_to_cfg(value,cfg);
return cfg;
}
};
class leader_aspects_visitor : public boost::static_visitor<std::string> {
public:
std::string operator()(const bool b) const { return utils::bool_string(b); }
std::string operator()(const std::vector<std::string> s) const { return utils::join(s); }
};
template<>
class config_value_translator< boost::variant<bool, std::vector<std::string>> > {
public:
static boost::variant<bool, std::vector<std::string>> cfg_to_value(const config &cfg)
{
if (cfg["value"].to_bool(true) == cfg["value"].to_bool(false)) {
return cfg["value"].to_bool();
}
return utils::split(cfg["value"]);
}
static void cfg_to_value(const config &cfg, boost::variant<bool, std::vector<std::string>> &value)
{
value = cfg_to_value(cfg);
}
static void value_to_cfg(const boost::variant<bool, std::vector<std::string>> &value, config &cfg)
{
cfg["value"] = boost::apply_visitor(leader_aspects_visitor(), value);
}
static config value_to_cfg(const boost::variant<bool, std::vector<std::string>> &value)
{
config cfg;
value_to_cfg(value,cfg);
return cfg;
}
};
template<>

View file

@ -712,12 +712,12 @@ config readonly_context_impl::get_leader_goal() const
}
std::string readonly_context_impl::get_leader_ignores_keep() const
boost::variant<bool, std::vector<std::string>> readonly_context_impl::get_leader_ignores_keep() const
{
if (leader_ignores_keep_) {
return leader_ignores_keep_->get();
}
return std::string();
return boost::variant<bool, std::vector<std::string>>();
}
@ -730,21 +730,21 @@ double readonly_context_impl::get_leader_value() const
}
std::string readonly_context_impl::get_passive_leader() const
boost::variant<bool, std::vector<std::string>> readonly_context_impl::get_passive_leader() const
{
if (passive_leader_) {
return passive_leader_->get();
}
return std::string();
return boost::variant<bool, std::vector<std::string>>();
}
std::string readonly_context_impl::get_passive_leader_shares_keep() const
boost::variant<bool, std::vector<std::string>> readonly_context_impl::get_passive_leader_shares_keep() const
{
if (passive_leader_shares_keep_) {
return passive_leader_shares_keep_->get();
}
return std::string();
return boost::variant<bool, std::vector<std::string>>();
}
@ -1277,18 +1277,16 @@ bool readonly_context_impl::is_active(const std::string &time_of_day, const std:
return true;
}
bool readonly_context_impl::applies_to_leader(const std::string &aspect_value, const std::string &id) const
bool readonly_context_impl::applies_to_leader(const boost::variant<bool, std::vector<std::string>> &aspect_value, const std::string &id) const
{
if(aspect_value == "yes") {
return true;
}
if(aspect_value == "no") {
return false;
}
std::vector<std::string> aspect_ids = utils::split(aspect_value);
for(std::vector<std::string>::const_iterator aspect_id = aspect_ids.begin(); aspect_id != aspect_ids.end() ; ++aspect_id ) {
if(*aspect_id == id) {
return true;
if (aspect_value.which() == 0) {
return boost::get<bool>(aspect_value);
} else {
std::vector<std::string> aspect_ids = boost::get<std::vector<std::string>>(aspect_value);
for(std::vector<std::string>::const_iterator aspect_id = aspect_ids.begin(); aspect_id != aspect_ids.end() ; ++aspect_id ) {
if(*aspect_id == id) {
return true;
}
}
}
return false;

View file

@ -276,16 +276,16 @@ public:
virtual config get_leader_goal() const = 0;
virtual std::string get_leader_ignores_keep() const = 0;
virtual boost::variant<bool, std::vector<std::string>> get_leader_ignores_keep() const = 0;
virtual double get_leader_value() const = 0;
virtual std::string get_passive_leader() const = 0;
virtual boost::variant<bool, std::vector<std::string>> get_passive_leader() const = 0;
virtual std::string get_passive_leader_shares_keep() const = 0;
virtual boost::variant<bool, std::vector<std::string>> get_passive_leader_shares_keep() const = 0;
virtual const moves_map& get_possible_moves() const = 0;
@ -758,7 +758,7 @@ public:
}
virtual std::string get_leader_ignores_keep() const override
virtual boost::variant<bool, std::vector<std::string>> get_leader_ignores_keep() const override
{
return target_->get_leader_ignores_keep();
}
@ -770,13 +770,13 @@ public:
}
virtual std::string get_passive_leader() const override
virtual boost::variant<bool, std::vector<std::string>> get_passive_leader() const override
{
return target_->get_passive_leader();
}
virtual std::string get_passive_leader_shares_keep() const override
virtual boost::variant<bool, std::vector<std::string>> get_passive_leader_shares_keep() const override
{
return target_->get_passive_leader_shares_keep();
}
@ -1372,16 +1372,16 @@ public:
virtual config get_leader_goal() const override;
virtual std::string get_leader_ignores_keep() const override;
virtual boost::variant<bool, std::vector<std::string>> get_leader_ignores_keep() const override;
virtual double get_leader_value() const override;
virtual std::string get_passive_leader() const override;
virtual boost::variant<bool, std::vector<std::string>> get_passive_leader() const override;
virtual std::string get_passive_leader_shares_keep() const override;
virtual boost::variant<bool, std::vector<std::string>> get_passive_leader_shares_keep() const override;
virtual const moves_map& get_possible_moves() const override;
@ -1494,7 +1494,7 @@ private:
template<typename T>
void add_known_aspect(const std::string &name, typesafe_aspect_ptr<T>& where);
bool applies_to_leader(const std::string &aspect_value, const std::string &id) const;
bool applies_to_leader(const boost::variant<bool, std::vector<std::string>> &aspect_value, const std::string &id) const;
const config cfg_;
@ -1521,7 +1521,7 @@ private:
mutable keeps_cache keeps_;
typesafe_aspect_ptr<double> leader_aggression_;
typesafe_aspect_ptr<config> leader_goal_;
typesafe_aspect_ptr<std::string> leader_ignores_keep_;
typesafe_aspect_ptr<boost::variant<bool, std::vector<std::string>>> leader_ignores_keep_;
typesafe_aspect_ptr<double> leader_value_;
mutable bool move_maps_enemy_valid_;
mutable bool move_maps_valid_;
@ -1529,8 +1529,8 @@ private:
mutable bool dst_src_enemy_valid_lua_;
mutable bool src_dst_valid_lua_;
mutable bool src_dst_enemy_valid_lua_;
typesafe_aspect_ptr<std::string> passive_leader_;
typesafe_aspect_ptr<std::string> passive_leader_shares_keep_;
typesafe_aspect_ptr<boost::variant<bool, std::vector<std::string>>> passive_leader_;
typesafe_aspect_ptr<boost::variant<bool, std::vector<std::string>>> passive_leader_shares_keep_;
mutable moves_map possible_moves_;
typesafe_aspect_ptr<double> recruitment_diversity_;
typesafe_aspect_ptr<config> recruitment_instructions_;

View file

@ -312,7 +312,17 @@ variant formula_ai::get_value(const std::string& key) const
} else if(key == "leader_ignores_keep")
{
return variant(get_leader_ignores_keep());
boost::variant<bool, std::vector<std::string>> leader_ignores_keep = get_leader_ignores_keep();
if (leader_ignores_keep.which() == 0) {
return variant(boost::get<bool>(leader_ignores_keep));
} else {
std::vector<std::string> &strlist = boost::get<std::vector<std::string>>(leader_ignores_keep);
std::vector<variant> vars;
for(const std::string &i : strlist) {
vars.emplace_back(i);
}
return variant(vars);
}
} else if(key == "leader_value")
{
@ -320,11 +330,31 @@ variant formula_ai::get_value(const std::string& key) const
} else if(key == "passive_leader")
{
return variant(get_passive_leader());
boost::variant<bool, std::vector<std::string>> passive_leader = get_passive_leader();
if (passive_leader.which() == 0) {
return variant(boost::get<bool>(passive_leader));
} else {
std::vector<std::string> &strlist = boost::get<std::vector<std::string>>(passive_leader);
std::vector<variant> vars;
for(const std::string &i : strlist) {
vars.emplace_back(i);
}
return variant(vars);
}
} else if(key == "passive_leader_shares_keep")
{
return variant(get_passive_leader_shares_keep());
boost::variant<bool, std::vector<std::string>> passive_leader_shares_keep = get_passive_leader_shares_keep();
if (passive_leader_shares_keep.which() == 0) {
return variant(boost::get<bool>(passive_leader_shares_keep));
} else {
std::vector<std::string> &strlist = boost::get<std::vector<std::string>>(passive_leader_shares_keep);
std::vector<variant> vars;
for(const std::string &i : strlist) {
vars.emplace_back(i);
}
return variant(vars);
}
} else if(key == "recruitment_pattern")
{

View file

@ -438,8 +438,17 @@ static int cfun_ai_get_leader_goal(lua_State *L)
static int cfun_ai_get_leader_ignores_keep(lua_State *L)
{
DEPRECATED_ASPECT_MESSAGE("leader_ignores_keep");
std::string leader_ignores_keep = get_readonly_context(L).get_leader_ignores_keep();
lua_pushstring(L, leader_ignores_keep.c_str());
boost::variant<bool, std::vector<std::string>> leader_ignores_keep = get_readonly_context(L).get_leader_ignores_keep();
if (leader_ignores_keep.which() == 0) {
lua_pushboolean(L, boost::get<bool>(leader_ignores_keep));
} else {
std::vector<std::string> strlist = boost::get<std::vector<std::string>>(leader_ignores_keep);
lua_createtable(L, strlist.size(), 0);
for(const std::string& str : strlist) {
lua_pushlstring(L, str.c_str(), str.size());
lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
}
}
return 1;
}
@ -454,16 +463,34 @@ static int cfun_ai_get_leader_value(lua_State *L)
static int cfun_ai_get_passive_leader(lua_State *L)
{
DEPRECATED_ASPECT_MESSAGE("passive_leader");
std::string passive_leader = get_readonly_context(L).get_passive_leader();
lua_pushstring(L, passive_leader.c_str());
boost::variant<bool, std::vector<std::string>> passive_leader = get_readonly_context(L).get_passive_leader();
if (passive_leader.which() == 0) {
lua_pushboolean(L, boost::get<bool>(passive_leader));
} else {
std::vector<std::string> strlist = boost::get<std::vector<std::string>>(passive_leader);
lua_createtable(L, strlist.size(), 0);
for(const std::string& str : strlist) {
lua_pushlstring(L, str.c_str(), str.size());
lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
}
}
return 1;
}
static int cfun_ai_get_passive_leader_shares_keep(lua_State *L)
{
DEPRECATED_ASPECT_MESSAGE("passive_leader_shares_keep");
std::string passive_leader_shares_keep = get_readonly_context(L).get_passive_leader_shares_keep();
lua_pushstring(L, passive_leader_shares_keep.c_str());
boost::variant<bool, std::vector<std::string>> passive_leader_shares_keep = get_readonly_context(L).get_passive_leader_shares_keep();
if (passive_leader_shares_keep.which() == 0) {
lua_pushboolean(L, boost::get<bool>(passive_leader_shares_keep));
} else {
std::vector<std::string> strlist = boost::get<std::vector<std::string>>(passive_leader_shares_keep);
lua_createtable(L, strlist.size(), 0);
for(const std::string& str : strlist) {
lua_pushlstring(L, str.c_str(), str.size());
lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
}
}
return 1;
}

View file

@ -31,6 +31,7 @@
#include "ai/default/contexts.hpp"
#include "ai/lua/aspect_advancements.hpp"
#include <boost/variant/get.hpp>
#include <iterator>
#include <string>
#include <vector>
@ -118,6 +119,44 @@ inline std::shared_ptr<std::string> lua_object<std::string>::to_type(lua_State *
return std::make_shared<std::string>(lua_tostring(L, n));
}
template <>
inline void lua_object<boost::variant<bool, std::vector<std::string>>>::from_type(lua_State *L, std::shared_ptr<boost::variant<bool, std::vector<std::string>>> value)
{
if(value) {
if (value->which() == 0) {
lua_pushboolean(L, boost::get<bool>(*value));
} else {
std::vector<std::string> strlist = boost::get<std::vector<std::string>>(*value);
lua_createtable(L, strlist.size(), 0);
for(const std::string& str : strlist) {
lua_pushlstring(L, str.c_str(), str.size());
lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
}
}
} else lua_pushnil(L);
}
template <>
inline std::shared_ptr< boost::variant<bool, std::vector<std::string>> > lua_object< boost::variant<bool, std::vector<std::string>> >::to_type(lua_State *L, int n)
{
if (lua_isboolean(L, n)) {
return std::make_shared<boost::variant<bool, std::vector<std::string>>>(luaW_toboolean(L, n));
} else {
std::shared_ptr<std::vector<std::string>> v(new std::vector<std::string>());
int l = lua_rawlen(L, n);
for (int i = 1; i < l + 1; ++i)
{
lua_pushinteger(L, i);
lua_gettable(L, n);
std::string s = lua_tostring(L, -1);
lua_settop(L, n);
v->push_back(s);
}
return std::make_shared<boost::variant<bool, std::vector<std::string>>>(*v);
}
}
template <>
inline void lua_object<std::string>::from_type(lua_State *L, std::shared_ptr<std::string> value)
{

View file

@ -30,6 +30,7 @@
#include "ai/composite/ai.hpp" // for ai_composite
#include "ai/composite/component.hpp" // for component_manager
#include "ai/composite/engine.hpp" // for engine
#include "ai/composite/value_translator.hpp"
#include "ai/configuration.hpp" // for configuration
#include "ai/contexts.hpp" // for readonly_context, etc
#include "ai/default/contexts.hpp" // for default_ai_context, etc
@ -234,16 +235,20 @@ const std::string holder::get_ai_overview()
if (!this->ai_) {
get_ai_ref();
}
// These assignments are necessary because the code will otherwise not compile on some platforms with an lvalue/rvalue mismatch error
boost::variant<bool, std::vector<std::string>> lik = this->ai_->get_leader_ignores_keep();
boost::variant<bool, std::vector<std::string>> pl = this->ai_->get_passive_leader();
boost::variant<bool, std::vector<std::string>> plsk = this->ai_->get_passive_leader_shares_keep();
std::stringstream s;
s << "advancements: " << this->ai_->get_advancements().get_value() << std::endl;
s << "aggression: " << this->ai_->get_aggression() << std::endl;
s << "caution: " << this->ai_->get_caution() << std::endl;
s << "grouping: " << this->ai_->get_grouping() << std::endl;
s << "leader_aggression: " << this->ai_->get_leader_aggression() << std::endl;
s << "leader_ignores_keep: " << this->ai_->get_leader_ignores_keep() << std::endl;
s << "leader_ignores_keep: " << boost::apply_visitor(leader_aspects_visitor(), lik) << std::endl;
s << "leader_value: " << this->ai_->get_leader_value() << std::endl;
s << "passive_leader: " << this->ai_->get_passive_leader() << std::endl;
s << "passive_leader_shares_keep: " << this->ai_->get_passive_leader_shares_keep() << std::endl;
s << "passive_leader: " << boost::apply_visitor(leader_aspects_visitor(), pl) << std::endl;
s << "passive_leader_shares_keep: " << boost::apply_visitor(leader_aspects_visitor(), plsk) << std::endl;
s << "recruitment_diversity: " << this->ai_->get_recruitment_diversity() << std::endl;
s << "recruitment_instructions: " << std::endl << "----config begin----" << std::endl;
s << this->ai_->get_recruitment_instructions() << "-----config end-----" << std::endl;

View file

@ -206,16 +206,16 @@ static register_aspect_factory< composite_aspect<double>>
static register_aspect_factory< composite_aspect<config>>
leader_goal__composite_aspect_factory("leader_goal*composite_aspect");
static register_aspect_factory< composite_aspect<std::string>>
static register_aspect_factory< composite_aspect<boost::variant<bool, std::vector<std::string>>>>
leader_igores_keep__composite_aspect_factory("leader_ignores_keep*composite_aspect");
static register_aspect_factory< composite_aspect<double>>
leader_value__composite_aspect_factory("leader_value*composite_aspect");
static register_aspect_factory< composite_aspect<std::string>>
static register_aspect_factory< composite_aspect<boost::variant<bool, std::vector<std::string>>>>
passive_leader__composite_aspect_factory("passive_leader*composite_aspect");
static register_aspect_factory< composite_aspect<std::string>>
static register_aspect_factory< composite_aspect<boost::variant<bool, std::vector<std::string>>>>
passive_leader_shares_keep__composite_aspect_factory("passive_leader_shares_keep*composite_aspect");
static register_aspect_factory< composite_aspect<double>>
@ -277,16 +277,16 @@ static register_aspect_factory< standard_aspect<double>>
static register_aspect_factory< standard_aspect<config>>
leader_goal__standard_aspect_factory("leader_goal*standard_aspect");
static register_aspect_factory< standard_aspect<std::string>>
static register_aspect_factory< standard_aspect<boost::variant<bool, std::vector<std::string>>>>
leader_ignores_keep__standard_aspect_factory("leader_ignores_keep*standard_aspect");
static register_aspect_factory< standard_aspect<double>>
leader_value__standard_aspect_factory("leader_value*standard_aspect");
static register_aspect_factory< standard_aspect<std::string>>
static register_aspect_factory< standard_aspect<boost::variant<bool, std::vector<std::string>>>>
passive_leader__standard_aspect_factory("passive_leader*standard_aspect");
static register_aspect_factory< standard_aspect<std::string>>
static register_aspect_factory< standard_aspect<boost::variant<bool, std::vector<std::string>>>>
passive_leader_shares_keep__standard_aspect_factory("passive_leader_shares_keep*standard_aspect");
static register_aspect_factory< standard_aspect<double>>
@ -352,16 +352,16 @@ static register_aspect_factory< standard_aspect<double>>
static register_aspect_factory< standard_aspect<config>>
leader_goal__standard_aspect_factory2("leader_goal*");
static register_aspect_factory< standard_aspect<std::string>>
static register_aspect_factory< standard_aspect<boost::variant<bool, std::vector<std::string>>>>
leader_ignores_keep__standard_aspect_factory2("leader_ignores_keep*");
static register_aspect_factory< standard_aspect<double>>
leader_value__standard_aspect_factory2("leader_value*");
static register_aspect_factory< standard_aspect<std::string>>
static register_aspect_factory< standard_aspect<boost::variant<bool, std::vector<std::string>>>>
passive_leader__standard_aspect_factory2("passive_leader*");
static register_aspect_factory< standard_aspect<std::string>>
static register_aspect_factory< standard_aspect<boost::variant<bool, std::vector<std::string>>>>
passive_leader_shares_keep__standard_aspect_factory2("passive_leader_shares_keep*");
static register_aspect_factory< standard_aspect<double>>
@ -423,16 +423,16 @@ static register_lua_aspect_factory< lua_aspect<double>>
static register_lua_aspect_factory< lua_aspect<config>>
leader_goal__lua_aspect_factory("leader_goal*lua_aspect");
static register_lua_aspect_factory< lua_aspect<std::string>>
static register_lua_aspect_factory< lua_aspect<boost::variant<bool, std::vector<std::string>>>>
leader_ignores_keep__lua_aspect_factory("leader_ignores_keep*lua_aspect");
static register_lua_aspect_factory< lua_aspect<double>>
leader_value__lua_aspect_factory("leader_value*lua_aspect");
static register_lua_aspect_factory< lua_aspect<std::string>>
static register_lua_aspect_factory< lua_aspect<boost::variant<bool, std::vector<std::string>>>>
passive_leader__lua_aspect_factory("passive_leader*lua_aspect");
static register_lua_aspect_factory< lua_aspect<std::string>>
static register_lua_aspect_factory< lua_aspect<boost::variant<bool, std::vector<std::string>>>>
passive_leader_shares_keep__lua_aspect_factory("passive_leader_shares_keep*lua_aspect");
static register_lua_aspect_factory< lua_aspect<double>>