The Battle for Wesnoth  1.19.13+dev
manager.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2025
3  by Yurii Chernyi <terraninfo@terraninfo.net>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 /**
17  * @file
18  * Managing the AIs lifecycle - headers
19  * TODO: Refactor history handling and internal commands.
20  * TODO: AI Interface command to clear the history.
21  */
22 
23 #pragma once
24 
25 #include "ai/game_info.hpp" // for side_number, ai_ptr
26 #include "config.hpp" // for config, etc
27 #include "generic_event.hpp" // for generic_event, etc
28 
29 #include <deque> // for deque
30 #include <map> // for map, map<>::value_compare
31 #include <stack> // for stack
32 #include <string> // for string
33 
34 class game_launcher;
35 namespace ai { class unit_advancements_aspect; } // lines 45-45
36 namespace ai { class ai_composite; } // lines 45-45
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 
43 namespace ai
44 {
45 
46 /**
47  * Base class that holds the AI and current AI parameters.
48  * It is an implementation detail.
49  */
50 class holder{
51 public:
52  holder(side_number side, const config &cfg);
53 
54  virtual ~holder();
55 
57 
58  std::string describe_ai() const;
59 
60  config to_config() const;
61 
62  void modify_ai(const config& cfg);
63  void micro_ai(const config& cfg);
64 
65  void append_ai(const config& cfg);
66 
67  std::string get_ai_overview();
68 
69  std::string get_ai_structure();
70 
71  std::string get_ai_identifier() const;
72 
73  component* get_component(component *root, const std::string &path); // Ai debug method
74 
75 private:
76  void init( side_number side );
77 
79  std::unique_ptr<side_context> side_context_;
80  std::unique_ptr<readonly_context> readonly_context_;
81  std::unique_ptr<readwrite_context> readwrite_context_;
82  std::unique_ptr<default_ai_context> default_ai_context_;
85 };
86 
87 /**
88  * AI Command History Item. It is an implementation detail. See TODOs above.
89  */
91 public:
92 
93  command_history_item(int number, const std::string &command)
94  : number_(number), command_(command)
95  {}
96 
97  int get_number() const { return number_; }
98 
99  const std::string& get_command() const { return command_; }
100 
101 private:
102  int number_;
103  std::string command_;
104 };
105 
106 /**
107  * Class that manages AIs for all sides and manages AI redeployment.
108  * This class is responsible for managing the AI lifecycle.
109  */
110 class manager
111 {
112 public:
113 
114  // =======================================================================
115  // CONSTANTS
116  // =======================================================================
117 
118  static const std::size_t MAX_HISTORY_SIZE = 200;
119 
120  static const std::string AI_TYPE_COMPOSITE_AI;
121  static const std::string AI_TYPE_SAMPLE_AI;
122  static const std::string AI_TYPE_IDLE_AI;
123  static const std::string AI_TYPE_FORMULA_AI;
124  static const std::string AI_TYPE_DFOOL_AI;
125  static const std::string AI_TYPE_AI2;
126  static const std::string AI_TYPE_DEFAULT;
127 
128  // =======================================================================
129  // CONSTRUCTORS AND DESTRUCTORS
130  // =======================================================================
131 
132  manager();
133 
134  ~manager();
135 
136  // =======================================================================
137  // ACCESS TO MANAGER
138  // =======================================================================
139 
141  {
142  assert(singleton_ != nullptr);
143  return *singleton_;
144  }
145 
146  static bool has_manager()
147  {
148  return singleton_ != nullptr;
149  }
150 
151  // =======================================================================
152  // LIFECYCLE
153  // =======================================================================
154 
155  /**
156  * Adds observer of game events.
157  * Should be called in playsingle_controller 's constructor.
158  */
159  void add_observer( events::observer* event_observer);
160 
161  /**
162  * Removes an observer of game events.
163  * Should be called in playsingle_controller 's destructor.
164  */
165  void remove_observer( events::observer* event_observer );
166 
167  /**
168  * Adds observer of game events except ai_user_interact event and ai_sync_network event
169  */
170  void add_gamestate_observer( events::observer* event_observer);
171 
172  /**
173  * Removes an observer of game events except ai_user_interact event and ai_sync_network event
174  */
175  void remove_gamestate_observer( events::observer* event_observer );
176 
177  /**
178  * Notifies all observers of 'ai_user_interact' event.
179  * Function which should be called frequently to allow the user to interact
180  * with the interface. This function will make sure that interaction
181  * doesn't occur too often, so there is no problem with calling it very
182  * regularly.
183  */
184  void raise_user_interact();
185 
186  /**
187  * Notifies all observers of 'ai_sync_network' event.
188  * Basically a request from the AI to sync the network.
189  */
190  void raise_sync_network();
191 
192  /**
193  * Notifies all observers of 'ai_gamestate_changed' event.
194  */
196 
197  /**
198  * Notifies all observers of 'ai_tod_changed' event.
199  */
200  void raise_tod_changed();
201 
202  /**
203  * Notifies all observers of 'ai_recruit_list_changed' event.
204  */
206 
207  /**
208  * Notifies all observers of 'ai_turn_started' event.
209  */
210  void raise_turn_started();
211 
212  /**
213  * Notifies all observers of 'ai_map_changed' event.
214  */
215  void raise_map_changed();
216 
217  /**
218  * Adds an observer of 'ai_map_changed' event.
219  */
220  void add_map_changed_observer( events::observer* event_observer );
221 
222  /**
223  * Adds an observer of 'ai_recruit_list_changed' event.
224  */
225  void add_recruit_list_changed_observer( events::observer* event_observer );
226 
227  /**
228  * Adds an observer of 'ai_turn_started' event.
229  */
230  void add_turn_started_observer( events::observer* event_observer );
231 
232  /**
233  * Adds an observer of 'ai_tod_changed' event.
234  */
235  void add_tod_changed_observer( events::observer* event_observer );
236 
237  /**
238  * Deletes an observer of 'ai_map_changed' event.
239  */
240  void remove_map_changed_observer( events::observer* event_observer );
241 
242 
243  /**
244  * Deletes an observer of 'ai_recruit_list_changed' event.
245  */
247 
248  /**
249  * Deletes an observer of 'ai_turn_started' event.
250  */
251  void remove_turn_started_observer( events::observer* event_observer );
252 
253  /**
254  * Deletes an observer of 'ai_tod_changed' event.
255  */
256  void remove_tod_changed_observer( events::observer* event_observer );
257 
258 public:
259 
260  // =======================================================================
261  // ADD, CREATE AIs, OR LIST AI TYPES
262  // =======================================================================
263 
264  /**
265  * Adds active AI for specified @a side from @a file.
266  * @note Running this command may invalidate references previously returned
267  * by manager. AI is not initialized at this point.
268  * @param side side number (1-based, as in game_info).
269  * @param file file name, follows the usual WML convention.
270  * @param replace should new ai replace the current ai or 'be placed on top of it'.
271  * @return true if successful.
272  */
273  bool add_ai_for_side_from_file( side_number side, const std::string& file, bool replace = true );
274 
275  /**
276  * Adds active AI for specified @a side from @a cfg.
277  * @note Running this command may invalidate references previously returned
278  * by manager. AI is not initialized at this point.
279  * @param side side number (1-based, as in game_info).
280  * @param cfg the config from which all ai parameters are to be read.
281  * @param replace should new ai replace the current ai or 'be placed on top of it'.
282  * @return true if successful.
283  */
284  bool add_ai_for_side_from_config(side_number side, const config &cfg, bool replace = true);
285 
286  // =======================================================================
287  // REMOVE
288  // =======================================================================
289 
290  /**
291  * Removes top-level AI from @a side.
292  * @note Running this command may invalidate references previously returned
293  * by manager.
294  * @param side side number (1-based, as in game_info).
295  */
296  void remove_ai_for_side( side_number side );
297 
298  /**
299  * Removes all AIs from @a side.
300  * @note Running this command may invalidate references previously returned
301  * by manager.
302  * @param side side number (1-based, as in game_info).
303  */
305 
306  /**
307  * Clears all the AIs.
308  * @note Running this command may invalidate references previously returned
309  * by manager. For example, this is called from the destructor of
310  * playsingle_controller. It is necessary to do this if any of the
311  * info structures used by the AI goes out of scope.
312  */
313  void clear_ais();
314 
315  // =======================================================================
316  // GET active AI parameters
317  // =======================================================================
318 
319  /**
320  * Gets AI info for active AI of the given @a side.
321  * @param side side number (1-based).
322  * @return a reference to active AI info.
323  */
325 
326  /**
327  * Gets AI Overview for active AI of the given @a side
328  * @param side side number (1-based)
329  * @return an ai overview
330  */
331  std::string get_active_ai_overview_for_side( side_number side );
332 
333  /**
334  * Gets AI Structure for active AI of the given @a side
335  * @param side side number (1-based)
336  * @return an ai structure
337  */
338  std::string get_active_ai_structure_for_side( side_number side );
339 
340  /**
341  * Gets AI algorithm identifier for active AI of the given @a side.
342  * @param side side number (1-based).
343  * @return ai identifier for the active AI
344  */
346 
347  /**
348  * Gets the active AI holder for debug purposes.
349  * Will only work in debug mode, otherwise returns a reference to an empty holder
350  * @param side side number(1-based)
351  * @return debug ? active holder : empty holder
352  */
354 
355  /**
356  * Gets AI config for active AI of the given @a side.
357  * @param side side number (1-based).
358  * @return a config object for the active AI
359  */
360  config to_config( side_number side );
361 
362  /**
363  * Gets global AI-game info
364  * @return a reference to the AI-game info.
365  */
367 
369 
370  // =======================================================================
371  // SET active AI parameters
372  // =======================================================================
373 
374  /**
375  * Modifies AI parameters for active AI of the given @a side.
376  * This function is a backend for [modify_ai] tag
377  * @param side side_number (1-based, as in game_info).
378  * @param cfg - content of [modify_ai] tag
379  */
380 
382 
383  /**
384  * Appends AI parameters to active AI of the given @a side.
385  * This function is a backend for [modify_side][ai] tag
386  * @param side side_number (1-based, as in game_info).
387  * @param cfg - content of [modify_side][ai] tag
388  */
389 
391 
392  // =======================================================================
393  // PROXY
394  // =======================================================================
395 
396  /**
397  * Plays a turn for the specified side using its active AI.
398  * @param side side number (1-based, as in game_info).
399  */
400  void play_turn(side_number side);
401 
402 private:
403 
404  typedef std::map< side_number, std::stack< holder >> AI_map_of_stacks;
405 
406  std::deque< command_history_item > history_;
409 
417  std::chrono::steady_clock::time_point last_interact_;
419 
421 
423 
424  // =======================================================================
425  // AI STACKS
426  // =======================================================================
427 
428  /**
429  * Gets the AI stack for the specified side, create it if it doesn't exist.
430  */
431  std::stack< holder >& get_or_create_ai_stack_for_side(side_number side);
432 
433  // =======================================================================
434  // AI HOLDERS
435  // =======================================================================
436 
437  /**
438  * Gets active holder for specified @a side.
439  */
441 
442  // =======================================================================
443  // AI POINTERS
444  // =======================================================================
445 
446  /**
447  * Gets active AI for specified side.
448  * @note Running this command may invalidate references previously returned
449  * by manager.
450  * @param side side number (1-based, as in game_info).
451  * @return a reference to the active AI.
452  * @note This reference may become invalid after specific manager operations.
453  */
455 
456  friend class ::game_launcher;
457 };
458 
459 } //end of namespace ai
AI Command History Item.
Definition: manager.hpp:90
int get_number() const
Definition: manager.hpp:97
const std::string & get_command() const
Definition: manager.hpp:99
command_history_item(int number, const std::string &command)
Definition: manager.hpp:93
Base class that holds the AI and current AI parameters.
Definition: manager.hpp:50
std::string describe_ai() const
Definition: manager.cpp:244
std::string get_ai_structure()
Definition: manager.cpp:297
config to_config() const
Definition: manager.cpp:221
composite_ai_ptr ai_
Definition: manager.hpp:78
std::string get_ai_identifier() const
Definition: manager.cpp:305
void micro_ai(const config &cfg)
Definition: manager.cpp:147
void modify_ai(const config &cfg)
Definition: manager.cpp:160
config cfg_
Definition: manager.hpp:84
ai_composite & get_ai_ref()
Definition: manager.cpp:137
virtual ~holder()
Definition: manager.cpp:128
component * get_component(component *root, const std::string &path)
Definition: manager.cpp:310
std::unique_ptr< side_context > side_context_
Definition: manager.hpp:79
side_number side_
Definition: manager.hpp:83
std::unique_ptr< readwrite_context > readwrite_context_
Definition: manager.hpp:81
std::string get_ai_overview()
Definition: manager.cpp:253
std::unique_ptr< readonly_context > readonly_context_
Definition: manager.hpp:80
void init(side_number side)
Definition: manager.cpp:80
void append_ai(const config &cfg)
Definition: manager.cpp:189
std::unique_ptr< default_ai_context > default_ai_context_
Definition: manager.hpp:82
holder(side_number side, const config &cfg)
Definition: manager.cpp:74
Class that manages AIs for all sides and manages AI redeployment.
Definition: manager.hpp:111
static const std::string AI_TYPE_SAMPLE_AI
Definition: manager.hpp:121
events::generic_event map_changed_
Definition: manager.hpp:410
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:542
void clear_ais()
Clears all the AIs.
Definition: manager.cpp:517
std::string get_active_ai_overview_for_side(side_number side)
Gets AI Overview for active AI of the given side.
Definition: manager.cpp:532
ai_composite & get_active_ai_for_side(side_number side)
Gets active AI for specified side.
Definition: manager.cpp:634
void raise_tod_changed()
Notifies all observers of 'ai_tod_changed' event.
Definition: manager.cpp:452
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:482
config to_config(side_number side)
Gets AI config for active AI of the given side.
Definition: manager.cpp:557
events::generic_event user_interact_
Definition: manager.hpp:412
void remove_all_ais_for_side(side_number side)
Removes all AIs from side.
Definition: manager.cpp:507
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:380
void remove_observer(events::observer *event_observer)
Removes an observer of game events.
Definition: manager.cpp:367
void raise_turn_started()
Notifies all observers of 'ai_turn_started' event.
Definition: manager.cpp:456
static manager * singleton_
Definition: manager.hpp:422
static const std::string AI_TYPE_IDLE_AI
Definition: manager.hpp:122
static const std::string AI_TYPE_COMPOSITE_AI
Definition: manager.hpp:120
static const std::size_t MAX_HISTORY_SIZE
Definition: manager.hpp:118
static const std::string AI_TYPE_DFOOL_AI
Definition: manager.hpp:124
void raise_gamestate_changed()
Notifies all observers of 'ai_gamestate_changed' event.
Definition: manager.cpp:448
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:374
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:527
AI_map_of_stacks ai_map_
Definition: manager.hpp:420
std::map< side_number, std::stack< holder > > AI_map_of_stacks
Definition: manager.hpp:404
std::string get_active_ai_structure_for_side(side_number side)
Gets AI Structure for active AI of the given side.
Definition: manager.cpp:537
events::generic_event sync_network_
Definition: manager.hpp:413
void raise_user_interact()
Notifies all observers of 'ai_user_interact' event.
Definition: manager.cpp:424
static const std::string AI_TYPE_FORMULA_AI
Definition: manager.hpp:123
events::generic_event recruit_list_changed_
Definition: manager.hpp:411
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:605
holder & get_active_ai_holder_for_side(side_number side)
Gets active holder for specified side.
Definition: manager.cpp:617
void add_recruit_list_changed_observer(events::observer *event_observer)
Adds an observer of 'ai_recruit_list_changed' event.
Definition: manager.cpp:399
game_info & get_active_ai_info_for_side(side_number side)
Gets AI info for active AI of the given side.
Definition: manager.cpp:562
void add_map_changed_observer(events::observer *event_observer)
Adds an observer of 'ai_map_changed' event.
Definition: manager.cpp:394
static manager & get_singleton()
Definition: manager.hpp:140
static const std::string AI_TYPE_AI2
Definition: manager.hpp:125
void add_turn_started_observer(events::observer *event_observer)
Adds an observer of 'ai_turn_started' event.
Definition: manager.cpp:404
static const std::string AI_TYPE_DEFAULT
Definition: manager.hpp:126
std::deque< command_history_item > history_
Definition: manager.hpp:406
static bool has_manager()
Definition: manager.hpp:146
game_info & get_ai_info()
Gets global AI-game info.
Definition: manager.cpp:567
game_info ai_info_
Definition: manager.hpp:408
events::generic_event gamestate_changed_
Definition: manager.hpp:415
const ai::unit_advancements_aspect & get_advancement_aspect_for_side(side_number side)
Definition: manager.cpp:572
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:472
events::generic_event turn_started_
Definition: manager.hpp:416
void remove_ai_for_side(side_number side)
Removes top-level AI from side.
Definition: manager.cpp:499
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:522
int num_interact_
Definition: manager.hpp:418
void play_turn(side_number side)
Plays a turn for the specified side using its active AI.
Definition: manager.cpp:581
std::chrono::steady_clock::time_point last_interact_
Definition: manager.hpp:417
long history_item_counter_
Definition: manager.hpp:407
void raise_map_changed()
Notifies all observers of 'ai_map_changed' event.
Definition: manager.cpp:464
void raise_recruit_list_changed()
Notifies all observers of 'ai_recruit_list_changed' event.
Definition: manager.cpp:460
void remove_turn_started_observer(events::observer *event_observer)
Deletes an observer of 'ai_turn_started' event.
Definition: manager.cpp:419
ai::holder & get_active_ai_holder_for_side_dbg(side_number side)
Gets the active AI holder for debug purposes.
Definition: manager.cpp:547
void raise_sync_network()
Notifies all observers of 'ai_sync_network' event.
Definition: manager.cpp:444
events::generic_event tod_changed_
Definition: manager.hpp:414
void remove_map_changed_observer(events::observer *event_observer)
Deletes an observer of 'ai_map_changed' event.
Definition: manager.cpp:414
void add_tod_changed_observer(events::observer *event_observer)
Adds an observer of 'ai_tod_changed' event.
Definition: manager.cpp:386
void remove_tod_changed_observer(events::observer *event_observer)
Deletes an observer of 'ai_tod_changed' event.
Definition: manager.cpp:390
void add_observer(events::observer *event_observer)
Adds observer of game events.
Definition: manager.cpp:360
void remove_recruit_list_changed_observer(events::observer *event_observer)
Deletes an observer of 'ai_recruit_list_changed' event.
Definition: manager.cpp:409
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:158
Definitions for the interface to Wesnoth Markup Language (WML).
const config * cfg
Game information for the AI.
A small explanation about what's going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:59
int side_number
Definition: game_info.hpp:40
std::unique_ptr< ai_composite > composite_ai_ptr
Definition: game_info.hpp:48
std::string path
Definition: filesystem.cpp:106