Author: torangan
Date: Tue Apr 10 16:19:15 2007
New Revision: 16729

URL: http://svn.gna.org/viewcvs/wesnoth?rev=16729&view=rev
Log:
patch #721: Fix incorrect power projection for AI

Modified:
    trunk/src/ai_attack.cpp

Modified: trunk/src/ai_attack.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/ai_attack.cpp?rev=16729&r1=16728&r2=16729&view=diff
==============================================================================
--- trunk/src/ai_attack.cpp (original)
+++ trunk/src/ai_attack.cpp Tue Apr 10 16:19:15 2007
@@ -575,19 +575,28 @@
 
 double ai::power_projection(const gamemap::location& loc,  const move_map& 
dstsrc, bool use_terrain) const
 {
-       static gamemap::location used_locs[6];
-       static double ratings[6];
+       gamemap::location used_locs[6];
+       int ratings[6];
        int num_used_locs = 0;
 
-       static gamemap::location locs[6];
+       gamemap::location locs[6];
        get_adjacent_tiles(loc,locs);
 
        const int lawful_bonus = state_.get_time_of_day().lawful_bonus;
 
-       double res = 0.0;
-
-       for(int i = 0; i != 6; ++i) {
-               if(map_.on_board(locs[i]) == false) {
+       int res = 0;
+
+       bool changed = false;
+       for (int i = 0;; ++i) {
+               if (i == 6) {
+                       if (!changed) break;
+                       // Loop once again, in case a unit found a better
+                       // spot and freed the place for another unit.
+                       changed = false;
+                       i = 0;
+               }
+
+               if (map_.on_board(locs[i]) == false) {
                        continue;
                }
 
@@ -600,87 +609,70 @@
                gamemap::location* const beg_used = used_locs;
                gamemap::location* end_used = used_locs + num_used_locs;
 
-               double best_rating = 0.0;
+               int best_rating = 0;
                gamemap::location best_unit;
 
-               for(int n = 0; n != 2; ++n) {
-                       for(Itor it = its.first; it != its.second; ++it) {
-                               if(std::find(beg_used,end_used,it->second) != 
end_used) {
-                                       continue;
+               for(Itor it = its.first; it != its.second; ++it) {
+                       const unit_map::const_iterator u = 
units_.find(it->second);
+
+                       //unit might have been killed, and no longer exist
+                       if(u == units_.end()) {
+                               continue;
+                       }
+
+                       const unit& un = u->second;
+
+                       int tod_modifier = 0;
+                       if(un.alignment() == unit_type::LAWFUL) {
+                               tod_modifier = lawful_bonus;
+                       } else if(un.alignment() == unit_type::CHAOTIC) {
+                               tod_modifier = -lawful_bonus;
+                       }
+
+                       int hp = un.hitpoints() * 1000 / un.max_hitpoints();
+                       int most_damage = 0;
+                       for(std::vector<attack_type>::const_iterator att =
+                           un.attacks().begin(); att != un.attacks().end(); 
++att) {
+                               int damage = att->damage() * att->num_attacks() 
*
+                                            (100 + tod_modifier);
+                               if(damage > most_damage) {
+                                       most_damage = damage;
                                }
-
-                               const unit_map::const_iterator u = 
units_.find(it->second);
-
-                               //unit might have been killed, and no longer 
exist
-                               if(u == units_.end()) {
-                                       continue;
-                               }
-
-                               const unit& un = u->second;
-
-                               int tod_modifier = 0;
-                               if(un.alignment() == unit_type::LAWFUL) {
-                                       tod_modifier = lawful_bonus;
-                               } else if(un.alignment() == unit_type::CHAOTIC) 
{
-                                       tod_modifier = -lawful_bonus;
-                               }
-
-                               const double hp = double(un.hitpoints())/
-                                                 double(un.max_hitpoints());
-                               int most_damage = 0;
-                               for(std::vector<attack_type>::const_iterator 
att =
-                                   un.attacks().begin(); att != 
un.attacks().end(); ++att) {
-                                       const int damage = 
(att->damage()*att->num_attacks()*(100+tod_modifier))/100;
-                                       if(damage > most_damage) {
-                                               most_damage = damage;
-                                       }
-                               }
-
-                               const bool village = map_.is_village(terrain);
-                               const double village_bonus = (use_terrain && 
village) ? 1.5 : 1.0;
-
-                               const double defense = use_terrain ? double(100 
- un.defense_modifier(terrain))/100.0 : 0.5;
-                               const double rating = 
village_bonus*hp*defense*double(most_damage);
-                               if(rating > best_rating) {
+                       }
+
+                       int village_bonus = use_terrain && 
map_.is_village(terrain) ? 3 : 2;
+                       int defense = use_terrain ? 100 - 
un.defense_modifier(terrain) : 50;
+                       int rating = hp * defense * most_damage * village_bonus 
/ 200;
+                       if(rating > best_rating) {
+                               gamemap::location *pos = std::find(beg_used, 
end_used, it->second);
+                               // Check if the spot is the same or better than 
an older one.
+                               if (pos == end_used || rating >= ratings[pos - 
beg_used]) {
                                        best_rating = rating;
                                        best_unit = it->second;
                                }
                        }
-
-                       //if this is the second time through, then we are 
looking at a unit
-                       //that has already been used, but for whom we may have 
found
-                       //a better position to attack from
-                       if(n == 1 && best_unit.valid()) {
-                               end_used = beg_used + num_used_locs;
-                               gamemap::location* const pos = 
std::find(beg_used,end_used,best_unit);
-                               const int index = pos - beg_used;
-                               if(best_rating >= ratings[index]) {
-                                       res -= ratings[index];
-                                       res += best_rating;
-                                       used_locs[index] = best_unit;
-                                       ratings[index] = best_rating;
-                               }
-
-                               best_unit = gamemap::location();
-                               break;
-                       }
-
-                       if(best_unit.valid()) {
-                               break;
-                       }
-
-                       end_used = beg_used;
-               }
-
-               if(best_unit.valid()) {
-                       used_locs[num_used_locs] = best_unit;
-                       ratings[num_used_locs] = best_rating;
+               }
+
+               if (!best_unit.valid()) continue;
+               gamemap::location *pos = std::find(beg_used, end_used, 
best_unit);
+               int index = pos - beg_used;
+               if (index == num_used_locs)
                        ++num_used_locs;
-                       res += best_rating;
-               }
-       }
-
-       return res;
+               else if (best_rating == ratings[index])
+                       continue;
+               else {
+                       // The unit was in another spot already, so remove its 
older
+                       // rating from the final result and require a new run 
to fill
+                       // its old spot.
+                       res -= ratings[index];
+                       changed = true;
+               }
+               used_locs[index] = best_unit;
+               ratings[index] = best_rating;
+               res += best_rating;
+       }
+
+       return res / 100000.;
 }
 
 // There is no real hope for us: we should try to do some damage to the enemy.


_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits

Reply via email to