The Battle for Wesnoth  1.13.10+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
manager.hpp
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  * @file
17  * Managing the AIs lifecycle - headers
18  * @todo 1.9 Refactor history handling and internal commands.
19  * @todo 1.9 AI Interface command to clear the history.
20  */
21 
22 #pragma once
23 
24 #include "config.hpp" // for config, etc
25 #include "ai/game_info.hpp" // for side_number, ai_ptr
26 
27 #include <deque> // for deque
28 #include <map> // for map, map<>::value_compare
29 #include <stack> // for stack
30 #include <string> // for string
31 
32 namespace ai { class ai_composite; } // lines 45-45
33 namespace ai { class ai_context; } // lines 42-42
34 namespace ai { class component; } // lines 43-43
35 namespace ai { class default_ai_context; } // lines 41-41
36 namespace ai { class readonly_context; } // lines 39-39
37 namespace ai { class readwrite_context; } // lines 40-40
38 namespace ai { class side_context; } // lines 38-38
39 namespace events { class generic_event; }
40 namespace events { class observer; }
41 
42 
43 namespace ai {
44 
45 typedef std::shared_ptr<ai_composite> composite_ai_ptr;
46 
47 /**
48  * Base class that holds the AI and current AI parameters.
49  * It is an implementation detail.
50  * @todo 1.9 move it out of public view
51  */
52 class holder{
53 public:
54  holder(side_number side, const config &cfg);
55 
56  virtual ~holder();
57 
59 
60  const std::string describe_ai();
61 
62  config to_config() const;
63 
64  void modify_ai(const config& cfg);
65 
66 
67  void append_ai(const config& cfg);
68 
69 
71 
72 
74 
75 
76  const std::string get_ai_identifier() const;
77 
78  component* get_component(component *root, const std::string &path); // Ai debug method
79 
80 private:
81  void init( side_number side );
82 
83 
84  composite_ai_ptr ai_;
85  std::unique_ptr<side_context> side_context_;
86  std::unique_ptr<readonly_context> readonly_context_;
87  std::unique_ptr<readwrite_context> readwrite_context_;
88  std::unique_ptr<default_ai_context> default_ai_context_;
91 };
92 
93 /**
94  * AI Command History Item. It is an implementation detail
95  */
97 public:
98 
99  command_history_item(int number, const std::string &command)
100  : number_(number), command_(command)
101  {}
102 
103  int get_number() const { return number_; }
104 
105  const std::string& get_command() const { return command_; }
106 
107 private:
108  int number_;
110 
111 };
112 
113 /**
114  * Class that manages AIs for all sides and manages AI redeployment.
115  * This class is responsible for managing the AI lifecycle
116  * It can be accessed like this: ai::manager::foo(...);
117  */
118 class manager
119 {
120 public:
121 
122  // =======================================================================
123  // CONSTANTS
124  // =======================================================================
125 
126  static const size_t MAX_HISTORY_SIZE = 200;
127 
133  static const std::string AI_TYPE_AI2;
135 
136 
137  // =======================================================================
138  // LIFECYCLE
139  // =======================================================================
140 
141  /**
142  * Sets AI information.
143  * @param info ai_information to be set.
144  */
145  static void set_ai_info(const game_info& info);
146 
147 
148  /**
149  * Clears AI information.
150  * Should be called in playsingle_controller 's destructor.
151  */
152  static void clear_ai_info();
153 
154 
155  /**
156  * Adds observer of game events.
157  * Should be called in playsingle_controller 's constructor.
158  */
159  static void add_observer( events::observer* event_observer);
160 
161 
162  /**
163  * Removes an observer of game events.
164  * Should be called in playsingle_controller 's destructor.
165  */
166  static void remove_observer( events::observer* event_observer );
167 
168 
169  /**
170  * Adds observer of game events except ai_user_interact event and ai_sync_network event
171  */
172  static void add_gamestate_observer( events::observer* event_observer);
173 
174 
175  /**
176  * Removes an observer of game events except ai_user_interact event and ai_sync_network event
177  */
178  static void remove_gamestate_observer( events::observer* event_observer );
179 
180 
181  /**
182  * Notifies all observers of 'ai_user_interact' event.
183  * Function which should be called frequently to allow the user to interact
184  * with the interface. This function will make sure that interaction
185  * doesn't occur too often, so there is no problem with calling it very
186  * regularly.
187  */
188  static void raise_user_interact();
189 
190  /**
191  * Notifies all observers of 'ai_sync_network' event.
192  * Basically a request from the AI to sync the network.
193  */
194  static void raise_sync_network();
195 
196 
197  /**
198  * Notifies all observers of 'ai_gamestate_changed' event.
199  */
200  static void raise_gamestate_changed();
201 
202 
203  /**
204  * Notifies all observers of 'ai_tod_changed' event.
205  */
206  static void raise_tod_changed();
207 
208 
209  /**
210  * Notifies all observers of 'ai_recruit_list_changed' event.
211  */
212  static void raise_recruit_list_changed();
213 
214 
215  /**
216  * Notifies all observers of 'ai_turn_started' event.
217  */
218  static void raise_turn_started();
219 
220 
221  /**
222  * Notifies all observers of 'ai_map_changed' event.
223  */
224  static void raise_map_changed();
225 
226 
227  /**
228  * Adds an observer of 'ai_map_changed' event.
229  */
230  static void add_map_changed_observer( events::observer* event_observer );
231 
232 
233  /**
234  * Adds an observer of 'ai_recruit_list_changed' event.
235  */
236  static void add_recruit_list_changed_observer( events::observer* event_observer );
237 
238 
239  /**
240  * Adds an observer of 'ai_turn_started' event.
241  */
242  static void add_turn_started_observer( events::observer* event_observer );
243 
244 
245  /**
246  * Adds an observer of 'ai_tod_changed' event.
247  */
248  static void add_tod_changed_observer( events::observer* event_observer );
249 
250 
251  /**
252  * Deletes an observer of 'ai_map_changed' event.
253  */
254  static void remove_map_changed_observer( events::observer* event_observer );
255 
256 
257 
258  /**
259  * Deletes an observer of 'ai_recruit_list_changed' event.
260  */
261  static void remove_recruit_list_changed_observer( events::observer* event_observer );
262 
263 
264  /**
265  * Deletes an observer of 'ai_turn_started' event.
266  */
267  static void remove_turn_started_observer( events::observer* event_observer );
268 
269 
270  /**
271  * Deletes an observer of 'ai_tod_changed' event.
272  */
273  static void remove_tod_changed_observer( events::observer* event_observer );
274 
275 
276 private:
277 
278  manager();
279 
280 
281 public:
282 
283  // =======================================================================
284  // EVALUATION
285  // =======================================================================
286 
287  /**
288  * Evaluates a string command using command AI.
289  * @note Running this command may invalidate references previously returned
290  * by manager. Will intercept those commands which start with '!'
291  * and '?', and will try to evaluate them as internal commands.
292  * @param side side number (1-based).
293  * @param str string to evaluate.
294  * @return string result of evaluation.
295  */
296  static const std::string evaluate_command( side_number side, const std::string& str );
297 
298 
299  // =======================================================================
300  // ADD, CREATE AIs, OR LIST AI TYPES
301  // =======================================================================
302 
303  /**
304  * Adds active AI for specified @a side from @a file.
305  * @note Running this command may invalidate references previously returned
306  * by manager. AI is not initialized at this point.
307  * @param side side number (1-based, as in game_info).
308  * @param file file name, follows the usual WML convention.
309  * @param replace should new ai replace the current ai or 'be placed on top of it'.
310  * @return true if successful.
311  */
312  static bool add_ai_for_side_from_file( side_number side, const std::string& file, bool replace = true );
313 
314 
315  /**
316  * Adds active AI for specified @a side from @a cfg.
317  * @note Running this command may invalidate references previously returned
318  * by manager. AI is not initialized at this point.
319  * @param side side number (1-based, as in game_info).
320  * @param cfg the config from which all ai parameters are to be read.
321  * @param replace should new ai replace the current ai or 'be placed on top of it'.
322  * @return true if successful.
323  */
324  static bool add_ai_for_side_from_config(side_number side, const config &cfg, bool replace = true);
325 
326 
327  /**
328  * Adds active AI for specified @a side from parameters.
329  * @note Running this command may invalidate references previously returned
330  * by manager. AI is not initialized at this point.
331  * @param side side number (1-based, as in game_info).
332  * @param ai_algorithm_type type of AI algorithm to create.
333  * @param replace should new ai replace the current ai or 'be placed on top of it'.
334  * @return true if successful.
335  */
336  static bool add_ai_for_side( side_number side, const std::string& ai_algorithm_type, bool replace = true);
337 
338 
339  // =======================================================================
340  // REMOVE
341  // =======================================================================
342 
343  /**
344  * Removes top-level AI from @a side.
345  * @note Running this command may invalidate references previously returned
346  * by manager.
347  * @param side side number (1-based, as in game_info).
348  */
349  static void remove_ai_for_side( side_number side );
350 
351 
352  /**
353  * Removes all AIs from @a side.
354  * @note Running this command may invalidate references previously returned
355  * by manager.
356  * @param side side number (1-based, as in game_info).
357  */
358  static void remove_all_ais_for_side( side_number side );
359 
360 
361  /**
362  * Clears all the AIs.
363  * @note Running this command may invalidate references previously returned
364  * by manager. For example, this is called from the destructor of
365  * playsingle_controller. It is necessary to do this if any of the
366  * info structures used by the AI goes out of scope.
367  */
368  static void clear_ais();
369 
370  // =======================================================================
371  // GET active AI parameters
372  // =======================================================================
373 
374 
375  /**
376  * Gets AI info for active AI of the given @a side.
377  * @param side side number (1-based).
378  * @return a reference to active AI info.
379  */
381 
382 
383  /**
384  * Gets AI Overview for active AI of the given @a side
385  * @param side side number (1-based)
386  * @return an ai overview
387  */
389 
390 
391  /**
392  * Gets AI Structure for active AI of the given @a side
393  * @param side side number (1-based)
394  * @return an ai structure
395  */
397 
398  /**
399  * Gets AI algorithm identifier for active AI of the given @a side.
400  * @param side side number (1-based).
401  * @return ai identifier for the active AI
402  */
404 
405  /**
406  * Gets the active AI holder for debug purposes.
407  * Will only work in debug mode, otherwise returns a reference to an empty holder
408  * @param side side number(1-based)
409  * @return debug ? active holder : empty holder
410  */
412 
413  /**
414  * Gets AI config for active AI of the given @a side.
415  * @param side side number (1-based).
416  * @return a config object for the active AI
417  */
418  static config to_config( side_number side );
419 
420 
421  /**
422  * Gets global AI-game info
423  * @return a reference to the AI-game info.
424  */
425  static game_info& get_ai_info();
426 
427 
428  // =======================================================================
429  // SET active AI parameters
430  // =======================================================================
431 
432  /**
433  * Modifies AI parameters for active AI of the given @a side.
434  * This function is a backend for [modify_ai] tag
435  * @param side side_number (1-based, as in game_info).
436  * @param cfg - content of [modify_ai] tag
437  */
438 
439  static void modify_active_ai_for_side( ai::side_number side, const config &cfg );
440 
441  /**
442  * Appends AI parameters to active AI of the given @a side.
443  * This function is a backend for [modify_side][ai] tag
444  * @param side side_number (1-based, as in game_info).
445  * @param cfg - content of [modify_side][ai] tag
446  */
447 
448  static void append_active_ai_for_side( ai::side_number side, const config &cfg );
449 
450  // =======================================================================
451  // PROXY
452  // =======================================================================
453 
454  /**
455  * Plays a turn for the specified side using its active AI.
456  * @param side side number (1-based, as in game_info).
457  */
458  static void play_turn(side_number side);
459 
460 
461 private:
462 
463  typedef std::map< side_number, std::stack< holder > > AI_map_of_stacks;
464  static AI_map_of_stacks ai_map_;
465  static std::deque< command_history_item > history_;
467  static std::unique_ptr<game_info> ai_info_;
468 
476  static int last_interact_;
477  static int num_interact_;
478 
479 
480 
481  // =======================================================================
482  // EVALUATION
483  // =======================================================================
484 
485  /**
486  * Evaluates an internal manager command.
487  * @param side side number (1-based).
488  * @param str string to evaluate.
489  * @return string result of evaluation.
490  * @todo 1.9 rewrite this function to use a fai or lua parser.
491  */
492  static const std::string internal_evaluate_command( side_number side, const std::string& str );
493 
494  /**
495  * Determines if the command should be intercepted and evaluated as internal command.
496  * @param str command string to check.
497  * @return true if the command should be intercepted and evaluated.
498  */
499  static bool should_intercept( const std::string& str );
500 
501  // =======================================================================
502  // AI STACKS
503  // =======================================================================
504 
505 
506  /**
507  * Gets the AI stack for the specified side, create it if it doesn't exist.
508  */
509  static std::stack< holder >& get_or_create_ai_stack_for_side(side_number side);
510 
511  // =======================================================================
512  // AI HOLDERS
513  // =======================================================================
514 
515 
516  /**
517  * Gets active holder for specified @a side.
518  */
520 
521  // =======================================================================
522  // AI POINTERS
523  // =======================================================================
524 
525  /**
526  * Gets active AI for specified side.
527  * @note Running this command may invalidate references previously returned
528  * by manager.
529  * @param side side number (1-based, as in game_info).
530  * @return a reference to the active AI.
531  * @note This reference may become invalid after specific manager operations.
532  */
534 
535 
536 };
537 
538 } //end of namespace ai
static void add_observer(events::observer *event_observer)
Adds observer of game events.
Definition: manager.cpp:334
static std::unique_ptr< game_info > ai_info_
Definition: manager.hpp:467
static const std::string AI_TYPE_DFOOL_AI
Definition: manager.hpp:132
std::vector< char_t > string
static void raise_gamestate_changed()
Notifies all observers of 'ai_gamestate_changed' event.
Definition: manager.cpp:433
static void raise_map_changed()
Notifies all observers of 'ai_map_changed' event.
Definition: manager.cpp:453
logger & info()
Definition: log.cpp:91
static game_info & get_active_ai_info_for_side(side_number side)
Gets AI info for active AI of the given side.
Definition: manager.cpp:740
config cfg_
Definition: manager.hpp:90
static void add_turn_started_observer(events::observer *event_observer)
Adds an observer of 'ai_turn_started' event.
Definition: manager.cpp:387
holder(side_number side, const config &cfg)
Definition: manager.cpp:75
const std::string get_ai_identifier() const
Definition: manager.cpp:277
static events::generic_event gamestate_changed_
Definition: manager.hpp:474
Class that manages AIs for all sides and manages AI redeployment.
Definition: manager.hpp:118
std::unique_ptr< readonly_context > readonly_context_
Definition: manager.hpp:86
config to_config() const
Definition: manager.cpp:196
static const std::string internal_evaluate_command(side_number side, const std::string &str)
Evaluates an internal manager command.
Definition: manager.cpp:505
Definitions for the interface to Wesnoth Markup Language (WML).
static void add_tod_changed_observer(events::observer *event_observer)
Adds an observer of 'ai_tod_changed' event.
Definition: manager.cpp:364
command_history_item(int number, const std::string &command)
Definition: manager.hpp:99
composite_ai_ptr ai_
Definition: manager.hpp:84
static AI_map_of_stacks ai_map_
Definition: manager.hpp:464
const std::string get_ai_overview()
Definition: manager.cpp:233
void init(side_number side)
Definition: manager.cpp:82
static void append_active_ai_for_side(ai::side_number side, const config &cfg)
Appends AI parameters to active AI of the given side.
Definition: manager.cpp:698
static bool should_intercept(const std::string &str)
Determines if the command should be intercepted and evaluated as internal command.
Definition: manager.cpp:483
std::unique_ptr< side_context > side_context_
Definition: manager.hpp:85
std::shared_ptr< ai_composite > composite_ai_ptr
Definition: manager.hpp:45
static std::stack< holder > & get_or_create_ai_stack_for_side(side_number side)
Gets the AI stack for the specified side, create it if it doesn't exist.
Definition: manager.cpp:782
static bool add_ai_for_side_from_file(side_number side, const std::string &file, bool replace=true)
Adds active AI for specified side from file.
Definition: manager.cpp:619
static void clear_ais()
Clears all the AIs.
Definition: manager.cpp:682
static void raise_recruit_list_changed()
Notifies all observers of 'ai_recruit_list_changed' event.
Definition: manager.cpp:448
const std::string get_ai_structure()
Definition: manager.cpp:268
A small explanation about what's going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:58
static void remove_gamestate_observer(events::observer *event_observer)
Removes an observer of game events except ai_user_interact event and ai_sync_network event...
Definition: manager.cpp:357
const std::string & get_command() const
Definition: manager.hpp:105
static std::deque< command_history_item > history_
Definition: manager.hpp:465
component * get_component(component *root, const std::string &path)
Definition: manager.cpp:282
static void remove_turn_started_observer(events::observer *event_observer)
Deletes an observer of 'ai_turn_started' event.
Definition: manager.cpp:405
static std::string get_active_ai_overview_for_side(side_number side)
Gets AI Overview for active AI of the given side.
Definition: manager.cpp:706
static void set_ai_info(const game_info &info)
Sets AI information.
Definition: manager.cpp:319
static events::generic_event user_interact_
Definition: manager.hpp:471
static bool add_ai_for_side(side_number side, const std::string &ai_algorithm_type, bool replace=true)
Adds active AI for specified side from parameters.
Definition: manager.cpp:645
static config to_config(side_number side)
Gets AI config for active AI of the given side.
Definition: manager.cpp:734
static const std::string AI_TYPE_AI2
Definition: manager.hpp:133
std::unique_ptr< default_ai_context > default_ai_context_
Definition: manager.hpp:88
int get_number() const
Definition: manager.hpp:103
std::string path
Definition: game_config.cpp:56
static void play_turn(side_number side)
Plays a turn for the specified side using its active AI.
Definition: manager.cpp:756
static void modify_active_ai_for_side(ai::side_number side, const config &cfg)
Modifies AI parameters for active AI of the given side.
Definition: manager.cpp:688
void modify_ai(const config &cfg)
Definition: manager.cpp:146
static void remove_all_ais_for_side(side_number side)
Removes all AIs from side.
Definition: manager.cpp:671
static const std::string AI_TYPE_DEFAULT
Definition: manager.hpp:134
virtual ~holder()
Definition: manager.cpp:125
static const std::string AI_TYPE_IDLE_AI
Definition: manager.hpp:130
static void clear_ai_info()
Clears AI information.
Definition: manager.cpp:329
static void remove_ai_for_side(side_number side)
Removes top-level AI from side.
Definition: manager.cpp:662
static const std::string evaluate_command(side_number side, const std::string &str)
Evaluates a string command using command AI.
Definition: manager.cpp:462
static events::generic_event sync_network_
Definition: manager.hpp:472
static void raise_user_interact()
Notifies all observers of 'ai_user_interact' event.
Definition: manager.cpp:410
static const std::string AI_TYPE_COMPOSITE_AI
Definition: manager.hpp:128
Game information for the AI.
static std::string get_active_ai_identifier_for_side(side_number side)
Gets AI algorithm identifier for active AI of the given side.
Definition: manager.cpp:718
void append_ai(const config &cfg)
Definition: manager.cpp:175
static events::generic_event map_changed_
Definition: manager.hpp:469
static void add_recruit_list_changed_observer(events::observer *event_observer)
Adds an observer of 'ai_recruit_list_changed' event.
Definition: manager.cpp:381
static void remove_tod_changed_observer(events::observer *event_observer)
Deletes an observer of 'ai_tod_changed' event.
Definition: manager.cpp:369
static events::generic_event turn_started_
Definition: manager.hpp:475
static long history_item_counter_
Definition: manager.hpp:466
static const size_t MAX_HISTORY_SIZE
Definition: manager.hpp:126
static bool add_ai_for_side_from_config(side_number side, const config &cfg, bool replace=true)
Adds active AI for specified side from cfg.
Definition: manager.cpp:630
std::string observer
static std::string get_active_ai_structure_for_side(side_number side)
Gets AI Structure for active AI of the given side.
Definition: manager.cpp:712
static events::generic_event tod_changed_
Definition: manager.hpp:473
std::map< side_number, std::stack< holder > > AI_map_of_stacks
Definition: manager.hpp:463
Handling of system events.
Definition: manager.hpp:39
const std::string describe_ai()
Definition: manager.cpp:221
static void remove_observer(events::observer *event_observer)
Removes an observer of game events.
Definition: manager.cpp:342
static const std::string AI_TYPE_FORMULA_AI
Definition: manager.hpp:131
ai_composite & get_ai_ref()
Definition: manager.cpp:135
static const std::string AI_TYPE_SAMPLE_AI
Definition: manager.hpp:129
static game_info & get_ai_info()
Gets global AI-game info.
Definition: manager.cpp:746
side_number side_
Definition: manager.hpp:89
static void add_gamestate_observer(events::observer *event_observer)
Adds observer of game events except ai_user_interact event and ai_sync_network event.
Definition: manager.cpp:350
std::unique_ptr< readwrite_context > readwrite_context_
Definition: manager.hpp:87
static int num_interact_
Definition: manager.hpp:477
static void raise_sync_network()
Notifies all observers of 'ai_sync_network' event.
Definition: manager.cpp:428
static ai_composite & get_active_ai_for_side(side_number side)
Gets active AI for specified side.
Definition: manager.cpp:811
int side_number
Definition: game_info.hpp:36
static void raise_tod_changed()
Notifies all observers of 'ai_tod_changed' event.
Definition: manager.cpp:438
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
AI Command History Item.
Definition: manager.hpp:96
static ai::holder & get_active_ai_holder_for_side_dbg(side_number side)
Gets the active AI holder for debug purposes.
Definition: manager.cpp:723
static int last_interact_
Definition: manager.hpp:476
static void remove_recruit_list_changed_observer(events::observer *event_observer)
Deletes an observer of 'ai_recruit_list_changed' event.
Definition: manager.cpp:393
static events::generic_event recruit_list_changed_
Definition: manager.hpp:470
static void raise_turn_started()
Notifies all observers of 'ai_turn_started' event.
Definition: manager.cpp:443
Base class that holds the AI and current AI parameters.
Definition: manager.hpp:52
static holder & get_active_ai_holder_for_side(side_number side)
Gets active holder for specified side.
Definition: manager.cpp:794
static void add_map_changed_observer(events::observer *event_observer)
Adds an observer of 'ai_map_changed' event.
Definition: manager.cpp:375
static void remove_map_changed_observer(events::observer *event_observer)
Deletes an observer of 'ai_map_changed' event.
Definition: manager.cpp:399