37 #define LOG_AI LOG_STREAM(info, log_ai)
38 #define ERR_AI LOG_STREAM(err, log_ai)
45 const move_map& enemy_dstsrc,
double aggression)
48 assert(defend_it != units.
end());
53 for(tile = 0; tile < adj.size(); ++tile) {
64 const unsigned int defend_experience = defend_it->can_advance() ? defend_it->experience() : 0;
66 static_cast<double>(defend_it->max_experience()))*
target_value;
68 defend_it->hitpoints();
75 double cost_sum = 0.0;
78 const double cost = att->cost();
91 double def_avg_experience = 0.0;
92 double first_chance_kill = 0.0;
94 double prob_dead_already = 0.0;
96 std::vector<std::pair<map_location,map_location>>::const_iterator m;
98 std::unique_ptr<battle_context> bc(
nullptr);
99 std::unique_ptr<battle_context> old_bc(
nullptr);
106 up->set_location(m->second);
108 double m_aggression = aggression;
110 if (up->can_recruit()) {
117 bool from_cache =
false;
126 const readonly_context::unit_stats_cache_t::key_type cache_key = std::pair(
target, &up->
type());
130 usc->second.first.attack_num <
131 static_cast<int>(up->attacks().size())) {
134 bc.reset(
new battle_context(usc->second.first, usc->second.second));
138 const combatant &att = bc->get_attacker_combatant(prev_def);
139 const combatant &def = bc->get_defender_combatant(prev_def);
141 prev_def = &bc->get_defender_combatant(prev_def);
144 old_bc.reset(
nullptr);
148 bc->get_attacker_stats(),
149 bc->get_defender_stats()
154 double prob_fought = (1.0 - prob_dead_already);
156 double prob_killed = def.
hp_dist[0] - prob_dead_already;
157 prob_dead_already = def.
hp_dist[0];
159 double prob_died = att.
hp_dist[0];
160 double prob_survived = (1.0 - prob_died) * prob_fought;
162 double cost = up->cost();
163 const bool on_village = map.
is_village(m->second);
165 const unsigned int up_experience = up->can_advance() ? up->experience() : 0;
166 cost += (
static_cast<double>(up_experience) / up->max_experience())*cost;
173 if (!bc->get_defender_stats().is_poisoned) {
182 terrain_quality += (
static_cast<double>(bc->get_defender_stats().chance_to_hit)/100.0)*cost * (on_village ? 0.5 : 1.0);
184 double advance_prob = 0.0;
186 if (!up->advances_to().empty()) {
187 int xp_for_advance = up->experience_to_advance();
191 if (xp_for_advance == 0)
197 if (fight_xp >= xp_for_advance) {
198 advance_prob = prob_fought;
200 }
else if (
kill_xp >= xp_for_advance) {
201 advance_prob = prob_killed;
210 fight_xp * (prob_fought - prob_killed)
214 (
kill_xp * prob_killed + fight_xp * (prob_fought - prob_killed))
220 if (bc->get_attacker_stats().plagues) {
232 first_chance_kill = def.
hp_dist[0];
236 if (!defend_it->advances_to().empty() &&
237 def_avg_experience >= defend_it->experience_to_advance()) {
251 units.
move(m->second, m->first);
258 for(std::set<map_location>::const_iterator
i = attacks.begin();
i != attacks.end(); ++
i) {
288 LOG_AI <<
"attack option has base value " << value <<
" with exposure " << exposure <<
": "
290 value -= exposure*(1.0-aggression);
Various functions that implement attacks and attack calculations.
Managing the AI-Game interaction - AI actions and their results.
static lg::log_domain log_ai("ai/attack")
Managing the AIs lifecycle - headers TODO: Refactor history handling and internal commands.
std::vector< std::pair< map_location, map_location > > movements
void analyze(const gamemap &map, unit_map &units, const readonly_context &ai_obj, const move_map &dstsrc, const move_map &srcdst, const move_map &enemy_dstsrc, double aggression)
bool uses_leader
Is true if this attack sequence makes use of the leader.
double target_value
The value of the unit being targeted.
double avg_damage_inflicted
The average hitpoints damage inflicted.
double chance_to_kill
Estimated % chance to kill the unit.
bool attack_close(const map_location &loc) const
double terrain_quality
The weighted average of the % chance to hit each attacking unit.
double avg_damage_taken
The average hitpoints damage taken.
double alternative_terrain_quality
The weighted average of the % defense of the best possible terrain that the attacking units could rea...
bool leader_threat
Is true if the unit is a threat to our leader.
double avg_losses
The value on average, of units lost in the combat.
double vulnerability
The vulnerability is the power projection of enemy units onto the hex we're standing on.
double resources_used
The sum of the values of units used in the attack.
double rating(double aggression, const readonly_context &ai_obj) const
int target_starting_damage
bool is_surrounded
Is true if the units involved in this attack sequence are surrounded.
std::set< map_location > recent_attacks
static manager & get_singleton()
game_info & get_ai_info()
Gets global AI-game info.
virtual const defensive_position & best_defensive_position(const map_location &unit, const move_map &dstsrc, const move_map &srcdst, const move_map &enemy_dstsrc) const =0
virtual unit_stats_cache_t & unit_stats_cache() const =0
virtual const team & current_team() const =0
virtual double get_caution() const =0
virtual double get_leader_aggression() const =0
Computes the statistics of a battle between an attacker and a defender unit.
Encapsulates the map of the game.
bool is_village(const map_location &loc) const
int gives_healing(const map_location &loc) const
bool is_enemy(int n) const
Container associating units to locations.
unit_ptr extract(const map_location &loc)
Extracts a unit from the map.
unit_iterator find(std::size_t id)
umap_retval_pair_t insert(const unit_ptr &p)
Inserts the unit pointed to by p into the map.
umap_retval_pair_t move(const map_location &src, const map_location &dst)
Moves a unit from location src to location dst.
@ STATE_POISONED
The unit is slowed - it moves slower and does less damage.
std::size_t distance_between(const map_location &a, const map_location &b)
Function which gives the number of hexes between two tiles (i.e.
void get_adjacent_tiles(const map_location &a, utils::span< map_location, 6 > res)
Function which, given a location, will place all adjacent locations in res.
Standard logging facilities (interface).
A small explanation about what's going on here: Each action has access to two game_info objects First...
std::multimap< map_location, map_location > move_map
The standard way in which a map of possible moves is recorded.
std::string::const_iterator iterator
std::shared_ptr< unit > unit_ptr
std::vector< double > hp_dist
Resulting probability distribution (might be not as large as max_hp)
double average_hp(unsigned int healing=0) const
What's the average hp (weighted average of hp_dist).
Encapsulates the map of the game.