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