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]
!= ¤t_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] !=
¤t_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