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