The Battle for Wesnoth  1.19.14+dev
manager.cpp
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  * Managing the AI lifecycle and interface for the rest of Wesnoth
18  * @file
19  */
20 
21 #include "ai/manager.hpp"
22 
23 #include "config.hpp" // for config, etc
24 #include "game_events/pump.hpp"
25 #include "log.hpp"
26 #include "map/location.hpp" // for map_location
27 #include "resources.hpp"
29 #include "tod_manager.hpp"
30 
31 #include "ai/composite/ai.hpp" // for ai_composite
32 #include "ai/composite/component.hpp" // for component_manager
33 #include "ai/composite/engine.hpp" // for engine
35 #include "ai/configuration.hpp" // for configuration
36 #include "ai/contexts.hpp" // for readonly_context, etc
37 #include "ai/default/contexts.hpp" // for default_ai_context, etc
38 #include "ai/game_info.hpp" // for side_number, engine_ptr, etc
39 #include "game_config.hpp" // for debug
41 #include "ai/registry.hpp" // for init
42 #include "ai/lua/engine_lua.hpp"
43 
44 #include <algorithm> // for min
45 #include <cassert> // for assert
46 #include <iterator> // for reverse_iterator, etc
47 #include <map> // for _Rb_tree_iterator, etc
48 #include <set> // for set
49 #include <stack> // for stack
50 #include <utility> // for pair, make_pair
51 #include <vector> // for vector, allocator, etc
52 
53 #include <SDL2/SDL_timer.h>
54 
55 namespace ai {
56 
57 const std::string manager::AI_TYPE_COMPOSITE_AI = "composite_ai";
58 const std::string manager::AI_TYPE_SAMPLE_AI = "sample_ai";
59 const std::string manager::AI_TYPE_IDLE_AI = "idle_ai";
60 const std::string manager::AI_TYPE_FORMULA_AI = "formula_ai";
61 const std::string manager::AI_TYPE_DEFAULT = "default";
62 
63 static lg::log_domain log_ai_manager("ai/manager");
64 #define DBG_AI_MANAGER LOG_STREAM(debug, log_ai_manager)
65 #define LOG_AI_MANAGER LOG_STREAM(info, log_ai_manager)
66 #define ERR_AI_MANAGER LOG_STREAM(err, log_ai_manager)
67 
68 static lg::log_domain log_ai_mod("ai/mod");
69 #define DBG_AI_MOD LOG_STREAM(debug, log_ai_mod)
70 #define LOG_AI_MOD LOG_STREAM(info, log_ai_mod)
71 #define WRN_AI_MOD LOG_STREAM(warn, log_ai_mod)
72 #define ERR_AI_MOD LOG_STREAM(err, log_ai_mod)
73 
75  : ai_(), side_context_(nullptr), readonly_context_(nullptr), readwrite_context_(nullptr), default_ai_context_(nullptr), side_(side), cfg_(cfg)
76 {
77  DBG_AI_MANAGER << describe_ai() << "Preparing new AI holder";
78 }
79 
81 {
82  if (side_context_ == nullptr) {
83  side_context_.reset(new side_context_impl(side,cfg_));
84  } else {
85  side_context_->set_side(side);
86  }
87  if (readonly_context_ == nullptr){
89  readonly_context_->on_readonly_context_create();
90  }
91  if (readwrite_context_ == nullptr){
93  }
94  if (default_ai_context_ == nullptr){
96  }
97  if (!ai_){
99  }
100 
101  if (ai_) {
102  ai_->on_create();
103  for (config &mod_ai : cfg_.child_range("modify_ai")) {
104  if (!mod_ai.has_attribute("side")) {
105  mod_ai["side"] = side;
106  }
107  modify_ai(mod_ai);
108  }
109  for(config& micro : cfg_.child_range("micro_ai")) {
110  micro["side"] = side;
111  micro["action"] = "add";
112  micro_ai(micro);
113  }
114  cfg_.clear_children("modify_ai", "micro_ai");
115 
116  std::vector<engine_ptr> engines = ai_->get_engines();
117  for (std::vector<engine_ptr>::iterator it = engines.begin(); it != engines.end(); ++it)
118  {
119  (*it)->set_ai_context(&(ai_->get_ai_context()));
120  }
121 
122  } else {
123  ERR_AI_MANAGER << describe_ai()<<"AI lazy initialization error!";
124  }
125 
126 }
127 
129 {
130  try {
131  if (ai_) {
132  LOG_AI_MANAGER << describe_ai() << "Managed AI will be deleted";
133  }
134  } catch (...) {}
135 }
136 
138 {
139  if (!ai_) {
140  init(side_);
141  }
142  assert(ai_);
143 
144  return *ai_;
145 }
146 
148 {
149  if (!ai_) {
150  init(side_);
151  }
152  assert(ai_);
153 
154  auto engine = ai_->get_engine_by_cfg(config{"engine", "lua"});
155  if(auto lua = std::dynamic_pointer_cast<engine_lua>(engine)) {
156  lua->apply_micro_ai(cfg);
157  }
158 }
159 
161 {
162  if (!ai_) {
163  // if not initialized, initialize now.
164  get_ai_ref();
165  }
166  const std::string &act = cfg["action"];
167  LOG_AI_MOD << "side "<< side_ << " "<<act<<"_ai_component \""<<cfg["path"]<<"\"";
168  DBG_AI_MOD << std::endl << cfg;
169  DBG_AI_MOD << "side "<< side_ << " before "<<act<<"_ai_component"<<std::endl << to_config();
170  bool res = false;
171  if (act == "add") {
172  res = component_manager::add_component(&*ai_,cfg["path"],cfg);
173  } else if (act == "change") {
175  } else if (act == "delete") {
177  } else {
178  ERR_AI_MOD << "modify_ai tag has invalid 'action' attribute " << act;
179  }
180  DBG_AI_MOD << "side "<< side_ << " after [modify_ai]"<<act<<std::endl << to_config();
181  if (!res) {
182  LOG_AI_MOD << act << "_ai_component failed";
183  } else {
184  LOG_AI_MOD << act << "_ai_component success";
185  }
186 
187 }
188 
190 {
191  if(!ai_) {
192  get_ai_ref();
193  }
194  for(const config& aspect : cfg.child_range("aspect")) {
195  const std::string& id = aspect["id"];
196  for(const config& facet : aspect.child_range("facet")) {
197  ai_->add_facet(id, facet);
198  }
199  }
200  for(const config& goal : cfg.child_range("goal")) {
201  ai_->add_goal(goal);
202  }
203  for(const config& stage : cfg.child_range("stage")) {
204  if(stage["name"] != "empty") {
205  ai_->add_stage(stage);
206  }
207  }
208  for(config mod : cfg.child_range("modify_ai")) {
209  if (!mod.has_attribute("side")) {
210  mod["side"] = side_context_->get_side();
211  }
212  modify_ai(mod);
213  }
214  for(config micro : cfg.child_range("micro_ai")) {
215  micro["side"] = side_context_->get_side();
216  micro["action"] = "add";
217  micro_ai(micro);
218  }
219 }
220 
222 {
223  if (!ai_) {
224  return cfg_;
225  } else {
226  config cfg = ai_->to_config();
227  if (side_context_!=nullptr) {
228  cfg.merge_with(side_context_->to_side_context_config());
229  }
230  if (readonly_context_!=nullptr) {
231  cfg.merge_with(readonly_context_->to_readonly_context_config());
232  }
233  if (readwrite_context_!=nullptr) {
234  cfg.merge_with(readwrite_context_->to_readwrite_context_config());
235  }
236  if (default_ai_context_!=nullptr) {
237  cfg.merge_with(default_ai_context_->to_default_ai_context_config());
238  }
239 
240  return cfg;
241  }
242 }
243 
244 std::string holder::describe_ai() const
245 {
246  if(ai_) {
247  return formatter() << ai_->describe_self() << " for side " << side_ << " : ";
248  } else {
249  return formatter() << "not initialized ai with id=[" << cfg_["id"] << "] for side " << side_ << " : ";
250  }
251 }
252 
254 {
255  if (!ai_) {
256  get_ai_ref();
257  }
258  // These assignments are necessary because the code will otherwise not compile on some platforms with an lvalue/rvalue mismatch error
259  auto lik = ai_->get_leader_ignores_keep();
260  auto pl = ai_->get_passive_leader();
261  auto plsk = ai_->get_passive_leader_shares_keep();
262  // In order to display booleans as yes/no rather than 1/0 or true/false
263  config cfg;
264  cfg["allow_ally_villages"] = ai_->get_allow_ally_villages();
265  cfg["simple_targeting"] = ai_->get_simple_targeting();
266  cfg["support_villages"] = ai_->get_support_villages();
267  std::stringstream s;
268  s << "advancements: " << ai_->get_advancements().get_value() << std::endl;
269  s << "aggression: " << ai_->get_aggression() << std::endl;
270  s << "allow_ally_villages: " << cfg["allow_ally_villages"] << std::endl;
271  s << "caution: " << ai_->get_caution() << std::endl;
272  s << "grouping: " << ai_->get_grouping() << std::endl;
273  s << "leader_aggression: " << ai_->get_leader_aggression() << std::endl;
274  s << "leader_ignores_keep: " << utils::visit(leader_aspects_visitor(), lik) << std::endl;
275  s << "leader_value: " << ai_->get_leader_value() << std::endl;
276  s << "passive_leader: " << utils::visit(leader_aspects_visitor(), pl) << std::endl;
277  s << "passive_leader_shares_keep: " << utils::visit(leader_aspects_visitor(), plsk) << std::endl;
278  s << "recruitment_diversity: " << ai_->get_recruitment_diversity() << std::endl;
279  s << "recruitment_instructions: " << std::endl << "----config begin----" << std::endl;
280  s << ai_->get_recruitment_instructions() << "-----config end-----" << std::endl;
281  s << "recruitment_more: " << utils::join(ai_->get_recruitment_more()) << std::endl;
282  s << "recruitment_pattern: " << utils::join(ai_->get_recruitment_pattern()) << std::endl;
283  s << "recruitment_randomness: " << ai_->get_recruitment_randomness() << std::endl;
284  s << "recruitment_save_gold: " << std::endl << "----config begin----" << std::endl;
285  s << ai_->get_recruitment_save_gold() << "-----config end-----" << std::endl;
286  s << "retreat_enemy_weight: " << ai_->get_retreat_enemy_weight() << std::endl;
287  s << "retreat_factor: " << ai_->get_retreat_factor() << std::endl;
288  s << "scout_village_targeting: " << ai_->get_scout_village_targeting() << std::endl;
289  s << "simple_targeting: " << cfg["simple_targeting"] << std::endl;
290  s << "support_villages: " << cfg["support_villages"] << std::endl;
291  s << "village_value: " << ai_->get_village_value() << std::endl;
292  s << "villages_per_scout: " << ai_->get_villages_per_scout() << std::endl;
293 
294  return s.str();
295 }
296 
298 {
299  if (!ai_) {
300  get_ai_ref();
301  }
303 }
304 
305 std::string holder::get_ai_identifier() const
306 {
307  return cfg_["id"];
308 }
309 
310 component* holder::get_component(component *root, const std::string &path) {
311  if (!game_config::debug) // Debug guard
312  {
313  return nullptr;
314  }
315 
316  if (root == nullptr) // Return root component(ai_)
317  {
318  if (!ai_) {
319  init(side_);
320  }
321  assert(ai_);
322 
323  return &*ai_;
324  }
325 
327 }
328 
329 // =======================================================================
330 // LIFECYCLE
331 // =======================================================================
332 
334  : history_()
335  , history_item_counter_(0)
336  , ai_info_()
337  , map_changed_("ai_map_changed")
338  , recruit_list_changed_("ai_recruit_list_changed")
339  , user_interact_("ai_user_interact")
340  , sync_network_("ai_sync_network")
341  , tod_changed_("ai_tod_changed")
342  , gamestate_changed_("ai_gamestate_changed")
343  , turn_started_("ai_turn_started")
344  , last_interact_()
345  , num_interact_(0)
346 {
347  registry::init();
348  singleton_ = this;
349 }
350 
352  ai_map_.clear();
353  if(singleton_ == this) {
354  singleton_ = nullptr;
355  }
356 }
357 
358 manager* manager::singleton_ = nullptr;
359 
361  user_interact_.attach_handler(event_observer);
362  sync_network_.attach_handler(event_observer);
363  turn_started_.attach_handler(event_observer);
364  gamestate_changed_.attach_handler(event_observer);
365 }
366 
368  user_interact_.detach_handler(event_observer);
369  sync_network_.detach_handler(event_observer);
370  turn_started_.detach_handler(event_observer);
371  gamestate_changed_.detach_handler(event_observer);
372 }
373 
375  gamestate_changed_.attach_handler(event_observer);
376  turn_started_.attach_handler(event_observer);
377  map_changed_.attach_handler(event_observer);
378 }
379 
381  gamestate_changed_.detach_handler(event_observer);
382  turn_started_.detach_handler(event_observer);
383  map_changed_.detach_handler(event_observer);
384 }
385 
387  tod_changed_.attach_handler(event_observer);
388 }
389 
391  tod_changed_.detach_handler(event_observer);
392 }
393 
395 {
396  map_changed_.attach_handler(event_observer);
397 }
398 
400 {
401  recruit_list_changed_.attach_handler(event_observer);
402 }
403 
405 {
406  turn_started_.attach_handler(event_observer);
407 }
408 
410 {
411  recruit_list_changed_.detach_handler(event_observer);
412 }
413 
415 {
416  map_changed_.detach_handler(event_observer);
417 }
418 
420 {
421  turn_started_.detach_handler(event_observer);
422 }
423 
426  return;
427  }
428 
429  using namespace std::chrono_literals;
430  constexpr auto interact_time = 30ms;
431 
432  const auto now = std::chrono::steady_clock::now();
433  const auto time_since_interact = now - last_interact_;
434  if(time_since_interact < interact_time) {
435  return;
436  }
437 
438  ++num_interact_;
440 
441  last_interact_ = now;
442 }
443 
446 }
447 
450 }
451 
454 }
455 
458 }
459 
462 }
463 
466 }
467 
468 // =======================================================================
469 // ADD, CREATE AIs, OR LIST AI TYPES
470 // =======================================================================
471 
472 bool manager::add_ai_for_side_from_file( side_number side, const std::string& file, bool replace )
473 {
474  config cfg;
476  ERR_AI_MANAGER << " unable to read [SIDE] config for side "<< side << "from file [" << file <<"]";
477  return false;
478  }
479  return add_ai_for_side_from_config(side,cfg,replace);
480 }
481 
482 bool manager::add_ai_for_side_from_config( side_number side, const config& cfg, bool replace ){
483  config parsed_cfg;
484  configuration::parse_side_config(side, cfg, parsed_cfg);
485 
486  if (replace) {
487  remove_ai_for_side(side);
488  }
489 
490  std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
491  ai_stack_for_specific_side.emplace(side, parsed_cfg);
492  return true;
493 }
494 
495 // =======================================================================
496 // REMOVE
497 // =======================================================================
498 
500 {
501  std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
502  if (!ai_stack_for_specific_side.empty()){
503  ai_stack_for_specific_side.pop();
504  }
505 }
506 
508 {
509  std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
510 
511  //clear the stack. std::stack doesn't have a '.clear()' method to do it
512  while (!ai_stack_for_specific_side.empty()){
513  ai_stack_for_specific_side.pop();
514  }
515 }
516 
518 {
519  ai_map_.clear();
520 }
521 
523 {
525 }
526 
528 {
530 }
531 
533 {
535 }
536 
538 {
540 }
541 
543 {
545 }
546 
548 {
549  if (!game_config::debug)
550  {
551  static ai::holder empty_holder(side, config());
552  return empty_holder;
553  }
554  return get_active_ai_holder_for_side(side);
555 }
556 
558 {
560 }
561 
563 {
564  return ai_info_;
565 }
566 
568 {
569  return ai_info_;
570 }
571 
573 {
575 }
576 
577 // =======================================================================
578 // PROXY
579 // =======================================================================
580 
582  last_interact_ = {};
583  num_interact_ = 0;
584  const auto turn_start_time = std::chrono::steady_clock::now();
585  get_ai_info().recent_attacks.clear();
586  ai_composite& ai_obj = get_active_ai_for_side(side);
587  resources::game_events->pump().fire("ai_turn");
589  if (resources::tod_manager->has_tod_bonus_changed()) {
591  }
592  ai_obj.new_turn();
593  ai_obj.play_turn();
594  const auto turn_end_time = std::chrono::steady_clock::now();
595  DBG_AI_MANAGER << "side " << side << ": number of user interactions: "<<num_interact_;
596  DBG_AI_MANAGER << "side " << side << ": total turn time: " << (turn_end_time - turn_start_time).count() << " ms ";
597 }
598 
599 // =======================================================================
600 // PRIVATE
601 // =======================================================================
602 // =======================================================================
603 // AI STACKS
604 // =======================================================================
606 {
607  AI_map_of_stacks::iterator iter = ai_map_.find(side);
608  if (iter!=ai_map_.end()){
609  return iter->second;
610  }
611  return ai_map_.emplace(side, std::stack<holder>()).first->second;
612 }
613 
614 // =======================================================================
615 // AI HOLDERS
616 // =======================================================================
618 {
619  std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
620 
621  if (!ai_stack_for_specific_side.empty()){
622  return ai_stack_for_specific_side.top();
623  } else {
625  ai_stack_for_specific_side.emplace(side, cfg);
626  return ai_stack_for_specific_side.top();
627  }
628 }
629 
630 // =======================================================================
631 // AI POINTERS
632 // =======================================================================
633 
635 {
637 }
638 
639 // =======================================================================
640 // MISC
641 // =======================================================================
642 
643 } //end of namespace ai
#define LOG_AI_MOD
Definition: manager.cpp:70
#define DBG_AI_MOD
Definition: manager.cpp:69
#define ERR_AI_MOD
Definition: manager.cpp:72
#define LOG_AI_MANAGER
Definition: manager.cpp:65
#define DBG_AI_MANAGER
Definition: manager.cpp:64
#define ERR_AI_MANAGER
Definition: manager.cpp:66
Managing the AIs lifecycle - headers TODO: Refactor history handling and internal commands.
Composite AI with turn sequence which is a vector of stages.
virtual void new_turn()
On new turn.
Definition: ai.cpp:149
void play_turn()
Play the turn.
Definition: ai.cpp:127
static bool delete_component(component *root, const std::string &path)
Definition: component.cpp:201
static component * get_component(component *root, const std::string &path)
Definition: component.cpp:249
static bool change_component(component *root, const std::string &path, const config &cfg)
Definition: component.cpp:187
static bool add_component(component *root, const std::string &path, const config &cfg)
Definition: component.cpp:172
static std::string print_component_tree(component *root, const std::string &path)
Definition: component.cpp:231
static bool get_side_config_from_file(const std::string &file, config &cfg)
get side config from file
static bool parse_side_config(side_number side, const config &original_cfg, config &cfg)
static const config & get_default_ai_parameters()
get default AI parameters
std::set< map_location > recent_attacks
Definition: game_info.hpp:115
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
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::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
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
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
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
virtual const unit_advancements_aspect & get_advancements() const override
Definition: contexts.hpp:538
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:158
void clear_children(T... keys)
Definition: config.hpp:602
void merge_with(const config &c)
Merge config 'c' into this config, overwriting this config's values.
Definition: config.cpp:1113
child_itors child_range(config_key_type key)
Definition: config.cpp:268
virtual bool attach_handler(observer *obs)
virtual bool detach_handler(observer *obs)
virtual void notify_observers()
std::ostringstream wrapper.
Definition: formatter.hpp:40
game_events::wml_event_pump & pump()
Definition: manager.cpp:257
pump_result_t fire(const std::string &event, const entity_location &loc1=entity_location::null_entity, const entity_location &loc2=entity_location::null_entity, const config &data=config())
Function to fire an event.
Definition: pump.cpp:399
A component of the AI framework.
Definitions for the interface to Wesnoth Markup Language (WML).
Managing the AIs configuration - headers.
Helper functions for the object which operates in the context of AI for specific side this is part of...
Default AI contexts.
AI Support engine - creating specific ai components from config.
LUA AI Support engine - creating specific ai components from config.
const config * cfg
Game information for the AI.
Standard logging facilities (interface).
void init()
Definition: registry.cpp:500
A small explanation about what's going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:59
static lg::log_domain log_ai_mod("ai/mod")
static lg::log_domain log_ai_manager("ai/manager")
int side_number
Definition: game_info.hpp:40
std::string path
Definition: filesystem.cpp:106
const bool & debug
Definition: game_config.cpp:95
::tod_manager * tod_manager
Definition: resources.cpp:29
bool simulation
Definition: resources.cpp:35
game_events::manager * game_events
Definition: resources.cpp:24
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
Define the game's event mechanism.
All known AI parts.
static map_location::direction s