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
00022 #include "contexts.hpp"
00023
00024 #include "../../actions.hpp"
00025 #include "../../foreach.hpp"
00026 #include "../../log.hpp"
00027 #include "../../map.hpp"
00028 #include "../../resources.hpp"
00029 #include "../../team.hpp"
00030 #include "../composite/goal.hpp"
00031 #include "../../pathfind/pathfind.hpp"
00032
00033 static lg::log_domain log_ai("ai/general");
00034 #define DBG_AI LOG_STREAM(debug, log_ai)
00035 #define LOG_AI LOG_STREAM(info, log_ai)
00036 #define WRN_AI LOG_STREAM(warn, log_ai)
00037 #define ERR_AI LOG_STREAM(err, log_ai)
00038
00039
00040 namespace ai {
00041
00042
00043
00044 default_ai_context::default_ai_context()
00045 {
00046 }
00047
00048
00049 default_ai_context::~default_ai_context()
00050 {
00051 }
00052
00053
00054
00055 default_ai_context_proxy::~default_ai_context_proxy()
00056 {
00057 }
00058
00059 void default_ai_context_proxy::init_default_ai_context_proxy(default_ai_context &target)
00060 {
00061 init_readwrite_context_proxy(target);
00062 target_= &target.get_default_ai_context();
00063 }
00064
00065
00066 const int max_positions = 10000;
00067
00068
00069 default_ai_context_impl::~default_ai_context_impl()
00070 {
00071 }
00072
00073
00074 int default_ai_context_impl::count_free_hexes_in_castle(const map_location &loc, std::set<map_location> &checked_hexes)
00075 {
00076 int ret = 0;
00077 unit_map &units_ = *resources::units;
00078 map_location adj[6];
00079 get_adjacent_tiles(loc,adj);
00080 for(size_t n = 0; n != 6; ++n) {
00081 if (checked_hexes.find(adj[n]) != checked_hexes.end())
00082 continue;
00083 checked_hexes.insert(adj[n]);
00084 if (resources::game_map->is_castle(adj[n])) {
00085 const unit_map::const_iterator u = units_.find(adj[n]);
00086 ret += count_free_hexes_in_castle(adj[n], checked_hexes);
00087 if (u == units_.end()
00088 || (current_team().is_enemy(u->side())
00089 && u->invisible(adj[n]))
00090 || ((&(*resources::teams)[u->side() - 1]) == ¤t_team()
00091 && u->movement_left() > 0)) {
00092 ret += 1;
00093 }
00094 }
00095 }
00096 return ret;
00097 }
00098
00099
00100 default_ai_context& default_ai_context_impl::get_default_ai_context(){
00101 return *this;
00102 }
00103
00104
00105 int default_ai_context_impl::rate_terrain(const unit& u, const map_location& loc) const
00106 {
00107 gamemap &map_ = *resources::game_map;
00108 const t_translation::t_terrain terrain = map_.get_terrain(loc);
00109 const int defense = u.defense_modifier(terrain);
00110 int rating = 100 - defense;
00111
00112 const int healing_value = 10;
00113 const int friendly_village_value = 5;
00114 const int neutral_village_value = 10;
00115 const int enemy_village_value = 15;
00116
00117 if(map_.gives_healing(terrain) && u.get_ability_bool("regenerate",loc) == false) {
00118 rating += healing_value;
00119 }
00120
00121 if(map_.is_village(terrain)) {
00122 int owner = village_owner(loc, *resources::teams) + 1;
00123
00124 if(owner == get_side()) {
00125 rating += friendly_village_value;
00126 } else if(owner == 0) {
00127 rating += neutral_village_value;
00128 } else {
00129 rating += enemy_village_value;
00130 }
00131 }
00132
00133 return rating;
00134 }
00135
00136 std::vector<target> default_ai_context_impl::find_targets(const move_map& enemy_dstsrc)
00137 {
00138
00139 log_scope2(log_ai, "finding targets...");
00140 unit_map &units_ = *resources::units;
00141 unit_map::iterator leader = units_.find_leader(get_side());
00142 gamemap &map_ = *resources::game_map;
00143 std::vector<team> teams_ = *resources::teams;
00144 const bool has_leader = leader != units_.end();
00145
00146 std::vector<target> targets;
00147
00148 std::map<map_location,pathfind::paths> friends_possible_moves;
00149 move_map friends_srcdst, friends_dstsrc;
00150 calculate_possible_moves(friends_possible_moves,friends_srcdst,friends_dstsrc,false,true);
00151
00152
00153
00154
00155 if(has_leader) {
00156 double threat = power_projection(leader->get_location(), enemy_dstsrc);
00157 if(threat > 0.0) {
00158
00159 std::set<map_location> threats;
00160
00161 map_location adj[6];
00162 get_adjacent_tiles(leader->get_location(), adj);
00163 for(size_t n = 0; n != 6; ++n) {
00164 std::pair<move_map::const_iterator,move_map::const_iterator> itors = enemy_dstsrc.equal_range(adj[n]);
00165 while(itors.first != itors.second) {
00166 if(units_.count(itors.first->second)) {
00167 threats.insert(itors.first->second);
00168 }
00169
00170 ++itors.first;
00171 }
00172 }
00173
00174 assert(threats.empty() == false);
00175
00176 #ifdef SUOKKO
00177
00178 const double value = threat*get_protect_leader()/leader->second.hitpoints();
00179 #else
00180 const double value = threat/double(threats.size());
00181 #endif
00182 for(std::set<map_location>::const_iterator i = threats.begin(); i != threats.end(); ++i) {
00183 LOG_AI << "found threat target... " << *i << " with value: " << value << "\n";
00184 targets.push_back(target(*i,value,target::THREAT));
00185 }
00186 }
00187 }
00188
00189 double corner_distance = distance_between(map_location(0,0), map_location(map_.w(),map_.h()));
00190 double village_value = get_village_value();
00191 if(has_leader && get_village_value() > 0.0) {
00192 const std::vector<map_location>& villages = map_.villages();
00193 for(std::vector<map_location>::const_iterator t =
00194 villages.begin(); t != villages.end(); ++t) {
00195
00196 assert(map_.on_board(*t));
00197 bool ally_village = false;
00198 for (size_t i = 0; i != teams_.size(); ++i)
00199 {
00200 if (!current_team().is_enemy(i + 1) && teams_[i].owns_village(*t)) {
00201 ally_village = true;
00202 break;
00203 }
00204 }
00205
00206 if (ally_village)
00207 {
00208
00209
00210 if(get_support_villages()) {
00211 double enemy = power_projection(*t, enemy_dstsrc);
00212 if (enemy > 0)
00213 {
00214 enemy *= 1.7;
00215 double our = power_projection(*t, friends_dstsrc);
00216 double value = village_value * our / enemy;
00217 add_target(target(*t, value, target::SUPPORT));
00218 }
00219 }
00220 }
00221 else
00222 {
00223 double leader_distance = distance_between(*t, leader->get_location());
00224 double value = village_value * (1.0 - leader_distance / corner_distance);
00225 LOG_AI << "found village target... " << *t
00226 << " with value: " << value
00227 << " distance: " << leader_distance << '\n';
00228 targets.push_back(target(*t,value,target::VILLAGE));
00229 }
00230 }
00231 }
00232
00233 std::vector<goal_ptr>& goals = get_goals();
00234
00235
00236 unit_map::const_iterator u;
00237 if (get_leader_value()>0.0) {
00238 for(u = units_.begin(); u != units_.end(); ++u) {
00239
00240 if (u->can_recruit() && current_team().is_enemy(u->side())
00241 && !u->invisible(u->get_location())) {
00242 assert(map_.on_board(u->get_location()));
00243 LOG_AI << "found enemy leader (side: " << u->side() << ") target... " << u->get_location() << " with value: " << get_leader_value() << "\n";
00244 targets.push_back(target(u->get_location(), get_leader_value(), target::LEADER));
00245 }
00246 }
00247
00248 }
00249
00250
00251 for(std::vector<goal_ptr>::iterator j = goals.begin();
00252 j != goals.end(); ++j) {
00253
00254 if (!(*j)->active()) {
00255 continue;
00256 }
00257 (*j)->add_targets(std::back_inserter(targets));
00258
00259 }
00260
00261
00262
00263 std::vector<double> new_values;
00264
00265 for(std::vector<target>::iterator i = targets.begin();
00266 i != targets.end(); ++i) {
00267
00268 new_values.push_back(i->value);
00269
00270 for(std::vector<target>::const_iterator j = targets.begin(); j != targets.end(); ++j) {
00271 if(i->loc == j->loc) {
00272 continue;
00273 }
00274
00275 const double distance = abs(j->loc.x - i->loc.x) +
00276 abs(j->loc.y - i->loc.y);
00277 new_values.back() += j->value/(distance*distance);
00278 }
00279 }
00280
00281 assert(new_values.size() == targets.size());
00282 for(size_t n = 0; n != new_values.size(); ++n) {
00283 LOG_AI << "target value: " << targets[n].value << " -> " << new_values[n] << "\n";
00284 targets[n].value = new_values[n];
00285 }
00286
00287 return targets;
00288 }
00289
00290
00291 const std::vector<target>& default_ai_context_impl::additional_targets() const
00292 {
00293 return additional_targets_;
00294 }
00295
00296
00297 void default_ai_context_impl::add_target(const target& t) const
00298 {
00299 additional_targets_.push_back(t);
00300 }
00301
00302
00303 void default_ai_context_impl::clear_additional_targets() const
00304 {
00305 additional_targets_.clear();
00306 }
00307
00308 config default_ai_context_impl::to_default_ai_context_config() const
00309 {
00310 return config();
00311 }
00312
00313 }