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