Skip to content

Commit

Permalink
Generalize/fix some aspect stuff
Browse files Browse the repository at this point in the history
- Facets no longer have to be standard aspects - they can be lua aspects or even a nested composite aspect
- Ensure aspect tags from simplified aspect contain name=composite_aspect (normally not a problem, but could be in some unusual cases)
- Merge default aspect tags instead of simply taking the first one
- Fix crash that occurred if a composite aspect somehow lacked a default (an unusual case, but not impossible)
- Fix Lua aspects
- Fix simple Lua aspects (with value= instead of code=) quoting numeric values
- Ensure Lua aspects always have name=lua_aspect and standard aspects always have name=standard_aspect
- A few additional [modify_ai] cases:
    - aspect[id].facet[*] matches the default facet; this facet can be changed but not deleted, and if it's composite, subfacets can be referenced
    - action=change works on aspects (with path=aspect[id]); requires the new aspect to have matching id= key
    - aspect[id].facet[id].facet[id] etc works in the case of more deeply nested aspects (or even aspect[id].facet[*].facet[id])
  • Loading branch information
CelticMinstrel authored and mattsc committed Mar 22, 2016
1 parent 597ab40 commit b472056
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 45 deletions.
13 changes: 12 additions & 1 deletion src/ai/composite/ai.cpp
Expand Up @@ -80,10 +80,13 @@ void ai_composite::on_create()
boost::function2<void, std::vector<stage_ptr>&, const config&> factory_stages =
boost::bind(&ai::ai_composite::create_stage,*this,_1,_2);

boost::function3<void, std::map<std::string,aspect_ptr>&, const config&, std::string> factory_aspects =
boost::bind(&ai::ai_composite::replace_aspect,*this,_1,_2,_3);

register_vector_property(property_handlers(),"engine",get_engines(), factory_engines);
register_vector_property(property_handlers(),"goal",get_goals(), factory_goals);
register_vector_property(property_handlers(),"stage",stages_, factory_stages);
register_aspect_property(property_handlers(),"aspect",get_aspects());
register_aspect_property(property_handlers(),"aspect",get_aspects(), factory_aspects);

}

Expand All @@ -105,6 +108,14 @@ void ai_composite::create_engine(std::vector<engine_ptr> &engines, const config
engine::parse_engine_from_config(*this,cfg,std::back_inserter(engines));
}


void ai_composite::replace_aspect(std::map<std::string,aspect_ptr> &aspects, const config &cfg, std::string id)
{
std::vector<aspect_ptr> temp_aspects;
engine::parse_aspect_from_config(*this,cfg,id,std::back_inserter(temp_aspects));
aspects[id] = temp_aspects.back();
}

ai_composite::~ai_composite()
{
}
Expand Down
3 changes: 3 additions & 0 deletions src/ai/composite/ai.hpp
Expand Up @@ -95,6 +95,9 @@ class ai_composite : public ai_context, public virtual default_ai_context_proxy,
void create_engine(std::vector<engine_ptr> &engines, const config &cfg);


void replace_aspect(std::map<std::string,aspect_ptr> &aspects, const config &cfg, std::string id);


void on_create();

