The Battle for Wesnoth  1.13.4+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 - 2016 by Yurii Chernyi <[email protected]>
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/manager.hpp"
24 #include "game_events/pump.hpp"
25 #include "generic_event.hpp" // for generic_event, etc
26 #include "log.hpp"
27 #include "map/location.hpp" // for map_location
28 #include "resources.hpp"
30 #include "tod_manager.hpp"
31 
32 #include "ai/composite/ai.hpp" // for ai_composite
33 #include "ai/composite/component.hpp" // for component_manager
34 #include "ai/composite/engine.hpp" // for engine
35 #include "ai/configuration.hpp" // for configuration
36 #include "ai/contexts.hpp" // for readonly_context, etc
37 #include "ai/default/contexts.hpp" // for default_ai_context, etc
38 #include "game_end_exceptions.hpp" // for ai_end_turn_exception
39 #include "game_info.hpp" // for side_number, engine_ptr, etc
40 #include "game_config.hpp" // for debug
41 #include "game_errors.hpp" // for game_error
43 #include "ai/registry.hpp" // for init
44 #include "util.hpp" // for lexical_cast
45 
46 
47 #include <algorithm> // for min
48 #include <cassert> // for assert
49 #include <iterator> // for reverse_iterator, etc
50 #include <map> // for _Rb_tree_iterator, etc
51 #include <ostream> // for operator<<, basic_ostream, etc
52 #include <set> // for set
53 #include <stack> // for stack
54 #include <utility> // for pair, make_pair
55 #include <vector> // for vector, allocator, etc
56 
57 #include <SDL_timer.h>
58 
59 namespace ai {
60 
61 const std::string manager::AI_TYPE_COMPOSITE_AI = "composite_ai";
62 const std::string manager::AI_TYPE_SAMPLE_AI = "sample_ai";
63 const std::string manager::AI_TYPE_IDLE_AI = "idle_ai";
64 const std::string manager::AI_TYPE_FORMULA_AI = "formula_ai";
65 const std::string manager::AI_TYPE_DEFAULT = "default";
66 
67 
68 static lg::log_domain log_ai_manager("ai/manager");
69 #define DBG_AI_MANAGER LOG_STREAM(debug, log_ai_manager)
70 #define LOG_AI_MANAGER LOG_STREAM(info, log_ai_manager)
71 #define ERR_AI_MANAGER LOG_STREAM(err, log_ai_manager)
72 
73 static lg::log_domain log_ai_mod("ai/mod");
74 #define DBG_AI_MOD LOG_STREAM(debug, log_ai_mod)
75 #define LOG_AI_MOD LOG_STREAM(info, log_ai_mod)
76 #define WRN_AI_MOD LOG_STREAM(warn, log_ai_mod)
77 #define ERR_AI_MOD LOG_STREAM(err, log_ai_mod)
78 
79 holder::holder( side_number side, const config &cfg )
80  : ai_(), side_context_(nullptr), readonly_context_(nullptr), readwrite_context_(nullptr), default_ai_context_(nullptr), side_(side), cfg_(cfg)
81 {
82  DBG_AI_MANAGER << describe_ai() << "Preparing new AI holder" << std::endl;
83 }
84 
85 
87 {
88  if (side_context_ == nullptr) {
90  } else {
91  side_context_->set_side(side);
92  }
93  if (readonly_context_ == nullptr){
96  }
97  if (readwrite_context_ == nullptr){
99  }
100  if (default_ai_context_ == nullptr){
102  }
103  if (!this->ai_){
105  }
106 
107  if (this->ai_) {
108  ai_->on_create();
109  for (config &mod_ai : cfg_.child_range("modify_ai")) {
110  if (!mod_ai.has_attribute("side")) {
111  mod_ai["side"] = side;
112  }
113  modify_ai(mod_ai);
114  }
115  cfg_.clear_children("modify_ai");
116 
117  std::vector<engine_ptr> engines = ai_->get_engines();
118  for (std::vector<engine_ptr>::iterator it = engines.begin(); it != engines.end(); ++it)
119  {
120  (*it)->set_ai_context(&(ai_->get_ai_context()));
121  }
122 
123  } else {
124  ERR_AI_MANAGER << describe_ai()<<"AI lazy initialization error!" << std::endl;
125  }
126 
127 }
128 
130 {
131  try {
132  if (this->ai_) {
133  LOG_AI_MANAGER << describe_ai() << "Managed AI will be deleted" << std::endl;
134  }
135  } catch (...) {}
136  delete this->default_ai_context_;
137  delete this->readwrite_context_;
138  delete this->readonly_context_;
139  delete this->side_context_;
140 }
141 
142 
144 {
145  if (!this->ai_) {
146  this->init(this->side_);
147  }
148  assert(this->ai_);
149 
150  return *this->ai_;
151 }
152 
153 
155 {
156  // only handle aspects
157  // transform ai_parameters to new-style config
158 
160  //at this point we have a single config which contains [aspect][facet] tags
161  DBG_AI_MANAGER << "after transforming [modify_side][ai] into new syntax, config contains:"<< std::endl << cfg << std::endl;
162 
163  // TODO: Also add [goal] tags. And what about [stage] or [engine] tags? (Maybe they're not important.)
164  if (this->readonly_context_ == nullptr) {
165  // if not initialized, append that config to the bottom of base cfg
166  // then, merge aspects with the same id
167  cfg_.merge_with(cfg);
168  cfg_.merge_children_by_attribute("aspect","id");
169  } else {
170  // else run 'add_facet' command on each [aspect][facet]
171  for (const config &cfg_a : cfg.child_range("aspect")) {
172  for (const config &cfg_f : cfg_a.child_range("facet")) {
173  readonly_context_->add_facet(cfg_a["id"],cfg_f);
174  }
175  }
176  }
177 }
178 
179 
180 void holder::modify_ai(const config &cfg)
181 {
182  if (!this->ai_) {
183  // if not initialized, initialize now.
184  get_ai_ref();
185  }
186  const std::string &act = cfg["action"];
187  LOG_AI_MOD << "side "<< side_ << " [modify_ai] "<<act<<" \""<<cfg["path"]<<"\""<<std::endl;
188  DBG_AI_MOD << std::endl << cfg << std::endl;
189  DBG_AI_MOD << "side "<< side_ << " before [modify_ai]"<<std::endl << to_config() << std::endl;
190  bool res = false;
191  if (act == "add") {
192  res = component_manager::add_component(&*this->ai_,cfg["path"],cfg);
193  } else if (act == "change") {
194  res = component_manager::change_component(&*this->ai_,cfg["path"],cfg);
195  } else if (act == "delete") {
196  res = component_manager::delete_component(&*this->ai_,cfg["path"]);
197  } else if (act == "try_delete") {
198  res = component_manager::delete_component(&*this->ai_,cfg["path"]);
199  if (!res) {
200  LOG_AI_MOD << "[modify_ai] "<<act<<" failed, ignoring because it's a try_delete"<< std::endl;
201  res = true;
202  }
203  } else {
204  ERR_AI_MOD << "modify_ai tag has invalid 'action' attribute " << act << std::endl;
205  }
206  DBG_AI_MOD << "side "<< side_ << " after [modify_ai]"<<act<<std::endl << to_config() << std::endl;
207  if (!res) {
208  LOG_AI_MOD << "[modify_ai] "<<act<<" failed"<< std::endl;
209  } else {
210  LOG_AI_MOD << "[modify_ai] "<<act<<" success"<< std::endl;
211  }
212 
213 }
214 
216 {
217  if (!this->ai_) {
218  return cfg_;
219  } else {
220  config cfg = ai_->to_config();
221  cfg["version"] = "10703";
222  if (this->side_context_!=nullptr) {
224  }
225  if (this->readonly_context_!=nullptr) {
227  }
228  if (this->readwrite_context_!=nullptr) {
230  }
231  if (this->default_ai_context_!=nullptr) {
233  }
234 
235  return cfg;
236  }
237 }
238 
239 
240 
242 {
243  std::string sidestr = std::to_string(this->side_);
244 
245  if (this->ai_!=nullptr) {
246  return this->ai_->describe_self()+std::string(" for side ")+sidestr+std::string(" : ");
247  } else {
248  return std::string("not initialized ai with id=[")+cfg_["id"]+std::string("] for side ")+sidestr+std::string(" : ");
249  }
250 }
251 
252 
254 {
255  if (!this->ai_) {
256  get_ai_ref();
257  }
258  std::stringstream s;
259  s << "advancements: " << this->ai_->get_advancements().get_value() << std::endl;
260  s << "aggression: " << this->ai_->get_aggression() << std::endl;
261  s << "attack_depth: " << this->ai_->get_attack_depth() << std::endl;
262  s << "caution: " << this->ai_->get_caution() << std::endl;
263  s << "grouping: " << this->ai_->get_grouping() << std::endl;
264  s << "leader_aggression: " << this->ai_->get_leader_aggression() << std::endl;
265  s << "leader_ignores_keep: " << this->ai_->get_leader_ignores_keep() << std::endl;
266  s << "leader_value: " << this->ai_->get_leader_value() << std::endl;
267  s << "passive_leader: " << this->ai_->get_passive_leader() << std::endl;
268  s << "passive_leader_shares_keep: " << this->ai_->get_passive_leader_shares_keep() << std::endl;
269  s << "recruitment_diversity: " << this->ai_->get_recruitment_diversity() << std::endl;
270  s << "recruitment_instructions: " << std::endl << "----config begin----" << std::endl;
271  s << this->ai_->get_recruitment_instructions() << "-----config end-----" << std::endl;
272  s << "recruitment_more: " << utils::join(this->ai_->get_recruitment_more()) << std::endl;
273  s << "recruitment_pattern: " << utils::join(this->ai_->get_recruitment_pattern()) << std::endl;
274  s << "recruitment_randomness: " << this->ai_->get_recruitment_randomness() << std::endl;
275  s << "recruitment_save_gold: " << std::endl << "----config begin----" << std::endl;
276  s << this->ai_->get_recruitment_save_gold() << "-----config end-----" << std::endl;
277  s << "scout_village_targeting: " << this->ai_->get_scout_village_targeting() << std::endl;
278  s << "simple_targeting: " << this->ai_->get_simple_targeting() << std::endl;
279  s << "support_villages: " << this->ai_->get_support_villages() << std::endl;
280  s << "village_value: " << this->ai_->get_village_value() << std::endl;
281  s << "villages_per_scout: " << this->ai_->get_villages_per_scout() << std::endl;
282 
283  return s.str();
284 }
285 
286 
287 
289 {
290  if (!this->ai_) {
291  get_ai_ref();
292  }
293  return component_manager::print_component_tree(&*this->ai_,"");
294 }
295 
296 
298 {
299  return cfg_["id"];
300 }
301 
303  if (!game_config::debug) // Debug guard
304  {
305  return nullptr;
306  }
307 
308  if (root == nullptr) // Return root component(ai_)
309  {
310  if (!this->ai_) {
311  this->init(this->side_);
312  }
313  assert(this->ai_);
314 
315  return &*this->ai_;
316  }
317 
318  return component_manager::get_component(root, path);
319 }
320 
321 // =======================================================================
322 // LIFECYCLE
323 // =======================================================================
324 
325 
331 events::generic_event manager::gamestate_changed_("ai_gamestate_changed");
333 events::generic_event manager::recruit_list_changed_("ai_recruit_list_changed");
336 int manager::num_interact_ = 0;
337 
338 
340 {
341  if (ai_info_!=nullptr){
342  clear_ai_info();
343  }
344  ai_info_ = new game_info(i);
345  registry::init();
346 }
347 
348 
350  delete ai_info_;
351  ai_info_ = nullptr;
352 }
353 
354 
356  user_interact_.attach_handler(event_observer);
357  sync_network_.attach_handler(event_observer);
358  turn_started_.attach_handler(event_observer);
359  gamestate_changed_.attach_handler(event_observer);
360 }
361 
362 
364  user_interact_.detach_handler(event_observer);
365  sync_network_.detach_handler(event_observer);
366  turn_started_.detach_handler(event_observer);
367  gamestate_changed_.detach_handler(event_observer);
368 }
369 
370 
372  gamestate_changed_.attach_handler(event_observer);
373  turn_started_.attach_handler(event_observer);
374  map_changed_.attach_handler(event_observer);
375 }
376 
377 
379  gamestate_changed_.detach_handler(event_observer);
380  turn_started_.detach_handler(event_observer);
381  map_changed_.detach_handler(event_observer);
382 }
383 
384 
386  tod_changed_.attach_handler(event_observer);
387 }
388 
389 
391  tod_changed_.detach_handler(event_observer);
392 }
393 
394 
395 
397 {
398  map_changed_.attach_handler(event_observer);
399 }
400 
401 
403 {
404  recruit_list_changed_.attach_handler(event_observer);
405 }
406 
407 
409 {
410  turn_started_.attach_handler(event_observer);
411 }
412 
413 
415 {
416  recruit_list_changed_.detach_handler(event_observer);
417 }
418 
419 
421 {
422  map_changed_.detach_handler(event_observer);
423 }
424 
425 
427 {
428  turn_started_.detach_handler(event_observer);
429 }
430 
433  return;
434  }
435 
436  const int interact_time = 30;
437  const int time_since_interact = SDL_GetTicks() - last_interact_;
438  if(time_since_interact < interact_time) {
439  return;
440  }
441 
442  ++num_interact_;
444 
445  last_interact_ = SDL_GetTicks();
446 
447 }
448 
451 }
452 
453 
456 }
457 
458 
461 }
462 
463 
466 }
467 
468 
471 }
472 
473 
476 }
477 
478 
479 // =======================================================================
480 // EVALUATION
481 // =======================================================================
482 
484 {
485  //insert new command into history
487 
488  //prune history - erase 1/2 of it if it grows too large
489  if (history_.size()>MAX_HISTORY_SIZE){
490  history_.erase(history_.begin(),history_.begin()+MAX_HISTORY_SIZE/2);
491  LOG_AI_MANAGER << "AI MANAGER: pruned history" << std::endl;
492  }
493 
494  if (!should_intercept(str)){
497  return ai.evaluate(str);
498  }
499 
500  return internal_evaluate_command(side,str);
501 }
502 
503 
505 {
506  if (str.length()<1) {
507  return false;
508  }
509  if (str.at(0)=='!'){
510  return true;
511  }
512  if (str.at(0)=='?'){
513  return true;
514  }
515  return false;
516 
517 }
518 
519 std::deque< command_history_item > manager::history_;
521 
522 //this is stub code to allow testing of basic 'history', 'repeat-last-command', 'add/remove/replace ai' capabilities.
523 //yes, it doesn't look nice. but it is usable.
524 //to be refactored at earliest opportunity
525 ///@todo 1.9 extract to separate class which will use fai or lua parser
527  const int MAX_HISTORY_VISIBLE = 30;
528 
529  //repeat last command
530  if (str=="!") {
531  //this command should not be recorded in history
532  if (!history_.empty()){
533  history_.pop_back();
535  }
536 
537  if (history_.empty()){
538  return "AI MANAGER: empty history";
539  }
540  return evaluate_command(side, history_.back().get_command());//no infinite loop since '!' commands are not present in history
541  };
542  //show last command
543  if (str=="?") {
544  //this command should not be recorded in history
545  if (!history_.empty()){
546  history_.pop_back();
548  }
549 
550  if (history_.empty()){
551  return "AI MANAGER: History is empty";
552  }
553 
554  int n = std::min<int>( MAX_HISTORY_VISIBLE, history_.size() );
555  std::stringstream strstream;
556  strstream << "AI MANAGER: History - last "<< n <<" commands:\n";
557  std::deque< command_history_item >::reverse_iterator j = history_.rbegin();
558 
559  for (int cmd_id=n; cmd_id>0; --cmd_id){
560  strstream << j->get_number() << " :" << j->get_command() << '\n';
561  ++j;//this is *reverse* iterator
562  }
563 
564  return strstream.str();
565  };
566 
567 
568  std::vector< std::string > cmd = utils::parenthetical_split(str, ' ',"'","'");
569 
570  if (cmd.size()==3){
571  //!add_ai side file
572  if (cmd.at(0)=="!add_ai"){
573  side_number side = lexical_cast<side_number>(cmd.at(1));
574  std::string file = cmd.at(2);
575  if (add_ai_for_side_from_file(side,file,false)){
576  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;
577  } else {
578  return std::string("AI MANAGER: failed attempt to add AI for side ")+std::to_string(side)+std::string(" from file ")+file;
579  }
580  }
581  //!replace_ai side file
582  if (cmd.at(0)=="!replace_ai"){
583  side_number side = lexical_cast<side_number>(cmd.at(1));
584  std::string file = cmd.at(2);
585  if (add_ai_for_side_from_file(side,file,true)){
586  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;
587  } else {
588  return std::string("AI MANAGER: failed attempt to add AI for side ")+std::to_string(side)+std::string(" from file ")+file;
589  }
590  }
591 
592  } else if (cmd.size()==2){
593  //!remove_ai side
594  if (cmd.at(0)=="!remove_ai"){
595  side_number side = lexical_cast<side_number>(cmd.at(1));
596  remove_ai_for_side(side);
597  return std::string("AI MANAGER: made an attempt to remove AI for side ")+std::to_string(side);
598  }
599  if (cmd.at(0)=="!"){
600  //this command should not be recorded in history
601  if (!history_.empty()){
602  history_.pop_back();
604  }
605 
606  int command = lexical_cast<int>(cmd.at(1));
607  std::deque< command_history_item >::reverse_iterator j = history_.rbegin();
608  //yes, the iterator could be precisely positioned (since command numbers go 1,2,3,4,..). will do it later.
609  while ( (j!=history_.rend()) && (j->get_number()!=command) ){
610  ++j;// this is *reverse* iterator
611  }
612  if (j!=history_.rend()){
613  return evaluate_command(side,j->get_command());//no infinite loop since '!' commands are not present in history
614  }
615  return "AI MANAGER: no command with requested number found";
616  }
617  } else if (cmd.size()==1){
618  if (cmd.at(0)=="!help") {
619  return
620  "known commands:\n"
621  "! - repeat last command (? and ! do not count)\n"
622  "! NUMBER - repeat numbered command\n"
623  "? - show a history list\n"
624  "!add_ai TEAM FILE - add a AI to side (0 - command AI, N - AI for side #N) from file\n"
625  "!remove_ai TEAM - remove AI from side (0 - command AI, N - AI for side #N)\n"
626  "!replace_ai TEAM FILE - replace AI of side (0 - command AI, N - AI for side #N) from file\n"
627  "!help - show this help message";
628  }
629  }
630 
631 
632  return "AI MANAGER: nothing to do";
633 }
634 
635 // =======================================================================
636 // ADD, CREATE AIs, OR LIST AI TYPES
637 // =======================================================================
638 
639 ///@todo 1.9 add error reporting
641 {
642  config cfg;
644  ERR_AI_MANAGER << " unable to read [SIDE] config for side "<< side << "from file [" << file <<"]"<< std::endl;
645  return false;
646  }
647  return add_ai_for_side_from_config(side,cfg,replace);
648 }
649 
650 
652  config parsed_cfg;
653  configuration::parse_side_config(side, cfg, parsed_cfg);
654 
655  if (replace) {
656  remove_ai_for_side(side);
657  }
658 
659  holder new_holder(side,parsed_cfg);
660  std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
661  ai_stack_for_specific_side.push(new_holder);
662  return true;
663 }
664 
665 
666 ///@todo 1.9 add error reporting
667 bool manager::add_ai_for_side( side_number side, const std::string& ai_algorithm_type, bool replace )
668 {
669  if (replace) {
670  remove_ai_for_side (side);
671  }
672  config cfg;
673  cfg["ai_algorithm"] = ai_algorithm_type;
674  holder new_holder(side,cfg);
675  std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
676  ai_stack_for_specific_side.push(new_holder);
677  return true;
678 }
679 
680 
681 // =======================================================================
682 // REMOVE
683 // =======================================================================
684 
686 {
687  std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
688  if (!ai_stack_for_specific_side.empty()){
689  ai_stack_for_specific_side.pop();
690  }
691 }
692 
693 
695 {
696  std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
697 
698  //clear the stack. std::stack doesn't have a '.clear()' method to do it
699  while (!ai_stack_for_specific_side.empty()){
700  ai_stack_for_specific_side.pop();
701  }
702 }
703 
704 
706 {
707  ai_map_.clear();
708 }
709 
710 // =======================================================================
711 // Work with active AI parameters
712 // =======================================================================
713 
715 {
716  for (const config& cfg : ai_parameters) {
718  }
719 }
720 
721 
723 {
724  if (ai_info_==nullptr) {
725  //replay ?
726  return;
727  }
729 }
730 
731 
733 {
735 }
736 
737 
739 {
741 }
742 
743 
745 {
747 }
748 
750 {
751  if (!game_config::debug)
752  {
753  return *(new ai::holder(side, config()));
754  }
755  return get_active_ai_holder_for_side(side);
756 }
757 
758 
760 {
762 }
763 
764 
766 {
767  return *ai_info_;
768 }
769 
770 
772 {
773  return *ai_info_;
774 }
775 
776 
777 // =======================================================================
778 // PROXY
779 // =======================================================================
780 
782  last_interact_ = 0;
783  num_interact_ = 0;
784  const int turn_start_time = SDL_GetTicks();
785  /*hack. @todo 1.9 rework via extended event system*/
786  get_ai_info().recent_attacks.clear();
787  ai_composite& ai_obj = get_active_ai_for_side(side);
788  resources::game_events->pump().fire("ai turn");
790  if (resources::tod_manager->has_tod_bonus_changed()) {
792  }
793  ai_obj.new_turn();
794  ai_obj.play_turn();
795  const int turn_end_time= SDL_GetTicks();
796  DBG_AI_MANAGER << "side " << side << ": number of user interactions: "<<num_interact_<<std::endl;
797  DBG_AI_MANAGER << "side " << side << ": total turn time: "<<turn_end_time - turn_start_time << " ms "<< std::endl;
798 }
799 
800 
801 // =======================================================================
802 // PRIVATE
803 // =======================================================================
804 // =======================================================================
805 // AI STACKS
806 // =======================================================================
808 {
809  AI_map_of_stacks::iterator iter = ai_map_.find(side);
810  if (iter!=ai_map_.end()){
811  return iter->second;
812  }
813  return ai_map_.insert(std::make_pair(side, std::stack<holder>())).first->second;
814 }
815 
816 // =======================================================================
817 // AI HOLDERS
818 // =======================================================================
820 {
821  std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
822 
823  if (!ai_stack_for_specific_side.empty()){
824  return ai_stack_for_specific_side.top();
825  } else {
827  holder new_holder(side, cfg);
828  ai_stack_for_specific_side.push(new_holder);
829  return ai_stack_for_specific_side.top();
830  }
831 }
832 
833 // =======================================================================
834 // AI POINTERS
835 // =======================================================================
836 
838 {
840 }
841 
842 
843 // =======================================================================
844 // MISC
845 // =======================================================================
846 
847 } //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:355
child_itors child_range(const std::string &key)
Definition: config.cpp:613
#define ERR_AI_MANAGER
Definition: manager.cpp:71
::tod_manager * tod_manager
Definition: resources.cpp:31
virtual void set_side(side_number side)=0
Set the side number.
virtual void notify_observers()
static void raise_gamestate_changed()
Notifies all observers of 'ai_gamestate_changed' event.
Definition: manager.cpp:454
static bool change_component(component *root, const std::string &path, const config &cfg)
Definition: component.cpp:205
virtual config to_readwrite_context_config() const =0
serialize this context to config
#define LOG_AI_MANAGER
Definition: manager.cpp:70
static void raise_map_changed()
Notifies all observers of 'ai_map_changed' event.
Definition: manager.cpp:474
readonly_context * readonly_context_
Definition: manager.hpp:87
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:765
config cfg_
Definition: manager.hpp:91
static void add_turn_started_observer(events::observer *event_observer)
Adds an observer of 'ai_turn_started' event.
Definition: manager.cpp:408
holder(side_number side, const config &cfg)
Definition: manager.cpp:79
const std::string get_ai_identifier() const
Definition: manager.cpp:297
static events::generic_event gamestate_changed_
Definition: manager.hpp:478
AI Support engine - creating specific ai components from config.
bool 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:471
config to_config() const
Definition: manager.cpp:215
virtual config to_side_context_config() const =0
serialize this context to config
static bool parse_side_config(side_number side, const config &cfg, config &parsed_cfg)
#define DBG_AI_MOD
Definition: manager.cpp:74
void modify_side_ai_config(config cfg)
Definition: manager.cpp:154
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:526
void clear_children(const std::string &key)
Definition: config.cpp:820
To lexical_cast(From value)
Lexical cast converts one type to another.
Definitions for the interface to Wesnoth Markup Language (WML).
std::pair< const_child_iterator, const_child_iterator > const_child_itors
Definition: config.hpp:214
static void add_tod_changed_observer(events::observer *event_observer)
Adds an observer of 'ai_tod_changed' event.
Definition: manager.cpp:385
composite_ai_ptr ai_
Definition: manager.hpp:85
static AI_map_of_stacks ai_map_
Definition: manager.hpp:468
const std::string get_ai_overview()
Definition: manager.cpp:253
virtual config to_readonly_context_config() const =0
serialize to config
void init(side_number side)
Definition: manager.cpp:86
#define LOG_AI_MOD
Definition: manager.cpp:75
const 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:504
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:807
void merge_with(const config &c)
Merge config 'c' into this config, overwriting this config's values.
Definition: config.cpp:1350
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:640
static void clear_ais()
Clears all the AIs.
Definition: manager.cpp:705
static void raise_recruit_list_changed()
Notifies all observers of 'ai_recruit_list_changed' event.
Definition: manager.cpp:469
const std::string get_ai_structure()
Definition: manager.cpp:288
A small explanation about what's going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:57
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:378
static component * get_component(component *root, const std::string &path)
Definition: component.cpp:268
GLsizei const char ** path
Definition: glew.h:4654
static std::deque< command_history_item > history_
Definition: manager.hpp:469
virtual void new_turn()
On new turn.
Definition: ai.cpp:187
component * get_component(component *root, const std::string &path)
Definition: manager.cpp:302
virtual void on_readonly_context_create()=0
static void remove_turn_started_observer(events::observer *event_observer)
Deletes an observer of 'ai_turn_started' event.
Definition: manager.cpp:426
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:732
static void set_ai_info(const game_info &info)
Sets AI information.
Definition: manager.cpp:339
static events::generic_event user_interact_
Definition: manager.hpp:475
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:667
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:759
side_context * side_context_
Definition: manager.hpp:86
#define ERR_AI_MOD
Definition: manager.cpp:77
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:781
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:722
static void expand_simplified_aspects(side_number side, config &cfg)
Expand simplified aspects, similar to the change from 1.7.2 to 1.7.3 but with some additional syntax ...
Templates and utility-routines for strings and numbers.
void init()
Initializes the gui subsystems.
Definition: registry.cpp:482
game_events::manager * game_events
Definition: resources.cpp:24
void modify_ai(const config &cfg)
Definition: manager.cpp:180
static void remove_all_ais_for_side(side_number side)
Removes all AIs from side.
Definition: manager.cpp:694
std::string join(T const &v, const std::string &s=",")
Generates a new string joining container items in a list.
static const std::string AI_TYPE_DEFAULT
Definition: manager.hpp:135
virtual ~holder()
Definition: manager.cpp:129
static const std::string AI_TYPE_IDLE_AI
Definition: manager.hpp:131
static void clear_ai_info()
Clears AI information.
Definition: manager.cpp:349
static bool delete_component(component *root, const std::string &path)
Definition: component.cpp:219
static void remove_ai_for_side(side_number side)
Removes top-level AI from side.
Definition: manager.cpp:685
GLuint res
Definition: glew.h:9258
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:483
static events::generic_event sync_network_
Definition: manager.hpp:476
static bool add_component(component *root, const std::string &path, const config &cfg)
Definition: component.cpp:190
static void raise_user_interact()
Notifies all observers of 'ai_user_interact' event.
Definition: manager.cpp:431
static const std::string AI_TYPE_COMPOSITE_AI
Definition: manager.hpp:129
static std::string print_component_tree(component *root, const std::string &path)
Definition: component.cpp:250
#define DBG_AI_MANAGER
Definition: manager.cpp:69
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:744
virtual void add_facet(const std::string &id, const config &cfg) const =0
std::set< map_location > recent_attacks
hack.
Definition: game_info.hpp:125
Default AI contexts.
static events::generic_event map_changed_
Definition: manager.hpp:473
Define the game's event mechanism.
size_t i
Definition: function.cpp:1057
static void add_recruit_list_changed_observer(events::observer *event_observer)
Adds an observer of 'ai_recruit_list_changed' event.
Definition: manager.cpp:402
static void remove_tod_changed_observer(events::observer *event_observer)
Deletes an observer of 'ai_tod_changed' event.
Definition: manager.cpp:390
static game_info * ai_info_
Definition: manager.hpp:471
static events::generic_event turn_started_
Definition: manager.hpp:479
static long history_item_counter_
Definition: manager.hpp:470
default_ai_context * default_ai_context_
Definition: manager.hpp:89
bool simulation_
Definition: resources.cpp:39
static const size_t MAX_HISTORY_SIZE
Definition: manager.hpp:127
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:651
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:738
game_events::t_pump & pump()
Definition: manager.cpp:194
static events::generic_event tod_changed_
Definition: manager.hpp:477
readwrite_context * readwrite_context_
Definition: manager.hpp:88
std::map< side_number, std::stack< holder > > AI_map_of_stacks
Definition: manager.hpp:467
std::string replace(std::string str, const std::string &src, const std::string &dst)
Replace all instances of src in str with dst.
const std::string describe_ai()
Definition: manager.cpp:241
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:363
std::vector< std::string > parenthetical_split(std::string const &val, const char separator, std::string const &left, std::string const &right, const int flags)
Splits a string based either on a separator where text within parenthesis is protected from splitting...
static const std::string AI_TYPE_FORMULA_AI
Definition: manager.hpp:132
GLclampd n
Definition: glew.h:5903
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:143
static const std::string AI_TYPE_SAMPLE_AI
Definition: manager.hpp:130
static game_info & get_ai_info()
Gets global AI-game info.
Definition: manager.cpp:771
side_number side_
Definition: manager.hpp:90
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:371
static int num_interact_
Definition: manager.hpp:481
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:449
static ai_composite & get_active_ai_for_side(side_number side)
Gets active AI for specified side.
Definition: manager.cpp:837
int side_number
Definition: game_info.hpp:44
static void raise_tod_changed()
Notifies all observers of 'ai_tod_changed' event.
Definition: manager.cpp:459
std::string::const_iterator iterator
Definition: tokenizer.hpp:21
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
AI Command History Item.
Definition: manager.hpp:97
static ai::holder & get_active_ai_holder_for_side_dbg(side_number side)
Gets the active AI holder for debug purposes.
Definition: manager.cpp:749
virtual config to_default_ai_context_config() const =0
GLdouble s
Definition: glew.h:1358
static int last_interact_
Definition: manager.hpp:480
GLsizei const GLcharARB ** string
Definition: glew.h:4503
static void remove_recruit_list_changed_observer(events::observer *event_observer)
Deletes an observer of 'ai_recruit_list_changed' event.
Definition: manager.cpp:414
static events::generic_event recruit_list_changed_
Definition: manager.hpp:474
static void raise_turn_started()
Notifies all observers of 'ai_turn_started' event.
Definition: manager.cpp:464
All known AI parts.
Base class that holds the AI and current AI parameters.
Definition: manager.hpp:55
static holder & get_active_ai_holder_for_side(side_number side)
Gets active holder for specified side.
Definition: manager.cpp:819
static void add_map_changed_observer(events::observer *event_observer)
Adds an observer of 'ai_map_changed' event.
Definition: manager.cpp:396
static void modify_active_ai_config_old_for_side(side_number side, const config::const_child_itors &ai_parameters)
Modifies AI parameters for active AI of the given side.
Definition: manager.cpp:714
void merge_children_by_attribute(const std::string &key, const std::string &attribute)
All children with the given key and with equal values of the specified attribute will be merged into ...
Definition: config.cpp:589
static void remove_map_changed_observer(events::observer *event_observer)
Deletes an observer of 'ai_map_changed' event.
Definition: manager.cpp:420