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