The Battle for Wesnoth  1.13.10+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
component.cpp
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 
21 #include "ai/composite/engine.hpp"
23 #include "config.hpp"
24 #include "log.hpp"
25 #include "units/unit.hpp"
26 
27 #include "ai/formula/ai.hpp"
28 
29 #include <boost/regex.hpp>
30 
31 namespace pathfind {
32 
33 struct pathfind;
34 
35 } //of namespace pathfind
36 
37 namespace ai {
38 
39 static lg::log_domain log_ai_component("ai/component");
40 #define DBG_AI_COMPONENT LOG_STREAM(debug, log_ai_component)
41 #define LOG_AI_COMPONENT LOG_STREAM(info, log_ai_component)
42 #define ERR_AI_COMPONENT LOG_STREAM(err, log_ai_component)
43 
44 
45 /*
46 [modify_ai]
47  path = "stage[fallback]
48  action = "change"
49  [stage]...[/stage]
50 [/modify_ai]
51 
52 [modify_ai]
53  component = "aspect[avoid].facet[zzz]"
54  action = "change"
55  [facet]...[/facet]
56 [/modify_ai]
57 
58 [modify_ai]
59  path = "aspect[aggression].facet[zzzz]
60  action = "delete"
61 [/modify_ai]
62 
63 [modify_ai]
64  component = "aspect[aggression].facet"
65  action = "add"
66  [facet]...[/facet]
67 [/modify_ai]
68 */
69 
70 
72 {
74  if (i!=property_handlers_.end()) {
75  return i->second->handle_get(child);
76  }
77  return nullptr;
78 }
79 
80 
81 bool component::add_child(const path_element &child, const config &cfg)
82 {
84  if (i!=property_handlers_.end()) {
85  return i->second->handle_add(child,cfg);
86  }
87  return false;
88 }
89 
90 
91 bool component::change_child(const path_element &child, const config &cfg)
92 {
94  if (i!=property_handlers_.end()) {
95  return i->second->handle_change(child,cfg);
96  }
97  return false;
98 }
99 
100 
102 {
104  if (i!=property_handlers_.end()) {
105  return i->second->handle_delete(child);
106  }
107  return false;
108 }
109 
110 
111 std::vector<component*> component::get_children(const std::string &type)
112 {
114  if (i!=property_handlers_.end()) {
115  return i->second->handle_get_children();
116  }
117 
118  return std::vector<component*>();
119 }
120 
121 
122 std::vector<std::string> component::get_children_types()
123 {
124  std::vector<std::string> types;
125  for (property_handler_map::value_type &ph : property_handlers_) {
126  types.push_back(ph.first);
127  }
128  return types;
129 }
130 
131 
133 {
134  return property_handlers_;
135 }
136 
138 {
139  if (root==nullptr) {
140  return nullptr;
141  }
142 
143  //match path elements in [modify_ai] tag
144  boost::regex re(R"""(([^\.^\[]+)(\[(\d*)\]|\[([^\]]+)\]|()))""");
145  const int sub_matches[] {1,3,4};
146  boost::sregex_token_iterator i(path.begin(), path.end(), re, sub_matches);
147  boost::sregex_token_iterator j;
148 
149  component *c = root;
150 
151  std::vector< path_element > elements;
152  while(i != j)
153  {
154  path_element pe;
155  pe.property = *i++;
156  std::string position = *i++;
157  pe.id = *i++;
158  if (position.empty()) {
159  pe.position = -2;
160  } else {
161  try {
162  pe.position = std::stoi(position);
163  } catch (std::invalid_argument&) {
164  pe.position = -2;
165  }
166  }
167  //DBG_AI_COMPONENT << "adding path element: "<< pe << std::endl;
168  elements.push_back(pe);
169  }
170  if (elements.size()<1) {
171  return nullptr;
172  }
173 
174  std::vector< path_element >::iterator k_max = elements.end()-1;
175  for (std::vector< path_element >::iterator k = elements.begin(); k!=k_max; ++k) {
176  //not last
177  c = c->get_child(*k);
178  if (c==nullptr) {
179  return nullptr;
180  }
181  }
182 
183  tail = *k_max;
184  return c;
185 
186 }
187 
188 
190 {
191  path_element tail;
192  component *c = find_component(root,path,tail);
193  if (c==nullptr) {
194  return false;
195  }
196  const config &ch = cfg.child(tail.property);
197  if (!ch) {
198  return false;
199  }
200  return c->add_child(tail, ch);
201 
202 }
203 
205 {
206  path_element tail;
207  component *c = find_component(root,path,tail);
208  if (c==nullptr) {
209  return false;
210  }
211  const config &ch = cfg.child(tail.property);
212  if (!ch) {
213  return false;
214  }
215  return c->change_child(tail,ch);
216 }
217 
219 {
220  path_element tail;
221  component *c = find_component(root,path,tail);
222  if (c==nullptr) {
223  return false;
224  }
225  return c->delete_child(tail);
226 }
227 
228 
229 static void print_component(component *root, const std::string &type, std::stringstream &s, int offset)
230 {
231  std::stringstream offset_ss;
232  for (int i=0;i<offset;++i) {
233  offset_ss<<" ";
234  }
235  const std::string &offset_str = offset_ss.str();
236 
237  const std::vector<std::string> &t_list = root->get_children_types();
238 
239  s << offset_str << type<<"["<<root->get_id() <<"] "<<root->get_engine()<<" "<<root->get_name()<< std::endl;
240 
241  for (std::string t : t_list) {
242  std::vector<component*> c_list = root->get_children(t);
243  for (component *c : c_list) {
244  print_component(c,t,s,offset+1);
245  }
246  }
247 }
248 
250 {
251  path_element tail;
252  component *c;
253  if (!path.empty()) {
254  c = find_component(root,path,tail);
255  if (c==nullptr) {
256  ERR_AI_COMPONENT << "unable to find component" <<std::endl;
257  return "";
258  }
259  } else {
260  c = root;
261  }
262  std::stringstream s;
263  print_component(c, "", s, 0);
264  return s.str();
265 }
266 
268 {
269  if(!path.empty()) {
270  path_element tail;
271  return find_component(root, path, tail);
272  }
273  return nullptr;
274 }
275 
276 } //end of namespace ai
277 
278 
279 std::ostream &operator<<(std::ostream &o, const ai::path_element &e)
280 {
281  o << "property["<<e.property<<"] id["<<e.id <<"] position["<<e.position<<"]"<<std::endl;
282  return o;
283 }
Defines formula ai.
virtual std::string get_id() const =0
virtual bool change_child(const path_element &child, const config &cfg)
Definition: component.cpp:91
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:400
std::vector< char_t > string
property_handler_map property_handlers_
Definition: component.hpp:78
static bool change_component(component *root, const std::string &path, const config &cfg)
Definition: component.cpp:204
virtual std::vector< component * > get_children(const std::string &type)
Definition: component.cpp:111
property_handler_map & property_handlers()
Definition: component.cpp:132
AI Support engine - creating specific ai components from config.
Definitions for the interface to Wesnoth Markup Language (WML).
virtual bool add_child(const path_element &child, const config &cfg)
Definition: component.cpp:81
static component * find_component(component *root, const std::string &path, path_element &tail)
Definition: component.cpp:137
A small explanation about what's going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:58
static component * get_component(component *root, const std::string &path)
Definition: component.cpp:267
static void print_component(component *root, const std::string &type, std::stringstream &s, int offset)
Definition: component.cpp:229
virtual std::string get_engine() const =0
A component of the AI framework.
std::ostream & operator<<(std::ostream &o, const ai::path_element &e)
Definition: component.cpp:279
virtual component * get_child(const path_element &child)
Definition: component.cpp:71
std::string path
Definition: game_config.cpp:56
std::string property
Definition: component.hpp:48
std::string id
Definition: component.hpp:49
virtual std::string get_name() const =0
static bool delete_component(component *root, const std::string &path)
Definition: component.cpp:218
static lg::log_domain log_ai_component("ai/component")
static bool add_component(component *root, const std::string &path, const config &cfg)
Definition: component.cpp:189
virtual bool delete_child(const path_element &child)
Definition: component.cpp:101
static std::string print_component_tree(component *root, const std::string &path)
Definition: component.cpp:249
static map_location::DIRECTION s
size_t i
Definition: function.cpp:933
virtual std::vector< std::string > get_children_types()
Definition: component.cpp:122
Composite AI component.
double t
Definition: astarsearch.cpp:64
std::map< std::string, property_handler_ptr > property_handler_map
Definition: component.hpp:55
#define ERR_AI_COMPONENT
Definition: component.cpp:42
Standard logging facilities (interface).
#define e
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
mock_char c
std::string::const_iterator iterator
Definition: tokenizer.hpp:24