Some more improvements to AI movement and attack selection

Fixed team survival AI parameters
This commit is contained in:
Pauli Nieminen 2008-09-17 00:33:01 +00:00
parent ff3b3a3623
commit 89ddafd8c7
5 changed files with 94 additions and 38 deletions

View file

@ -379,14 +379,27 @@ usage=mask
{SIDE_COMPUTER 1 Attacker (_ "Attacker") 1000 47 () (
leader_value=7.0
aggression=0.95
aggression=0.99
caution=0.0
)}
{SIDE_PLAYER 2 Defenders (_ "Defender") 125 -2 ()}
{SIDE_PLAYER 3 Defenders (_ "Defender") 125 -2 ()}
{SIDE_PLAYER 4 Defenders (_ "Defender") 125 -2 ()}
{SIDE_PLAYER 5 Defenders (_ "Defender") 125 -2 ()}
{SIDE_PLAYER 6 Defenders (_ "Defender") 125 -2 ()}
{SIDE_PLAYER 7 Defenders (_ "Defender") 125 -2 ()}
{SIDE_PLAYER 2 Defenders (_ "Defender") 125 -2 ([ai]
villages_per_scout=0
[/ai])}
{SIDE_PLAYER 3 Defenders (_ "Defender") 125 -2 ([ai]
villages_per_scout=0
[/ai])}
{SIDE_PLAYER 4 Defenders (_ "Defender") 125 -2 ([ai]
villages_per_scout=0
[/ai])}
{SIDE_PLAYER 5 Defenders (_ "Defender") 125 -2 ([ai]
villages_per_scout=0
[/ai])}
{SIDE_PLAYER 6 Defenders (_ "Defender") 125 -2 ([ai]
villages_per_scout=0
[/ai])}
{SIDE_PLAYER 7 Defenders (_ "Defender") 125 -2 ([ai]
villages_per_scout=0
[/ai])}
[/multiplayer]
#undef TS_MAP_DATA

View file