/**
Expand Down
12 changes: 12 additions & 0 deletions src/ai/composite/aspect.cpp
Expand Up @@ -29,6 +29,7 @@ static lg::log_domain log_ai_aspect("ai/aspect");
#define ERR_AI_ASPECT LOG_STREAM(err, log_ai_aspect)

aspect::aspect(readonly_context &context, const config &cfg, const std::string &id):
time_of_day_(cfg["time_of_day"]),turns_(cfg["turns"]),
valid_(false), valid_variant_(false), valid_lua_(false), cfg_(cfg),
invalidate_on_turn_start_(cfg["invalidate_on_turn_start"].to_bool(true)),
invalidate_on_tod_change_(cfg["invalidate_on_tod_change"].to_bool(true)),
Expand All @@ -39,6 +40,7 @@ aspect::aspect(readonly_context &context, const config &cfg, const std::string &
DBG_AI_ASPECT << "creating new aspect: engine=["<<engine_<<"], name=["<<name_<<"], id=["<<id_<<"]"<< std::endl;
init_readonly_context_proxy(context);
redeploy(cfg,id);
DBG_AI_ASPECT << "aspect has time_of_day=["<<time_of_day_<<"], turns=["<<turns_<<"]" << std::endl;
}


Expand Down Expand Up @@ -122,12 +124,22 @@ config aspect::to_config() const
cfg["invalidate_on_tod_change"] = invalidate_on_tod_change_;
cfg["invalidate_on_gamestate_change"] = invalidate_on_gamestate_change_;
cfg["invalidate_on_minor_gamestate_change"] = invalidate_on_minor_gamestate_change_;
if (!time_of_day_.empty()) {
cfg["time_of_day"] = time_of_day_;
}
if (!turns_.empty()) {
cfg["turns"] = turns_;
}
cfg["engine"] = engine_;
cfg["name"] = name_;
cfg["id"] = id_;
return cfg;
}

bool aspect::active() const
{
return this->is_active(time_of_day_,turns_);
}

bool aspect::delete_all_facets()
{
Expand Down
66 changes: 35 additions & 31 deletions src/ai/composite/aspect.hpp
Expand Up @@ -78,12 +78,9 @@ class aspect : public readonly_context_proxy, public events::observer, public co
{
invalidate();
}


virtual bool active() const
{
return true;
}


virtual bool active() const;

virtual std::string get_name() const
{ return name_; }
Expand All @@ -97,6 +94,9 @@ class aspect : public readonly_context_proxy, public events::observer, public co
static lg::log_domain& log();

protected:
std::string time_of_day_;
std::string turns_;

mutable bool valid_;
mutable bool valid_variant_;
mutable bool valid_lua_;
Expand Down Expand Up @@ -263,6 +263,7 @@ class composite_aspect : public typesafe_aspect<T> {
: typesafe_aspect<T>(context, cfg, id)
, facets_()
, default_()
, parent_id_(id)
{
BOOST_FOREACH(const config &cfg_element, this->cfg_.child_range("facet") ){
add_facet(-1,cfg_element);
Expand All @@ -271,30 +272,36 @@ class composite_aspect : public typesafe_aspect<T> {
const config &_default = this->cfg_.child("default");
if (_default) {
std::vector< aspect_ptr > default_aspects;
engine::parse_aspect_from_config(*this,_default,this->get_id(),std::back_inserter(default_aspects));
engine::parse_aspect_from_config(*this,_default,parent_id_,std::back_inserter(default_aspects));
if (!default_aspects.empty()) {
typename aspect_type<T>::typesafe_ptr b = boost::dynamic_pointer_cast< typesafe_aspect<T> >(default_aspects.front());
if (composite_aspect<T>* c = dynamic_cast<composite_aspect<T>*>(b.get())) {
c->parent_id_ = parent_id_;
}
default_ = b;
}
}

boost::function2<void, typename aspect_type<T>::typesafe_ptr_vector&, const config&> factory_facets =
boost::bind(&ai::composite_aspect<T>::create_facet,*this,_1,_2);

register_vector_property(this->property_handlers(),"facet",facets_, factory_facets);
register_facets_property(this->property_handlers(),"facet",facets_,default_, factory_facets);

}


void create_facet( typename aspect_type<T>::typesafe_ptr_vector &facets, const config &cfg)
{
{
std::vector<aspect_ptr> facets_base;
engine::parse_aspect_from_config(*this,cfg,this->get_id(),std::back_inserter(facets_base));
engine::parse_aspect_from_config(*this,cfg,parent_id_,std::back_inserter(facets_base));
BOOST_FOREACH(aspect_ptr a, facets_base ){
typename aspect_type<T>::typesafe_ptr b = boost::dynamic_pointer_cast< typesafe_aspect<T> > (a);
if (composite_aspect<T>* c = dynamic_cast<composite_aspect<T>*>(b.get())) {
c->parent_id_ = parent_id_;
}
facets.push_back(b);
}
}
}


virtual void recalculate() const
Expand All @@ -307,8 +314,10 @@ class composite_aspect : public typesafe_aspect<T> {
return;
}
}
this->value_ = boost::shared_ptr<T>(default_->get_ptr());
this->valid_ = true;
if (default_) {
this->value_ = boost::shared_ptr<T>(default_->get_ptr());
this->valid_ = true;
}
}


Expand All @@ -332,10 +341,13 @@ class composite_aspect : public typesafe_aspect<T> {
pos = facets_.size();
}
std::vector< aspect_ptr > facets;
engine::parse_aspect_from_config(*this,cfg,this->get_id(),std::back_inserter(facets));
engine::parse_aspect_from_config(*this,cfg,parent_id_,std::back_inserter(facets));
int j=0;
BOOST_FOREACH(aspect_ptr a, facets ){
typename aspect_type<T>::typesafe_ptr b = boost::dynamic_pointer_cast< typesafe_aspect<T> > (a);
if (composite_aspect<T>* c = dynamic_cast<composite_aspect<T>*>(b.get())) {
c->parent_id_ = parent_id_;
}
facets_.insert(facets_.begin()+pos+j,b);
j++;
}
Expand All @@ -353,24 +365,20 @@ class composite_aspect : public typesafe_aspect<T> {
protected:
typename aspect_type<T>::typesafe_ptr_vector facets_;
typename aspect_type<T>::typesafe_ptr default_;
std::string parent_id_;

};

template<typename T>
class standard_aspect : public typesafe_aspect<T> {
public:
standard_aspect(readonly_context &context, const config &cfg, const std::string &id)
: typesafe_aspect<T>(context, cfg, id), time_of_day_(cfg["time_of_day"]),turns_(cfg["turns"])
: typesafe_aspect<T>(context, cfg, id)
{
this->name_ = "standard_aspect";
boost::shared_ptr<T> value(new T(config_value_translator<T>::cfg_to_value(this->cfg_)));
this->value_= value;
LOG_STREAM(debug, aspect::log()) << "standard aspect has time_of_day=["<<time_of_day_<<"], turns=["<<turns_<<"], and value: "<< std::endl << config_value_translator<T>::value_to_cfg(this->get()) << std::endl;
}


virtual bool active() const
{
return this->is_active(time_of_day_,turns_);
LOG_STREAM(debug, aspect::log()) << "standard aspect has value: "<< std::endl << config_value_translator<T>::value_to_cfg(this->get()) << std::endl;
}


Expand All @@ -385,24 +393,18 @@ class standard_aspect : public typesafe_aspect<T> {
{
config cfg = aspect::to_config();
config_value_translator<T>::value_to_cfg(this->get(),cfg);
cfg["time_of_day"] = time_of_day_;
cfg["turns"] = turns_;
return cfg;
}

protected:
std::string time_of_day_;
std::string turns_;

};

class lua_aspect_visitor : public boost::static_visitor<std::string> {
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()(int i) const {return str_cast(i);}
std::string operator()(unsigned long long i) const {return str_cast(i);}
std::string operator()(double i) const {return 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";}
Expand All @@ -416,6 +418,7 @@ class lua_aspect : public typesafe_aspect<T>
: typesafe_aspect<T>(context, cfg, id)
, handler_(), code_(), params_(cfg.child_or_empty("args"))
{
this->name_ = "lua_aspect";
if (cfg.has_attribute("value"))
{
code_ = "return " + cfg["value"].apply_visitor(lua_aspect_visitor());
Expand All @@ -435,6 +438,7 @@ class lua_aspect : public typesafe_aspect<T>
void recalculate() const
{
this->valid_lua_ = true;
this->value_lua_.reset(new lua_object<T>);
handler_->handle(params_, true, this->value_lua_);
}

Expand Down
77 changes: 70 additions & 7 deletions src/ai/composite/property_handler.hpp
Expand Up @@ -139,14 +139,19 @@ class vector_property_handler : public base_property_handler {
return children;
}

protected:
void call_factory(t_ptr_vector& vec, const config& cfg)
{
factory_(vec, cfg);
}
private:
bool do_add(int pos, const config &cfg)
{
if (pos<0) {
pos = values_.size();
}
t_ptr_vector values;
factory_(values,cfg);
call_factory(values,cfg);
int j=0;
BOOST_FOREACH(t_ptr b, values ){
values_.insert(values_.begin()+pos+j,b);
Expand All @@ -163,14 +168,60 @@ class vector_property_handler : public base_property_handler {



template<typename T>
class facets_property_handler : public vector_property_handler<T> {
typedef typename vector_property_handler<T>::t_ptr t_ptr;
typedef typename vector_property_handler<T>::t_ptr_vector t_ptr_vector;
public:

facets_property_handler(const std::string &property, t_ptr_vector &values, t_ptr& def, boost::function2<void, t_ptr_vector&, const config&> &construction_factory)
: vector_property_handler<T>(property, values, construction_factory)
, default_(def)
{
}

component* handle_get(const path_element &child)
{
//* is a special case - 'get the default facet'
if (child.id == "*") {
return default_.get();
}
return vector_property_handler<T>::handle_get(child);
}

bool handle_change(const path_element &child, const config &cfg)
{
//* is a special case - 'replace the default facet'
if (child.id == "*") {
t_ptr_vector values;
this->call_factory(values,cfg);
default_ = values.back();
return true;
}
return vector_property_handler<T>::handle_change(child, cfg);
}

std::vector<component*> handle_get_children()
{
std::vector<component*> children = vector_property_handler<T>::handle_get_children();
children.push_back(default_.get());
return children;
}

private:
t_ptr& default_;
};



template<typename T>
class aspect_property_handler : public base_property_handler {
public:
typedef boost::shared_ptr<T> t_ptr;
typedef std::map< std::string, t_ptr > aspect_map;

aspect_property_handler(const std::string &property, aspect_map &aspects)
: property_(property), aspects_(aspects)
aspect_property_handler(const std::string &property, aspect_map &aspects, boost::function3<void, aspect_map&, const config&, std::string> &construction_factory)
: property_(property), aspects_(aspects), factory_(construction_factory)
{
}

Expand All @@ -184,9 +235,13 @@ class aspect_property_handler : public base_property_handler {
return NULL;
}

bool handle_change(const path_element &/*child*/, const config &/*cfg*/)
bool handle_change(const path_element &child, const config &cfg)
{
return false;
if (cfg["id"] != child.id || aspects_.find(child.id) == aspects_.end()) {
return false;
}
factory_(aspects_, cfg, child.id);
return true;
}

