00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef AI_COMPOSITE_ASPECT_HPP_INCLUDED
00021 #define AI_COMPOSITE_ASPECT_HPP_INCLUDED
00022
00023 #include "property_handler.hpp"
00024 #include "value_translator.hpp"
00025 #include "../lua/lua_object.hpp"
00026 #include "../lua/core.hpp"
00027 #include "../../scripting/lua.hpp"
00028
00029 #include "../../log.hpp"
00030
00031 #include <boost/bind.hpp>
00032 #include <boost/lexical_cast.hpp>
00033 #include <boost/pointer_cast.hpp>
00034
00035 #ifdef _MSC_VER
00036 #pragma warning(push)
00037
00038 #pragma warning(disable:4250)
00039 #endif
00040
00041 namespace ai {
00042
00043 class aspect : public readonly_context_proxy, public events::observer, public component {
00044 public:
00045 aspect(readonly_context &context, const config &cfg, const std::string &id);
00046
00047 virtual ~aspect();
00048
00049 void invalidate() const
00050 {
00051 valid_ = false;
00052 valid_variant_ = false;
00053 valid_lua_ = false;
00054 }
00055
00056
00057 virtual const variant& get_variant() const = 0;
00058
00059
00060 virtual boost::shared_ptr<variant> get_variant_ptr() const = 0;
00061
00062
00063 virtual void recalculate() const = 0;
00064
00065
00066 virtual void on_create();
00067
00068
00069 virtual bool redeploy(const config &cfg, const std::string & id);
00070
00071
00072 virtual config to_config() const;
00073
00074
00075 virtual bool delete_all_facets();
00076
00077
00078 void handle_generic_event(const std::string &)
00079 {
00080 invalidate();
00081 }
00082
00083
00084 virtual bool active() const
00085 {
00086 return true;
00087 }
00088
00089 virtual std::string get_name() const
00090 { return name_; }
00091
00092 virtual std::string get_id() const
00093 { return id_; }
00094
00095 virtual std::string get_engine() const
00096 { return engine_; }
00097
00098 static lg::log_domain& log();
00099
00100 protected:
00101 mutable bool valid_;
00102 mutable bool valid_variant_;
00103 mutable bool valid_lua_;
00104
00105 config cfg_;
00106 bool invalidate_on_turn_start_;
00107 bool invalidate_on_tod_change_;
00108 bool invalidate_on_gamestate_change_;
00109 bool invalidate_on_minor_gamestate_change_;
00110 std::string engine_;
00111 std::string name_;
00112 std::string id_;
00113
00114 };
00115
00116 template<typename T>
00117 class typesafe_aspect : public aspect {
00118 public:
00119 typesafe_aspect(readonly_context &context, const config &cfg, const std::string &id)
00120 : aspect(context,cfg,id)
00121 , value_()
00122 , value_variant_()
00123 , value_lua_()
00124 {
00125 }
00126
00127 virtual ~typesafe_aspect()
00128 {
00129 }
00130
00131
00132 virtual const T& get() const
00133 {
00134 return *get_ptr();
00135 }
00136
00137
00138 virtual const variant& get_variant() const
00139 {
00140 return *get_variant_ptr();
00141 }
00142
00143 virtual boost::shared_ptr<variant> get_variant_ptr() const
00144 {
00145 if (!valid_variant_) {
00146 if (!valid_) {
00147 recalculate();
00148 }
00149
00150 if (!valid_variant_ && valid_ ) {
00151 value_variant_ = boost::shared_ptr<variant>(new variant(variant_value_translator<T>::value_to_variant(this->get())));
00152 valid_variant_ = true;
00153 } else if (!valid_variant_ && valid_lua_) {
00154 value_ = value_lua_->get();
00155 value_variant_ = boost::shared_ptr<variant>(new variant(variant_value_translator<T>::value_to_variant(this->get())));
00156 valid_variant_ = true;
00157 } else {
00158 assert(valid_variant_);
00159 }
00160 }
00161 return value_variant_;
00162 }
00163
00164 virtual void recalculate() const = 0;
00165
00166
00167 virtual boost::shared_ptr<T> get_ptr() const
00168 {
00169 if (!valid_) {
00170 if (!(valid_variant_ || valid_lua_)) {
00171 recalculate();
00172 }
00173
00174 if (!valid_ ) {
00175 if (valid_variant_) {
00176 value_ = boost::shared_ptr<T>(new T(variant_value_translator<T>::variant_to_value(get_variant())));
00177 valid_ = true;
00178 } else if (valid_lua_){
00179 value_ = value_lua_->get();
00180 valid_ = true;
00181 } else {
00182 assert(valid_);
00183 }
00184 }
00185 }
00186 return value_;
00187 }
00188
00189 protected:
00190 mutable boost::shared_ptr<T> value_;
00191 mutable boost::shared_ptr<variant> value_variant_;
00192 mutable boost::shared_ptr< lua_object<T> > value_lua_;
00193 };
00194
00195
00196 class known_aspect {
00197 public:
00198 known_aspect(const std::string &name);
00199
00200
00201 virtual ~known_aspect();
00202
00203
00204 virtual void set(aspect_ptr a) = 0;
00205
00206
00207 virtual void add_facet(const config &cfg) = 0;
00208
00209
00210 const std::string& get_name() const;
00211
00212 protected:
00213 const std::string name_;
00214 };
00215
00216
00217 template<class T>
00218 class composite_aspect;
00219
00220 template<typename T>
00221 class typesafe_known_aspect : public known_aspect {
00222 public:
00223 typesafe_known_aspect(const std::string &name, boost::shared_ptr< typesafe_aspect<T> > &where, aspect_map &aspects)
00224 : known_aspect(name), where_(where), aspects_(aspects)
00225 {
00226 }
00227
00228 void set(aspect_ptr a)
00229 {
00230 boost::shared_ptr< typesafe_aspect <T> > c = boost::dynamic_pointer_cast< typesafe_aspect<T> >(a);
00231 if (c) {
00232 assert (c->get_id()== this->get_name());
00233 where_ = c;
00234 aspects_.insert(make_pair(this->get_name(),c));
00235 } else {
00236 LOG_STREAM(debug, aspect::log()) << "typesafe_known_aspect [" << this->get_name() << "] : while setting aspect, got null. this might be caused by invalid [aspect] WML" << std::endl;
00237 }
00238 }
00239
00240 virtual void add_facet(const config &cfg)
00241 {
00242 boost::shared_ptr< composite_aspect <T> > c = boost::dynamic_pointer_cast< composite_aspect<T> >(where_);
00243 if (c) {
00244 assert (c->get_id()==this->get_name());
00245 c->add_facet(-1, cfg);
00246 c->invalidate();
00247 } else {
00248 LOG_STREAM(debug, aspect::log()) << "typesafe_known_aspect [" << this->get_name() << "] : while adding facet to aspect, got null. this might be caused by target [aspect] being not composite" << std::endl;
00249 }
00250 }
00251
00252 protected:
00253 boost::shared_ptr<typesafe_aspect <T> > &where_;
00254 aspect_map &aspects_;
00255
00256 };
00257
00258
00259 template<typename T>
00260 class composite_aspect : public typesafe_aspect<T> {
00261 public:
00262
00263 composite_aspect(readonly_context &context, const config &cfg, const std::string &id)
00264 : typesafe_aspect<T>(context, cfg, id)
00265 , facets_()
00266 , default_()
00267 {
00268 foreach (const config &cfg_element, this->cfg_.child_range("facet") ){
00269 add_facet(-1,cfg_element);
00270 }
00271
00272 const config &_default = this->cfg_.child("default");
00273 if (_default) {
00274 std::vector< aspect_ptr > default_aspects;
00275 engine::parse_aspect_from_config(*this,_default,this->get_id(),std::back_inserter(default_aspects));
00276 if (!default_aspects.empty()) {
00277 typename aspect_type<T>::typesafe_ptr b = boost::dynamic_pointer_cast< typesafe_aspect<T> >(default_aspects.front());
00278 default_ = b;
00279 }
00280 }
00281
00282 boost::function2<void, typename aspect_type<T>::typesafe_ptr_vector&, const config&> factory_facets =
00283 boost::bind(&ai::composite_aspect<T>::create_facet,*this,_1,_2);
00284
00285 register_vector_property(this->property_handlers(),"facet",facets_, factory_facets);
00286
00287 }
00288
00289
00290 void create_facet( typename aspect_type<T>::typesafe_ptr_vector &facets, const config &cfg)
00291 {
00292 std::vector<aspect_ptr> facets_base;
00293 engine::parse_aspect_from_config(*this,cfg,this->get_id(),std::back_inserter(facets_base));
00294 foreach (aspect_ptr a, facets_base ){
00295 typename aspect_type<T>::typesafe_ptr b = boost::dynamic_pointer_cast< typesafe_aspect<T> > (a);
00296 facets.push_back(b);
00297 }
00298 }
00299
00300
00301 virtual void recalculate() const
00302 {
00303
00304 foreach (const typename aspect_type<T>::typesafe_ptr &f, make_pair(facets_.rbegin(),facets_.rend())) {
00305 if (f->active()) {
00306 this->value_ = boost::shared_ptr<T>(f->get_ptr());
00307 this->valid_ = true;
00308 return;
00309 }
00310 }
00311 this->value_ = boost::shared_ptr<T>(default_->get_ptr());
00312 this->valid_ = true;
00313 }
00314
00315
00316 virtual config to_config() const
00317 {
00318 config cfg = aspect::to_config();
00319 foreach (const typename aspect_type<T>::typesafe_ptr f, facets_) {
00320 cfg.add_child("facet",f->to_config());
00321 }
00322 if (default_) {
00323 cfg.add_child("default",default_->to_config());
00324 }
00325 return cfg;
00326 }
00327
00328
00329 virtual bool add_facet(int pos, const config &cfg)
00330 {
00331 if (pos<0) {
00332 pos = facets_.size();
00333 }
00334 std::vector< aspect_ptr > facets;
00335 engine::parse_aspect_from_config(*this,cfg,this->get_id(),std::back_inserter(facets));
00336 int j=0;
00337 foreach (aspect_ptr a, facets ){
00338 typename aspect_type<T>::typesafe_ptr b = boost::dynamic_pointer_cast< typesafe_aspect<T> > (a);
00339 facets_.insert(facets_.begin()+pos+j,b);
00340 j++;
00341 }
00342 return (j>0);
00343 }
00344
00345
00346 virtual bool delete_all_facets()
00347 {
00348 bool b = !facets_.empty();
00349 facets_.clear();
00350 return b;
00351 }
00352
00353 protected:
00354 typename aspect_type<T>::typesafe_ptr_vector facets_;
00355 typename aspect_type<T>::typesafe_ptr default_;
00356
00357 };
00358
00359 template<typename T>
00360 class standard_aspect : public typesafe_aspect<T> {
00361 public:
00362 standard_aspect(readonly_context &context, const config &cfg, const std::string &id)
00363 : typesafe_aspect<T>(context, cfg, id), time_of_day_(cfg["time_of_day"]),turns_(cfg["turns"])
00364 {
00365 boost::shared_ptr<T> value(new T(config_value_translator<T>::cfg_to_value(this->cfg_)));
00366 this->value_= value;
00367 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;
00368 }
00369
00370
00371 virtual bool active() const
00372 {
00373 return this->is_active(time_of_day_,turns_);
00374 }
00375
00376
00377 void recalculate() const
00378 {
00379
00380 this->valid_ = true;
00381 }
00382
00383
00384 config to_config() const
00385 {
00386 config cfg = aspect::to_config();
00387 config_value_translator<T>::value_to_cfg(this->get(),cfg);
00388 cfg["time_of_day"] = time_of_day_;
00389 cfg["turns"] = turns_;
00390 return cfg;
00391 }
00392
00393 protected:
00394 std::string time_of_day_;
00395 std::string turns_;
00396
00397 };
00398
00399 template<typename T>
00400 class lua_aspect : public typesafe_aspect<T>
00401 {
00402 public:
00403 lua_aspect(readonly_context &context, const config &cfg, const std::string &id, boost::shared_ptr<lua_ai_context>& l_ctx)
00404 : typesafe_aspect<T>(context, cfg, id)
00405 , handler_(), code_()
00406 {
00407 std::string value;
00408 if (cfg.has_attribute("value"))
00409 {
00410 value = cfg["value"].str();
00411 if (value == "yes")
00412 {
00413 value = "true";
00414 }
00415 value = "return " + value;
00416 }
00417 else if (cfg.has_attribute("code"))
00418 {
00419 value = cfg["code"].str();
00420 }
00421 else
00422 {
00423
00424 return;
00425 }
00426 code_ = value;
00427 handler_ = boost::shared_ptr<lua_ai_action_handler>(resources::lua_kernel->create_lua_ai_action_handler(value.c_str(), *l_ctx));
00428 }
00429
00430 void recalculate() const
00431 {
00432 this->valid_lua_ = true;
00433 boost::shared_ptr< lua_object<T> > l_obj = boost::shared_ptr< lua_object<T> >(new lua_object<T>());
00434 config c = config();
00435 handler_->handle(c, true, l_obj);
00436 this->value_lua_ = l_obj;
00437 }
00438
00439 config to_config() const
00440 {
00441 config cfg = aspect::to_config();
00442 cfg["code"] = code_;
00443 return cfg;
00444 }
00445
00446 private:
00447 boost::shared_ptr<lua_ai_action_handler> handler_;
00448 std::string code_;
00449 };
00450
00451
00452 class aspect_factory{
00453 public:
00454 typedef boost::shared_ptr< aspect_factory > factory_ptr;
00455 typedef std::map<std::string, factory_ptr> factory_map;
00456 typedef std::pair<const std::string, factory_ptr> factory_map_pair;
00457
00458 static factory_map& get_list() {
00459 static factory_map *aspect_factories;
00460 if (aspect_factories==NULL) {
00461 aspect_factories = new factory_map;
00462 }
00463 return *aspect_factories;
00464 }
00465
00466 virtual aspect_ptr get_new_instance( readonly_context &context, const config &cfg, const std::string &id) = 0;
00467
00468 aspect_factory( const std::string &name )
00469 {
00470 factory_ptr ptr_to_this(this);
00471 get_list().insert(make_pair(name,ptr_to_this));
00472 }
00473
00474 virtual ~aspect_factory() {}
00475 };
00476
00477
00478 template<class ASPECT>
00479 class register_aspect_factory : public aspect_factory {
00480 public:
00481 register_aspect_factory( const std::string &name )
00482 : aspect_factory( name )
00483 {
00484 }
00485
00486 aspect_ptr get_new_instance( readonly_context &context, const config &cfg, const std::string &id)
00487 {
00488 boost::shared_ptr<ASPECT> _a(new ASPECT(context,cfg,id));
00489 aspect_ptr a = _a;
00490 a->on_create();
00491 return a;
00492 }
00493 };
00494
00495 class lua_aspect_factory{
00496 public:
00497 typedef boost::shared_ptr< lua_aspect_factory > factory_ptr;
00498 typedef std::map<std::string, factory_ptr> factory_map;
00499 typedef std::pair<const std::string, factory_ptr> factory_map_pair;
00500
00501 static factory_map& get_list() {
00502 static factory_map *aspect_factories;
00503 if (aspect_factories==NULL) {
00504 aspect_factories = new factory_map;
00505 }
00506 return *aspect_factories;
00507 }
00508
00509 virtual aspect_ptr get_new_instance( readonly_context &context, const config &cfg, const std::string &id, boost::shared_ptr<lua_ai_context>& l_ctx) = 0;
00510
00511 lua_aspect_factory( const std::string &name )
00512 {
00513 factory_ptr ptr_to_this(this);
00514 get_list().insert(make_pair(name,ptr_to_this));
00515 }
00516
00517 virtual ~lua_aspect_factory() {}
00518 };
00519
00520 template<class ASPECT>
00521 class register_lua_aspect_factory : public lua_aspect_factory {
00522 public:
00523 register_lua_aspect_factory( const std::string &name )
00524 : lua_aspect_factory( name )
00525 {
00526 }
00527
00528 aspect_ptr get_new_instance( readonly_context &context, const config &cfg, const std::string &id, boost::shared_ptr<lua_ai_context>& l_ctx)
00529 {
00530 boost::shared_ptr<ASPECT> _a(new ASPECT(context,cfg,id,l_ctx));
00531 aspect_ptr a = _a;
00532 a->on_create();
00533 return a;
00534 }
00535 };
00536
00537
00538 }
00539
00540 #ifdef _MSC_VER
00541 #pragma warning(pop)
00542 #endif
00543
00544 #endif