PageRenderTime 26ms CodeModel.GetById 35ms RepoModel.GetById 0ms app.codeStats 0ms

/wesnoth-1.10.3/src/ai/composite/component.cpp

#
C++ | 277 lines | 185 code | 47 blank | 45 comment | 21 complexity | dc992cf20d4531c5f0814efec59a0065 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, EPL-1.0
  1. /* $Id: component.cpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
  2. /*
  3. Copyright (C) 2009 - 2012 by Yurii Chernyi <terraninfo@terraninfo.net>
  4. Part of the Battle for Wesnoth Project http://www.wesnoth.org/
  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. See the COPYING file for more details.
  12. */
  13. /**
  14. * Composite AI component
  15. * @file
  16. */
  17. #include "component.hpp"
  18. #include "engine.hpp"
  19. #include "property_handler.hpp"
  20. #include "../../config.hpp"
  21. #include "../../log.hpp"
  22. #include "../../foreach.hpp"
  23. #include "../formula/ai.hpp"
  24. #include <boost/lexical_cast.hpp>
  25. #include <boost/regex.hpp>
  26. namespace pathfind {
  27. struct pathfind;
  28. } //of namespace pathfind
  29. namespace ai {
  30. static lg::log_domain log_ai_component("ai/component");
  31. #define DBG_AI_COMPONENT LOG_STREAM(debug, log_ai_component)
  32. #define LOG_AI_COMPONENT LOG_STREAM(info, log_ai_component)
  33. #define ERR_AI_COMPONENT LOG_STREAM(err, log_ai_component)
  34. /*
  35. [modify_ai]
  36. path = "stage[fallback]
  37. action = "change"
  38. [stage]...[/stage]
  39. [/modify_ai]
  40. [modify_ai]
  41. component = "aspect[avoid].facet[zzz]"
  42. action = "change"
  43. [facet]...[/facet]
  44. [/modify_ai]
  45. [modify_ai]
  46. path = "aspect[aggression].facet[zzzz]
  47. action = "delete"
  48. [/modify_ai]
  49. [modify_ai]
  50. component = "aspect[aggression].facet"
  51. action = "add"
  52. [facet]...[/facet]
  53. [/modify_ai]
  54. */
  55. component* component::get_child(const path_element &child)
  56. {
  57. std::map<std::string, property_handler_ptr>::iterator i = property_handlers_.find(child.property);
  58. if (i!=property_handlers_.end()) {
  59. return i->second->handle_get(child);
  60. }
  61. return NULL;
  62. }
  63. bool component::add_child(const path_element &child, const config &cfg)
  64. {
  65. std::map<std::string, property_handler_ptr>::iterator i = property_handlers_.find(child.property);
  66. if (i!=property_handlers_.end()) {
  67. return i->second->handle_add(child,cfg);
  68. }
  69. return false;
  70. }
  71. bool component::change_child(const path_element &child, const config &cfg)
  72. {
  73. std::map<std::string, property_handler_ptr>::iterator i = property_handlers_.find(child.property);
  74. if (i!=property_handlers_.end()) {
  75. return i->second->handle_change(child,cfg);
  76. }
  77. return false;
  78. }
  79. bool component::delete_child(const path_element &child)
  80. {
  81. std::map<std::string, property_handler_ptr>::iterator i = property_handlers_.find(child.property);
  82. if (i!=property_handlers_.end()) {
  83. return i->second->handle_delete(child);
  84. }
  85. return false;
  86. }
  87. std::vector<component*> component::get_children(const std::string &type)
  88. {
  89. std::vector<component*> components;
  90. property_handler_map::iterator i = property_handlers_.find(type);
  91. if (i!=property_handlers_.end()) {
  92. return i->second->handle_get_children();
  93. }
  94. return components;
  95. }
  96. std::vector<std::string> component::get_children_types()
  97. {
  98. std::vector<std::string> types;
  99. foreach (property_handler_map::value_type &ph, property_handlers_) {
  100. types.push_back(ph.first);
  101. }
  102. return types;
  103. }
  104. property_handler_map& component::property_handlers()
  105. {
  106. return property_handlers_;
  107. }
  108. static component *find_component(component *root, const std::string &path, path_element &tail)
  109. {
  110. if (root==NULL) {
  111. return NULL;
  112. }
  113. //match path elements in [modify_ai] tag
  114. boost::regex re("([^\\.^\\[]+)(\\[(\\d*)\\]|\\[([^\\]]+)\\]|())");
  115. int const sub_matches[] = {1,3,4};
  116. boost::sregex_token_iterator i(path.begin(), path.end(), re, sub_matches);
  117. boost::sregex_token_iterator j;
  118. component *c = root;
  119. std::vector< path_element > elements;
  120. while(i != j)
  121. {
  122. path_element pe;
  123. pe.property = *i++;
  124. std::string position = *i++;
  125. pe.id = *i++;
  126. if (position.empty()) {
  127. pe.position = -2;
  128. } else {
  129. try {
  130. pe.position = boost::lexical_cast<int>(position);
  131. } catch (boost::bad_lexical_cast){
  132. pe.position = -2;
  133. }
  134. }
  135. //DBG_AI_COMPONENT << "adding path element: "<< pe << std::endl;
  136. elements.push_back(pe);
  137. }
  138. if (elements.size()<1) {
  139. return NULL;
  140. }
  141. std::vector< path_element >::iterator k_max = elements.end()-1;
  142. for (std::vector< path_element >::iterator k = elements.begin(); k!=k_max; ++k) {
  143. //not last
  144. c = c->get_child(*k);
  145. if (c==NULL) {
  146. return NULL;
  147. }
  148. }
  149. tail = *k_max;
  150. return c;
  151. }
  152. bool component_manager::add_component(component *root, const std::string &path, const config &cfg)
  153. {
  154. path_element tail;
  155. component *c = find_component(root,path,tail);
  156. if (c==NULL) {
  157. return false;
  158. }
  159. const config &ch = cfg.child(tail.property);
  160. if (!ch) {
  161. return false;
  162. }
  163. return c->add_child(tail, ch);
  164. }
  165. bool component_manager::change_component(component *root, const std::string &path, const config &cfg)
  166. {
  167. path_element tail;
  168. component *c = find_component(root,path,tail);
  169. if (c==NULL) {
  170. return false;
  171. }
  172. const config &ch = cfg.child(tail.property);
  173. if (!ch) {
  174. return false;
  175. }
  176. return c->change_child(tail,ch);
  177. }
  178. bool component_manager::delete_component(component *root, const std::string &path)
  179. {
  180. path_element tail;
  181. component *c = find_component(root,path,tail);
  182. if (c==NULL) {
  183. return false;
  184. }
  185. return c->delete_child(tail);
  186. }
  187. static void print_component(component *root, const std::string &type, std::stringstream &s, int offset)
  188. {
  189. std::stringstream offset_ss;
  190. for (int i=0;i<offset;++i) {
  191. offset_ss<<" ";
  192. }
  193. const std::string &offset_str = offset_ss.str();
  194. const std::vector<std::string> &t_list = root->get_children_types();
  195. s << offset_str << type<<"["<<root->get_id() <<"] "<<root->get_engine()<<" "<<root->get_name()<< std::endl;
  196. foreach (std::string t, t_list) {
  197. std::vector<component*> c_list = root->get_children(t);
  198. foreach (component *c, c_list) {
  199. print_component(c,t,s,offset+1);
  200. }
  201. }
  202. }
  203. std::string component_manager::print_component_tree(component *root, const std::string &path)
  204. {
  205. path_element tail;
  206. component *c;
  207. if (!path.empty()) {
  208. c = find_component(root,path,tail);
  209. if (c==NULL) {
  210. ERR_AI_COMPONENT << "unable to find component" <<std::endl;
  211. return "";
  212. }
  213. } else {
  214. c = root;
  215. }
  216. std::stringstream s;
  217. print_component(c, "", s, 0);
  218. return s.str();
  219. }
  220. } //end of namespace ai
  221. std::ostream &operator<<(std::ostream &o, const ai::path_element &e)
  222. {
  223. o << "property["<<e.property<<"] id["<<e.id <<"] position["<<e.position<<"]"<<std::endl;
  224. return o;
  225. }