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