The Battle for Wesnoth  1.13.10+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
property_handler.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2017 by Yurii Chernyi <terraninfo@terraninfo.net>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * Composite AI component
17  * @file
18  */
19 
20 #pragma once
21 
22 #include "utils/functional.hpp"
23 #include "config.hpp"
25 
26 #include <algorithm>
27 
28 namespace ai{
29 
30 template<typename T>
32 public:
34  : count_(0), element_(element)
35  {
36  }
38 
39  bool operator()(const T& t)
40  {
41  if ( (!element_.id.empty()) && (element_.id == t->get_id()) ) {
42  return true;
43  }
44  if (count_ == element_.position) {
45  return true;
46  }
47  count_++;
48  return false;
49  }
50 
51 private:
52  int count_;
54 };
55 
56 
57 class component;
58 
60 public:
61 
63 
64  virtual component* handle_get(const path_element &child) = 0;
65  virtual bool handle_change(const path_element &child, config cfg) = 0;
66  virtual bool handle_add(const path_element &child, const config &cfg) = 0;
67  virtual bool handle_delete(const path_element &child) = 0;
68  virtual std::vector< component* > handle_get_children() = 0;
69 };
70 
71 typedef std::shared_ptr< base_property_handler > property_handler_ptr;
72 
73 template<typename T>
75 public:
76  typedef std::shared_ptr<T> ptr;
77  typedef std::vector< std::shared_ptr<T> > ptr_vector;
78 
79  vector_property_handler(const std::string &property, ptr_vector &values, std::function<void(ptr_vector&, const config&)> &construction_factory)
80  : factory_(construction_factory), property_(property), values_(values){}
81 
82 
84  {
85  typename ptr_vector::iterator i = std::find_if(values_.begin(),values_.end(),path_element_matches<ptr>(child));
86  if (i!=values_.end()){
87  return &*(*i);
88  }
89  return nullptr;
90  }
91  bool handle_change(const path_element &child, config cfg)
92  {
93  if (!handle_delete(child)) {
94  return false;
95  }
96  if (!cfg.has_attribute("id")) {
97  cfg["id"] = child.id;
98  }
99 
100  return handle_add(child,cfg);
101  }
102  bool handle_add(const path_element &child, const config &cfg)
103  {
104  //if the id is not empty, try to delete all with this id
105  if (!cfg["id"].empty()) {
106  path_element with_same_id;
107  with_same_id.id = cfg["id"].str();
108  with_same_id.property = property_;
109  with_same_id.position=-1;
110  handle_delete(with_same_id);
111  }
112 
113  typename ptr_vector::iterator i = std::find_if(values_.begin(),values_.end(),path_element_matches<ptr>(child));
114  return do_add(i-values_.begin(),cfg);
115  }
116 
117  bool handle_delete(const path_element &child)
118  {
119  //* is a special case - 'delete all'
120  if (child.id == "*") {
121  values_.clear();
122  return true;
123  }
124 
125  typename ptr_vector::iterator i = std::find_if(values_.begin(),values_.end(),path_element_matches<ptr>(child));
126  if (i!=values_.end()){
127  values_.erase(i);
128  return true;
129  }
130  return false;
131  }
132 
133 
134  std::vector<component*> handle_get_children()
135  {
136  std::vector<component*> children;
137  for (ptr v : values_) {
138  children.push_back(&*v);
139  }
140  return children;
141  }
142 
143 protected:
144  void call_factory(ptr_vector& vec, const config& cfg)
145  {
146  factory_(vec, cfg);
147  }
148 private:
149  bool do_add(int pos, const config &cfg)
150  {
151  if (pos<0) {
152  pos = values_.size();
153  }
154  ptr_vector values;
155  call_factory(values,cfg);
156  int j=0;
157  for (ptr b : values ) {
158  values_.insert(values_.begin()+pos+j,b);
159  j++;
160  }
161  return (j>0);
162  }
163 
164  std::function<void(ptr_vector&, const config&)> factory_;
166  ptr_vector &values_;
167 
168 };
169 
170 
171 
172 template<typename T>
176 public:
177 
178  facets_property_handler(const std::string &property, ptr_vector &values, ptr& def, std::function<void(ptr_vector&, const config&)> &construction_factory)
179  : vector_property_handler<T>(property, values, construction_factory)
180  , default_(def)
181  {
182  }
183 
185  {
186  // special case - 'get the default facet'
187  if (child.id == "default_facet") {
188  return default_.get();
189  }
191  }
192 
193  bool handle_change(const path_element &child, config cfg)
194  {
195  // special case - 'replace the default facet'
196  if (child.id == "default_facet") {
197  ptr_vector values;
198  this->call_factory(values,cfg);
199  default_ = values.back();
200  return true;
201  }
203  }
204 
205  std::vector<component*> handle_get_children()
206  {
207  std::vector<component*> children = vector_property_handler<T>::handle_get_children();
208  children.push_back(default_.get());
209  return children;
210  }
211 
212 private:
213  ptr& default_;
214 };
215 
216 
217 
218 template<typename T>
220 public:
221  typedef std::shared_ptr<T> ptr;
222  typedef std::map< std::string, ptr > aspect_map;
223 
224  aspect_property_handler(const std::string &property, aspect_map &aspects, std::function<void(aspect_map&, const config&, std::string)> &construction_factory)
225  : property_(property), aspects_(aspects), factory_(construction_factory)
226  {
227  }
228 
229 
231  {
232  typename aspect_map::const_iterator a = aspects_.find(child.id);
233  if (a!=aspects_.end()){
234  return &*a->second;
235  }
236  return nullptr;
237  }
238 
239  bool handle_change(const path_element &child, config cfg)
240  {
241  if (aspects_.find(child.id) == aspects_.end()) {
242  return false;
243  }
244  if (!cfg.has_attribute("name")) {
245  cfg["name"] = "composite_aspect";
246  }
247  cfg["id"] = child.id;
248  factory_(aspects_, cfg, child.id);
249  return true;
250  }
251 
252  bool handle_add(const path_element &/*child*/, const config &/*cfg*/)
253  {
254  return false;
255  }
256 
257  bool handle_delete(const path_element &child)
258  {
259  //* is a special case - 'delete all facets'
260  if (child.id == "*") {
261  bool b = false;
262  for (typename aspect_map::value_type a : aspects_) {
263  b |= a.second->delete_all_facets();
264  }
265  return b;
266  }
267  return false;
268  }
269 
270 
271  std::vector<component*> handle_get_children()
272  {
273  std::vector<component*> children;
274  for (typename aspect_map::value_type a : aspects_) {
275  children.push_back(&*a.second);
276  }
277  return children;
278  }
279 
280 private:
281 
283  aspect_map &aspects_;
284  std::function<void(aspect_map&, const config&, std::string)> factory_;
285 
286 };
287 
288 
289 template<typename X>
290 static inline void register_vector_property(property_handler_map& property_handlers, const std::string& property,
291  std::vector<std::shared_ptr<X>>& values, std::function<void(std::vector<std::shared_ptr<X>>&, const config&)> construction_factory)
292 {
293  property_handler_ptr handler_ptr(new vector_property_handler<X>(property, values, construction_factory));
294  property_handlers.emplace(property, handler_ptr);
295 }
296 
297 template<typename X>
298 static inline void register_facets_property(property_handler_map& property_handlers, const std::string& property,
299  std::vector<std::shared_ptr<X>>& values, std::shared_ptr<X>& def, std::function<void(std::vector<std::shared_ptr<X>>&, const config&)> construction_factory)
300 {
301  property_handler_ptr handler_ptr(new facets_property_handler<X>(property, values, def, construction_factory));
302  property_handlers.emplace(property, handler_ptr);
303 }
304 
305 template<typename X>
306 static inline void register_aspect_property(property_handler_map& property_handlers, const std::string& property,
307  std::map<std::string, std::shared_ptr<X>>& aspects, std::function<void(std::map<std::string, std::shared_ptr<X>>&, const config&, std::string)> construction_factory)
308 {
309  property_handler_ptr handler_ptr(new aspect_property_handler<X>(property, aspects, construction_factory));
310  property_handlers.emplace(property, handler_ptr);
311 }
312 
313 } //of namespace ai
std::vector< char_t > string
std::vector< component * > handle_get_children()
#define a
void call_factory(ptr_vector &vec, const config &cfg)
bool handle_add(const path_element &, const config &)
bool handle_add(const path_element &child, const config &cfg)
vector_property_handler(const std::string &property, ptr_vector &values, std::function< void(ptr_vector &, const config &)> &construction_factory)
Definitions for the interface to Wesnoth Markup Language (WML).
static void register_vector_property(property_handler_map &property_handlers, const std::string &property, std::vector< std::shared_ptr< X >> &values, std::function< void(std::vector< std::shared_ptr< X >> &, const config &)> construction_factory)
std::vector< component * > handle_get_children()
bool handle_delete(const path_element &child)
bool handle_delete(const path_element &child)
#define b
facets_property_handler(const std::string &property, ptr_vector &values, ptr &def, std::function< void(ptr_vector &, const config &)> &construction_factory)
A small explanation about what's going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:58
component * handle_get(const path_element &child)
std::vector< component * > handle_get_children()
std::vector< std::shared_ptr< T > > ptr_vector
path_element_matches(const path_element &element)
A component of the AI framework.
bool handle_change(const path_element &child, config cfg)
std::string property
Definition: component.hpp:48
virtual bool handle_change(const path_element &child, config cfg)=0
std::string id
Definition: component.hpp:49
bool has_attribute(config_key_type key) const
Definition: config.cpp:196
virtual component * handle_get(const path_element &child)=0
vector_property_handler< T >::ptr ptr
#define i
std::shared_ptr< event_handler > handler_ptr
Shared pointer to handler objects.
Definition: handlers.hpp:40
virtual bool handle_delete(const path_element &child)=0
bool do_add(int pos, const config &cfg)
component * handle_get(const path_element &child)
std::function< void(ptr_vector &, const config &)> factory_
double t
Definition: astarsearch.cpp:64
std::map< std::string, ptr > aspect_map
bool handle_change(const path_element &child, config cfg)
std::map< std::string, property_handler_ptr > property_handler_map
Definition: component.hpp:55
component * handle_get(const path_element &child)
std::function< void(aspect_map &, const config &, std::string)> factory_
vector_property_handler< T >::ptr_vector ptr_vector
static void register_facets_property(property_handler_map &property_handlers, const std::string &property, std::vector< std::shared_ptr< X >> &values, std::shared_ptr< X > &def, std::function< void(std::vector< std::shared_ptr< X >> &, const config &)> construction_factory)
virtual bool handle_add(const path_element &child, const config &cfg)=0
std::shared_ptr< base_property_handler > property_handler_ptr
Definition: component.hpp:53
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
bool handle_change(const path_element &child, config cfg)
virtual std::vector< component * > handle_get_children()=0
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
static void register_aspect_property(property_handler_map &property_handlers, const std::string &property, std::map< std::string, std::shared_ptr< X >> &aspects, std::function< void(std::map< std::string, std::shared_ptr< X >> &, const config &, std::string)> construction_factory)
aspect_property_handler(const std::string &property, aspect_map &aspects, std::function< void(aspect_map &, const config &, std::string)> &construction_factory)