The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
property_handler.hpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2009 - 2025
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
29namespace ai{
30
31template<typename T>
33public:
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
52private:
53 int count_;
55};
56
57class component;
58
60public:
61
63
64 virtual component* handle_get(const path_element &child) const = 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() const = 0;
69};
70
71typedef std::shared_ptr< base_property_handler > property_handler_ptr;
72
73template<typename T>
75public:
76 typedef std::shared_ptr<T> ptr;
77 typedef std::vector< std::shared_ptr<T>> ptr_vector;
78
79 template<typename Factory>
80 vector_property_handler(const std::string &property, ptr_vector &values, Factory&& construction_factory)
81 : factory_(construction_factory), property_(property), values_(values){}
82
83 component* handle_get(const path_element &child) const
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 }
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 std::vector<component*> handle_get_children() const
134 {
135 std::vector<component*> children;
136 for (ptr v : values_) {
137 children.push_back(&*v);
138 }
139 return children;
140 }
141
142protected:
144 {
145 factory_(vec, cfg);
146 }
147private:
148 bool do_add(int pos, const config &cfg)
149 {
150 if (pos<0) {
151 pos = values_.size();
152 }
153 ptr_vector values;
154 call_factory(values,cfg);
155 int j=0;
156 for (ptr b : values ) {
157 values_.insert(values_.begin()+pos+j,b);
158 j++;
159 }
160 return (j>0);
161 }
162
163 std::function<void(ptr_vector&, const config&)> factory_;
164 const std::string property_;
166
167};
168
169template<typename T>
173public:
174
175 template<typename Factory>
176 facets_property_handler(const std::string &property, ptr_vector &values, ptr& def, Factory&& construction_factory)
177 : vector_property_handler<T>(property, values, construction_factory)
178 , default_(def)
179 {
180 }
181
182 component* handle_get(const path_element &child) const
183 {
184 // special case - 'get the default facet'
185 if (child.id == "default_facet") {
186 return default_.get();
187 }
189 }
190
192 {
193 // special case - 'replace the default facet'
194 if (child.id == "default_facet") {
195 ptr_vector values;
196 this->call_factory(values,cfg);
197 default_ = values.back();
198 return true;
199 }
201 }
202
203 std::vector<component*> handle_get_children() const
204 {
205 std::vector<component*> children = vector_property_handler<T>::handle_get_children();
206 children.push_back(default_.get());
207 return children;
208 }
209
210private:
212};
213
214template<typename T>
216public:
217 typedef std::shared_ptr<T> ptr;
218 typedef std::map< std::string, ptr > aspect_map;
219
220 template<typename Factory>
221 aspect_property_handler(const std::string &property, aspect_map &aspects, Factory&& construction_factory)
222 : property_(property), aspects_(aspects), factory_(construction_factory)
223 {
224 }
225
226 component* handle_get(const path_element &child) const
227 {
228 typename aspect_map::const_iterator a = aspects_.find(child.id);
229 if (a!=aspects_.end()){
230 return &*a->second;
231 }
232 return nullptr;
233 }
234
236 {
237 if (aspects_.find(child.id) == aspects_.end()) {
238 return false;
239 }
240 if (!cfg.has_attribute("name")) {
241 cfg["name"] = "composite_aspect";
242 }
243 cfg["id"] = child.id;
244 factory_(aspects_, cfg, child.id);
245 return true;
246 }
247
248 bool handle_add(const path_element &/*child*/, const config &/*cfg*/)
249 {
250 return false;
251 }
252
253 bool handle_delete(const path_element &child)
254 {
255 //* is a special case - 'delete all facets'
256 if (child.id == "*") {
257 bool b = false;
258 for (typename aspect_map::value_type a : aspects_) {
259 b |= a.second->delete_all_facets();
260 }
261 return b;
262 }
263 return false;
264 }
265
266 std::vector<component*> handle_get_children() const
267 {
268 std::vector<component*> children;
269 for (typename aspect_map::value_type a : aspects_) {
270 children.push_back(&*a.second);
271 }
272 return children;
273 }
274
275private:
276
277 const std::string &property_;
279 std::function<void(aspect_map&, const config&, std::string)> factory_;
280
281};
282
283template<typename X, typename Factory>
284static inline void register_vector_property(property_handler_map& property_handlers, const std::string& property,
285 std::vector<std::shared_ptr<X>>& values, Factory&& construction_factory)
286{
287 property_handlers.emplace(property,
288 std::make_shared<vector_property_handler<X>>(property, values, std::move(construction_factory)));
289}
290
291template<typename X, typename Factory>
292static inline void register_facets_property(property_handler_map& property_handlers, const std::string& property,
293 std::vector<std::shared_ptr<X>>& values, std::shared_ptr<X>& def, Factory&& construction_factory)
294{
295 property_handlers.emplace(property,
296 std::make_shared<facets_property_handler<X>>(property, values, def, std::move(construction_factory)));
297}
298
299template<typename X, typename Factory>
300static inline void register_aspect_property(property_handler_map& property_handlers, const std::string& property,
301 std::map<std::string, std::shared_ptr<X>>& aspects, Factory&& construction_factory)
302{
303 property_handlers.emplace(property,
304 std::make_shared<aspect_property_handler<X>>(property, aspects, std::move(construction_factory)));
305}
306
307} //of namespace ai
double t
bool handle_add(const path_element &, const config &)
std::function< void(aspect_map &, const config &, std::string)> factory_
std::vector< component * > handle_get_children() const
std::map< std::string, ptr > aspect_map
bool handle_change(const path_element &child, config cfg)
bool handle_delete(const path_element &child)
component * handle_get(const path_element &child) const
aspect_property_handler(const std::string &property, aspect_map &aspects, Factory &&construction_factory)
virtual bool handle_delete(const path_element &child)=0
virtual bool handle_add(const path_element &child, const config &cfg)=0
virtual bool handle_change(const path_element &child, config cfg)=0
virtual std::vector< component * > handle_get_children() const =0
virtual component * handle_get(const path_element &child) const =0
std::vector< component * > handle_get_children() const
component * handle_get(const path_element &child) const
vector_property_handler< T >::ptr ptr
bool handle_change(const path_element &child, config cfg)
facets_property_handler(const std::string &property, ptr_vector &values, ptr &def, Factory &&construction_factory)
vector_property_handler< T >::ptr_vector ptr_vector
path_element_matches(const path_element &element)
void call_factory(ptr_vector &vec, const config &cfg)
std::function< void(ptr_vector &, const config &)> factory_
bool handle_add(const path_element &child, const config &cfg)
std::vector< component * > handle_get_children() const
vector_property_handler(const std::string &property, ptr_vector &values, Factory &&construction_factory)
bool do_add(int pos, const config &cfg)
component * handle_get(const path_element &child) const
std::vector< std::shared_ptr< T > > ptr_vector
bool handle_change(const path_element &child, config cfg)
bool handle_delete(const path_element &child)
A config object defines a single node in a WML file, with access to child nodes.
Definition config.hpp:157
bool has_attribute(std::string_view key) const
Definition config.cpp:157
A component of the AI framework.
Definitions for the interface to Wesnoth Markup Language (WML).
const config * cfg
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_vector_property(property_handler_map &property_handlers, const std::string &property, std::vector< std::shared_ptr< X > > &values, Factory &&construction_factory)
std::shared_ptr< base_property_handler > property_handler_ptr
Definition component.hpp:47
static void register_aspect_property(property_handler_map &property_handlers, const std::string &property, std::map< std::string, std::shared_ptr< X > > &aspects, Factory &&construction_factory)
std::map< std::string, property_handler_ptr > property_handler_map
Definition component.hpp:48
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, Factory &&construction_factory)
std::string property
Definition component.hpp:41
std::string id
Definition component.hpp:42
#define i
#define b