00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "composite/ai.hpp"
00022 #include "configuration.hpp"
00023 #include "contexts.hpp"
00024 #include "default/ai.hpp"
00025 #include "manager.hpp"
00026 #include "formula/ai.hpp"
00027 #include "registry.hpp"
00028 #include "../game_events.hpp"
00029 #include "../foreach.hpp"
00030 #include "../log.hpp"
00031 #include "../serialization/string_utils.hpp"
00032 #include "composite/component.hpp"
00033
00034 #include <map>
00035 #include <stack>
00036 #include <vector>
00037 #include "composite/engine.hpp"
00038
00039 namespace ai {
00040
00041 const std::string manager::AI_TYPE_COMPOSITE_AI = "composite_ai";
00042 const std::string manager::AI_TYPE_SAMPLE_AI = "sample_ai";
00043 const std::string manager::AI_TYPE_IDLE_AI = "idle_ai";
00044 const std::string manager::AI_TYPE_FORMULA_AI = "formula_ai";
00045 const std::string manager::AI_TYPE_DEFAULT = "default";
00046
00047
00048 static lg::log_domain log_ai_manager("ai/manager");
00049 #define DBG_AI_MANAGER LOG_STREAM(debug, log_ai_manager)
00050 #define LOG_AI_MANAGER LOG_STREAM(info, log_ai_manager)
00051 #define ERR_AI_MANAGER LOG_STREAM(err, log_ai_manager)
00052
00053 static lg::log_domain log_ai_mod("ai/mod");
00054 #define DBG_AI_MOD LOG_STREAM(debug, log_ai_mod)
00055 #define LOG_AI_MOD LOG_STREAM(info, log_ai_mod)
00056 #define WRN_AI_MOD LOG_STREAM(warn, log_ai_mod)
00057 #define ERR_AI_MOD LOG_STREAM(err, log_ai_mod)
00058
00059 holder::holder( side_number side, const config &cfg )
00060 : ai_(), side_context_(NULL), readonly_context_(NULL), readwrite_context_(NULL), default_ai_context_(NULL), side_(side), cfg_(cfg)
00061 {
00062 DBG_AI_MANAGER << describe_ai() << "Preparing new AI holder" << std::endl;
00063 }
00064
00065
00066 void holder::init( side_number side )
00067 {
00068 if (side_context_ == NULL) {
00069 side_context_ = new side_context_impl(side,cfg_);
00070 } else {
00071 side_context_->set_side(side);
00072 }
00073 if (readonly_context_ == NULL){
00074 readonly_context_ = new readonly_context_impl(*side_context_,cfg_);
00075 readonly_context_->on_readonly_context_create();
00076 }
00077 if (readwrite_context_ == NULL){
00078 readwrite_context_ = new readwrite_context_impl(*readonly_context_,cfg_);
00079 }
00080 if (default_ai_context_ == NULL){
00081 default_ai_context_ = new default_ai_context_impl(*readwrite_context_,cfg_);
00082 }
00083 if (!this->ai_){
00084 ai_ = boost::shared_ptr<ai_composite>(new ai_composite(*default_ai_context_,cfg_));
00085 }
00086
00087 if (this->ai_) {
00088 ai_->on_create();
00089 foreach (config &mod_ai, cfg_.child_range("modify_ai")) {
00090 if (!mod_ai.has_attribute("side")) {
00091 mod_ai["side"] = side;
00092 }
00093 modify_ai(mod_ai);
00094 }
00095 cfg_.clear_children("modify_ai");
00096
00097 std::vector<engine_ptr> engines = ai_->get_engines();
00098 for (std::vector<engine_ptr>::iterator it = engines.begin(); it != engines.end(); ++it)
00099 {
00100 (*it)->set_ai_context(&(ai_->get_ai_context()));
00101 }
00102
00103 } else {
00104 ERR_AI_MANAGER << describe_ai()<<"AI lazy initialization error!" << std::endl;
00105 }
00106
00107 }
00108
00109 holder::~holder()
00110 {
00111 if (this->ai_) {
00112 LOG_AI_MANAGER << describe_ai() << "Managed AI will be deleted" << std::endl;
00113 }
00114 delete this->default_ai_context_;
00115 delete this->readwrite_context_;
00116 delete this->readonly_context_;
00117 delete this->side_context_;
00118 }
00119
00120
00121 interface& holder::get_ai_ref()
00122 {
00123 if (!this->ai_) {
00124 this->init(this->side_);
00125 }
00126 assert(this->ai_);
00127
00128 return *this->ai_;
00129 }
00130
00131
00132 void holder::modify_ai_config_old( const config::const_child_itors &ai_parameters)
00133 {
00134
00135
00136
00137 config cfg;
00138 configuration::upgrade_aspect_configs_from_1_07_02_to_1_07_03(this->side_,ai_parameters,cfg);
00139
00140 DBG_AI_MANAGER << "after transforming [modify_side][ai] into new syntax, config contains:"<< std::endl << cfg << std::endl;
00141
00142 if (this->readonly_context_ == NULL) {
00143
00144
00145 cfg_.merge_with(cfg);
00146 cfg_.merge_children_by_attribute("aspect","id");
00147 } else {
00148
00149 foreach (const config &cfg_a, cfg.child_range("aspect")) {
00150 foreach (const config &cfg_f, cfg_a.child_range("facet")) {
00151 readonly_context_->add_facet(cfg_a["id"],cfg_f);
00152 }
00153 }
00154 }
00155 }
00156
00157
00158 void holder::modify_ai(const config &cfg)
00159 {
00160 if (!this->ai_) {
00161
00162 get_ai_ref();
00163 }
00164 const std::string &act = cfg["action"];
00165 LOG_AI_MOD << "side "<< side_ << " [modify_ai] "<<act<<" \""<<cfg["path"]<<"\""<<std::endl;
00166 DBG_AI_MOD << std::endl << cfg << std::endl;
00167 DBG_AI_MOD << "side "<< side_ << " before [modify_ai]"<<std::endl << to_config() << std::endl;
00168 bool res = false;
00169 if (act == "add") {
00170 res = component_manager::add_component(&*this->ai_,cfg["path"],cfg);
00171 } else if (act == "change") {
00172 res = component_manager::change_component(&*this->ai_,cfg["path"],cfg);
00173 } else if (act == "delete") {
00174 res = component_manager::delete_component(&*this->ai_,cfg["path"]);
00175 } else if (act == "try_delete") {
00176 res = component_manager::delete_component(&*this->ai_,cfg["path"]);
00177 if (!res) {
00178 LOG_AI_MOD << "[modify_ai] "<<act<<" failed, ignoring because it's a try_delete"<< std::endl;
00179 res = true;
00180 }
00181 } else {
00182 ERR_AI_MOD << "modify_ai tag has invalid 'action' attribute " << act << std::endl;
00183 }
00184 DBG_AI_MOD << "side "<< side_ << " after [modify_ai]"<<act<<std::endl << to_config() << std::endl;
00185 if (!res) {
00186 LOG_AI_MOD << "[modify_ai] "<<act<<" failed"<< std::endl;
00187 } else {
00188 LOG_AI_MOD << "[modify_ai] "<<act<<" success"<< std::endl;
00189 }
00190
00191 }
00192
00193 config holder::to_config() const
00194 {
00195 if (!this->ai_) {
00196 return cfg_;
00197 } else {
00198 config cfg = ai_->to_config();
00199 cfg["version"] = "10703";
00200 if (this->side_context_!=NULL) {
00201 cfg.merge_with(this->side_context_->to_side_context_config());
00202 }
00203 if (this->readonly_context_!=NULL) {
00204 cfg.merge_with(this->readonly_context_->to_readonly_context_config());
00205 }
00206 if (this->readwrite_context_!=NULL) {
00207 cfg.merge_with(this->readwrite_context_->to_readwrite_context_config());
00208 }
00209 if (this->default_ai_context_!=NULL) {
00210 cfg.merge_with(this->default_ai_context_->to_default_ai_context_config());
00211 }
00212
00213 return cfg;
00214 }
00215 }
00216
00217
00218
00219 const std::string holder::describe_ai()
00220 {
00221 std::string sidestr = lexical_cast<std::string>(this->side_);
00222
00223 if (this->ai_!=NULL) {
00224 return this->ai_->describe_self()+std::string(" for side ")+sidestr+std::string(" : ");
00225 } else {
00226 return std::string("not initialized ai with id=[")+cfg_["id"]+std::string("] for side ")+sidestr+std::string(" : ");
00227 }
00228 }
00229
00230
00231 const std::string holder::get_ai_overview()
00232 {
00233 if (!this->ai_) {
00234 get_ai_ref();
00235 }
00236 std::stringstream s;
00237 s << "aggression: " << this->ai_->get_aggression() << std::endl;
00238 s << "attack_depth: " << this->ai_->get_attack_depth() << std::endl;
00239 s << "caution: " << this->ai_->get_caution() << std::endl;
00240 s << "grouping: " << this->ai_->get_grouping() << std::endl;
00241 s << "leader_aggression: " << this->ai_->get_leader_aggression() << std::endl;
00242 s << "leader_value: " << this->ai_->get_leader_value() << std::endl;
00243 s << "number_of_possible_recruits_to_force_recruit: " << this->ai_->get_number_of_possible_recruits_to_force_recruit() << std::endl;
00244 s << "passive_leader: " << this->ai_->get_passive_leader() << std::endl;
00245 s << "passive_leader_shares_keep: " << this->ai_->get_passive_leader_shares_keep() << std::endl;
00246 s << "recruitment_ignore_bad_combat: " << this->ai_->get_recruitment_ignore_bad_combat() << std::endl;
00247 s << "recruitment_ignore_bad_movement: " << this->ai_->get_recruitment_ignore_bad_movement() << std::endl;
00248
00249
00250
00251
00252
00253
00254
00255
00256 s << "scout_village_targeting: " << this->ai_->get_scout_village_targeting() << std::endl;
00257 s << "simple_targeting: " << this->ai_->get_simple_targeting() << std::endl;
00258 s << "support_villages: " << this->ai_->get_support_villages() << std::endl;
00259 s << "village_value: " << this->ai_->get_village_value() << std::endl;
00260 s << "villages_per_scout: " << this->ai_->get_villages_per_scout() << std::endl;
00261 return s.str();
00262 }
00263
00264
00265
00266 const std::string holder::get_ai_structure()
00267 {
00268 if (!this->ai_) {
00269 get_ai_ref();
00270 }
00271 return component_manager::print_component_tree(&*this->ai_,"");
00272 }
00273
00274
00275 const std::string holder::get_ai_identifier() const
00276 {
00277 return cfg_["id"];
00278 }
00279
00280
00281
00282
00283
00284
00285 manager::AI_map_of_stacks manager::ai_map_;
00286 game_info *manager::ai_info_;
00287 events::generic_event manager::user_interact_("ai_user_interact");
00288 events::generic_event manager::sync_network_("ai_sync_network");
00289 events::generic_event manager::gamestate_changed_("ai_gamestate_changed");
00290 events::generic_event manager::turn_started_("ai_turn_started");
00291 events::generic_event manager::recruit_list_changed_("ai_recruit_list_changed");
00292 events::generic_event manager::map_changed_("ai_map_changed");
00293 int manager::last_interact_ = 0;
00294 int manager::num_interact_ = 0;
00295
00296
00297 void manager::set_ai_info(const game_info& i)
00298 {
00299 if (ai_info_!=NULL){
00300 clear_ai_info();
00301 }
00302 ai_info_ = new game_info(i);
00303 registry::init();
00304 }
00305
00306
00307 void manager::clear_ai_info(){
00308 delete ai_info_;
00309 ai_info_ = NULL;
00310 }
00311
00312
00313 void manager::add_observer( events::observer* event_observer){
00314 user_interact_.attach_handler(event_observer);
00315 sync_network_.attach_handler(event_observer);
00316 turn_started_.attach_handler(event_observer);
00317 gamestate_changed_.attach_handler(event_observer);
00318 }
00319
00320
00321 void manager::remove_observer(events::observer* event_observer){
00322 user_interact_.detach_handler(event_observer);
00323 sync_network_.detach_handler(event_observer);
00324 turn_started_.detach_handler(event_observer);
00325 gamestate_changed_.detach_handler(event_observer);
00326 }
00327
00328
00329 void manager::add_gamestate_observer( events::observer* event_observer){
00330 gamestate_changed_.attach_handler(event_observer);
00331 turn_started_.attach_handler(event_observer);
00332 map_changed_.attach_handler(event_observer);
00333 }
00334
00335
00336 void manager::remove_gamestate_observer(events::observer* event_observer){
00337 gamestate_changed_.detach_handler(event_observer);
00338 turn_started_.detach_handler(event_observer);
00339 map_changed_.detach_handler(event_observer);
00340 }
00341
00342
00343
00344 void manager::add_map_changed_observer( events::observer* event_observer )
00345 {
00346 map_changed_.attach_handler(event_observer);
00347 }
00348
00349
00350 void manager::add_recruit_list_changed_observer( events::observer* event_observer )
00351 {
00352 recruit_list_changed_.attach_handler(event_observer);
00353 }
00354
00355
00356 void manager::add_turn_started_observer( events::observer* event_observer )
00357 {
00358 turn_started_.attach_handler(event_observer);
00359 }
00360
00361
00362 void manager::remove_recruit_list_changed_observer( events::observer* event_observer )
00363 {
00364 recruit_list_changed_.detach_handler(event_observer);
00365 }
00366
00367
00368 void manager::remove_map_changed_observer( events::observer* event_observer )
00369 {
00370 map_changed_.detach_handler(event_observer);
00371 }
00372
00373
00374 void manager::remove_turn_started_observer( events::observer* event_observer )
00375 {
00376 turn_started_.detach_handler(event_observer);
00377 }
00378
00379 void manager::raise_user_interact() {
00380 const int interact_time = 30;
00381 const int time_since_interact = SDL_GetTicks() - last_interact_;
00382 if(time_since_interact < interact_time) {
00383 return;
00384 }
00385
00386 ++num_interact_;
00387 user_interact_.notify_observers();
00388
00389 last_interact_ = SDL_GetTicks();
00390
00391 }
00392
00393 void manager::raise_sync_network() {
00394 sync_network_.notify_observers();
00395 }
00396
00397
00398 void manager::raise_gamestate_changed() {
00399 gamestate_changed_.notify_observers();
00400 }
00401
00402
00403 void manager::raise_turn_started() {
00404 turn_started_.notify_observers();
00405 }
00406
00407
00408 void manager::raise_recruit_list_changed() {
00409 recruit_list_changed_.notify_observers();
00410 }
00411
00412
00413 void manager::raise_map_changed() {
00414 map_changed_.notify_observers();
00415 }
00416
00417
00418
00419
00420
00421
00422 const std::string manager::evaluate_command( side_number side, const std::string& str )
00423 {
00424
00425 history_.push_back(command_history_item(history_item_counter_++,str));
00426
00427
00428 if (history_.size()>MAX_HISTORY_SIZE){
00429 history_.erase(history_.begin(),history_.begin()+MAX_HISTORY_SIZE/2);
00430 LOG_AI_MANAGER << "AI MANAGER: pruned history" << std::endl;
00431 }
00432
00433 if (!should_intercept(str)){
00434 interface& ai = get_active_ai_for_side(side);
00435 raise_gamestate_changed();
00436 return ai.evaluate(str);
00437 }
00438
00439 return internal_evaluate_command(side,str);
00440 }
00441
00442
00443 bool manager::should_intercept( const std::string& str )
00444 {
00445 if (str.length()<1) {
00446 return false;
00447 }
00448 if (str.at(0)=='!'){
00449 return true;
00450 }
00451 if (str.at(0)=='?'){
00452 return true;
00453 }
00454 return false;
00455
00456 }
00457
00458 std::deque< command_history_item > manager::history_;
00459 long manager::history_item_counter_ = 1;
00460
00461
00462
00463
00464
00465 const std::string manager::internal_evaluate_command( side_number side, const std::string& str ){
00466 const int MAX_HISTORY_VISIBLE = 30;
00467
00468
00469 if (str=="!") {
00470
00471 if (!history_.empty()){
00472 history_.pop_back();
00473 history_item_counter_--;
00474 }
00475
00476 if (history_.empty()){
00477 return "AI MANAGER: empty history";
00478 }
00479 return evaluate_command(side, history_.back().get_command());
00480 };
00481
00482 if (str=="?") {
00483
00484 if (!history_.empty()){
00485 history_.pop_back();
00486 history_item_counter_--;
00487 }
00488
00489 if (history_.empty()){
00490 return "AI MANAGER: History is empty";
00491 }
00492
00493 int n = std::min<int>( MAX_HISTORY_VISIBLE, history_.size() );
00494 std::stringstream strstream;
00495 strstream << "AI MANAGER: History - last "<< n <<" commands:\n";
00496 std::deque< command_history_item >::reverse_iterator j = history_.rbegin();
00497
00498 for (int cmd_id=n; cmd_id>0; --cmd_id){
00499 strstream << j->get_number() << " :" << j->get_command() << '\n';
00500 ++j;
00501 }
00502
00503 return strstream.str();
00504 };
00505
00506
00507 std::vector< std::string > cmd = utils::parenthetical_split(str, ' ',"'","'");
00508
00509 if (cmd.size()==3){
00510
00511 if (cmd.at(0)=="!add_ai"){
00512 side_number side = lexical_cast<side_number>(cmd.at(1));
00513 std::string file = cmd.at(2);
00514 if (add_ai_for_side_from_file(side,file,false)){
00515 return std::string("AI MANAGER: added [")+manager::get_active_ai_identifier_for_side(side)+std::string("] AI for side ")+lexical_cast<std::string>(side)+std::string(" from file ")+file;
00516 } else {
00517 return std::string("AI MANAGER: failed attempt to add AI for side ")+lexical_cast<std::string>(side)+std::string(" from file ")+file;
00518 }
00519 }
00520
00521 if (cmd.at(0)=="!replace_ai"){
00522 side_number side = lexical_cast<side_number>(cmd.at(1));
00523 std::string file = cmd.at(2);
00524 if (add_ai_for_side_from_file(side,file,true)){
00525 return std::string("AI MANAGER: added [")+manager::get_active_ai_identifier_for_side(side)+std::string("] AI for side ")+lexical_cast<std::string>(side)+std::string(" from file ")+file;
00526 } else {
00527 return std::string("AI MANAGER: failed attempt to add AI for side ")+lexical_cast<std::string>(side)+std::string(" from file ")+file;
00528 }
00529 }
00530
00531 } else if (cmd.size()==2){
00532
00533 if (cmd.at(0)=="!remove_ai"){
00534 side_number side = lexical_cast<side_number>(cmd.at(1));
00535 remove_ai_for_side(side);
00536 return std::string("AI MANAGER: made an attempt to remove AI for side ")+lexical_cast<std::string>(side);
00537 }
00538 if (cmd.at(0)=="!"){
00539
00540 if (!history_.empty()){
00541 history_.pop_back();
00542 history_item_counter_--;
00543 }
00544
00545 int command = lexical_cast<int>(cmd.at(1));
00546 std::deque< command_history_item >::reverse_iterator j = history_.rbegin();
00547
00548 while ( (j!=history_.rend()) && (j->get_number()!=command) ){
00549 ++j;
00550 }
00551 if (j!=history_.rend()){
00552 return evaluate_command(side,j->get_command());
00553 }
00554 return "AI MANAGER: no command with requested number found";
00555 }
00556 } else if (cmd.size()==1){
00557 if (cmd.at(0)=="!help") {
00558 return
00559 "known commands:\n"
00560 "! - repeat last command (? and ! do not count)\n"
00561 "! NUMBER - repeat numbered command\n"
00562 "? - show a history list\n"
00563 "!add_ai TEAM FILE - add a AI to side (0 - command AI, N - AI for side #N) from file\n"
00564 "!remove_ai TEAM - remove AI from side (0 - command AI, N - AI for side #N)\n"
00565 "!replace_ai TEAM FILE - replace AI of side (0 - command AI, N - AI for side #N) from file\n"
00566 "!help - show this help message";
00567 }
00568 }
00569
00570
00571 return "AI MANAGER: nothing to do";
00572 }
00573
00574
00575
00576
00577
00578
00579 bool manager::add_ai_for_side_from_file( side_number side, const std::string& file, bool replace )
00580 {
00581 config cfg;
00582 if (!configuration::get_side_config_from_file(file,cfg)){
00583 ERR_AI_MANAGER << " unable to read [SIDE] config for side "<< side << "from file [" << file <<"]"<< std::endl;
00584 return false;
00585 }
00586 return add_ai_for_side_from_config(side,cfg,replace);
00587 }
00588
00589
00590 bool manager::add_ai_for_side_from_config( side_number side, const config& cfg, bool replace ){
00591 config parsed_cfg;
00592 configuration::parse_side_config(side, cfg, parsed_cfg);
00593
00594 if (replace) {
00595 remove_ai_for_side(side);
00596 }
00597
00598 holder new_holder(side,parsed_cfg);
00599 std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
00600 ai_stack_for_specific_side.push(new_holder);
00601 return true;
00602 }
00603
00604
00605
00606 bool manager::add_ai_for_side( side_number side, const std::string& ai_algorithm_type, bool replace )
00607 {
00608 if (replace) {
00609 remove_ai_for_side (side);
00610 }
00611 config cfg;
00612 cfg["ai_algorithm"] = ai_algorithm_type;
00613 holder new_holder(side,cfg);
00614 std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
00615 ai_stack_for_specific_side.push(new_holder);
00616 return true;
00617 }
00618
00619
00620 ai_ptr manager::create_transient_ai(const std::string &ai_algorithm_type, const config &cfg, ai_context *ai_context )
00621 {
00622 assert(ai_context!=NULL);
00623
00624
00625 ai_factory::factory_map::iterator aii = ai_factory::get_list().find(ai_algorithm_type);
00626 if (aii == ai_factory::get_list().end()){
00627 aii = ai_factory::get_list().find("");
00628 if (aii == ai_factory::get_list().end()){
00629 throw game::game_error("no default ai set!");
00630 }
00631 }
00632 LOG_AI_MANAGER << "Creating new AI of type [" << ai_algorithm_type << "]"<< std::endl;
00633 ai_ptr new_ai = aii->second->get_new_instance(*ai_context,cfg);
00634 return new_ai;
00635 }
00636
00637
00638
00639
00640
00641
00642 void manager::remove_ai_for_side( side_number side )
00643 {
00644 std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
00645 if (!ai_stack_for_specific_side.empty()){
00646 ai_stack_for_specific_side.pop();
00647 }
00648 }
00649
00650
00651 void manager::remove_all_ais_for_side( side_number side )
00652 {
00653 std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
00654
00655
00656 while (!ai_stack_for_specific_side.empty()){
00657 ai_stack_for_specific_side.pop();
00658 }
00659 }
00660
00661
00662 void manager::clear_ais()
00663 {
00664 ai_map_.clear();
00665 }
00666
00667
00668
00669
00670
00671 void manager::modify_active_ai_config_old_for_side ( side_number side, const config::const_child_itors &ai_parameters )
00672 {
00673 get_active_ai_holder_for_side(side).modify_ai_config_old(ai_parameters);
00674 }
00675
00676
00677 void manager::modify_active_ai_for_side ( side_number side, const config &cfg )
00678 {
00679 if (ai_info_==NULL) {
00680
00681 return;
00682 }
00683 get_active_ai_holder_for_side(side).modify_ai(cfg);
00684 }
00685
00686
00687 std::string manager::get_active_ai_overview_for_side( side_number side)
00688 {
00689 return get_active_ai_holder_for_side(side).get_ai_overview();
00690 }
00691
00692
00693 std::string manager::get_active_ai_structure_for_side( side_number side)
00694 {
00695 return get_active_ai_holder_for_side(side).get_ai_structure();
00696 }
00697
00698
00699 std::string manager::get_active_ai_identifier_for_side( side_number side )
00700 {
00701 return get_active_ai_holder_for_side(side).get_ai_identifier();
00702 }
00703
00704
00705 config manager::to_config( side_number side )
00706 {
00707 return get_active_ai_holder_for_side(side).to_config();
00708 }
00709
00710
00711 game_info& manager::get_active_ai_info_for_side( side_number )
00712 {
00713 return *ai_info_;
00714 }
00715
00716
00717 game_info& manager::get_ai_info()
00718 {
00719 return *ai_info_;
00720 }
00721
00722
00723
00724
00725
00726
00727 void manager::play_turn( side_number side ){
00728 last_interact_ = 0;
00729 num_interact_ = 0;
00730 const int turn_start_time = SDL_GetTicks();
00731
00732 get_ai_info().recent_attacks.clear();
00733 interface& ai_obj = get_active_ai_for_side(side);
00734 game_events::fire("ai turn");
00735 raise_turn_started();
00736 ai_obj.new_turn();
00737 ai_obj.play_turn();
00738 const int turn_end_time= SDL_GetTicks();
00739 DBG_AI_MANAGER << "side " << side << ": number of user interactions: "<<num_interact_<<std::endl;
00740 DBG_AI_MANAGER << "side " << side << ": total turn time: "<<turn_end_time - turn_start_time << " ms "<< std::endl;
00741 }
00742
00743
00744
00745
00746
00747
00748
00749
00750 std::stack<holder>& manager::get_or_create_ai_stack_for_side( side_number side )
00751 {
00752 AI_map_of_stacks::iterator iter = ai_map_.find(side);
00753 if (iter!=ai_map_.end()){
00754 return iter->second;
00755 }
00756 return ai_map_.insert(std::make_pair(side, std::stack<holder>())).first->second;
00757 }
00758
00759
00760
00761
00762 holder& manager::get_active_ai_holder_for_side( side_number side )
00763 {
00764 std::stack<holder>& ai_stack_for_specific_side = get_or_create_ai_stack_for_side(side);
00765
00766 if (!ai_stack_for_specific_side.empty()){
00767 return ai_stack_for_specific_side.top();
00768 } else {
00769 config cfg = configuration::get_default_ai_parameters();
00770 holder new_holder(side, cfg);
00771 ai_stack_for_specific_side.push(new_holder);
00772 return ai_stack_for_specific_side.top();
00773 }
00774 }
00775
00776
00777
00778
00779
00780 interface& manager::get_active_ai_for_side( side_number side )
00781 {
00782 return get_active_ai_holder_for_side(side).get_ai_ref();
00783 }
00784
00785
00786
00787
00788
00789
00790 }