00001 /* $Id: manager.hpp 52533 2012-01-07 02:35:17Z shadowmaster $ */ 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 * @file 00018 * Managing the AIs lifecycle - headers 00019 * @todo 1.9 Refactor history handling and internal commands. 00020 * @todo 1.9 AI Interface command to clear the history. 00021 */ 00022 00023 #ifndef AI_MANAGER_HPP_INCLUDED 00024 #define AI_MANAGER_HPP_INCLUDED 00025 00026 #include "../config.hpp" 00027 #include "../generic_event.hpp" 00028 00029 #include "game_info.hpp" 00030 00031 #include <stack> 00032 #include <deque> 00033 00034 00035 namespace ai { 00036 00037 class interface; 00038 00039 class side_context; 00040 class readonly_context; 00041 class readwrite_context; 00042 class default_ai_context; 00043 class ai_context; 00044 00045 class ai_composite; 00046 typedef boost::shared_ptr<ai_composite> composite_ai_ptr; 00047 00048 /** 00049 * Base class that holds the AI and current AI parameters. 00050 * It is an implementation detail. 00051 * @todo 1.9 move it out of public view 00052 */ 00053 class holder{ 00054 public: 00055 holder(side_number side, const config &cfg); 00056 00057 virtual ~holder(); 00058 00059 interface& get_ai_ref(); 00060 00061 const std::string describe_ai(); 00062 00063 void modify_ai_config_old( const config::const_child_itors &ai_parameters ); 00064 00065 config to_config() const; 00066 00067 void modify_ai(const config& cfg); 00068 00069 00070 const std::string get_ai_overview(); 00071 00072 00073 const std::string get_ai_structure(); 00074 00075 00076 const std::string get_ai_identifier() const; 00077 00078 private: 00079 void init( side_number side ); 00080 00081 00082 composite_ai_ptr ai_; 00083 side_context *side_context_; 00084 readonly_context *readonly_context_; 00085 readwrite_context *readwrite_context_; 00086 default_ai_context *default_ai_context_; 00087 side_number side_; 00088 config cfg_; 00089 }; 00090 00091 /** 00092 * AI Command History Item. It is an implementation detail 00093 */ 00094 class command_history_item{ 00095 public: 00096 00097 command_history_item(int number, const std::string &command) 00098 : number_(number), command_(command) 00099 {} 00100 00101 int get_number() const { return number_; } 00102 00103 const std::string& get_command() const { return command_; } 00104 00105 private: 00106 int number_; 00107 std::string command_; 00108 00109 }; 00110 00111 /** 00112 * Class that manages AIs for all sides and manages AI redeployment. 00113 * This class is responsible for managing the AI lifecycle 00114 * It can be accessed like this: ai::manager::foo(...); 00115 */ 00116 class manager 00117 { 00118 public: 00119 00120 // ======================================================================= 00121 // CONSTANTS 00122 // ======================================================================= 00123 00124 static const size_t MAX_HISTORY_SIZE = 200; 00125 00126 static const std::string AI_TYPE_COMPOSITE_AI; 00127 static const std::string AI_TYPE_SAMPLE_AI; 00128 static const std::string AI_TYPE_IDLE_AI; 00129 static const std::string AI_TYPE_FORMULA_AI; 00130 static const std::string AI_TYPE_DFOOL_AI; 00131 static const std::string AI_TYPE_AI2; 00132 static const std::string AI_TYPE_DEFAULT; 00133 00134 00135 // ======================================================================= 00136 // LIFECYCLE 00137 // ======================================================================= 00138 00139 /** 00140 * Sets AI information. 00141 * @param info ai_information to be set. 00142 */ 00143 static void set_ai_info(const game_info& info); 00144 00145 00146 /** 00147 * Clears AI information. 00148 * Should be called in playsingle_controller 's destructor. 00149 */ 00150 static void clear_ai_info(); 00151 00152 00153 /** 00154 * Adds observer of game events. 00155 * Should be called in playsingle_controller 's constructor. 00156 */ 00157 static void add_observer( events::observer* event_observer); 00158 00159 00160 /** 00161 * Removes an observer of game events. 00162 * Should be called in playsingle_controller 's destructor. 00163 */ 00164 static void remove_observer( events::observer* event_observer ); 00165 00166 00167 /** 00168 * Adds observer of game events except ai_user_interact event and ai_sync_network event 00169 */ 00170 static void add_gamestate_observer( events::observer* event_observer); 00171 00172 00173 /** 00174 * Removes an observer of game events except ai_user_interact event and ai_sync_network event 00175 */ 00176 static void remove_gamestate_observer( events::observer* event_observer ); 00177 00178 00179 /** 00180 * Notifies all observers of 'ai_user_interact' event. 00181 * Function which should be called frequently to allow the user to interact 00182 * with the interface. This function will make sure that interaction 00183 * doesn't occur too often, so there is no problem with calling it very 00184 * regularly. 00185 */ 00186 static void raise_user_interact(); 00187 00188 /** 00189 * Notifies all observers of 'ai_sync_network' event. 00190 * Basically a request from the AI to sync the network. 00191 */ 00192 static void raise_sync_network(); 00193 00194 00195 /** 00196 * Notifies all observers of 'ai_gamestate_changed' event. 00197 */ 00198 static void raise_gamestate_changed(); 00199 00200 00201 /** 00202 * Notifies all observers of 'ai_recruit_list_changed' event. 00203 */ 00204 static void raise_recruit_list_changed(); 00205 00206 00207 /** 00208 * Notifies all observers of 'ai_turn_started' event. 00209 */ 00210 static void raise_turn_started(); 00211 00212 00213 /** 00214 * Notifies all observers of 'ai_map_changed' event. 00215 */ 00216 static void raise_map_changed(); 00217 00218 00219 /** 00220 * Adds an observer of 'ai_map_changed' event. 00221 */ 00222 static void add_map_changed_observer( events::observer* event_observer ); 00223 00224 00225 /** 00226 * Adds an observer of 'ai_recruit_list_changed' event. 00227 */ 00228 static void add_recruit_list_changed_observer( events::observer* event_observer ); 00229 00230 00231 /** 00232 * Adds an observer of 'ai_turn_started' event. 00233 */ 00234 static void add_turn_started_observer( events::observer* event_observer ); 00235 00236 00237 /** 00238 * Deletes an observer of 'ai_map_changed' event. 00239 */ 00240 static void remove_map_changed_observer( events::observer* event_observer ); 00241 00242 00243 00244 /** 00245 * Deletes an observer of 'ai_recruit_list_changed' event. 00246 */ 00247 static void remove_recruit_list_changed_observer( events::observer* event_observer ); 00248 00249 00250 /** 00251 * Deletes an observer of 'ai_turn_started' event. 00252 */ 00253 static void remove_turn_started_observer( events::observer* event_observer ); 00254 00255 00256 private: 00257 00258 manager(); 00259 00260 00261 public: 00262 00263 // ======================================================================= 00264 // EVALUATION 00265 // ======================================================================= 00266 00267 /** 00268 * Evaluates a string command using command AI. 00269 * @note Running this command may invalidate references previously returned 00270 * by manager. Will intercept those commands which start with '!' 00271 * and '?', and will try to evaluate them as internal commands. 00272 * @param side side number (1-based). 00273 * @param str string to evaluate. 00274 * @return string result of evaluation. 00275 */ 00276 static const std::string evaluate_command( side_number side, const std::string& str ); 00277 00278 00279 // ======================================================================= 00280 // ADD, CREATE AIs, OR LIST AI TYPES 00281 // ======================================================================= 00282 00283 /** 00284 * Adds active AI for specified @a side from @a file. 00285 * @note Running this command may invalidate references previously returned 00286 * by manager. AI is not initialized at this point. 00287 * @param side side number (1-based, as in game_info). 00288 * @param file file name, follows the usual WML convention. 00289 * @param replace should new ai replace the current ai or 'be placed on top of it'. 00290 * @return true if successful. 00291 */ 00292 static bool add_ai_for_side_from_file( side_number side, const std::string& file, bool replace = true ); 00293 00294 00295 /** 00296 * Adds active AI for specified @a side from @a cfg. 00297 * @note Running this command may invalidate references previously returned 00298 * by manager. AI is not initialized at this point. 00299 * @param side side number (1-based, as in game_info). 00300 * @param cfg the config from which all ai parameters are to be read. 00301 * @param replace should new ai replace the current ai or 'be placed on top of it'. 00302 * @return true if successful. 00303 */ 00304 static bool add_ai_for_side_from_config(side_number side, const config &cfg, bool replace = true); 00305 00306 00307 /** 00308 * Adds active AI for specified @a side from parameters. 00309 * @note Running this command may invalidate references previously returned 00310 * by manager. AI is not initialized at this point. 00311 * @param side side number (1-based, as in game_info). 00312 * @param ai_algorithm_type type of AI algorithm to create. 00313 * @param replace should new ai replace the current ai or 'be placed on top of it'. 00314 * @return true if successful. 00315 */ 00316 static bool add_ai_for_side( side_number side, const std::string& ai_algorithm_type, bool replace = true); 00317 00318 00319 /** 00320 * Returns a smart pointer to a new AI. 00321 * @param ai_algorithm_type type of AI algorithm to create 00322 * @param cfg a config of the ai 00323 * @param context context in which this ai is created 00324 * @return the reference to the created AI 00325 */ 00326 static ai_ptr create_transient_ai( const std::string &ai_algorithm_type, const config &cfg, ai_context *ai_context); 00327 00328 00329 // ======================================================================= 00330 // REMOVE 00331 // ======================================================================= 00332 00333 /** 00334 * Removes top-level AI from @a side. 00335 * @note Running this command may invalidate references previously returned 00336 * by manager. 00337 * @param side side number (1-based, as in game_info). 00338 */ 00339 static void remove_ai_for_side( side_number side ); 00340 00341 00342 /** 00343 * Removes all AIs from @a side. 00344 * @note Running this command may invalidate references previously returned 00345 * by manager. 00346 * @param side side number (1-based, as in game_info). 00347 */ 00348 static void remove_all_ais_for_side( side_number side ); 00349 00350 00351 /** 00352 * Clears all the AIs. 00353 * @note Running this command may invalidate references previously returned 00354 * by manager. For example, this is called from the destructor of 00355 * playsingle_controller. It is necessary to do this if any of the 00356 * info structures used by the AI goes out of scope. 00357 */ 00358 static void clear_ais(); 00359 00360 // ======================================================================= 00361 // GET active AI parameters 00362 // ======================================================================= 00363 00364 00365 /** 00366 * Gets AI info for active AI of the given @a side. 00367 * @param side side number (1-based). 00368 * @return a reference to active AI info. 00369 */ 00370 static game_info& get_active_ai_info_for_side( side_number side ); 00371 00372 00373 /** 00374 * Gets AI Overview for active AI of the given @a side 00375 * @param side side number (1-based) 00376 * @return an ai overview 00377 */ 00378 static std::string get_active_ai_overview_for_side( side_number side); 00379 00380 00381 /** 00382 * Gets AI Structure for active AI of the given @a side 00383 * @param side side number (1-based) 00384 * @return an ai structure 00385 */ 00386 static std::string get_active_ai_structure_for_side( side_number side); 00387 00388 /** 00389 * Gets AI algorithm identifier for active AI of the given @a side. 00390 * @param side side number (1-based). 00391 * @return ai identifier for the active AI 00392 */ 00393 static std::string get_active_ai_identifier_for_side( side_number side ); 00394 00395 00396 /** 00397 * Gets AI config for active AI of the given @a side. 00398 * @param side side number (1-based). 00399 * @return a config object for the active AI 00400 */ 00401 static config to_config( side_number side ); 00402 00403 00404 /** 00405 * Gets global AI-game info 00406 * @return a reference to the AI-game info. 00407 */ 00408 static game_info& get_ai_info(); 00409 00410 00411 // ======================================================================= 00412 // SET active AI parameters 00413 // ======================================================================= 00414 00415 00416 /** 00417 * Modifies AI parameters for active AI of the given @a side. 00418 * This function is provided for backward-compatibility with [modify_side][ai]...[/ai][/modify_side] 00419 * It can only add new facets to aspects 00420 * @param side side_number (1-based, as in game_info). 00421 * @param ai_parameters AI parameters to be modified. 00422 */ 00423 static void modify_active_ai_config_old_for_side ( side_number side, const config::const_child_itors &ai_parameters ); 00424 00425 00426 00427 /** 00428 * Modifies AI parameters for active AI of the given @a side. 00429 * This function is a backend for [modify_ai] tag 00430 * @param side side_number (1-based, as in game_info). 00431 * @param cfg - content of [modify_ai] tag 00432 */ 00433 00434 static void modify_active_ai_for_side( ai::side_number, const config &cfg ); 00435 00436 // ======================================================================= 00437 // PROXY 00438 // ======================================================================= 00439 00440 /** 00441 * Plays a turn for the specified side using its active AI. 00442 * @param side side number (1-based, as in game_info). 00443 */ 00444 static void play_turn(side_number side); 00445 00446 00447 private: 00448 00449 typedef std::map< side_number, std::stack< holder > > AI_map_of_stacks; 00450 static AI_map_of_stacks ai_map_; 00451 static std::deque< command_history_item > history_; 00452 static long history_item_counter_; 00453 static game_info *ai_info_; 00454 00455 static events::generic_event map_changed_; 00456 static events::generic_event recruit_list_changed_; 00457 static events::generic_event user_interact_; 00458 static events::generic_event sync_network_; 00459 static events::generic_event gamestate_changed_; 00460 static events::generic_event turn_started_; 00461 static int last_interact_; 00462 static int num_interact_; 00463 00464 00465 00466 // ======================================================================= 00467 // EVALUATION 00468 // ======================================================================= 00469 00470 /** 00471 * Evaluates an internal manager command. 00472 * @param side side number (1-based). 00473 * @param str string to evaluate. 00474 * @return string result of evaluation. 00475 * @todo 1.9 rewrite this function to use a fai or lua parser. 00476 */ 00477 static const std::string internal_evaluate_command( side_number side, const std::string& str ); 00478 00479 /** 00480 * Determines if the command should be intercepted and evaluated as internal command. 00481 * @param str command string to check. 00482 * @return true if the command should be intercepted and evaluated. 00483 */ 00484 static bool should_intercept( const std::string& str ); 00485 00486 // ======================================================================= 00487 // AI STACKS 00488 // ======================================================================= 00489 00490 00491 /** 00492 * Gets the AI stack for the specified side, create it if it doesn't exist. 00493 */ 00494 static std::stack< holder >& get_or_create_ai_stack_for_side(side_number side); 00495 00496 // ======================================================================= 00497 // AI HOLDERS 00498 // ======================================================================= 00499 00500 00501 /** 00502 * Gets active holder for specified @a side. 00503 */ 00504 static holder& get_active_ai_holder_for_side( side_number side ); 00505 00506 // ======================================================================= 00507 // AI POINTERS 00508 // ======================================================================= 00509 00510 /** 00511 * Gets active AI for specified side. 00512 * @note Running this command may invalidate references previously returned 00513 * by manager. 00514 * @param side side number (1-based, as in game_info). 00515 * @return a reference to the active AI. 00516 * @note This reference may become invalid after specific manager operations. 00517 */ 00518 static interface& get_active_ai_for_side( side_number side ); 00519 00520 00521 }; 00522 00523 } //end of namespace ai 00524 00525 #endif
| Generated by doxygen 1.7.1 on Tue May 22 2012 01:03:34 for The Battle for Wesnoth | Gna! | Forum | Wiki | CIA | devdocs |