Author: esr
Date: Wed Oct 22 23:17:55 2008
New Revision: 30313

URL: http://svn.gna.org/viewcvs/wesnoth?rev=30313&view=rev
Log:
Forward-port the remaiunder of suokko's changes to move_leader_to_keep(),
previously reverted in emergency.

Modified:
    trunk/src/ai_move.cpp

Modified: trunk/src/ai_move.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/ai_move.cpp?rev=30313&r1=30312&r2=30313&view=diff
==============================================================================
--- trunk/src/ai_move.cpp (original)
+++ trunk/src/ai_move.cpp Wed Oct 22 23:17:55 2008
@@ -801,6 +801,20 @@
        }
 }
 
+namespace {
+        struct match_turn{
+                match_turn(int turn) : turn_(turn)
+                {
+                }
+                bool operator()(const std::map<map_location, 
paths::route::waypoint>::value_type& way)
+                {
+                        return way.second.turns == turn_;
+                }
+                private:
+                int& turn_;
+        };
+}
+
 void ai::move_leader_to_keep(const move_map& enemy_dstsrc)
 {
        const unit_map::iterator leader = find_leader(units_,team_num_);
@@ -822,57 +836,100 @@
                {
                        // Make a map of the possible locations the leader can 
move to,
                        // ordered by the distance from the keep.
-                       int best_value = INT_MAX;
+                       int best_value = INT_MAX - 1;
                        map_location best_target;
 
-                       // The leader can't move to his keep, try to move to 
the closest location
+                       const shortest_path_calculator 
cost_calc(leader->second, 
+                                       current_team(), 
+                                       units_, teams_, 
+                                       map_);
+
+                       std::set<map_location> allowed_teleports;
+
+                       
if(leader->second.get_ability_bool("teleport",leader->first)) {
+                               // search all known empty friendly villages
+                               for(std::set<map_location>::const_iterator vil 
= current_team().villages().begin();
+                                               vil != 
current_team().villages().end(); ++vil) {
+
+                                       unit_map::const_iterator occupant = 
units_.find(*vil);
+                                       if (occupant != units_.end() && 
occupant != leader)
+                                               continue;
+
+                                       allowed_teleports.insert(*vil);
+                               }
+                       }
+
+
+                       // The leader can't move to his keep, try to move to 
the closest map_location
                        // to the keep where there are no enemies in range.
-                       for(std::set<location>::iterator i = keeps().begin();
+                       for(std::set<map_location>::iterator i = 
keeps().begin();
                                        i != keeps().end(); ++i) {
 
-                               const shortest_path_calculator 
cost_calc(leader->second, current_team(), units_,
-                                               teams_,map_);
-                               
+                               const double limit = std::min(10000, best_value 
+ 1);
                                paths::routes_map::iterator route = 
path_itor->second.routes.insert(
                                                std::make_pair(*i,
-                                                       
a_star_search(leader->first, *i, 10000.0, &cost_calc,map_.w(), 
map_.h()))).first;
+                                                       
a_star_search(leader->first, *i, limit, &cost_calc,map_.w(), map_.h(), 
&allowed_teleports
+                                                               ))).first;
+                               if (route->second.steps.empty())
+                               {
+                                       path_itor->second.routes.erase(route);
+                                       continue;
+                               }
 
                                std::set<map_location> checked_hexes;
-                               const int distance = 
route->second.steps.size()-1;
                                checked_hexes.insert(*i);
                                const int free_slots = 
count_free_hexes_in_castle(*i, checked_hexes);
-                               const int tactical_value =  
std::sqrt(std::pow(static_cast<float>(map_.w()/2 - i->x),2) +
-                                                       
std::pow(static_cast<float>(map_.h()/2 - i->y),2))*2;
+                               map_location center(map_.w()/2, map_.h()/2);
+                               const int tactical_value = 
distance_between(center, *i);
                                const int empty_slots = 
leader->second.total_movement() * std::max(number_of_recruit - free_slots,0);
                                unit_map::const_iterator u = units_.find(*i);
                                const int reserved_penalty = 
leader->second.total_movement() * 
                                        (u != units_.end() 
-                                               && &teams_[u->second.side()-1] 
!= &current_team() 
-                                               && 
!u->second.invisible(u->first, units_, teams_)
-                                                       
?(current_team().is_enemy(u->second.side())?6:3)
-                                       :0);
-                               const int enemy = (power_projection(*i, 
enemy_dstsrc) * 8 * leader->second.total_movement())/leader->second.hitpoints();
+                                        && &teams_[u->second.side()-1] != 
&current_team() 
+                                        && !u->second.invisible(u->first, 
units_, teams_)
+                                        
?(current_team().is_enemy(u->second.side())?6:3)
+                                        :0);
+
+                               int value = empty_slots + tactical_value + 
reserved_penalty;
+
+                               // do enemy power projection so we know where 
enemy is
+                               int enemy = leader->second.hitpoints() - 
(power_projection(*i, enemy_dstsrc) * 3);
+                               if (enemy > 0)
+                                       enemy = ((leader->second.hitpoints() - 
enemy)*leader->second.total_movement()*4 / leader->second.hitpoints())*-1;
+                               else
+                                       enemy = (enemy * 
leader->second.total_movement() * -4)/leader->second.hitpoints();
+
+                               value += enemy;
+
+
+                               // Make first quess if this is worth 
calculateing
+                               if (value + 
static_cast<int>(route->second.steps.size()) - 1 >= best_value)
+                                       continue;
+
+                               int distance = 
route_turns_to_complete(leader->second,
+                                               route->second,
+                                               current_team(),
+                                               units_,
+                                               teams_,
+                                               map_) * 
leader->second.total_movement();
+
+                               map_location target;
+
+                               target = 
std::find_if(route->second.waypoints.begin(),
+                                               route->second.waypoints.end(),
+                                               match_turn(1))->first;
+
                                int multiturn_move_penalty = 0;
                                if (recruiting_preferred_)
                                        multiturn_move_penalty = 2;
 
                                const int distance_value = (distance > 
leader->second.movement_left()? 
                                                ((distance - 
leader->second.movement_left())/leader->second.total_movement()+multiturn_move_penalty)*leader->second.total_movement()
 : 0);
-                               const int value = distance_value + empty_slots 
+ enemy + tactical_value + reserved_penalty;
-       
-                               if (value > best_value)
+                               value += distance_value;
+
+                               if (value >= best_value)
                                        continue;
 
-                               map_location target;
-                               if (distance > leader->second.movement_left())
-                               {
-                                       target = 
route->second.steps[leader->second.movement_left()];
-                                       
route->second.steps.erase(route->second.steps.begin() + 
leader->second.movement_left()+1,route->second.steps.end());
-                                       route->second.move_left = 0;
-                               } else {
-                                       target = *i;
-                                       route->second.move_left = 
leader->second.movement_left() - distance;
-                               }
                                best_value = value;
                                best_target = target;
                                DBG_AI << "Considering keep: " << *i << 
@@ -883,12 +940,13 @@
                                        " reserved_penalty: " << 
reserved_penalty << 
                                        " target: " << target <<
                                        " value: " << value <<
-                                   " route: " << route->second.steps.size() << 
" " << route->second.move_left <<       
+                                       " route: " << 
route->second.steps.size() << " " << route->second.move_left <<   
                                        "\n";
-               }
+                       }
 
                        // Find the location with the best value
-                       if (leader->first != best_target)
+                       if (leader->first != best_target
+                                       && best_target != 
location::null_location)
                                
move_unit(leader->first,best_target,possible_moves);
                }
        }


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

Reply via email to