The Battle for Wesnoth  1.15.9+dev
manager.cpp
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  * Managing the AI lifecycle and interface for the rest of Wesnoth
17  * @file
18  */
19 
20 #include "ai/manager.hpp"
21 
22 #include "config.hpp" // for config, etc
23 #include "game_events/pump.hpp"
24 #include "log.hpp"
25 #include "map/location.hpp" // for map_location
26 #include "resources.hpp"
28 #include "tod_manager.hpp"
29 
30 #include "ai/composite/ai.hpp" // for ai_composite
31 #include "ai/composite/component.hpp" // for component_manager
32 #include "ai/composite/engine.hpp" // for engine
34 #include "ai/configuration.hpp" // for configuration
35 #include "ai/contexts.hpp" // for readonly_context, etc
36 #include "ai/default/contexts.hpp" // for default_ai_context, etc
37 #include "game_end_exceptions.hpp" // for ai_end_turn_exception
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 
43 #include <algorithm> // for min
44 #include <cassert> // for assert
45 #include <iterator> // for reverse_iterator, etc
46 #include <map> // for _Rb_tree_iterator, etc
47 #include <ostream> // for operator<<, basic_ostream, 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 
74 holder::holder( side_number side, const config &cfg )
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" << std::endl;
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 (!this->ai_){
99  }
100 
101  if (this->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  cfg_.clear_children("modify_ai");
110 
111  std::vector<engine_ptr> engines = ai_->get_engines();
112  for (std::vector<engine_ptr>::iterator it = engines.begin(); it != engines.end(); ++it)
113  {
114  (*it)->set_ai_context(&(ai_->get_ai_context()));
115  }
116 
117  } else {
118  ERR_AI_MANAGER << describe_ai()<<"AI lazy initialization error!" << std::endl;
119  }
120 
121 }
122 
124 {
125  try {
126  if (this->ai_) {
127  LOG_AI_MANAGER << describe_ai() << "Managed AI will be deleted" << std::endl;
128  }
129  } catch (...) {}
130 }
131 
133 {
134  if (!this->ai_) {
135  this->init(this->side_);
136  }
137  assert(this->ai_);
138 
139  return *this->ai_;
140 }
141 
142 void holder::modify_ai(const config &cfg)
143 {
144  if (!this->ai_) {
145  // if not initialized, initialize now.
146  get_ai_ref();
147  }
148  const std::string &act = cfg["action"];
149  LOG_AI_MOD << "side "<< side_ << " "<<act<<"_ai_component \""<<cfg["path"]<<"\""<<std::endl;
150  DBG_AI_MOD << std::endl << cfg << std::endl;
151  DBG_AI_MOD << "side "<< side_ << " before "<<act<<"_ai_component"<<std::endl << to_config() << std::endl;
152  bool res = false;
153  if (act == "add") {
154  res = component_manager::add_component(&*this->ai_,cfg["path"],cfg);
155  } else if (act == "change") {
156  res = component_manager::change_component(&*this->ai_,cfg["path"],cfg);
157  } else if (act == "delete") {
158  res = component_manager::delete_component(&*this->ai_,cfg["path"]);
159  } else {
160  ERR_AI_MOD << "modify_ai tag has invalid 'action' attribute " << act << std::endl;
161  }
162  DBG_AI_MOD << "side "<< side_ << " after [modify_ai]"<<act<<std::endl << to_config() << std::endl;
163  if (!res) {
164  LOG_AI_MOD << act << "_ai_component failed"<< std::endl;
165  } else {
166  LOG_AI_MOD << act << "_ai_component success"<< std::endl;
167  }
168 
169 }
170 
171 void holder::append_ai(const config& cfg)
172 {
173  if(!this->ai_) {
174  get_ai_ref();
175  }
176  for(const config& aspect : cfg.child_range("aspect")) {
177  const std::string& id = aspect["id"];
178  for(const config& facet : aspect.child_range("facet")) {
179  ai_->add_facet(id, facet);
180  }
181  }
182  for(const config& goal : cfg.child_range("goal")) {
183  ai_->add_goal(goal);
184  }
185  for(const config& stage : cfg.child_range("stage")) {
186  if(stage["name"] != "empty") {
187  ai_->add_stage(stage);
188  }
189  }
190 }
191 
193 {
194  if (!this->ai_) {
195  return cfg_;
196  } else {
197  config cfg = ai_->to_config();
198  if (this->side_context_!=nullptr) {
199  cfg.merge_with(this->side_context_->to_side_context_config());
200  }
201  if (this->readonly_context_!=nullptr) {
202  cfg.merge_with(this->readonly_context_->to_readonly_context_config());
203  }
204  if (this->readwrite_context_!=nullptr) {
205  cfg.merge_with(this->readwrite_context_->to_readwrite_context_config());
206  }
207  if (this->default_ai_context_!=nullptr) {
208  cfg.merge_with(this->default_ai_context_->to_default_ai_context_config());
209  }
210 
211  return cfg;
212  }
213 }
214 
215 const std::string holder::describe_ai()
216 {
217  std::string sidestr = std::to_string(this->side_);
218 
219  if (this->ai_!=nullptr) {
220  return this->ai_->describe_self()+std::string(" for side ")+sidestr+std::string(" : ");
221  } else {
222  return std::string("not initialized ai with id=[")+cfg_["id"]+std::string("] for side ")+sidestr+std::string(" : ");
223  }
224 }
225 
226 const std::string holder::get_ai_overview()
227 {
228  if (!this->ai_) {
229  get_ai_ref();
230  }
231  // These assignments are necessary because the code will otherwise not compile on some platforms with an lvalue/rvalue mismatch error
232  boost::variant<bool, std::vector<std::string>> lik = this->ai_->get_leader_ignores_keep();
233  boost::variant<bool, std::vector<std::string>> pl = this->ai_->get_passive_leader();
234  boost::variant<bool, std::vector<std::string>> plsk = this->ai_->get_passive_leader_shares_keep();
235  // In order to display booleans as yes/no rather than 1/0 or true/false
236  config cfg;
237  cfg["simple_targeting"] = this->ai_->get_simple_targeting();
238  cfg["support_villages"] = this->ai_->get_support_villages();
239  std::stringstream s;
240  s << "advancements: " << this->ai_->get_advancements().get_value() << std::endl;
241  s << "aggression: " << this->ai_->get_aggression() << std::endl;
242  s << "caution: " << this->ai_->get_caution() << std::endl;
243  s << "grouping: " << this->ai_->get_grouping() << std::endl;
244  s << "leader_aggression: " << this->ai_->get_leader_aggression() << std::endl;
245  s << "leader_ignores_keep: " << boost::apply_visitor(leader_aspects_visitor(), lik) << std::endl;
246  s << "leader_value: " << this->ai_->get_leader_value() << std::endl;
247  s << "passive_leader: " << boost::apply_visitor(leader_aspects_visitor(), pl) << std::endl;
248  s << "passive_leader_shares_keep: " << boost::apply_visitor(leader_aspects_visitor(), plsk) << std::endl;
249  s << "recruitment_diversity: " << this->ai_->get_recruitment_diversity() << std::endl;
250  s << "recruitment_instructions: " << std::endl << "----config begin----" << std::endl;
251  s << this->ai_->get_recruitment_instructions() << "-----config end-----" << std::endl;
252  s << "recruitment_more: " << utils::join(this->ai_->get_recruitment_more()) << std::endl;
253  s << "recruitment_pattern: " << utils::join(this->ai_->get_recruitment_pattern()) << std::endl;
254  s << "recruitment_randomness: " << this->ai_->get_recruitment_randomness() << std::endl;
255  s << "recruitment_save_gold: " << std::endl << "----config begin----" << std::endl;
256  s << this->ai_->get_recruitment_save_gold() << "-----config end-----" << std::endl;
257  s << "scout_village_targeting: " << this->ai_->get_scout_village_targeting() << std::endl;
258  s << "simple_targeting: " << cfg["simple_targeting"] << std::endl;
259  s << "support_villages: " << cfg["support_villages"] << std::endl;
260  s << "village_value: " << this->ai_->get_village_value() << std::endl;
261  s << "villages_per_scout: " << this->ai_->get_villages_per_scout() << std::endl;
262 
263  return s.str();
264 }
265 
266 const std::string holder::get_ai_structure()
267 {
268  if (!this->ai_) {
269  get_ai_ref();
270  }
271  return component_manager::print_component_tree(&*this->ai_,"");
272 }
273 
274 const std::string holder::get_ai_identifier() const
275 {
276  return cfg_["id"];
277 }
278 
279 component* holder::get_component(component *root, const std::string &path) {
280  if (!game_config::debug) // Debug guard
281  {
282  return nullptr;
283  }
284 
285  if (root == nullptr) // Return root component(ai_)
286  {
287  if (!this->ai_) {
288  this->init(this->side_);
289  }
290  assert(this->ai_);
291 
292  return &*this->ai_;
293  }
294 
295  return component_manager::get_component(root, path);
296 }
297 
298 // =======================================================================
299 // LIFECYCLE
300 // =======================================================================
301 
303  : history_()
304  , history_item_counter_(0)
305  , ai_info_()
306  , map_changed_("ai_map_changed")
307  , recruit_list_changed_("ai_recruit_list_changed")
308  , user_interact_("ai_user_interact")
309  , sync_network_("ai_sync_network")
310  , tod_changed_("ai_tod_changed")
311  , gamestate_changed_("ai_gamestate_changed")
312  , turn_started_("ai_turn_started")
313  , last_interact_(0)
314  , num_interact_(0)
315 {
316  registry::init();
317  singleton_ = this;
318 }
319 
320 manager* manager::singleton_ = nullptr;
321 
323  user_interact_.attach_handler(event_observer);
324  sync_network_.attach_handler(event_observer);
325  turn_started_.attach_handler(event_observer);
326  gamestate_changed_.attach_handler(event_observer);
327 }
328 
330  user_interact_.detach_handler(event_observer);
331  sync_network_.detach_handler(event_observer);
332  turn_started_.detach_handler(event_observer);
333  gamestate_changed_.detach_handler(event_observer);
334 }
335 
337  gamestate_changed_.attach_handler(event_observer);
338  turn_started_.attach_handler(event_observer);
339  map_changed_.attach_handler(event_observer);
340 }
341 
343  gamestate_changed_.detach_handler(event_observer);
344  turn_started_.detach_handler(event_observer);
345  map_changed_.detach_handler(event_observer);
346 }
347 
349  tod_changed_.attach_handler(event_observer);
350 }
351 
353  tod_changed_.detach_handler(event_observer);
354 }
355 
357 {
358  map_changed_.attach_handler(event_observer);
359 }
360 
362 {
363  recruit_list_changed_.attach_handler(event_observer);
364 }
365 
367 {
368  turn_started_.attach_handler(event_observer);
369 }
370 
372 {
373  recruit_list_changed_.detach_handler(event_observer);
374 }
375 
377 {
378  map_changed_.detach_handler(event_observer);
379 }
380 
382 {
383  turn_started_.detach_handler(event_observer);
384 }
385 
388  return;
389  }
390 
391  const int interact_time = 30;
392  const int time_since_interact = SDL_GetTicks() - last_interact_;
393  if(time_since_interact < interact_time) {
394  return;
395  }
396 
397  ++num_interact_;
399 
400  last_interact_ = SDL_GetTicks();
401 
402 }
403 
406 }
407 
410 }
411 
414 }
415 
418 }
419 
422 }
423 
426 }
427 
428 // =======================================================================
429 // EVALUATION
430 // =======================================================================
431 
432 const std::string manager::evaluate_command( side_number side, const std::string& str )
433 {
434  //insert new command into history
435  history_.emplace_back(history_item_counter_++,str);
436 
437  //prune history - erase 1/2 of it if it grows too large
438  if (history_.size()>MAX_HISTORY_SIZE){
439  history_.erase(history_.begin(),history_.begin()+MAX_HISTORY_SIZE/2);
440  LOG_AI_MANAGER << "AI MANAGER: pruned history" << std::endl;
441  }
442 
443  if (!should_intercept(str)){
446  return ai.evaluate(str);
447  }
448 
449  return internal_evaluate_command(side,str);
450 }
451 
452 bool manager::should_intercept( const std::string& str ) const
453 {
454  if (str.length()<1) {
455  return false;
456  }
457  if (str.at(0)=='!'){
458  return true;
459  }
460  if (str.at(0)=='?'){
461  return true;
462  }
463  return false;
464 
465 }
466 
467 // this is stub code to allow testing of basic 'history', 'repeat-last-command', 'add/remove/replace ai' capabilities.
468 // yes, it doesn't look nice. but it is usable.
469 // to be refactored at earliest opportunity
470 // TODO: extract to separate class which will use fai or lua parser
471 const std::string manager::internal_evaluate_command( side_number side, const std::string& str ){
472  const int MAX_HISTORY_VISIBLE = 30;
473 
474  //repeat last command
475  if (str=="!") {
476  //this command should not be recorded in history
477  if (!history_.empty()){
478  history_.pop_back();
480  }
481 
482  if (history_.empty()){
483  return "AI MANAGER: empty history";
484  }
485  return evaluate_command(side, history_.back().get_command());//no infinite loop since '!' commands are not present in history
486  };
487  //show last command
488  if (str=="?") {
489  //this command should not be recorded in history
490  if (!history_.empty()){
491  history_.pop_back();
493  }
494 
495  if (history_.empty()){
496  return "AI MANAGER: History is empty";
497  }
498 
499  int n = std::min<int>( MAX_HISTORY_VISIBLE, history_.size() );
500  std::stringstream strstream;
501  strstream << "AI MANAGER: History - last "<< n <<" commands:\n";
502  std::deque< command_history_item >::reverse_iterator j = history_.rbegin();
503 
504  for (int cmd_id=n; cmd_id>0; --cmd_id){
505  strstream << j->get_number() << " :" << j->get_command() << '\n';
506  ++j;//this is *reverse* iterator
507  }
508 
509  return strstream.str();
510  };
511 
512  std::vector< std::string > cmd = utils::parenthetical_split(str, ' ',"'","'");
513 
514  if (cmd.size()==3){
515  // add_ai side file
516  if (cmd.at(0)=="!add_ai"){
517  side = std::stoi(cmd.at(1));
518  std::string file = cmd.at(2);
519  if (add_ai_for_side_from_file(side,file,false)){
520  return std::string("AI MANAGER: added [")+manager::get_active_ai_identifier_for_side(side)+std::string("] AI for side ")+std::to_string(side)+std::string(" from file ")+file;
521  } else {
522  return std::string("AI MANAGER: failed attempt to add AI for side ")+std::to_string(side)+std::string(" from file ")+file;
523  }
524  }
525  // replace_ai side file
526  if (cmd.at(0)=="!replace_ai"){
527  side = std::stoi(cmd.at(1));
528  std::string file = cmd.at(2);
529  if (add_ai_for_side_from_file(side,file,true)){
530  return std::string("AI MANAGER: added [")+manager::get_active_ai_identifier_for_side(side)+std::string("] AI for side ")+std::to_string(side)+std::string(" from file ")+file;
531  } else {
532  return std::string("AI MANAGER: failed attempt to add AI for side ")+std::to_string(side)+std::string(" from file ")+file;
533  }
534  }
535 
536  } else if (cmd.size()==2){
537  // remove_ai side
538  if (cmd.at(0)=="!remove_ai"){
539  side = std::stoi(cmd.at(1));
540  remove_ai_for_side(side);
541  return std::string("AI MANAGER: made an attempt to remove AI for side ")+std::to_string(side);
542  }
543  if (cmd.at(0)=="!"){
544  //this command should not be recorded in history
545  if (!history_.empty()){
546  history_.pop_back();
548  }
549 
550  int command = std::stoi(cmd.at(1));
551  std::deque< command_history_item >::reverse_iterator j = history_.rbegin();
552  //yes, the iterator could be precisely positioned (since command numbers go 1,2,3,4,..). will do it later.
553  while ( (j!=history_.rend()) && (j->get_number()!=command) ){
554  ++j;// this is *reverse* iterator
555  }
556  if (j!=history_.rend()){
557  return evaluate_command(side,j->get_command());//no infinite loop since '!' commands are not present in history
558  }
559  return "AI MANAGER: no command with requested number found";
560  }
561  } else if (cmd.size()==1){
562  if (cmd.at(0)=="!help") {
563  return
564  "known commands:\n"
565  "! - repeat last command (? and ! do not count)\n"
566  "! NUMBER - repeat numbered command\n"
567  "? - show a history list\n"
568  "!add_ai TEAM FILE - add a AI to side (0 - command AI, N - AI for side #N) from file\n"
569  "!remove_ai TEAM - remove AI from side (0 - command AI, N - AI for side #N)\n"
570  "!replace_ai TEAM FILE - replace AI of side (0 - command AI, N - AI for side #N) from file\n"
571  "!help - show this help message";
572  }
573  }
574 
575  return "AI MANAGER: nothing to do";
576 }
577 
578 // =======================================================================
579 // ADD, CREATE AIs, OR LIST AI TYPES
580 // =======================================================================
581 
582 bool manager::add_ai_for_side_from_file( side_number side, const std::string& file, bool replace )
583 {
584  config cfg;
586  ERR_AI_MANAGER << " unable to read [SIDE] config for side "<< side << "from file [" << file <<"]"<< std::endl;
587  return false;
588  }
589  return add_ai_for_side_from_config(side,cfg,replace);
590 }
591 
592 bool manager::add_ai_for_side_from_config( side_number side, const config& cfg, bool replace ){
593  config parsed_cfg;
594  configuration::parse_side_config(side, cfg, parsed_cfg);
595 
596  if (replace) {
597  remove_ai_for_side(side);
598  }
599 
600  std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
601  ai_stack_for_specific_side.emplace(side, parsed_cfg);
602  return true;
603 }
604 
605 // =======================================================================
606 // REMOVE
607 // =======================================================================
608 
610 {
611  std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
612  if (!ai_stack_for_specific_side.empty()){
613  ai_stack_for_specific_side.pop();
614  }
615 }
616 
618 {
619  std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
620 
621  //clear the stack. std::stack doesn't have a '.clear()' method to do it
622  while (!ai_stack_for_specific_side.empty()){
623  ai_stack_for_specific_side.pop();
624  }
625 }
626 
628 {
629  ai_map_.clear();
630 }
631 
633 {
635 }
636 
638 {
640 }
641 
643 {
645 }
646 
648 {
650 }
651 
653 {
655 }
656 
658 {
659  if (!game_config::debug)
660  {
661  static ai::holder empty_holder(side, config());
662  return empty_holder;
663  }
664  return get_active_ai_holder_for_side(side);
665 }
666 
668 {
670 }
671 
673 {
674  return ai_info_;
675 }
676 
678 {
679  return ai_info_;
680 }
681 
683 {
685 }
686 
687 // =======================================================================
688 // PROXY
689 // =======================================================================
690 
692  last_interact_ = 0;
693  num_interact_ = 0;
694  const int turn_start_time = SDL_GetTicks();
695  get_ai_info().recent_attacks.clear();
696  ai_composite& ai_obj = get_active_ai_for_side(side);
697  resources::game_events->pump().fire("ai_turn");
699  if (resources::tod_manager->has_tod_bonus_changed()) {
701  }
702  ai_obj.new_turn();
703  ai_obj.play_turn();
704  const int turn_end_time= SDL_GetTicks();
705  DBG_AI_MANAGER << "side " << side << ": number of user interactions: "<<num_interact_<<std::endl;
706  DBG_AI_MANAGER << "side " << side << ": total turn time: "<<turn_end_time - turn_start_time << " ms "<< std::endl;
707 }
708 
709 // =======================================================================
710 // PRIVATE
711 // =======================================================================
712 // =======================================================================
713 // AI STACKS
714 // =======================================================================
716 {
717  AI_map_of_stacks::iterator iter = ai_map_.find(side);
718  if (iter!=ai_map_.end()){
719  return iter->second;
720  }
721  return ai_map_.emplace(side, std::stack<holder>()).first->second;
722 }
723 
724 // =======================================================================
725 // AI HOLDERS
726 // =======================================================================
728 {
729  std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
730 
731  if (!ai_stack_for_specific_side.empty()){
732  return ai_stack_for_specific_side.top();
733  } else {
735  ai_stack_for_specific_side.emplace(side, cfg);
736  return ai_stack_for_specific_side.top();
737  }
738 }
739 
740 // =======================================================================
741 // AI POINTERS
742 // =======================================================================
743 
745 {
747 }
748 
749 // =======================================================================
750 // MISC
751 // =======================================================================
752 
753 } //end of namespace ai
virtual std::string evaluate(const std::string &str)
Evaluate command (using fai)
Definition: ai.cpp:163
void add_observer(events::observer *event_observer)
Adds observer of game events.
Definition: manager.cpp:322
#define ERR_AI_MANAGER
Definition: manager.cpp:66
::tod_manager * tod_manager
Definition: resources.cpp:29
V::result_t apply_visitor(typename V::param_t state, T &&... args)
Helper function to apply the result of a specified visitor to a variable_info object.
void clear_children(T... keys)
Definition: config.hpp:490
virtual void notify_observers()
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
void raise_gamestate_changed()
Notifies all observers of &#39;ai_gamestate_changed&#39; event.
Definition: manager.cpp:408
static bool change_component(component *root, const std::string &path, const config &cfg)
Definition: component.cpp:195
#define LOG_AI_MANAGER
Definition: manager.cpp:65
void raise_map_changed()
Notifies all observers of &#39;ai_map_changed&#39; event.
Definition: manager.cpp:424
bool should_intercept(const std::string &str) const
Determines if the command should be intercepted and evaluated as internal command.
Definition: manager.cpp:452
game_info & get_active_ai_info_for_side(side_number side)
Gets AI info for active AI of the given side.
Definition: manager.cpp:672
child_itors child_range(config_key_type key)
Definition: config.cpp:362
config cfg_
Definition: manager.hpp:85
void add_turn_started_observer(events::observer *event_observer)
Adds an observer of &#39;ai_turn_started&#39; event.
Definition: manager.cpp:366
holder(side_number side, const config &cfg)
Definition: manager.cpp:74
events::generic_event gamestate_changed_
Definition: manager.hpp:433
Class that manages AIs for all sides and manages AI redeployment.
Definition: manager.hpp:111
AI Support engine - creating specific ai components from config.
std::unique_ptr< readonly_context > readonly_context_
Definition: manager.hpp:81
#define DBG_AI_MOD
Definition: manager.cpp:69
Contains the exception interfaces used to signal completion of a scenario, campaign or turn...
const std::string internal_evaluate_command(side_number side, const std::string &str)
Evaluates an internal manager command.
Definition: manager.cpp:471
Definitions for the interface to Wesnoth Markup Language (WML).
void add_tod_changed_observer(events::observer *event_observer)
Adds an observer of &#39;ai_tod_changed&#39; event.
Definition: manager.cpp:348
config to_config() const
Definition: manager.cpp:192
composite_ai_ptr ai_
Definition: manager.hpp:79
const std::string get_ai_overview()
Definition: manager.cpp:226
void init(side_number side)
Definition: manager.cpp:80
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:637
#define LOG_AI_MOD
Definition: manager.cpp:70
formula_ai & ai_
std::unique_ptr< side_context > side_context_
Definition: manager.hpp:80
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&#39;t exist.
Definition: manager.cpp:715
virtual const unit_advancements_aspect & get_advancements() const override
Definition: contexts.hpp:540
void merge_with(const config &c)
Merge config &#39;c&#39; into this config, overwriting this config&#39;s values.
Definition: config.cpp:1167
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:582
void clear_ais()
Clears all the AIs.
Definition: manager.cpp:627
void raise_recruit_list_changed()
Notifies all observers of &#39;ai_recruit_list_changed&#39; event.
Definition: manager.cpp:420
const std::string get_ai_structure()
Definition: manager.cpp:266
A small explanation about what&#39;s going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:59
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:342
static bool parse_side_config(side_number side, const config &original_cfg, config &cfg)
static component * get_component(component *root, const std::string &path)
Definition: component.cpp:257
std::deque< command_history_item > history_
Definition: manager.hpp:424
virtual void new_turn()
On new turn.
Definition: ai.cpp:175
component * get_component(component *root, const std::string &path)
Definition: manager.cpp:279
void remove_turn_started_observer(events::observer *event_observer)
Deletes an observer of &#39;ai_turn_started&#39; event.
Definition: manager.cpp:381
std::string get_active_ai_overview_for_side(side_number side)
Gets AI Overview for active AI of the given side.
Definition: manager.cpp:642
events::generic_event user_interact_
Definition: manager.hpp:430
A component of the AI framework.
Composite AI with turn sequence which is a vector of stages.
config to_config(side_number side)
Gets AI config for active AI of the given side.
Definition: manager.cpp:667
std::unique_ptr< default_ai_context > default_ai_context_
Definition: manager.hpp:83
#define ERR_AI_MOD
Definition: manager.cpp:72
std::string path
Definition: game_config.cpp:39
static lg::log_domain log_ai_manager("ai/manager")
Managing the AIs lifecycle - headers TODO: Refactor history handling and internal commands...
void play_turn(side_number side)
Plays a turn for the specified side using its active AI.
Definition: manager.cpp:691
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:632
void init()
Initializes the GUI subsystems.
Definition: registry.cpp:468
game_events::manager * game_events
Definition: resources.cpp:24
void modify_ai(const config &cfg)
Definition: manager.cpp:142
void remove_all_ais_for_side(side_number side)
Removes all AIs from side.
Definition: manager.cpp:617
static const std::string AI_TYPE_DEFAULT
Definition: manager.hpp:127
virtual ~holder()
Definition: manager.cpp:123
static const std::string AI_TYPE_IDLE_AI
Definition: manager.hpp:123
static bool delete_component(component *root, const std::string &path)
Definition: component.cpp:209
void remove_ai_for_side(side_number side)
Removes top-level AI from side.
Definition: manager.cpp:609
virtual bool attach_handler(observer *obs)
const std::string evaluate_command(side_number side, const std::string &str)
Evaluates a string command using command AI.
Definition: manager.cpp:432
events::generic_event sync_network_
Definition: manager.hpp:431
static bool add_component(component *root, const std::string &path, const config &cfg)
Definition: component.cpp:180
void raise_user_interact()
Notifies all observers of &#39;ai_user_interact&#39; event.
Definition: manager.cpp:386
static const std::string AI_TYPE_COMPOSITE_AI
Definition: manager.hpp:121
static std::string print_component_tree(component *root, const std::string &path)
Definition: component.cpp:239
#define DBG_AI_MANAGER
Definition: manager.cpp:64
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:652
static map_location::DIRECTION s
void append_ai(const config &cfg)
Definition: manager.cpp:171
std::set< map_location > recent_attacks
Definition: game_info.hpp:114
Default AI contexts.
events::generic_event map_changed_
Definition: manager.hpp:428
Define the game&#39;s event mechanism.
const std::string get_ai_identifier() const
Definition: manager.cpp:274
void add_recruit_list_changed_observer(events::observer *event_observer)
Adds an observer of &#39;ai_recruit_list_changed&#39; event.
Definition: manager.cpp:361
void remove_tod_changed_observer(events::observer *event_observer)
Deletes an observer of &#39;ai_tod_changed&#39; event.
Definition: manager.cpp:352
events::generic_event turn_started_
Definition: manager.hpp:434
long history_item_counter_
Definition: manager.hpp:425
bool simulation_
Definition: resources.cpp:35
const bool & debug
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:592
Helper functions for the object which operates in the context of AI for specific side this is part of...
std::string get_active_ai_structure_for_side(side_number side)
Gets AI Structure for active AI of the given side.
Definition: manager.cpp:647
events::generic_event tod_changed_
Definition: manager.hpp:432
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:486
game_info ai_info_
Definition: manager.hpp:426
const ai::unit_advancements_aspect & get_advancement_aspect_for_side(side_number side)
Definition: manager.cpp:682
static manager * singleton_
Definition: manager.hpp:440
const std::string describe_ai()
Definition: manager.cpp:215
static lg::log_domain log_ai_mod("ai/mod")
void remove_observer(events::observer *event_observer)
Removes an observer of game events.
Definition: manager.cpp:329
static const std::string AI_TYPE_FORMULA_AI
Definition: manager.hpp:124
void play_turn()
Play the turn.
Definition: ai.cpp:141
static const config & get_default_ai_parameters()
get default AI parameters
ai_composite & get_ai_ref()
Definition: manager.cpp:132
static const std::string AI_TYPE_SAMPLE_AI
Definition: manager.hpp:122
game_info & get_ai_info()
Gets global AI-game info.
Definition: manager.cpp:677
side_number side_
Definition: manager.hpp:84
Managing the AIs configuration - headers.
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:336
std::unique_ptr< readwrite_context > readwrite_context_
Definition: manager.hpp:82
int num_interact_
Definition: manager.hpp:436
Standard logging facilities (interface).
virtual bool detach_handler(observer *obs)
static bool get_side_config_from_file(const std::string &file, config &cfg)
get side config from file
void raise_sync_network()
Notifies all observers of &#39;ai_sync_network&#39; event.
Definition: manager.cpp:404
AI_map_of_stacks ai_map_
Definition: manager.hpp:438
ai_composite & get_active_ai_for_side(side_number side)
Gets active AI for specified side.
Definition: manager.cpp:744
int side_number
Definition: game_info.hpp:39
game_events::wml_event_pump & pump()
Definition: manager.cpp:229
void raise_tod_changed()
Notifies all observers of &#39;ai_tod_changed&#39; event.
Definition: manager.cpp:412
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:60
ai::holder & get_active_ai_holder_for_side_dbg(side_number side)
Gets the active AI holder for debug purposes.
Definition: manager.cpp:657
static map_location::DIRECTION n
static const std::size_t MAX_HISTORY_SIZE
Definition: manager.hpp:119
int last_interact_
Definition: manager.hpp:435
void remove_recruit_list_changed_observer(events::observer *event_observer)
Deletes an observer of &#39;ai_recruit_list_changed&#39; event.
Definition: manager.cpp:371
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
events::generic_event recruit_list_changed_
Definition: manager.hpp:429
void raise_turn_started()
Notifies all observers of &#39;ai_turn_started&#39; event.
Definition: manager.cpp:416
All known AI parts.
Base class that holds the AI and current AI parameters.
Definition: manager.hpp:52
holder & get_active_ai_holder_for_side(side_number side)
Gets active holder for specified side.
Definition: manager.cpp:727
void add_map_changed_observer(events::observer *event_observer)
Adds an observer of &#39;ai_map_changed&#39; event.
Definition: manager.cpp:356
std::vector< std::string > parenthetical_split(const std::string &val, const char separator, const std::string &left, const std::string &right, const int flags)
Splits a string based either on a separator, except then the text appears within specified parenthesi...
void remove_map_changed_observer(events::observer *event_observer)
Deletes an observer of &#39;ai_map_changed&#39; event.
Definition: manager.cpp:376