AI improvements:

- made AI not leave its units idle when it has a large number of units

- AI will try to defend its leader better
This commit is contained in:
uid68803 2004-02-06 05:38:34 +00:00
parent 3b60f0443d
commit a4d0c5e8fd
4 changed files with 66 additions and 9 deletions

View file

@ -537,12 +537,15 @@ bool ai::retreat_units(std::map<gamemap::location,paths>& possible_moves, const
void ai::move_to_targets(std::map<gamemap::location,paths>& possible_moves, move_map& srcdst, move_map& dstsrc, const move_map& enemy_srcdst, const move_map& enemy_dstsrc, unit_map::const_iterator leader)
{
std::cerr << "finding targets...\n";
std::vector<target> targets = find_targets(leader != units_.end());
targets.insert(targets.end(),additional_targets_.begin(),
additional_targets_.end());
std::vector<target> targets;
for(;;) {
if(targets.empty()) {
break;
targets = find_targets(leader,enemy_srcdst,enemy_dstsrc);
targets.insert(targets.end(),additional_targets_.begin(),
additional_targets_.end());
if(targets.empty()) {
return;
}
}
std::cerr << "choosing move...\n";

View file

@ -34,6 +34,9 @@ public:
void do_move();
team& current_team();
const team& current_team() const;
private:
void do_attack(const location& u, const location& target, int weapon);
@ -53,8 +56,6 @@ private:
bool recruit(const std::string& usage);
void move_unit(const location& from, const location& to, std::map<location,paths>& possible_moves);
team& current_team();
const team& current_team() const;
void calculate_possible_moves(std::map<location,paths>& moves, move_map& srcdst, move_map& dstsrc, bool enemy, bool assume_full_movement=false);
@ -97,7 +98,12 @@ private:
//the strength of its most powerful attack
double counter_strength_ratio;
//the vulnerability is the power projection of enemy units onto the hex
//we're standing on. support is the power projection of friendly units.
double vulnerability, support;
//is true if the unit is a threat to our leader
bool leader_threat;
};
void do_attack_analysis(
@ -131,7 +137,7 @@ private:
double value;
};
std::vector<target> find_targets(bool has_leader);
std::vector<target> find_targets(unit_map::const_iterator leader, const move_map& enemy_srcdst, const move_map& enemy_dstsrc);
std::pair<location,location> choose_move(std::vector<target>& targets,const move_map& dstsrc, const move_map& enemy_srcdst, const move_map& enemy_dstsrc);

View file

@ -225,9 +225,22 @@ void ai::attack_analysis::analyze(const gamemap& map,
const gamestatus& status,
const game_data& info, int num_sims, ai& ai_obj)
{
const std::map<location,unit>::const_iterator defend_it = units.find(target);
const unit_map::const_iterator defend_it = units.find(target);
assert(defend_it != units.end());
//see if the target is a threat to our leader or an ally's leader
gamemap::location adj[6];
get_adjacent_tiles(target,adj);
size_t tile;
for(tile = 0; tile != 6; ++tile) {
const unit_map::const_iterator leader = units.find(adj[tile]);
if(leader != units.end() && leader->second.can_recruit() && ai_obj.current_team().is_enemy(leader->second.side()) == false) {
break;
}
}
leader_threat = (tile != 6);
target_value = defend_it->second.type().cost();
target_value += (double(defend_it->second.experience())/
double(defend_it->second.max_experience()))*target_value;
@ -384,6 +397,10 @@ void ai::attack_analysis::analyze(const gamemap& map,
double ai::attack_analysis::rating(double aggression) const
{
if(leader_threat) {
aggression = 1.0;
}
double value = chance_to_kill*target_value - avg_losses;
//prefer to attack already damaged targets
@ -395,6 +412,10 @@ double ai::attack_analysis::rating(double aggression) const
value /= ((resources_used/2) + (resources_used/2)*terrain_quality);
if(leader_threat) {
value *= 5.0;
}
return value;
}

View file

@ -89,12 +89,39 @@ private:
};
std::vector<ai::target> ai::find_targets(bool has_leader)
std::vector<ai::target> ai::find_targets(unit_map::const_iterator leader, const move_map& enemy_srcdst, const move_map& enemy_dstsrc)
{
log_scope("finding targets...");
const bool has_leader = leader != units_.end();
std::vector<target> targets;
//if enemy units are in range of the leader, then we rally to the leader's defense
if(has_leader) {
const double threat = power_projection(leader->first,enemy_srcdst,enemy_dstsrc);
if(threat > 0.0) {
//find the specific tiles the enemy can reach, and set them as targets
std::vector<gamemap::location> threatened_tiles;
gamemap::location adj[6];
get_adjacent_tiles(leader->first,adj);
for(size_t n = 0; n != 6; ++n) {
if(enemy_dstsrc.count(adj[n]) > 0) {
threatened_tiles.push_back(adj[n]);
}
}
assert(threatened_tiles.size() > 0);
//divide the threat into the tiles the enemy can reach, and try to
//get units to reach those tiles
const double value = threat/double(threatened_tiles.size());
for(std::vector<gamemap::location>::const_iterator i = threatened_tiles.begin(); i != threatened_tiles.end(); ++i) {
targets.push_back(target(*i,value));
}
}
}
if(has_leader && current_team().village_value() > 0.0) {
const std::vector<location>& towers = map_.towers();
for(std::vector<location>::const_iterator t = towers.begin(); t != towers.end(); ++t) {