simplified code, removed ai_default custom handling of...

...srcdst-like maps. This will make the code more robust, and fix some
'stale cache' issues
This commit is contained in:
Iurii Chernyi 2009-08-22 23:22:01 +00:00
parent 971c994a39
commit f177bd9488
5 changed files with 51 additions and 109 deletions

View file

@ -211,58 +211,58 @@ void attack_result::do_check_before()
if(attacker==NULL)
{
ERR_AI_ACTIONS << "attempt to attack without attacker\n";
LOG_AI_ACTIONS << "attempt to attack without attacker\n";
set_error(E_EMPTY_ATTACKER);
return;
}
if (defender==NULL)
{
ERR_AI_ACTIONS << "attempt to attack without defender\n";
LOG_AI_ACTIONS << "attempt to attack without defender\n";
set_error(E_EMPTY_DEFENDER);
return;
}
if(attacker->incapacitated()) {
ERR_AI_ACTIONS << "attempt to attack with unit that is petrified\n";
LOG_AI_ACTIONS << "attempt to attack with unit that is petrified\n";
set_error(E_INCAPACITATED_ATTACKER);
return;
}
if(defender->incapacitated()) {
ERR_AI_ACTIONS << "attempt to attack unit that is petrified\n";
LOG_AI_ACTIONS << "attempt to attack unit that is petrified\n";
set_error(E_INCAPACITATED_DEFENDER);
return;
}
if(!attacker->attacks_left()) {
ERR_AI_ACTIONS << "attempt to attack with no attacks left\n";
LOG_AI_ACTIONS << "attempt to attack with no attacks left\n";
set_error(E_NO_ATTACKS_LEFT);
return;
}
if(attacker->side()!=get_side()) {
ERR_AI_ACTIONS << "attempt to attack with not own unit\n";
LOG_AI_ACTIONS << "attempt to attack with not own unit\n";
set_error(E_NOT_OWN_ATTACKER);
return;
}
if(!get_my_team(get_info()).is_enemy(defender->side())) {
ERR_AI_ACTIONS << "attempt to attack unit that is not enemy\n";
LOG_AI_ACTIONS << "attempt to attack unit that is not enemy\n";
set_error(E_NOT_ENEMY_DEFENDER);
return;
}
if (attacker_weapon_!=-1) {
if ((attacker_weapon_<0)||(attacker_weapon_ > static_cast<int>(attacker->attacks().size()))) {
ERR_AI_ACTIONS << "invalid weapon selection for the attacker\n";
LOG_AI_ACTIONS << "invalid weapon selection for the attacker\n";
set_error(E_WRONG_ATTACKER_WEAPON);
return;
}
}
if (!tiles_adjacent(attacker_loc_,defender_loc_)) {
ERR_AI_ACTIONS << "attacker and defender not adjacent\n";
LOG_AI_ACTIONS << "attacker and defender not adjacent\n";
set_error(E_ATTACKER_AND_DEFENDER_NOT_ADJACENT);
return;
}

View file

@ -522,18 +522,6 @@ map_location ai_default::move_unit(map_location from, map_location to, bool &gam
}
void ai_default::remove_unit_from_moves(const map_location& loc, move_map& srcdst, move_map& dstsrc)
{
srcdst.erase(loc);
for(move_map::iterator i = dstsrc.begin(); i != dstsrc.end(); ) {
if(i->second == loc) {
dstsrc.erase(i++);
} else {
++i;
}
}
}
namespace {
/** A structure for storing an item we're trying to protect. */
@ -670,12 +658,6 @@ void ai_default::do_move()
raise_user_interact();
typedef std::map<location,paths> moves_map;
moves_map possible_moves, enemy_possible_moves;
move_map srcdst, dstsrc, enemy_srcdst, enemy_dstsrc;
calculate_possible_moves(possible_moves,srcdst,dstsrc,false,false,&get_avoid());
calculate_possible_moves(enemy_possible_moves,enemy_srcdst,enemy_dstsrc,true);
const bool passive_leader_shares_keep = get_passive_leader_shares_keep();
const bool passive_leader = get_passive_leader()||passive_leader_shares_keep;
@ -685,10 +667,6 @@ void ai_default::do_move()
if (leader != units_.end())
{
evaluate_recruiting_value(leader->first);
if (passive_leader)
{
remove_unit_from_moves(leader->first,srcdst,dstsrc);
}
}
// Execute goto-movements - first collect gotos in a list
@ -706,7 +684,7 @@ void ai_default::do_move()
unit_map::const_iterator ui = units_.find(*g);
int closest_distance = -1;
std::pair<location,location> closest_move;
for(move_map::const_iterator i = dstsrc.begin(); i != dstsrc.end(); ++i) {
for(move_map::const_iterator i = get_dstsrc().begin(); i != get_dstsrc().end(); ++i) {
if(i->second != ui->first) {
continue;
}
@ -729,20 +707,18 @@ void ai_default::do_move()
}
std::vector<attack_analysis> analysis;
LOG_AI << "combat phase\n";
if(consider_combat_) {
LOG_AI << "combat...\n";
consider_combat_ = do_combat(possible_moves,srcdst,dstsrc,enemy_srcdst,enemy_dstsrc);
consider_combat_ = do_combat();
if(consider_combat_) {
do_move();
return;
}
}
move_leader_to_goals(enemy_dstsrc);
move_leader_to_goals();
LOG_AI << "get villages phase\n";
@ -750,13 +726,13 @@ void ai_default::do_move()
leader = units_.find_leader(get_side());
LOG_AI << "villages...\n";
if(get_villages(possible_moves, dstsrc, enemy_dstsrc, leader)) {
if(get_villages(get_possible_moves(),get_dstsrc(),get_enemy_dstsrc(),leader)) {
do_move();
return;
}
LOG_AI << "healing...\n";
const bool healed_unit = get_healing(possible_moves,srcdst,enemy_dstsrc);
const bool healed_unit = get_healing();
if(healed_unit) {
do_move();
return;
@ -767,21 +743,17 @@ void ai_default::do_move()
LOG_AI << "retreating...\n";
leader = units_.find_leader(get_side());
const bool retreated_unit = retreat_units(possible_moves,srcdst,dstsrc,enemy_dstsrc,leader);
const bool retreated_unit = retreat_units(leader);
if(retreated_unit) {
do_move();
return;
}
if(leader != units_.end()) {
remove_unit_from_moves(leader->first,srcdst,dstsrc);
}
find_threats();
LOG_AI << "move/targeting phase\n";
const bool met_invisible_unit = move_to_targets(possible_moves,srcdst,dstsrc,enemy_dstsrc,leader);
const bool met_invisible_unit = move_to_targets(leader);
if(met_invisible_unit) {
LOG_AI << "met_invisible_unit\n";
do_move();
@ -796,7 +768,7 @@ void ai_default::do_move()
if(leader != units_.end()) {
if(!passive_leader||passive_leader_shares_keep) {
map_location before = leader->first;
move_leader_to_keep(enemy_dstsrc);
move_leader_to_keep();
leader = units_.find_leader(get_side());
if(leader == units_.end()) {
return;
@ -826,13 +798,12 @@ void ai_default::do_move()
}
if(!passive_leader||passive_leader_shares_keep) {
move_leader_after_recruit(srcdst,dstsrc,enemy_dstsrc);
move_leader_after_recruit();
}
}
}
bool ai_default::do_combat(std::map<map_location,paths>& /*possible_moves*/, const move_map& /*srcdst*/,
const move_map& /*dstsrc*/, const move_map& /*enemy_srcdst*/, const move_map& /*enemy_dstsrc*/)
bool ai_default::do_combat()
{
const std::vector<attack_analysis> &analysis = get_attacks();
@ -928,8 +899,7 @@ bool ai_default::do_combat(std::map<map_location,paths>& /*possible_moves*/, con
}
bool ai_default::get_healing(std::map<map_location,paths>& /*possible_moves*/,
const move_map& srcdst, const move_map& enemy_dstsrc)
bool ai_default::get_healing()
{
// Find units in need of healing.
unit_map::iterator u_it = units_.begin();
@ -946,7 +916,7 @@ bool ai_default::get_healing(std::map<map_location,paths>& /*possible_moves*/,
{
// Look for the village which is the least vulnerable to enemy attack.
typedef std::multimap<location,location>::const_iterator Itor;
std::pair<Itor,Itor> it = srcdst.equal_range(u_it->first);
std::pair<Itor,Itor> it = get_srcdst().equal_range(u_it->first);
double best_vulnerability = 100000.0;
// Make leader units more unlikely to move to vulnerable villages
const double leader_penalty = (u.can_recruit()?2.0:1.0);
@ -954,7 +924,7 @@ bool ai_default::get_healing(std::map<map_location,paths>& /*possible_moves*/,
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, get_enemy_dstsrc());
LOG_AI << "found village with vulnerability: " << vuln << "\n";
if(vuln < best_vulnerability) {
best_vulnerability = vuln;
@ -1005,9 +975,7 @@ bool ai_default::should_retreat(const map_location& loc, const unit_map::const_i
return caution*their_power*(1.0+exposure) > our_power;
}
bool ai_default::retreat_units(std::map<map_location,paths>& /*possible_moves*/,
const move_map& srcdst, const move_map& dstsrc,
const move_map& enemy_dstsrc, unit_map::const_iterator leader)
bool ai_default::retreat_units(unit_map::const_iterator leader)
{
// Get versions of the move map that assume that all units are at full movement
std::map<map_location,paths> dummy_possible_moves;
@ -1031,7 +999,7 @@ bool ai_default::retreat_units(std::map<map_location,paths>& /*possible_moves*/,
// We see the amount of power of each side on the situation,
// and decide whether it should retreat.
if(should_retreat(i->first, i, fullmove_srcdst, fullmove_dstsrc,
enemy_dstsrc, get_caution())) {
get_enemy_dstsrc(), get_caution())) {
bool can_reach_leader = false;
@ -1040,7 +1008,7 @@ bool ai_default::retreat_units(std::map<map_location,paths>& /*possible_moves*/,
// If we can't find anywhere where we like the power balance,
// just try to get to the best defensive hex.
typedef move_map::const_iterator Itor;
std::pair<Itor,Itor> itors = srcdst.equal_range(i->first);
std::pair<Itor,Itor> itors = get_srcdst().equal_range(i->first);
map_location best_pos, best_defensive(i->first);
double best_rating = 0.0;
int best_defensive_rating = i->second.defense_modifier(map_.get_terrain(i->first))
@ -1059,8 +1027,8 @@ bool ai_default::retreat_units(std::map<map_location,paths>& /*possible_moves*/,
// chance to hit us on the hex we're planning to flee to.
const map_location& hex = itors.first->second;
const int defense = i->second.defense_modifier(map_.get_terrain(hex));
const double our_power = power_projection(hex,dstsrc);
const double their_power = power_projection(hex,enemy_dstsrc) * double(defense)/100.0;
const double our_power = power_projection(hex,get_dstsrc());
const double their_power = power_projection(hex,get_enemy_dstsrc()) * double(defense)/100.0;
const double rating = our_power - their_power;
if(rating > best_rating) {
best_pos = hex;
@ -1117,9 +1085,7 @@ bool ai_default::retreat_units(std::map<map_location,paths>& /*possible_moves*/,
return false;
}
bool ai_default::move_to_targets(std::map<map_location, paths>& possible_moves,
move_map& srcdst, move_map& dstsrc, const move_map& /*enemy_dstsrc*/,
unit_map::const_iterator leader)
bool ai_default::move_to_targets(unit_map::const_iterator leader)
{
LOG_AI << "finding targets...\n";
std::vector<target> targets;
@ -1155,21 +1121,6 @@ bool ai_default::move_to_targets(std::map<map_location, paths>& possible_moves,
bool gamestate_changed = false;
const map_location arrived_at = move_unit(move.first,move.second,gamestate_changed);
const unit_map::const_iterator u_it = units_.find(arrived_at);
// Event could have done anything: check
if (u_it.valid()) {
// Don't allow any other units to move onto the tile
// our unit just moved onto
typedef move_map::iterator Itor;
std::pair<Itor,Itor> del = dstsrc.equal_range(arrived_at);
dstsrc.erase(del.first,del.second);
for (move_map::iterator i = srcdst.begin(); i!= srcdst.end(); ++i){
if (i->second==arrived_at) {
srcdst.erase(i);
}
}
}
// We didn't arrive at our intended destination.
// We return true, meaning that the AI algorithm
// should be recalculated from the start.
@ -1584,7 +1535,7 @@ bool ai_default_recruitment_stage::do_play_stage()
}
void ai_default::move_leader_to_goals( const move_map& enemy_dstsrc)
void ai_default::move_leader_to_goals()
{
const config &goal = get_leader_goal();
@ -1631,7 +1582,7 @@ void ai_default::move_leader_to_goals( const move_map& enemy_dstsrc)
foreach (const map_location &l, route.steps)
{
if (leader_paths.destinations.contains(l) &&
power_projection(l, enemy_dstsrc) < double(leader->second.hitpoints() / 2))
power_projection(l, get_enemy_dstsrc()) < double(leader->second.hitpoints() / 2))
{
loc = l;
}
@ -1647,8 +1598,7 @@ void ai_default::move_leader_to_goals( const move_map& enemy_dstsrc)
}
}
void ai_default::move_leader_after_recruit(const move_map& /*srcdst*/,
const move_map& /*dstsrc*/, const move_map& enemy_dstsrc)
void ai_default::move_leader_after_recruit()
{
unit_map::iterator leader = units_.find_leader(get_side());
@ -1665,9 +1615,9 @@ void ai_default::move_leader_after_recruit(const move_map& /*srcdst*/,
std::map<map_location,paths> possible_moves;
possible_moves.insert(std::pair<map_location,paths>(leader->first,leader_paths));
if(!passive_leader && current_team().gold() < 20 && is_accessible(leader->first,enemy_dstsrc) == false) {
if(!passive_leader && current_team().gold() < 20 && is_accessible(leader->first,get_enemy_dstsrc()) == false) {
// See if we want to ward any enemy units off from getting our villages.
for(move_map::const_iterator i = enemy_dstsrc.begin(); i != enemy_dstsrc.end(); ++i) {
for(move_map::const_iterator i = get_enemy_dstsrc().begin(); i != get_enemy_dstsrc().end(); ++i) {
// If this is a village of ours, that an enemy can capture
// on their turn, and which we might be able to reach in two turns.
@ -1681,7 +1631,7 @@ void ai_default::move_leader_after_recruit(const move_map& /*srcdst*/,
{
const int distance = distance_between(i->first, dest.curr);
if (distance < current_distance &&
!is_accessible(dest.curr, enemy_dstsrc))
!is_accessible(dest.curr, get_enemy_dstsrc()))
{
current_distance = distance;
current_loc = dest.curr;
@ -1746,7 +1696,7 @@ void ai_default::move_leader_after_recruit(const move_map& /*srcdst*/,
// our leader can move to, and no enemies can reach.
if (map_.on_board(adj[n]) &&
leader_paths.destinations.contains(adj[n]) &&
!is_accessible(adj[n], enemy_dstsrc))
!is_accessible(adj[n], get_enemy_dstsrc()))
{
bool gamestate_changed = false;
map_location new_loc = move_unit(keep,adj[n],gamestate_changed);
@ -1769,7 +1719,7 @@ void ai_default::move_leader_after_recruit(const move_map& /*srcdst*/,
move_map fullmove_dstsrc;
calculate_possible_moves(dummy_possible_moves,fullmove_srcdst,fullmove_dstsrc,false,true,&get_avoid());
if (should_retreat(leader->first, leader, fullmove_srcdst, fullmove_dstsrc, enemy_dstsrc, 0.5)) {
if (should_retreat(leader->first, leader, fullmove_srcdst, fullmove_dstsrc, get_enemy_dstsrc(), 0.5)) {
desperate_attack(leader->first);
}
}

View file

@ -132,20 +132,14 @@ protected:
virtual void do_move();
virtual bool do_combat(std::map<map_location,paths>& possible_moves,
const move_map& srcdst, const move_map& dstsrc,
const move_map& enemy_srcdst, const move_map& enemy_dstsrc);
virtual bool get_villages(std::map<map_location,paths>& possible_moves,
const move_map& dstsrc, const move_map& enemy_dstsrc,
unit_map::iterator &leader);
virtual bool get_healing(std::map<map_location,paths>& possible_moves,
const move_map& srcdst, const move_map& enemy_dstsrc);
virtual bool retreat_units(std::map<map_location,paths>& possible_moves,
const move_map& srcdst, const move_map& dstsrc,
const move_map& enemy_dstsrc, unit_map::const_iterator leader);
virtual bool move_to_targets(std::map<map_location,paths>& possible_moves,
move_map& srcdst, move_map& dstsrc, const move_map& enemy_dstsrc,
unit_map::const_iterator leader);
virtual bool do_combat();
virtual bool get_villages(const std::map<map_location,paths>& possible_moves,
const move_map& dstsrc, const move_map& enemy_dstsrc,
unit_map::iterator &leader);
virtual bool get_healing();
virtual bool retreat_units(const unit_map::const_iterator leader);
virtual bool move_to_targets(const unit_map::const_iterator leader);
unit_map::const_iterator leader;
virtual bool should_retreat(const map_location& loc,
const unit_map::const_iterator un, const move_map& srcdst,
@ -153,17 +147,15 @@ protected:
virtual bool do_recruitment();
virtual void move_leader_to_keep(const move_map& enemy_dstsrc);
virtual void move_leader_after_recruit(const move_map& srcdst,
const move_map& dstsrc, const move_map& enemy_dstsrc);
virtual void move_leader_to_keep();
virtual void move_leader_to_goals(const move_map& enemy_dstsrc);
virtual void move_leader_after_recruit();
virtual void move_leader_to_goals();
virtual bool desperate_attack(const map_location &loc);
void remove_unit_from_moves(const map_location& u, move_map& srcdst, move_map& dstsrc);
/** Find enemy units that threaten our valuable assets. */
void find_threats();

View file

@ -716,7 +716,7 @@ void ai_default::access_points(const move_map& srcdst, const location& u, const
}
void ai_default::move_leader_to_keep(const move_map& enemy_dstsrc)
void ai_default::move_leader_to_keep()
{
const unit_map::iterator leader = units_.find_leader(get_side());
if(leader == units_.end() || leader->second.incapacitated()) {
@ -760,7 +760,7 @@ void ai_default::move_leader_to_keep(const move_map& enemy_dstsrc)
for(std::multimap<int,map_location>::const_iterator j = moves_toward_keep.begin();
j != moves_toward_keep.end(); ++j) {
if(enemy_dstsrc.count(j->second) == 0) {
if(get_enemy_dstsrc().count(j->second) == 0) {
bool gamestate_changed = false;
move_unit(leader->first,j->second,gamestate_changed);
if (!gamestate_changed) {

View file

@ -153,7 +153,7 @@ static void full_dispatch(treachmap& reachmap, tmoves& moves);
/** Shows which villages every unit can reach (debug function). */
static void dump_reachmap(treachmap& reachmap);
bool ai_default::get_villages(std::map<map_location,paths>& possible_moves,
bool ai_default::get_villages(const std::map<map_location,paths>& possible_moves,
const move_map& dstsrc, const move_map& enemy_dstsrc,
unit_map::iterator &leader)
{