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