ai/default/contexts.cpp

Go to the documentation of this file.
00001 /* $Id: contexts.cpp 52758 2012-01-23 15:09:23Z anonymissimus $ */
00002 /*
00003    Copyright (C) 2009 - 2012 by Yurii Chernyi <terraninfo@terraninfo.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 /**
00017  * Helper functions for the object which operates in the context of AI for specific side
00018  * This is part of AI interface
00019  * @file
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 // default ai context
00044 default_ai_context::default_ai_context()
00045 {
00046 }
00047 
00048 
00049 default_ai_context::~default_ai_context()
00050 {
00051 }
00052 
00053 // default ai context proxy
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]) == &current_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     //=== start getting targets
00153 
00154     //if enemy units are in range of the leader, then we target the enemies who are in range.
00155     if(has_leader) {
00156         double threat = power_projection(leader->get_location(), enemy_dstsrc);
00157         if(threat > 0.0) {
00158             //find the location of enemy threats
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             //FIXME: suokko's revision 29531 included this change.  Correct?
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                 //Support seems to cause the AI to just 'sit around' a lot, so
00209                 //only turn it on if it's explicitly enabled.
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     //find the enemy leaders and explicit targets
00236     unit_map::const_iterator u;
00237     if (get_leader_value()>0.0) {
00238         for(u = units_.begin(); u != units_.end(); ++u) {
00239             //is a visible enemy leader
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     //explicit targets for this team
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     //=== end getting targets
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 } //of namespace ai
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Thu May 24 2012 01:02:28 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs