ai/composite/component.cpp

Go to the documentation of this file.
00001 /* $Id: component.cpp 52816 2012-01-30 18:35:23Z mordante $ */
00002 /*
00003    Copyright (C) 2009 - 2012 by Yurii Chernyi <terraninfo@terraninfo.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 /**
00017  * Composite AI component
00018  * @file
00019  */
00020 
00021 #include "component.hpp"
00022 #include "engine.hpp"
00023 #include "property_handler.hpp"
00024 #include "../../config.hpp"
00025 #include "../../log.hpp"
00026 #include "../../foreach.hpp"
00027 
00028 #include "../formula/ai.hpp"
00029 
00030 #include <boost/lexical_cast.hpp>
00031 #include <boost/regex.hpp>
00032 
00033 namespace pathfind {
00034 
00035 struct pathfind;
00036 
00037 } //of namespace pathfind
00038 
00039 namespace ai {
00040 
00041 static lg::log_domain log_ai_component("ai/component");
00042 #define DBG_AI_COMPONENT LOG_STREAM(debug, log_ai_component)
00043 #define LOG_AI_COMPONENT LOG_STREAM(info, log_ai_component)
00044 #define ERR_AI_COMPONENT LOG_STREAM(err, log_ai_component)
00045 
00046 
00047 /*
00048 [modify_ai]
00049     path = "stage[fallback]
00050     action = "change"
00051     [stage]...[/stage]
00052 [/modify_ai]
00053 
00054 [modify_ai]
00055     component = "aspect[avoid].facet[zzz]"
00056     action = "change"
00057     [facet]...[/facet]
00058 [/modify_ai]
00059 
00060 [modify_ai]
00061     path = "aspect[aggression].facet[zzzz]
00062     action = "delete"
00063 [/modify_ai]
00064 
00065 [modify_ai]
00066     component = "aspect[aggression].facet"
00067     action = "add"
00068     [facet]...[/facet]
00069 [/modify_ai]
00070 */
00071 
00072 
00073 component* component::get_child(const path_element &child)
00074 {
00075     std::map<std::string, property_handler_ptr>::iterator i = property_handlers_.find(child.property);
00076     if (i!=property_handlers_.end()) {
00077         return i->second->handle_get(child);
00078     }
00079     return NULL;
00080 }
00081 
00082 
00083 bool component::add_child(const path_element &child, const config &cfg)
00084 {
00085     std::map<std::string, property_handler_ptr>::iterator i = property_handlers_.find(child.property);
00086     if (i!=property_handlers_.end()) {
00087         return i->second->handle_add(child,cfg);
00088     }
00089     return false;
00090 }
00091 
00092 
00093 bool component::change_child(const path_element &child, const config &cfg)
00094 {
00095     std::map<std::string, property_handler_ptr>::iterator i = property_handlers_.find(child.property);
00096     if (i!=property_handlers_.end()) {
00097         return i->second->handle_change(child,cfg);
00098     }
00099     return false;
00100 }
00101 
00102 
00103 bool component::delete_child(const path_element &child)
00104 {
00105     std::map<std::string, property_handler_ptr>::iterator i = property_handlers_.find(child.property);
00106     if (i!=property_handlers_.end()) {
00107         return i->second->handle_delete(child);
00108     }
00109     return false;
00110 }
00111 
00112 
00113 std::vector<component*> component::get_children(const std::string &type)
00114 {
00115     property_handler_map::iterator i = property_handlers_.find(type);
00116     if (i!=property_handlers_.end()) {
00117         return i->second->handle_get_children();
00118     }
00119 
00120     return std::vector<component*>();
00121 }
00122 
00123 
00124 std::vector<std::string> component::get_children_types()
00125 {
00126     std::vector<std::string> types;
00127     foreach (property_handler_map::value_type &ph, property_handlers_) {
00128         types.push_back(ph.first);
00129     }
00130     return types;
00131 }
00132 
00133 
00134 property_handler_map& component::property_handlers()
00135 {
00136     return property_handlers_;
00137 }
00138 
00139 static component *find_component(component *root, const std::string &path, path_element &tail)
00140 {
00141     if (root==NULL) {
00142         return NULL;
00143     }
00144 
00145     //match path elements in [modify_ai] tag
00146     boost::regex re("([^\\.^\\[]+)(\\[(\\d*)\\]|\\[([^\\]]+)\\]|())");
00147     int const sub_matches[] = {1,3,4};
00148     boost::sregex_token_iterator i(path.begin(), path.end(), re, sub_matches);
00149     boost::sregex_token_iterator j;
00150 
00151     component *c  = root;
00152 
00153     std::vector< path_element > elements;
00154     while(i != j)
00155     {
00156         path_element pe;
00157         pe.property = *i++;
00158         std::string position = *i++;
00159         pe.id = *i++;
00160         if (position.empty()) {
00161             pe.position = -2;
00162         } else {
00163             try {
00164                 pe.position = boost::lexical_cast<int>(position);
00165             } catch (boost::bad_lexical_cast){
00166                 pe.position = -2;
00167             }
00168         }
00169         //DBG_AI_COMPONENT << "adding path element: "<< pe << std::endl;
00170         elements.push_back(pe);
00171     }
00172     if (elements.size()<1) {
00173         return NULL;
00174     }
00175 
00176     std::vector< path_element >::iterator k_max = elements.end()-1;
00177     for (std::vector< path_element >::iterator k = elements.begin(); k!=k_max; ++k) {
00178         //not last
00179         c = c->get_child(*k);
00180         if (c==NULL) {
00181             return NULL;
00182         }
00183     }
00184 
00185     tail = *k_max;
00186     return c;
00187 
00188 }
00189 
00190 
00191 bool component_manager::add_component(component *root, const std::string &path, const config &cfg)
00192 {
00193     path_element tail;
00194     component *c = find_component(root,path,tail);
00195     if (c==NULL) {
00196         return false;
00197     }
00198     const config &ch = cfg.child(tail.property);
00199     if (!ch) {
00200         return false;
00201     }
00202     return c->add_child(tail, ch);
00203 
00204 }
00205 
00206 bool component_manager::change_component(component *root, const std::string &path, const config &cfg)
00207 {
00208     path_element tail;
00209     component *c = find_component(root,path,tail);
00210     if (c==NULL) {
00211         return false;
00212     }
00213     const config &ch = cfg.child(tail.property);
00214     if (!ch) {
00215         return false;
00216     }
00217     return c->change_child(tail,ch);
00218 }
00219 
00220 bool component_manager::delete_component(component *root, const std::string &path)
00221 {
00222     path_element tail;
00223     component *c = find_component(root,path,tail);
00224     if (c==NULL) {
00225         return false;
00226     }
00227     return c->delete_child(tail);
00228 }
00229 
00230 
00231 static void print_component(component *root, const std::string &type, std::stringstream &s, int offset)
00232 {
00233     std::stringstream offset_ss;
00234     for (int i=0;i<offset;++i) {
00235         offset_ss<<"    ";
00236     }
00237     const std::string &offset_str = offset_ss.str();
00238 
00239     const std::vector<std::string> &t_list = root->get_children_types();
00240 
00241     s << offset_str << type<<"["<<root->get_id() <<"] "<<root->get_engine()<<" "<<root->get_name()<< std::endl;
00242 
00243     foreach (std::string t, t_list) {
00244         std::vector<component*> c_list = root->get_children(t);
00245         foreach (component *c, c_list) {
00246             print_component(c,t,s,offset+1);
00247         }
00248     }
00249 }
00250 
00251 std::string component_manager::print_component_tree(component *root, const std::string &path)
00252 {
00253     path_element tail;
00254     component *c;
00255     if (!path.empty()) {
00256         c = find_component(root,path,tail);
00257         if (c==NULL) {
00258             ERR_AI_COMPONENT << "unable to find component" <<std::endl;
00259             return "";
00260         }
00261     } else {
00262         c = root;
00263     }
00264     std::stringstream s;
00265     print_component(c, "", s, 0);
00266     return s.str();
00267 }
00268 
00269 } //end of namespace ai
00270 
00271 
00272 std::ostream &operator<<(std::ostream &o, const ai::path_element &e)
00273 {
00274     o << "property["<<e.property<<"] id["<<e.id <<"] position["<<e.position<<"]"<<std::endl;
00275     return o;
00276 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Thu May 24 2012 01:02:28 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs