diff --git a/src/ai/composite/ai.cpp b/src/ai/composite/ai.cpp index d3711dd62a0e..41e838fa9993 100644 --- a/src/ai/composite/ai.cpp +++ b/src/ai/composite/ai.cpp @@ -80,10 +80,13 @@ void ai_composite::on_create() boost::function2&, const config&> factory_stages = boost::bind(&ai::ai_composite::create_stage,*this,_1,_2); + boost::function3&, 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); } @@ -105,6 +108,14 @@ void ai_composite::create_engine(std::vector &engines, const config engine::parse_engine_from_config(*this,cfg,std::back_inserter(engines)); } + +void ai_composite::replace_aspect(std::map &aspects, const config &cfg, std::string id) +{ + std::vector temp_aspects; + engine::parse_aspect_from_config(*this,cfg,id,std::back_inserter(temp_aspects)); + aspects[id] = temp_aspects.back(); +} + ai_composite::~ai_composite() { } diff --git a/src/ai/composite/ai.hpp b/src/ai/composite/ai.hpp index cf49192b7514..aee722a88990 100644 --- a/src/ai/composite/ai.hpp +++ b/src/ai/composite/ai.hpp @@ -95,6 +95,9 @@ class ai_composite : public ai_context, public virtual default_ai_context_proxy, void create_engine(std::vector &engines, const config &cfg); + void replace_aspect(std::map &aspects, const config &cfg, std::string id); + + void on_create(); /** diff --git a/src/ai/composite/aspect.cpp b/src/ai/composite/aspect.cpp index e4de2c2971c8..6a8a8ac62720 100644 --- a/src/ai/composite/aspect.cpp +++ b/src/ai/composite/aspect.cpp @@ -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)), @@ -39,6 +40,7 @@ aspect::aspect(readonly_context &context, const config &cfg, const std::string & DBG_AI_ASPECT << "creating new aspect: engine=["<is_active(time_of_day_,turns_); +} bool aspect::delete_all_facets() { diff --git a/src/ai/composite/aspect.hpp b/src/ai/composite/aspect.hpp index ba558cea3a84..6f8d210e78c5 100644 --- a/src/ai/composite/aspect.hpp +++ b/src/ai/composite/aspect.hpp @@ -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_; } @@ -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_; @@ -263,6 +263,7 @@ class composite_aspect : public typesafe_aspect { : typesafe_aspect(context, cfg, id) , facets_() , default_() + , parent_id_(id) { BOOST_FOREACH(const config &cfg_element, this->cfg_.child_range("facet") ){ add_facet(-1,cfg_element); @@ -271,9 +272,12 @@ class composite_aspect : public typesafe_aspect { 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::typesafe_ptr b = boost::dynamic_pointer_cast< typesafe_aspect >(default_aspects.front()); + if (composite_aspect* c = dynamic_cast*>(b.get())) { + c->parent_id_ = parent_id_; + } default_ = b; } } @@ -281,20 +285,23 @@ class composite_aspect : public typesafe_aspect { boost::function2::typesafe_ptr_vector&, const config&> factory_facets = boost::bind(&ai::composite_aspect::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::typesafe_ptr_vector &facets, const config &cfg) - { + { std::vector 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::typesafe_ptr b = boost::dynamic_pointer_cast< typesafe_aspect > (a); + if (composite_aspect* c = dynamic_cast*>(b.get())) { + c->parent_id_ = parent_id_; + } facets.push_back(b); } - } + } virtual void recalculate() const @@ -307,8 +314,10 @@ class composite_aspect : public typesafe_aspect { return; } } - this->value_ = boost::shared_ptr(default_->get_ptr()); - this->valid_ = true; + if (default_) { + this->value_ = boost::shared_ptr(default_->get_ptr()); + this->valid_ = true; + } } @@ -332,10 +341,13 @@ class composite_aspect : public typesafe_aspect { 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::typesafe_ptr b = boost::dynamic_pointer_cast< typesafe_aspect > (a); + if (composite_aspect* c = dynamic_cast*>(b.get())) { + c->parent_id_ = parent_id_; + } facets_.insert(facets_.begin()+pos+j,b); j++; } @@ -353,6 +365,7 @@ class composite_aspect : public typesafe_aspect { protected: typename aspect_type::typesafe_ptr_vector facets_; typename aspect_type::typesafe_ptr default_; + std::string parent_id_; }; @@ -360,17 +373,12 @@ template class standard_aspect : public typesafe_aspect { public: standard_aspect(readonly_context &context, const config &cfg, const std::string &id) - : typesafe_aspect(context, cfg, id), time_of_day_(cfg["time_of_day"]),turns_(cfg["turns"]) + : typesafe_aspect(context, cfg, id) { + this->name_ = "standard_aspect"; boost::shared_ptr value(new T(config_value_translator::cfg_to_value(this->cfg_))); this->value_= value; - LOG_STREAM(debug, aspect::log()) << "standard aspect has time_of_day=["<::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::value_to_cfg(this->get()) << std::endl; } @@ -385,24 +393,18 @@ class standard_aspect : public typesafe_aspect { { config cfg = aspect::to_config(); config_value_translator::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 { 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";} @@ -416,6 +418,7 @@ class lua_aspect : public typesafe_aspect : typesafe_aspect(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()); @@ -435,6 +438,7 @@ class lua_aspect : public typesafe_aspect void recalculate() const { this->valid_lua_ = true; + this->value_lua_.reset(new lua_object); handler_->handle(params_, true, this->value_lua_); } diff --git a/src/ai/composite/property_handler.hpp b/src/ai/composite/property_handler.hpp index d9a12aba6dc9..ee9330bca5c4 100644 --- a/src/ai/composite/property_handler.hpp +++ b/src/ai/composite/property_handler.hpp @@ -139,6 +139,11 @@ 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) { @@ -146,7 +151,7 @@ class vector_property_handler : public base_property_handler { 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); @@ -163,14 +168,60 @@ class vector_property_handler : public base_property_handler { +template +class facets_property_handler : public vector_property_handler { + typedef typename vector_property_handler::t_ptr t_ptr; + typedef typename vector_property_handler::t_ptr_vector t_ptr_vector; +public: + + facets_property_handler(const std::string &property, t_ptr_vector &values, t_ptr& def, boost::function2 &construction_factory) + : vector_property_handler(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::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::handle_change(child, cfg); + } + + std::vector handle_get_children() + { + std::vector children = vector_property_handler::handle_get_children(); + children.push_back(default_.get()); + return children; + } + +private: + t_ptr& default_; +}; + + + template class aspect_property_handler : public base_property_handler { public: typedef boost::shared_ptr 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 &construction_factory) + : property_(property), aspects_(aspects), factory_(construction_factory) { } @@ -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*/) @@ -221,6 +276,7 @@ class aspect_property_handler : public base_property_handler { const std::string &property_; aspect_map &aspects_; + boost::function3 factory_; }; @@ -234,9 +290,16 @@ static void register_vector_property(std::map } template -static void register_aspect_property(std::map &property_handlers, const std::string &property, std::map< std::string, boost::shared_ptr > &aspects) +static void register_facets_property(std::map &property_handlers, const std::string &property, std::vector< boost::shared_ptr > &values, boost::shared_ptr& def, boost::function2 >&, const config&> construction_factory) +{ + property_handler_ptr handler_ptr = property_handler_ptr(new facets_property_handler(property,values,def,construction_factory)); + property_handlers.insert(std::make_pair(property,handler_ptr)); +} + +template +static void register_aspect_property(std::map &property_handlers, const std::string &property, std::map< std::string, boost::shared_ptr > &aspects, boost::function3 >&, const config&, std::string> construction_factory) { - property_handler_ptr handler_ptr = property_handler_ptr(new aspect_property_handler(property,aspects)); + property_handler_ptr handler_ptr = property_handler_ptr(new aspect_property_handler(property,aspects,construction_factory)); property_handlers.insert(std::make_pair(property,handler_ptr)); } diff --git a/src/ai/configuration.cpp b/src/ai/configuration.cpp index c81ca3c8be91..41669f16d1f0 100644 --- a/src/ai/configuration.cpp +++ b/src/ai/configuration.cpp @@ -202,9 +202,10 @@ bool configuration::parse_side_config(side_number side, const config& original_c DBG_AI_CONFIGURATION << "side "<< side <<": applying default configuration" << std::endl; cfg.add_child_at("ai",default_config_,0); } else { - ERR_AI_CONFIGURATION << "side "<< side <<": default configuration is not available, do not applying it" << std::endl; + ERR_AI_CONFIGURATION << "side "<< side <<": default configuration is not available, not applying it" << std::endl; } + LOG_AI_CONFIGURATION << "side "<< side << ": expanding simplified aspects into full facets"<< std::endl; expand_simplified_aspects(side, cfg); //construct new-style integrated config @@ -226,9 +227,7 @@ bool configuration::parse_side_config(side_number side, const config& original_c WRN_AI_CONFIGURATION << "side "<< side <<": aspect with id=["<