The Battle for Wesnoth  1.13.10+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
manager.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2017 by Yurii Chernyi <terraninfo@terraninfo.net>
3  Part of the Battle for Wesnoth Project http://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 "generic_event.hpp" // for generic_event, etc
25 #include "log.hpp"
26 #include "map/location.hpp" // for map_location
27 #include "resources.hpp"
29 #include "tod_manager.hpp"
30 
31 #include "ai/composite/ai.hpp" // for ai_composite
32 #include "ai/composite/component.hpp" // for component_manager
33 #include "ai/composite/engine.hpp" // for engine
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 <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  std::stringstream s;
239  s << "advancements: " << this->ai_->get_advancements().get_value() << std::endl;
240  s << "aggression: " << this->ai_->get_aggression() << std::endl;
241  s << "attack_depth: " << this->ai_->get_attack_depth() << 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: " << this->ai_->get_leader_ignores_keep() << std::endl;
246  s << "leader_value: " << this->ai_->get_leader_value() << std::endl;
247  s << "passive_leader: " << this->ai_->get_passive_leader() << std::endl;
248  s << "passive_leader_shares_keep: " << this->ai_->get_passive_leader_shares_keep() << 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: " << this->ai_->get_simple_targeting() << std::endl;
259  s << "support_villages: " << this->ai_->get_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 
267 
269 {
270  if (!this->ai_) {
271  get_ai_ref();
272  }
273  return component_manager::print_component_tree(&*this->ai_,"");
274 }
275 
276 
278 {
279  return cfg_["id"];
280 }
281 
283  if (!game_config::debug) // Debug guard
284  {
285  return nullptr;
286  }
287 
288  if (root == nullptr) // Return root component(ai_)
289  {
290  if (!this->ai_) {
291  this->init(this->side_);
292  }
293  assert(this->ai_);
294 
295  return &*this->ai_;
296  }
297 
298  return component_manager::get_component(root, path);
299 }
300 
301 // =======================================================================
302 // LIFECYCLE
303 // =======================================================================
304 
305 
307 std::unique_ptr<game_info> manager::ai_info_;
311 events::generic_event manager::gamestate_changed_("ai_gamestate_changed");
313 events::generic_event manager::recruit_list_changed_("ai_recruit_list_changed");
316 int manager::num_interact_ = 0;
317 
318 
320 {
321  if (ai_info_!=nullptr){
322  clear_ai_info();
323  }
324  ai_info_.reset(new game_info(i));
325  registry::init();
326 }
327 
328 
330  ai_info_.reset(nullptr);
331 }
332 
333 
335  user_interact_.attach_handler(event_observer);
336  sync_network_.attach_handler(event_observer);
337  turn_started_.attach_handler(event_observer);
338  gamestate_changed_.attach_handler(event_observer);
339 }
340 
341 
343  user_interact_.detach_handler(event_observer);
344  sync_network_.detach_handler(event_observer);
345  turn_started_.detach_handler(event_observer);
346  gamestate_changed_.detach_handler(event_observer);
347 }
348 
349 
351  gamestate_changed_.attach_handler(event_observer);
352  turn_started_.attach_handler(event_observer);
353  map_changed_.attach_handler(event_observer);
354 }
355 
356 
358  gamestate_changed_.detach_handler(event_observer);
359  turn_started_.detach_handler(event_observer);
360  map_changed_.detach_handler(event_observer);
361 }
362 
363 
365  tod_changed_.attach_handler(event_observer);
366 }
367 
368 
370  tod_changed_.detach_handler(event_observer);
371 }
372 
373 
374 
376 {
377  map_changed_.attach_handler(event_observer);
378 }
379 
380 
382 {
383  recruit_list_changed_.attach_handler(event_observer);
384 }
385 
386 
388 {
389  turn_started_.attach_handler(event_observer);
390 }
391 
392 
394 {
395  recruit_list_changed_.detach_handler(event_observer);
396 }
397 
398 
400 {
401  map_changed_.detach_handler(event_observer);
402 }
403 
404 
406 {
407  turn_started_.detach_handler(event_observer);
408 }
409 
412  return;
413  }
414 
415  const int interact_time = 30;
416  const int time_since_interact = SDL_GetTicks() - last_interact_;
417  if(time_since_interact < interact_time) {
418  return;
419  }
420 
421  ++num_interact_;
423 
424  last_interact_ = SDL_GetTicks();
425 
426 }
427 
430 }
431 
432 
435 }
436 
437 
440 }
441 
442 
445 }
446 
447 
450 }
451 
452 
455 }
456 
457 
458 // =======================================================================
459 // EVALUATION
460 // =======================================================================
461 
463 {
464  //insert new command into history
465  history_.emplace_back(history_item_counter_++,str);
466 
467  //prune history - erase 1/2 of it if it grows too large
468  if (history_.size()>MAX_HISTORY_SIZE){
469  history_.erase(history_.begin(),history_.begin()+MAX_HISTORY_SIZE/2);
470  LOG_AI_MANAGER << "AI MANAGER: pruned history" << std::endl;
471  }
472 
473  if (!should_intercept(str)){
476  return ai.evaluate(str);
477  }
478 
479  return internal_evaluate_command(side,str);
480 }
481 
482 
484 {
485  if (str.length()<1) {
486  return false;
487  }
488  if (str.at(0)=='!'){
489  return true;
490  }
491  if (str.at(0)=='?'){
492  return true;
493  }
494  return false;
495 
496 }
497 
498 std::deque< command_history_item > manager::history_;
500 
501 //this is stub code to allow testing of basic 'history', 'repeat-last-command', 'add/remove/replace ai' capabilities.
502 //yes, it doesn't look nice. but it is usable.
503 //to be refactored at earliest opportunity
504 ///@todo 1.9 extract to separate class which will use fai or lua parser
506  const int MAX_HISTORY_VISIBLE = 30;
507 
508  //repeat last command
509  if (str=="!") {
510  //this command should not be recorded in history
511  if (!history_.empty()){
512  history_.pop_back();
514  }
515 
516  if (history_.empty()){
517  return "AI MANAGER: empty history";
518  }
519  return evaluate_command(side, history_.back().get_command());//no infinite loop since '!' commands are not present in history
520  };
521  //show last command
522  if (str=="?") {
523  //this command should not be recorded in history
524  if (!history_.empty()){
525  history_.pop_back();
527  }
528 
529  if (history_.empty()){
530  return "AI MANAGER: History is empty";
531  }
532 
533  int n = std::min<int>( MAX_HISTORY_VISIBLE, history_.size() );
534  std::stringstream strstream;
535  strstream << "AI MANAGER: History - last "<< n <<" commands:\n";
536  std::deque< command_history_item >::reverse_iterator j = history_.rbegin();
537 
538  for (int cmd_id=n; cmd_id>0; --cmd_id){
539  strstream << j->get_number() << " :" << j->get_command() << '\n';
540  ++j;//this is *reverse* iterator
541  }
542 
543  return strstream.str();
544  };
545 
546 
547  std::vector< std::string > cmd = utils::parenthetical_split(str, ' ',"'","'");
548 
549  if (cmd.size()==3){
550  //!add_ai side file
551  if (cmd.at(0)=="!add_ai"){
552  side = std::stoi(cmd.at(1));
553  std::string file = cmd.at(2);
554  if (add_ai_for_side_from_file(side,file,false)){
555  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;
556  } else {
557  return std::string("AI MANAGER: failed attempt to add AI for side ")+std::to_string(side)+std::string(" from file ")+file;
558  }
559  }
560  //!replace_ai side file
561  if (cmd.at(0)=="!replace_ai"){
562  side = std::stoi(cmd.at(1));
563  std::string file = cmd.at(2);
564  if (add_ai_for_side_from_file(side,file,true)){
565  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;
566  } else {
567  return std::string("AI MANAGER: failed attempt to add AI for side ")+std::to_string(side)+std::string(" from file ")+file;
568  }
569  }
570 
571  } else if (cmd.size()==2){
572  //!remove_ai side
573  if (cmd.at(0)=="!remove_ai"){
574  side = std::stoi(cmd.at(1));
575  remove_ai_for_side(side);
576  return std::string("AI MANAGER: made an attempt to remove AI for side ")+std::to_string(side);
577  }
578  if (cmd.at(0)=="!"){
579  //this command should not be recorded in history
580  if (!history_.empty()){
581  history_.pop_back();
583  }
584 
585  int command = std::stoi(cmd.at(1));
586  std::deque< command_history_item >::reverse_iterator j = history_.rbegin();
587  //yes, the iterator could be precisely positioned (since command numbers go 1,2,3,4,..). will do it later.
588  while ( (j!=history_.rend()) && (j->get_number()!=command) ){
589  ++j;// this is *reverse* iterator
590  }
591  if (j!=history_.rend()){
592  return evaluate_command(side,j->get_command());//no infinite loop since '!' commands are not present in history
593  }
594  return "AI MANAGER: no command with requested number found";
595  }
596  } else if (cmd.size()==1){
597  if (cmd.at(0)=="!help") {
598  return
599  "known commands:\n"
600  "! - repeat last command (? and ! do not count)\n"
601  "! NUMBER - repeat numbered command\n"
602  "? - show a history list\n"
603  "!add_ai TEAM FILE - add a AI to side (0 - command AI, N - AI for side #N) from file\n"
604  "!remove_ai TEAM - remove AI from side (0 - command AI, N - AI for side #N)\n"
605  "!replace_ai TEAM FILE - replace AI of side (0 - command AI, N - AI for side #N) from file\n"
606  "!help - show this help message";
607  }
608  }
609 
610 
611  return "AI MANAGER: nothing to do";
612 }
613 
614 // =======================================================================
615 // ADD, CREATE AIs, OR LIST AI TYPES
616 // =======================================================================
617 
618 ///@todo 1.9 add error reporting
619 bool manager::add_ai_for_side_from_file( side_number side, const std::string& file, bool replace )
620 {
621  config cfg;
623  ERR_AI_MANAGER << " unable to read [SIDE] config for side "<< side << "from file [" << file <<"]"<< std::endl;
624  return false;
625  }
626  return add_ai_for_side_from_config(side,cfg,replace);
627 }
628 
629 
630 bool manager::add_ai_for_side_from_config( side_number side, const config& cfg, bool replace ){
631  config parsed_cfg;
632  configuration::parse_side_config(side, cfg, parsed_cfg);
633 
634  if (replace) {
635  remove_ai_for_side(side);
636  }
637 
638  std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
639  ai_stack_for_specific_side.emplace(side, parsed_cfg);
640  return true;
641 }
642 
643 
644 ///@todo 1.9 add error reporting
645 bool manager::add_ai_for_side( side_number side, const std::string& ai_algorithm_type, bool replace )
646 {
647  if (replace) {
648  remove_ai_for_side (side);
649  }
650  config cfg;
651  cfg["ai_algorithm"] = ai_algorithm_type;
652  std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
653  ai_stack_for_specific_side.emplace(side, cfg);
654  return true;
655 }
656 
657 
658 // =======================================================================
659 // REMOVE
660 // =======================================================================
661 
663 {
664  std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
665  if (!ai_stack_for_specific_side.empty()){
666  ai_stack_for_specific_side.pop();
667  }
668 }
669 
670 
672 {
673  std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
674 
675  //clear the stack. std::stack doesn't have a '.clear()' method to do it
676  while (!ai_stack_for_specific_side.empty()){
677  ai_stack_for_specific_side.pop();
678  }
679 }
680 
681 
683 {
684  ai_map_.clear();
685 }
686 
687 
689 {
690  if (ai_info_==nullptr) {
691  //replay ?
692  return;
693  }
695 }
696 
697 
699 {
700  if(!ai_info_) {
701  return;
702  }
704 }
705 
707 {
709 }
710 
711 
713 {
715 }
716 
717 
719 {
721 }
722 
724 {
725  if (!game_config::debug)
726  {
727  static ai::holder empty_holder(side, config());
728  return empty_holder;
729  }
730  return get_active_ai_holder_for_side(side);
731 }
732 
733 
735 {
737 }
738 
739 
741 {
742  return *ai_info_;
743 }
744 
745 
747 {
748  return *ai_info_;
749 }
750 
751 
752 // =======================================================================
753 // PROXY
754 // =======================================================================
755 
757  last_interact_ = 0;
758  num_interact_ = 0;
759  const int turn_start_time = SDL_GetTicks();
760  /*hack. @todo 1.9 rework via extended event system*/
761  get_ai_info().recent_attacks.clear();
762  ai_composite& ai_obj = get_active_ai_for_side(side);
763  resources::game_events->pump().fire("ai_turn");
765  if (resources::tod_manager->has_tod_bonus_changed()) {
767  }
768  ai_obj.new_turn();
769  ai_obj.play_turn();
770  const int turn_end_time= SDL_GetTicks();
771  DBG_AI_MANAGER << "side " << side << ": number of user interactions: "<<num_interact_<<std::endl;
772  DBG_AI_MANAGER << "side " << side << ": total turn time: "<<turn_end_time - turn_start_time << " ms "<< std::endl;
773 }
774 
775 
776 // =======================================================================
777 // PRIVATE
778 // =======================================================================
779 // =======================================================================
780 // AI STACKS
781 // =======================================================================
783 {
784  AI_map_of_stacks::iterator iter = ai_map_.find(side);
785  if (iter!=ai_map_.end()){
786  return iter->second;
787  }
788  return ai_map_.emplace(side, std::stack<holder>()).first->second;
789 }
790 
791 // =======================================================================
792 // AI HOLDERS
793 // =======================================================================
795 {
796  std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
797 
798  if (!ai_stack_for_specific_side.empty()){
799  return ai_stack_for_specific_side.top();
800  } else {
802  ai_stack_for_specific_side.emplace(side, cfg);
803  return ai_stack_for_specific_side.top();
804  }
805 }
806 
807 // =======================================================================
808 // AI POINTERS
809 // =======================================================================
810 
812 {
814 }
815 
816 
817 // =======================================================================
818 // MISC
819 // =======================================================================
820 
821 } //end of namespace ai
virtual std::string evaluate(const std::string &str)
Evaluate command (using fai)
Definition: ai.cpp:174
static void add_observer(events::observer *event_observer)
Adds observer of game events.
Definition: manager.cpp:334
#define ERR_AI_MANAGER
Definition: manager.cpp:67
static std::unique_ptr< game_info > ai_info_
Definition: manager.hpp:467
::tod_manager * tod_manager
Definition: resources.cpp:30
std::vector< char_t > string
virtual void notify_observers()
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
static void raise_gamestate_changed()
Notifies all observers of 'ai_gamestate_changed' event.
Definition: manager.cpp:433
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
static void raise_map_changed()
Notifies all observers of 'ai_map_changed' event.
Definition: manager.cpp:453
static game_info & get_active_ai_info_for_side(side_number side)
Gets AI info for active AI of the given side.
Definition: manager.cpp:740
child_itors child_range(config_key_type key)
Definition: config.cpp:343
config cfg_
Definition: manager.hpp:90
static void add_turn_started_observer(events::observer *event_observer)
Adds an observer of 'ai_turn_started' event.
Definition: manager.cpp:387
holder(side_number side, const config &cfg)
Definition: manager.cpp:75
const std::string get_ai_identifier() const
Definition: manager.cpp:277
static events::generic_event gamestate_changed_
Definition: manager.hpp:474
AI Support engine - creating specific ai components from config.
std::unique_ptr< readonly_context > readonly_context_
Definition: manager.hpp:86
config to_config() const
Definition: manager.cpp:196
#define DBG_AI_MOD
Definition: manager.cpp:70
Contains the exception interfaces used to signal completion of a scenario, campaign or turn...
static const std::string internal_evaluate_command(side_number side, const std::string &str)
Evaluates an internal manager command.
Definition: manager.cpp:505
Definitions for the interface to Wesnoth Markup Language (WML).
static void add_tod_changed_observer(events::observer *event_observer)
Adds an observer of 'ai_tod_changed' event.
Definition: manager.cpp:364
composite_ai_ptr ai_
Definition: manager.hpp:84
static AI_map_of_stacks ai_map_
Definition: manager.hpp:464
const std::string get_ai_overview()
Definition: manager.cpp:233
void init(side_number side)
Definition: manager.cpp:82
static 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:698
#define LOG_AI_MOD
Definition: manager.cpp:71
formula_ai & ai_
static bool should_intercept(const std::string &str)
Determines if the command should be intercepted and evaluated as internal command.
Definition: manager.cpp:483
std::unique_ptr< side_context > side_context_
Definition: manager.hpp:85
static std::stack< holder > & get_or_create_ai_stack_for_side(side_number side)
Gets the AI stack for the specified side, create it if it doesn't exist.
Definition: manager.cpp:782
void merge_with(const config &c)
Merge config 'c' into this config, overwriting this config's values.
Definition: config.cpp:1094
static 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:619
static void clear_ais()
Clears all the AIs.
Definition: manager.cpp:682
static void raise_recruit_list_changed()
Notifies all observers of 'ai_recruit_list_changed' event.
Definition: manager.cpp:448
const std::string get_ai_structure()
Definition: manager.cpp:268
A small explanation about what's going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:58
static 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:357
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
static std::deque< command_history_item > history_
Definition: manager.hpp:465
virtual void new_turn()
On new turn.
Definition: ai.cpp:187
component * get_component(component *root, const std::string &path)
Definition: manager.cpp:282
void clear_children(T...keys)
Definition: config.hpp:507
static void remove_turn_started_observer(events::observer *event_observer)
Deletes an observer of 'ai_turn_started' event.
Definition: manager.cpp:405
static std::string get_active_ai_overview_for_side(side_number side)
Gets AI Overview for active AI of the given side.
Definition: manager.cpp:706
static void set_ai_info(const game_info &info)
Sets AI information.
Definition: manager.cpp:319
static events::generic_event user_interact_
Definition: manager.hpp:471
A component of the AI framework.
static bool add_ai_for_side(side_number side, const std::string &ai_algorithm_type, bool replace=true)
Adds active AI for specified side from parameters.
Definition: manager.cpp:645
Composite AI with turn sequence which is a vector of stages.
static config to_config(side_number side)
Gets AI config for active AI of the given side.
Definition: manager.cpp:734
std::unique_ptr< default_ai_context > default_ai_context_
Definition: manager.hpp:88
#define ERR_AI_MOD
Definition: manager.cpp:73
std::string path
Definition: game_config.cpp:56
static lg::log_domain log_ai_manager("ai/manager")
Managing the AIs lifecycle - headers.
static void play_turn(side_number side)
Plays a turn for the specified side using its active AI.
Definition: manager.cpp:756
static 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:688
void init()
Some tasks to run on startup.
Definition: registry.cpp:480
game_events::manager * game_events
Definition: resources.cpp:24
void modify_ai(const config &cfg)
Definition: manager.cpp:146
static void remove_all_ais_for_side(side_number side)
Removes all AIs from side.
Definition: manager.cpp:671
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 void clear_ai_info()
Clears AI information.
Definition: manager.cpp:329
static bool delete_component(component *root, const std::string &path)
Definition: component.cpp:218
static void remove_ai_for_side(side_number side)
Removes top-level AI from side.
Definition: manager.cpp:662
static boost::posix_time::time_facet facet("%Y%m%d %H:%M:%S%F ")
virtual bool attach_handler(observer *obs)
static const std::string evaluate_command(side_number side, const std::string &str)
Evaluates a string command using command AI.
Definition: manager.cpp:462
static events::generic_event sync_network_
Definition: manager.hpp:472
static bool add_component(component *root, const std::string &path, const config &cfg)
Definition: component.cpp:189
static void raise_user_interact()
Notifies all observers of 'ai_user_interact' event.
Definition: manager.cpp:410
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.
static 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:718
static map_location::DIRECTION s
void append_ai(const config &cfg)
Definition: manager.cpp:175
std::set< map_location > recent_attacks
hack.
Definition: game_info.hpp:117
Default AI contexts.
static events::generic_event map_changed_
Definition: manager.hpp:469
Define the game's event mechanism.
size_t i
Definition: function.cpp:933
static void add_recruit_list_changed_observer(events::observer *event_observer)
Adds an observer of 'ai_recruit_list_changed' event.
Definition: manager.cpp:381
static void remove_tod_changed_observer(events::observer *event_observer)
Deletes an observer of 'ai_tod_changed' event.
Definition: manager.cpp:369
static events::generic_event turn_started_
Definition: manager.hpp:475
static long history_item_counter_
Definition: manager.hpp:466
bool simulation_
Definition: resources.cpp:37
static const size_t MAX_HISTORY_SIZE
Definition: manager.hpp:126
static 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:630
Helper functions for the object which operates in the context of AI for specific side this is part of...
static std::string get_active_ai_structure_for_side(side_number side)
Gets AI Structure for active AI of the given side.
Definition: manager.cpp:712
static events::generic_event tod_changed_
Definition: manager.hpp:473
std::map< side_number, std::stack< holder > > AI_map_of_stacks
Definition: manager.hpp:463
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:491
const std::string describe_ai()
Definition: manager.cpp:221
static lg::log_domain log_ai_mod("ai/mod")
static void remove_observer(events::observer *event_observer)
Removes an observer of game events.
Definition: manager.cpp:342
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
static game_info & get_ai_info()
Gets global AI-game info.
Definition: manager.cpp:746
side_number side_
Definition: manager.hpp:89
Managing the AIs configuration - headers.
static 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:350
std::unique_ptr< readwrite_context > readwrite_context_
Definition: manager.hpp:87
static int num_interact_
Definition: manager.hpp:477
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
static void raise_sync_network()
Notifies all observers of 'ai_sync_network' event.
Definition: manager.cpp:428
static ai_composite & get_active_ai_for_side(side_number side)
Gets active AI for specified side.
Definition: manager.cpp:811
int side_number
Definition: game_info.hpp:36
game_events::wml_event_pump & pump()
Definition: manager.cpp:226
static void raise_tod_changed()
Notifies all observers of 'ai_tod_changed' event.
Definition: manager.cpp:438
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
static ai::holder & get_active_ai_holder_for_side_dbg(side_number side)
Gets the active AI holder for debug purposes.
Definition: manager.cpp:723
static map_location::DIRECTION n
static int last_interact_
Definition: manager.hpp:476
static void remove_recruit_list_changed_observer(events::observer *event_observer)
Deletes an observer of 'ai_recruit_list_changed' event.
Definition: manager.cpp:393
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
static events::generic_event recruit_list_changed_
Definition: manager.hpp:470
static void raise_turn_started()
Notifies all observers of 'ai_turn_started' event.
Definition: manager.cpp:443
All known AI parts.
Base class that holds the AI and current AI parameters.
Definition: manager.hpp:52
static holder & get_active_ai_holder_for_side(side_number side)
Gets active holder for specified side.
Definition: manager.cpp:794
static void add_map_changed_observer(events::observer *event_observer)
Adds an observer of 'ai_map_changed' event.
Definition: manager.cpp:375
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...
static void remove_map_changed_observer(events::observer *event_observer)
Deletes an observer of 'ai_map_changed' event.
Definition: manager.cpp:399