bool handle_add(const path_element &/*child*/, const config &/*cfg*/)
Expand Down Expand Up @@ -221,6 +276,7 @@ class aspect_property_handler : public base_property_handler {

const std::string &property_;
aspect_map &aspects_;
boost::function3<void, aspect_map&, const config&, std::string> factory_;

};

Expand All @@ -234,9 +290,16 @@ static void register_vector_property(std::map<std::string,property_handler_ptr>
}

template<typename X>
static void register_aspect_property(std::map<std::string,property_handler_ptr> &property_handlers, const std::string &property, std::map< std::string, boost::shared_ptr<X> > &aspects)
static void register_facets_property(std::map<std::string,property_handler_ptr> &property_handlers, const std::string &property, std::vector< boost::shared_ptr<X> > &values, boost::shared_ptr<X>& def, boost::function2<void, std::vector< boost::shared_ptr<X> >&, const config&> construction_factory)
{
property_handler_ptr handler_ptr = property_handler_ptr(new facets_property_handler<X>(property,values,def,construction_factory));
property_handlers.insert(std::make_pair(property,handler_ptr));
}

template<typename X>
static void register_aspect_property(std::map<std::string,property_handler_ptr> &property_handlers, const std::string &property, std::map< std::string, boost::shared_ptr<X> > &aspects, boost::function3<void, std::map< std::string, boost::shared_ptr<X> >&, const config&, std::string> construction_factory)
{
property_handler_ptr handler_ptr = property_handler_ptr(new aspect_property_handler<X>(property,aspects));
property_handler_ptr handler_ptr = property_handler_ptr(new aspect_property_handler<X>(property,aspects,construction_factory));
property_handlers.insert(std::make_pair(property,handler_ptr));
}

Expand Down

0 comments on commit b472056

Please sign in to comment.