Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "stage_rca.hpp"
00022
00023 #include "../manager.hpp"
00024 #include "../composite/ai.hpp"
00025 #include "../composite/engine.hpp"
00026 #include "../composite/property_handler.hpp"
00027 #include "../gamestate_observer.hpp"
00028 #include "../../foreach.hpp"
00029 #include "../../log.hpp"
00030
00031 #include <boost/bind.hpp>
00032
00033 namespace ai {
00034
00035 namespace testing_ai_default {
00036
00037 static lg::log_domain log_ai_testing_rca_default("ai/stage/rca");
00038 #define DBG_AI_TESTING_RCA_DEFAULT LOG_STREAM(debug, log_ai_testing_rca_default)
00039 #define LOG_AI_TESTING_RCA_DEFAULT LOG_STREAM(info, log_ai_testing_rca_default)
00040 #define ERR_AI_TESTING_RCA_DEFAULT LOG_STREAM(err, log_ai_testing_rca_default)
00041
00042 candidate_action_evaluation_loop::candidate_action_evaluation_loop( ai_context &context, const config &cfg)
00043 : stage(context,cfg)
00044 , candidate_actions_()
00045 , cfg_(cfg)
00046 {
00047 }
00048
00049 void candidate_action_evaluation_loop::on_create()
00050 {
00051
00052 foreach(const config &cfg_element, cfg_.child_range("candidate_action")){
00053 engine::parse_candidate_action_from_config(*this,cfg_element,back_inserter(candidate_actions_));
00054 }
00055
00056 boost::function2<void, std::vector<candidate_action_ptr>&, const config&> factory_candidate_actions =
00057 boost::bind(&testing_ai_default::candidate_action_evaluation_loop::create_candidate_action,*this,_1,_2);
00058
00059 register_vector_property(property_handlers(),"candidate_action",candidate_actions_, factory_candidate_actions);
00060
00061 }
00062
00063 void candidate_action_evaluation_loop::create_candidate_action(std::vector<candidate_action_ptr> &candidate_actions, const config &cfg)
00064 {
00065 engine::parse_candidate_action_from_config(*this,cfg,std::back_inserter(candidate_actions));
00066 }
00067
00068
00069 config candidate_action_evaluation_loop::to_config() const
00070 {
00071 config cfg = stage::to_config();
00072 foreach(candidate_action_ptr ca, candidate_actions_){
00073 cfg.add_child("candidate_action",ca->to_config());
00074 }
00075 return cfg;
00076 }
00077
00078
00079 class desc_sorter_of_candidate_actions {
00080 public:
00081 bool operator()(const candidate_action_ptr &a, const candidate_action_ptr &b)
00082 {
00083 return a->get_max_score() > b->get_max_score();
00084 }
00085 };
00086
00087 bool candidate_action_evaluation_loop::do_play_stage()
00088 {
00089 LOG_AI_TESTING_RCA_DEFAULT << "Starting candidate action evaluation loop for side "<< get_side() << std::endl;
00090
00091 foreach(candidate_action_ptr ca, candidate_actions_){
00092 ca->enable();
00093 }
00094
00095
00096 std::sort(candidate_actions_.begin(),candidate_actions_.end(),desc_sorter_of_candidate_actions());
00097
00098 bool executed = false;
00099 bool gamestate_changed = false;
00100 do {
00101 executed = false;
00102 double best_score = candidate_action::BAD_SCORE;
00103 candidate_action_ptr best_ptr;
00104
00105
00106 foreach(candidate_action_ptr ca_ptr, candidate_actions_){
00107 if (!ca_ptr->is_enabled()){
00108 DBG_AI_TESTING_RCA_DEFAULT << "Skipping disabled candidate action: "<< *ca_ptr << std::endl;
00109 continue;
00110 }
00111
00112 if (ca_ptr->get_max_score()<=best_score) {
00113 DBG_AI_TESTING_RCA_DEFAULT << "Ending candidate action evaluation loop because current score "<<best_score<<" is greater than the upper bound of score for remaining candidate actions "<< ca_ptr->get_max_score()<< std::endl;
00114 break;
00115 }
00116
00117 DBG_AI_TESTING_RCA_DEFAULT << "Evaluating candidate action: "<< *ca_ptr << std::endl;
00118 double score = ca_ptr->evaluate();
00119 DBG_AI_TESTING_RCA_DEFAULT << "Evaluated candidate action to score "<< score << " : " << *ca_ptr << std::endl;
00120
00121 if (score>best_score) {
00122 best_score = score;
00123 best_ptr = ca_ptr;
00124 }
00125 }
00126
00127
00128 if (best_score>candidate_action::BAD_SCORE) {
00129 DBG_AI_TESTING_RCA_DEFAULT << "Executing best candidate action: "<< *best_ptr << std::endl;
00130 gamestate_observer gs_o;
00131 best_ptr->execute();
00132 executed = true;
00133 if (!gs_o.is_gamestate_changed()) {
00134
00135
00136 DBG_AI_TESTING_RCA_DEFAULT << "Disabling candidate action because it failed to change the game state: "<< *best_ptr << std::endl;
00137 best_ptr->disable();
00138
00139 } else {
00140 gamestate_changed = true;
00141 }
00142 } else {
00143 LOG_AI_TESTING_RCA_DEFAULT << "Ending candidate action evaluation loop due to best score "<< best_score<<"<="<< candidate_action::BAD_SCORE<<std::endl;
00144 }
00145 } while (executed);
00146 LOG_AI_TESTING_RCA_DEFAULT << "Ended candidate action evaluation loop for side "<< get_side() << std::endl;
00147 remove_completed_cas();
00148 return gamestate_changed;
00149 }
00150
00151 void candidate_action_evaluation_loop::remove_completed_cas()
00152 {
00153 std::vector<size_t> tbr;
00154
00155 for (size_t i = 0; i != candidate_actions_.size(); ++i)
00156 {
00157 if (candidate_actions_[i]->to_be_removed())
00158 {
00159 tbr.push_back(i);
00160 }
00161 }
00162
00163 for (size_t i = 0; i != tbr.size(); ++i)
00164 {
00165
00166 size_t index = tbr.size() - i - 1;
00167 std::string path = "stage[" + this->get_id() + "].candidate_action[" + candidate_actions_[tbr[index]]->get_name() + "]";
00168
00169 config cfg = config();
00170 cfg["path"] = path;
00171 cfg["action"] = "delete";
00172
00173 ai::manager::modify_active_ai_for_side(this->get_side(), cfg);
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 }
00198
00199 rca_context& candidate_action_evaluation_loop::get_rca_context()
00200 {
00201 return *this;
00202 }
00203
00204 candidate_action_evaluation_loop::~candidate_action_evaluation_loop()
00205 {
00206 }
00207
00208 }
00209
00210 }