@ -536,7 +536,6 @@ gamemap::location ai_interface::move_unit_partial(location from, location to,
}
if(rt != p.routes.end()) {
assert(static_cast<size_t>(u_it->second.movement_left()) >= rt->second.steps.size() && "Trying to move unit without enough move points left\n");
u_it->second.set_movement(rt->second.move_left);
std::vector<location> steps = rt->second.steps;
@ -981,14 +980,21 @@ void ai::evaluate_recruiting_value(unit_map::iterator leader)
}
float free_slots = 0.0f;
const float gold = current_team().gold();
const float unit_price = current_team().average_recruit_price();
if (map_.is_keep(leader->first))
{
std::set<gamemap::location> checked_hexes;
checked_hexes.insert(leader->first);
free_slots = count_free_hexes_in_castle(leader->first, checked_hexes);
} else {
gamemap::location loc = nearest_keep(leader->first);
if (units_.find(loc) == units_.end()
&& gold/unit_price > 1.0f)
{
free_slots -= current_team().num_pos_recruits_to_force();
}
}
const float gold = current_team().gold();
const float unit_price = current_team().average_recruit_price();
recruiting_prefered_ = (gold/unit_price) - free_slots > current_team().num_pos_recruits_to_force();
DBG_AI << "recruiting prefered: " << (recruiting_prefered_?"yes":"no") <<
" units to recruit: " << (gold/unit_price) <<
@ -1132,7 +1138,17 @@ void ai::do_move()
if(leader != units_.end()) {
if(!passive_leader) {
gamemap::location before = leader->first;
move_leader_to_keep(enemy_dstsrc);
leader = find_leader(units_,team_num_);
if (leader->first != before
&& leader->second.movement_left() > 0
&& recruiting_prefered_)
{
recruiting_prefered_ = 2;
do_move();
return;
}
}
if (map_.is_keep(leader->first))
@ -1211,7 +1227,7 @@ bool ai::do_combat(std::map<gamemap::location,paths>& possible_moves, const move
time_taken = SDL_GetTicks() - ticks;
LOG_AI << "analysis took " << time_taken << " ticks\n";
if(choice_rating > current_team().caution()) {
if(choice_rating > current_team().caution()/2) {
location from = choice_it->movements[0].first;
location to = choice_it->movements[0].second;
location target_loc = choice_it->target;
@ -1322,11 +1338,12 @@ bool ai::get_healing(std::map<gamemap::location,paths>& possible_moves,
typedef std::multimap<location,location>::const_iterator Itor;
std::pair<Itor,Itor> it = srcdst.equal_range(u_it->first);
double best_vulnerability = 100000.0;
const double leader_penalty = (u.can_recruit()?2.0:1.0);
Itor best_loc = it.second;
while(it.first != it.second) {
const location& dst = it.first->second;
if(map_.gives_healing(dst) && (units_.find(dst) == units_.end() || dst == u_it->first)) {
const double vuln = power_projection(it.first->first, enemy_dstsrc);
const double vuln = power_projection(it.first->first, enemy_dstsrc)*leader_penalty;
LOG_AI << "found village with vulnerability: " << vuln << "\n";
if(vuln < best_vulnerability) {
best_vulnerability = vuln;
@ -1339,7 +1356,8 @@ bool ai::get_healing(std::map<gamemap::location,paths>& possible_moves,
}
// If we have found an eligible village:
if(best_loc != it.second) {
if(best_loc != it.second
&& best_vulnerability < u.hitpoints()) {
const location& src = best_loc->first;
const location& dst = best_loc->second;

View file

@ -207,22 +207,24 @@ void ai::do_attack_analysis(
}
// See if this position is the best rated we've seen so far.
const int rating = rate_terrain(unit_itor->second,tiles[j]) * backstab_bonus;
if(cur_position >= 0 && rating < best_rating) {
int rating = rate_terrain(unit_itor->second,tiles[j]) * backstab_bonus;
if(cur_position >= 0 && rating < best_rating * 2) {
continue;
}
// Find out how vulnerable we are to attack from enemy units in this hex.
const double vulnerability = power_projection(tiles[j],enemy_dstsrc);
const double vulnerability = power_projection(tiles[j],enemy_dstsrc)*current_team().caution()*10;
// Calculate how much support we have on this hex from allies.
// Support does not take into account terrain, because we don't want
// to move into a hex that is surrounded by good defensive terrain.
const double support = power_projection(tiles[j],fullmove_dstsrc,false);
const double support = power_projection(tiles[j],fullmove_dstsrc,false)*current_team().aggression();
// If this is a position with equal defense to another position,
// but more vulnerability then we don't want to use it.
if(cur_position >= 0 && rating == best_rating && vulnerability/surround_bonus - support*surround_bonus >= best_vulnerability - best_support) {
const double leader_penalty = (unit_itor->second.can_recruit()? 1.4:1.0);
rating -= ((vulnerability/surround_bonus)*leader_penalty - support*surround_bonus);
if(cur_position >= 0 && rating < best_rating) {
continue;
}

View file

@ -822,7 +822,7 @@ void ai::move_leader_to_keep(const move_map& enemy_dstsrc)
{
// 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;
gamemap::location best_target;
// The leader can't move to his keep, try to move to the closest location
@ -832,12 +832,16 @@ void ai::move_leader_to_keep(const move_map& enemy_dstsrc)
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()))).first;
if (route->second.steps.empty())
{
path_itor->second.routes.erase(route);
continue;
}
const int distance = route->second.steps.size()-1;
std::set<gamemap::location> checked_hexes;
checked_hexes.insert(*i);
const int free_slots = count_free_hexes_in_castle(*i, checked_hexes);
@ -851,7 +855,34 @@ void ai::move_leader_to_keep(const move_map& enemy_dstsrc)
&& !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();
const int enemy = (power_projection(*i, enemy_dstsrc) * 15 * leader->second.total_movement())/leader->second.hitpoints();
int value = empty_slots + enemy + tactical_value + reserved_penalty;
if (value + static_cast<int>(route->second.steps.size()) - 1 >= best_value)
continue;
route->second.move_left = leader->second.movement_left();
int distance = 0;
gamemap::location target;
std::vector<gamemap::location>::iterator loc;
for (loc = route->second.steps.begin() + 1;
loc != route->second.steps.end();
++loc)
{
distance += leader->second.movement_cost(map_.get_terrain(*loc));
if (route->second.move_left == 0)
continue;
route->second.move_left -= leader->second.movement_cost(map_.get_terrain(*loc));
if (route->second.move_left <= 0)
{
target = *loc;
route->second.move_left = 0;
}
}
if (route->second.move_left > 0)
target = *(loc-1);
int multiturn_move_penalty = 0;
if (recruiting_prefered_)
@ -859,20 +890,11 @@ void ai::move_leader_to_keep(const move_map& enemy_dstsrc)
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;
gamemap::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 << "Considiring keep: " << *i <<
@ -888,7 +910,8 @@ void ai::move_leader_to_keep(const move_map& enemy_dstsrc)
}
// Find the location with the best value
if (leader->first != best_target)
if (leader->first != best_target
&& best_target != gamemap::location::null_location)
move_unit(leader->first,best_target,possible_moves);
}
}

View file

@ -344,7 +344,7 @@ void ai::find_villages(
}
const unit& un = u->second;
const size_t threat_multipler = (current_loc == leader_loc?2:1) * current_team().caution() * 10;
const size_t threat_multipler = (current_loc == leader_loc?4:1) * current_team().caution() * 4;
if(un.hitpoints() < (threat_multipler*threat*2*un.defense_modifier(map_.get_terrain(current_loc)))/100) {
continue;
}