38 #include <boost/dynamic_bitset.hpp> 40 #include <SDL2/SDL_timer.h> 43 #define DBG_AI_TESTING_AI_DEFAULT LOG_STREAM(debug, log_ai_testing_ai_default) 44 #define LOG_AI_TESTING_AI_DEFAULT LOG_STREAM(info, log_ai_testing_ai_default) 45 #define WRN_AI_TESTING_AI_DEFAULT LOG_STREAM(warn, log_ai_testing_ai_default) 46 #define ERR_AI_TESTING_AI_DEFAULT LOG_STREAM(err, log_ai_testing_ai_default) 50 namespace ai_default_rca {
67 std::vector<map_location> gotos;
72 if (ui->get_goto() == ui->get_location()) {
75 gotos.push_back(ui->get_location());
79 for(std::vector<map_location>::const_iterator
g = gotos.begin();
g != gotos.end(); ++
g) {
96 route =
pathfind::a_star_search(ui->get_location(), ui->get_goto(), 10000.0, calc, map_.
w(), map_.
h(), &allowed_teleports);
98 if (!route.
steps.empty()){
105 int closest_distance = -1;
106 std::pair<map_location,map_location> closest_move;
108 if(
i->second != ui->get_location()) {
112 if(closest_distance == -1 || distance < closest_distance) {
113 closest_distance = distance;
117 if(closest_distance != -1) {
124 if (
move_->is_ok()) {
139 if (!
move_->is_ok()){
146 if (!
move_->is_gamestate_changed()){
170 int ticks = SDL_GetTicks();
172 const std::vector<attack_analysis> analysis =
get_attacks();
174 int time_taken = SDL_GetTicks() - ticks;
176 <<
" positions. Analyzing...";
178 ticks = SDL_GetTicks();
180 const int max_sims = 50000;
181 int num_sims = analysis.empty() ? 0 : max_sims/analysis.size();
189 const int max_positions = 30000;
190 const int skip_num = analysis.size()/max_positions;
192 std::vector<attack_analysis>::const_iterator choice_it = analysis.end();
193 for(std::vector<attack_analysis>::const_iterator it = analysis.begin();
194 it != analysis.end(); ++it) {
196 if(skip_num > 0 && ((it - analysis.begin())%skip_num) && it->movements.size() > 1)
204 bool skip_attack =
false;
205 for(std::size_t
i = 0;
i != it->movements.size(); ++
i) {
225 time_taken = SDL_GetTicks() - ticks;
248 if (!move_res->is_ok()) {
255 if (!attack_res->is_ok()) {
258 attack_res->execute();
259 if (!attack_res->is_ok()) {
292 double max_risk = goal[
"max_risk"].to_double(1 -
get_caution());
303 if (leaders.empty()) {
307 const unit* leader =
nullptr;
309 if (!l_itor->incapacitated() && l_itor->movement_left() > 0 &&
is_allowed_unit(*l_itor)) {
315 if (leader ==
nullptr) {
320 id_ = goal[
"id"].str();
327 if (
move_->is_ok()) {
339 if(route.
steps.empty()) {
346 std::map<map_location,pathfind::paths> possible_moves;
347 possible_moves.emplace(leader->
get_location(), leader_paths);
361 if (
move_->is_ok()) {
372 if (!
move_->is_ok()){
387 mod_ai[
"path"] =
"aspect[leader_goal].facet["+
id+
"]";
388 mod_ai[
"action"] =
"delete";
421 if (leaders.empty()) {
426 const unit* best_leader =
nullptr;
428 int shortest_distance = 99999;
437 const ai::moves_map::const_iterator& p_it = possible_moves.find(leader->get_location());
438 if (p_it == possible_moves.end()) {
455 if (!route.
steps.empty() || route.
move_cost < shortest_distance) {
456 best_leader = &(*leader);
462 if (best_leader ==
nullptr) {
467 const unit* leader = best_leader;
475 if (
move_->is_ok()) {
485 typedef std::multimap<int, map_location> ordered_locations;
486 ordered_locations moves_toward_keep;
493 int next_hop_cost = 0;
504 moves_toward_keep.emplace(0, next_hop);
518 for (
const ordered_locations::value_type& pair : moves_toward_keep) {
522 if (
move_->is_ok()) {
533 if (!
move_->is_ok()) {
571 std::pair<map_location,map_location> leader_move;
573 for(tmoves::const_iterator
i =
moves_.begin();
i !=
moves_.end(); ++
i) {
575 if(leader != units_.
end() && leader->get_location() ==
i->second) {
580 if (!move_res->is_ok()) {
588 if (new_unit != units_.
end() &&
597 if(leader_move.second.valid()) {
601 if (!move_res->is_ok()) {
616 const int ticks = SDL_GetTicks();
618 if(leader != units_.
end()) {
631 u_itor != units_.
end(); ++u_itor) {
636 reachmap.emplace(u_itor->get_location(), std::vector<map_location>());
645 while(itor != reachmap.end()) {
646 if(itor->second.empty()) {
653 if(!reachmap.empty()) {
655 "can't reach a village, send the to the dispatcher.";
665 <<
" ms, resulted in " <<
moves_.size() <<
" units being dispatched.";
672 const std::multimap<map_location,map_location>& dstsrc,
673 const std::multimap<map_location,map_location>& enemy_dstsrc)
676 std::map<map_location, double> vulnerability;
678 std::size_t min_distance = 100000;
684 std::vector<map_location> dispatched_units;
685 for(std::multimap<map_location, map_location>::const_iterator
687 j != dstsrc.end(); ++j) {
693 if(distance < min_distance) {
694 min_distance = distance;
699 if(std::find(dispatched_units.begin(), dispatched_units.end(),
700 j->second) != dispatched_units.end()) {
708 bool want_village =
true, owned =
false;
709 for(std::size_t
n = 0;
n != teams_.size(); ++
n) {
710 owned = teams_[
n].owns_village(current_loc);
712 want_village =
false;
720 if(want_village ==
false) {
731 const std::map<map_location,double>::const_iterator vuln = vulnerability.find(current_loc);
732 if(vuln != vulnerability.end()) {
733 threat = vuln->second;
736 vulnerability.emplace(current_loc, threat);
754 std::multimap<map_location, map_location>::const_iterator next = j;
756 const bool at_begin = (j == dstsrc.begin());
757 std::multimap<map_location, map_location>::const_iterator
prev = j;
762 if((next == dstsrc.end() || next->first != current_loc)
763 && (at_begin || prev->first != current_loc)) {
766 if (move_check_res->is_ok()) {
768 moves.emplace_back(j->first, j->second);
770 reachmap.erase(j->second);
771 dispatched_units.push_back(j->second);
775 reachmap[j->second].push_back(current_loc);
779 << reachmap.size() <<
" left to evaluate.";
793 std::size_t village_count = 0;
794 bool dispatched =
true;
801 if(reachmap.empty()) {
812 if(reachmap.empty()) {
820 if(!reachmap.empty() && dispatched) {
827 if(reachmap.empty()) {
833 << village_count <<
" villages left.";
847 while(itor != reachmap.end()) {
848 if(itor->second.size() == 1) {
853 moves.emplace_back(village, itor->first);
854 reachmap.erase(itor++);
857 itor = reachmap.begin();
866 if(reachmap.empty()) {
871 if(reachmap.size() == 1) {
874 <<
" to village " << reachmap.begin()->second[0];
876 moves.emplace_back(reachmap.begin()->second[0], reachmap.begin()->first);
891 bool dispatched =
true;
897 std::vector<map_location >>reversemap;
899 treachmap::const_iterator itor = reachmap.begin();
900 for(;itor != reachmap.end(); ++itor) {
902 for(std::vector<map_location>::const_iterator
903 v_itor = itor->second.begin();
904 v_itor != itor->second.end(); ++v_itor) {
906 reversemap[*v_itor].push_back(itor->first);
911 village_count = reversemap.size();
913 itor = reversemap.begin();
914 while(itor != reversemap.end()) {
915 if(itor->second.size() == 1) {
917 const map_location village = itor->first;
922 moves.emplace_back(itor->first, itor->second[0]);
924 reachmap.erase(itor->second[0]);
943 while(itor != reachmap.end()) {
944 itor->second.erase(
std::remove(itor->second.begin(), itor->second.end(), village), itor->second.end());
945 if(itor->second.empty()) {
958 assert(unit->second.empty());
967 reachmap.erase(unit++);
976 const std::size_t unit_count = reachmap.size();
978 const std::size_t max_result = unit_count < village_count ? unit_count : village_count;
980 assert(unit_count >= 2 && village_count >= 2);
983 if(unit_count == 2 && village_count == 2) {
989 std::vector<map_location> units(unit_count);
990 std::vector<std::size_t> villages_per_unit(unit_count);
991 std::vector<map_location> villages;
992 std::vector<std::size_t> units_per_village(village_count);
996 std::multimap<std::size_t ,
997 std::size_t > unit_lookup;
999 std::vector<
boost::dynamic_bitset<>> matrix(reachmap.size(), boost::dynamic_bitset<>(village_count));
1001 treachmap::const_iterator itor = reachmap.begin();
1002 for(std::size_t u = 0; u < unit_count; ++u, ++itor) {
1003 units[u] = itor->first;
1004 villages_per_unit[u] = itor->second.size();
1005 unit_lookup.emplace(villages_per_unit[u], u);
1007 assert(itor->second.size() >= 2);
1009 for(std::size_t v = 0; v < itor->second.size(); ++v) {
1011 std::size_t v_index;
1013 std::vector<map_location>::const_iterator v_itor =
1014 std::find(villages.begin(), villages.end(), itor->second[v]);
1015 if(v_itor == villages.end()) {
1016 v_index = villages.size();
1017 villages.push_back(itor->second[v]);
1019 v_index = v_itor - villages.begin();
1022 units_per_village[v_index]++;
1024 matrix[u][v_index] =
true;
1027 for(std::vector<std::size_t>::const_iterator upv_it = units_per_village.begin();
1028 upv_it != units_per_village.end(); ++upv_it) {
1030 assert(*upv_it >=2);
1037 for(v = 0; v < village_count; ++v) {
1043 for(u = 0; u < unit_count; ++u) {
1046 for(v = 0; v < village_count; ++v) {
1054 for(v = 0; v < village_count; ++v) {
1061 const bool reach_all = ((village_count == unit_count)
1062 && (std::accumulate(villages_per_unit.begin(), villages_per_unit.end(), std::size_t())
1063 == (village_count * unit_count)));
1073 std::multimap<std::size_t , std::size_t >
1074 ::const_iterator src_itor = unit_lookup.begin();
1076 while(src_itor != unit_lookup.end() && src_itor->first == 2) {
1078 for(std::multimap<std::size_t, std::size_t>::const_iterator
1079 dst_itor = unit_lookup.begin();
1080 dst_itor != unit_lookup.end(); ++ dst_itor) {
1083 if(src_itor == dst_itor) {
1087 boost::dynamic_bitset<> result = matrix[src_itor->second] & matrix[dst_itor->second];
1088 std::size_t matched = result.count();
1093 std::size_t first = result.find_first();
1094 std::size_t second = result.find_next(first);
1099 const bool perfect = (src_itor->first == 2 &&
1100 dst_itor->first == 2 &&
1101 units_per_village[first] == 2 &&
1102 units_per_village[second] == 2);
1106 <<
" to village " << village1;
1107 moves.emplace_back(village1, units[src_itor->second]);
1110 <<
" to village " << village2;
1111 moves.emplace_back(village2, units[dst_itor->second]);
1114 reachmap.erase(units[src_itor->second]);
1115 reachmap.erase(units[dst_itor->second]);
1147 std::vector<std::pair<map_location, map_location>> best_result;
1155 const std::size_t max_options = 8;
1156 if(unit_count >= max_options && village_count >= max_options) {
1159 << village_count<<
" found, evaluate only the first " 1160 << max_options <<
" options;";
1162 std::vector<std::size_t> perm (max_options, 0);
1163 for(std::size_t
i =0;
i < max_options; ++
i) {
1166 while(std::next_permutation(perm.begin(), perm.end())) {
1169 std::vector<std::pair<map_location,map_location>> result;
1170 for(std::size_t u = 0; u < max_options; ++u) {
1171 if(matrix[u][perm[u]]) {
1172 result.emplace_back(villages[perm[u]], units[u]);
1176 if(result.size() == max_result) {
1177 best_result.swap(result);
1181 if(result.size() > best_result.size()) {
1182 best_result.swap(result);
1186 moves.insert(moves.end(), best_result.begin(), best_result.end());
1189 for(
const auto& unit_village_pair : best_result) {
1190 reachmap.erase(unit_village_pair.second);
1197 }
else if(unit_count <= village_count) {
1201 std::vector<std::size_t> perm (unit_count, 0);
1202 for(std::size_t
i =0;
i < unit_count; ++
i) {
1205 while(std::next_permutation(perm.begin(), perm.end())) {
1207 std::vector<std::pair<map_location,map_location>> result;
1208 for(std::size_t u = 0; u < unit_count; ++u) {
1209 if(matrix[u][perm[u]]) {
1210 result.emplace_back(villages[perm[u]], units[u]);
1214 if(result.size() == max_result) {
1215 moves.insert(moves.end(), result.begin(), result.end());
1220 if(result.size() > best_result.size()) {
1221 best_result.swap(result);
1225 moves.insert(moves.end(), best_result.begin(), best_result.end());
1229 for(
const auto& unit_village_pair : best_result) {
1230 reachmap.erase(unit_village_pair.second);
1233 if(unit != reachmap.end()) {
1234 unit->second.clear();
1243 std::vector<std::size_t> perm (village_count, 0);
1244 for(std::size_t
i =0;
i < village_count; ++
i) {
1247 while(std::next_permutation(perm.begin(), perm.end())) {
1249 std::vector<std::pair<map_location,map_location>> result;
1250 for(std::size_t v = 0; v < village_count; ++v) {
1251 if(matrix[perm[v]][v]) {
1252 result.emplace_back(villages[v], units[perm[v]]);
1256 if(result.size() == max_result) {
1257 moves.insert(moves.end(), result.begin(), result.end());
1262 if(result.size() > best_result.size()) {
1263 best_result.swap(result);
1267 moves.insert(moves.end(), best_result.begin(), best_result.end());
1271 for(
const auto& unit_village_pair : best_result) {
1272 reachmap.erase(unit_village_pair.second);
1275 if(unit != reachmap.end()) {
1276 unit->second.clear();
1285 treachmap::const_iterator itor = reachmap.begin();
1286 for(std::size_t
i = 0;
i < reachmap.size(); ++
i, ++itor) {
1288 <<
" to village " << itor->second[
i];
1289 moves.emplace_back(itor->second[
i], itor->first);
1299 for(treachmap::const_iterator itor =
1300 reachmap.begin(); itor != reachmap.end(); ++itor) {
1304 if(itor->second.empty()) {
1308 for(std::vector<map_location>::const_iterator
1309 v_itor = itor->second.begin();
1310 v_itor != itor->second.end(); ++v_itor) {
1334 for(; u_it != units_.
end(); ++u_it) {
1350 typedef std::multimap<map_location,map_location>::const_iterator Itor;
1351 std::pair<Itor,Itor> it =
get_srcdst().equal_range(u_it->get_location());
1352 double best_vulnerability = 100000.0;
1354 const double leader_penalty = (u.
can_recruit()?2.0:1.0);
1355 Itor best_loc = it.second;
1356 while(it.first != it.second) {
1361 if(vuln < best_vulnerability) {
1362 best_vulnerability = vuln;
1363 best_loc = it.first;
1373 if(best_loc != it.second && best_vulnerability*leader_penalty < u.
hitpoints()) {
1375 if (
move_->is_ok()) {
1389 if (!
move_->is_ok()){
1413 std::map<map_location,pathfind::paths> dummy_possible_moves;
1420 std::vector<map_location> leaders_adj_v;
1431 leaders_adj_v.push_back(loc);
1439 i->movement_left() ==
i->total_movement() &&
1441 std::find(leaders.begin(), leaders.end(),
i) == leaders.end() &&
1449 bool can_reach_leader =
false;
1455 typedef move_map::const_iterator Itor;
1456 std::pair<Itor,Itor> itors =
get_srcdst().equal_range(
i->get_location());
1459 double best_rating = -1000.0;
1460 int best_defensive_rating =
i->defense_modifier(
resources::gameboard->map().get_terrain(
i->get_location()))
1462 while(itors.first != itors.second) {
1466 if(std::find(leaders_adj_v.begin(), leaders_adj_v.end(), itors.first->second) != leaders_adj_v.end()){
1468 can_reach_leader =
true;
1479 const double rating = our_power - their_power;
1480 if(rating > best_rating) {
1482 best_rating = rating;
1488 if(modified_defense < best_defensive_rating) {
1489 best_defensive_rating = modified_defense;
1490 best_defensive = hex;
1498 if(can_reach_leader) {
1502 if(!best_pos.
valid()) {
1503 best_pos = best_defensive;
1506 if(best_pos.
valid()) {
1508 if (
move_->is_ok()) {
1522 if (!
move_->is_ok()){
1531 if(caution <= 0.0) {
1536 srcdst, enemy_dstsrc).chance_to_hit/100.0;
1537 const double proposed_terrain =
1542 const double exposure = proposed_terrain - optimal_terrain;
1546 return caution*their_power*(1.0+exposure) > our_power;
1584 bool have_active_leader =
false;
1588 have_active_leader =
true;
1592 if(!have_active_leader) {
1596 bool allied_leaders_available =
false;
1600 if (!allied_leaders.empty()){
1601 allied_leaders_available =
true;
1606 if(allied_leaders_available){
1618 typedef std::map<map_location, pathfind::paths> path_map;
1619 path_map possible_moves;
1620 move_map friends_srcdst, friends_dstsrc;
1638 bool friend_can_reach_keep =
false;
1641 for(path_map::const_iterator
i = possible_moves.begin();
i != possible_moves.end(); ++
i){
1643 assert(itor.
valid());
1645 if(itor !=
resources::gameboard->units().end() && itor->can_recruit() && itor->side() !=
get_side() && (leader_team.total_income() + leader_team.gold() > leader_team.minimum_recruit_price())){
1646 pathfind::paths::dest_vect::const_iterator tokeep =
i->second.destinations.find(keep);
1647 if(tokeep !=
i->second.destinations.end()){
1648 friend_can_reach_keep =
true;
1654 if(friend_can_reach_keep){
1657 int defense_modifier = 100;
1658 for(pathfind::paths::dest_vect::const_iterator
i = possible_moves[keep].destinations.begin()
1659 ;
i != possible_moves[keep].destinations.end()
1664 &&
static_cast<int>(
distance_between(
i->curr, keep)) <= ai_leader->movement_left()){
1667 if(tmp_def_mod < defense_modifier){
1668 defense_modifier = tmp_def_mod;
1669 best_move =
i->curr;
1674 if(defense_modifier < 100){
1678 if (!move->is_ok()){
1681 ai_leader->set_goto(keep);
1685 possible_moves.clear();
1692 ai_leader->remove_movement_ai();
void remove()
Removes a tip.
virtual void execute()
Execute the candidate action.
virtual void execute()
Execute the candidate action.
virtual attack_result_ptr check_attack_action(const map_location &attacker_loc, const map_location &defender_loc, int attacker_weapon) override
std::vector< unit_iterator > find_leaders(int side)
virtual const attacks_vector & get_attacks() const override
virtual const std::vector< team > & teams() const override
std::vector< std::pair< map_location, map_location > > tmoves
std::shared_ptr< stopunit_result > stopunit_result_ptr
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
virtual const unit_map & units() const override
virtual const map_location & nearest_keep(const map_location &loc) const override
This class represents a single unit of a specific type.
void dispatch(treachmap &reachmap, tmoves &moves)
Dispatches all units to their best location.
int movement_cost(const t_translation::terrain_code &terrain) const
Get the unit's movement cost on a particular terrain.
map_location find_vacant_castle(const unit &leader)
Wrapper for find_vacant_tile() when looking for a vacant castle tile near a leader.
goto_phase(rca_context &context, const config &cfg)
static manager & get_singleton()
map_location best_leader_loc_
The best possible location for our leader if it can't reach a village.
bool get_state(const std::string &state) const
Check if the unit is affected by a status effect.
virtual stopunit_result_ptr check_stopunit_action(const map_location &unit_location, bool remove_movement=true, bool remove_attacks=false) override
unit_iterator find_leader(int side)
void dump_reachmap(treachmap &reachmap)
Shows which villages every unit can reach (debug function).
Managing the AI-Game interaction - AI actions and their results.
int hitpoints() const
The current number of hitpoints this unit has.
leader_shares_keep_phase(rca_context &context, const config &cfg)
map_location keep_loc_
Location of the keep the closest to our leader.
virtual const move_map & get_srcdst() const override
virtual double evaluate()
Evaluate the candidate action, resetting the internal state of the action.
std::shared_ptr< move_result > move_result_ptr
virtual ~move_leader_to_keep_phase()
virtual const gamemap & map() const override
The unit is slowed - it moves slower and does less damage.
virtual double evaluate()
Evaluate the candidate action, resetting the internal state of the action.
virtual double evaluate()
Evaluate the candidate action, resetting the internal state of the action.
AI Support engine - creating specific ai components from config.
virtual ~move_leader_to_goals_phase()
std::shared_ptr< attack_result > attack_result_ptr
move_leader_to_keep_phase(rca_context &context, const config &cfg)
retreat_phase(rca_context &context, const config &cfg)
virtual double evaluate()
Evaluate the candidate action, resetting the internal state of the action.
#define ERR_AI_TESTING_AI_DEFAULT
bool remove_village(treachmap &reachmap, tmoves &moves, const map_location &village)
Removes a village for all units, returns true if anything is deleted.
virtual void execute()
Execute the candidate action.
virtual double evaluate()
Evaluate the candidate action, resetting the internal state of the action.
std::multimap< map_location, map_location > move_map
The standard way in which a map of possible moves is recorded.
std::map< map_location, pathfind::paths > moves_map
The standard way in which a map of possible movement routes to location is recorded.
int defense_modifier(const t_translation::terrain_code &terrain) const
The unit's defense on a given terrain.
This class stores all the data for a single 'side' (in game nomenclature).
static lg::log_domain log_ai_testing_ai_default("ai/ca/testing_ai_default")
A small explanation about what's going on here: Each action has access to two game_info objects First...
virtual double evaluate()
Evaluate the candidate action, resetting the internal state of the action.
const std::string & id() const
Gets this unit's id.
std::vector< map_location > steps
bool should_retreat(const map_location &loc, const unit_map::const_iterator &un, const move_map &srcdst, const move_map &dstsrc, double caution)
virtual void execute()
Execute the candidate action.
int w() const
Effective map width.
Structure which holds a single route between one location and another.
void dispatch_complex(treachmap &reachmap, tmoves &moves, const std::size_t village_count)
Dispatches the units to a village after the simple dispatching failed.
terrain_code get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
const defensive_position & best_defensive_position(const map_location &unit, const move_map &dstsrc, const move_map &srcdst, const move_map &enemy_dstsrc) const override
bool is_allowed_unit(const unit &u) const
Flag indicating whether unit may be used by this candidate action.
virtual double evaluate()
Evaluate the candidate action, resetting the internal state of the action.
virtual double get_leader_aggression() const override
boost::dynamic_bitset<> dynamic_bitset
Encapsulates the map of the game.
virtual double evaluate()
Evaluate the candidate action, resetting the internal state of the action.
bool is_enemy(int n) const
virtual bool is_passive_leader(const std::string &id) const override
virtual const move_map & get_enemy_dstsrc() const override
leader_control_phase(rca_context &context, const config &cfg)
Managing the AIs lifecycle - headers TODO: Refactor history handling and internal commands...
virtual const std::vector< std::string > get_recruitment_pattern() const override
std::size_t count(const map_location &loc) const
void modify_active_ai_for_side(ai::side_number side, const config &cfg)
Modifies AI parameters for active AI of the given side.
bool dont_log(const log_domain &domain) const
int move_cost
Movement cost for reaching the end of the route.
#define DBG_AI_TESTING_AI_DEFAULT
bool dispatch_village_simple(treachmap &reachmap, tmoves &moves, std::size_t &village_count)
Encapsulates the map of the game.
map_location leader_loc_
Locaton of our leader.
unit_iterator find(std::size_t id)
virtual ~leader_control_phase()
get_healing_phase(rca_context &context, const config &cfg)
bool get_ability_bool(const std::string &tag_name, const map_location &loc) const
Checks whether this unit currently possesses or is affected by a given ability.
bool debug_
debug log level for AI enabled?
virtual const map_location & suitable_keep(const map_location &leader_location, const pathfind::paths &leader_paths) const override
get most suitable keep for leader - nearest free that can be reached in 1 turn, if none - return near...
bool dispatch_unit_simple(treachmap &reachmap, tmoves &moves)
Dispatches all units who can reach one village.
virtual const team & current_team() const override
int max_hitpoints() const
The max number of hitpoints this unit can have.
virtual ~leader_shares_keep_phase()
virtual ~get_villages_phase()
std::vector< std::pair< map_location, map_location > > movements
bool can_recruit() const
Whether this unit can recruit other units - ie, are they a leader unit.
virtual double power_projection(const map_location &loc, const move_map &dstsrc) const override
Function which finds how much 'power' a side can attack a certain location with.
#define LOG_AI_TESTING_AI_DEFAULT
virtual void execute()
Execute the candidate action.
virtual side_number get_side() const override
Get the side number.
virtual move_result_ptr check_move_action(const map_location &from, const map_location &to, bool remove_movement=true, bool unreach_is_ok=false) override
bool on_board(const map_location &loc) const
Tell if a location is on the map.
std::map< map_location, std::vector< map_location > > treachmap
virtual bool is_passive_keep_sharing_leader(const std::string &id) const override
virtual std::string get_name() const
Get the name of the candidate action (useful for debug purposes)
void get_villages(const move_map &dstsrc, const move_map &enemy_dstsrc, unit_map::const_iterator &leader)
virtual ~get_healing_phase()
void full_dispatch(treachmap &reachmap, tmoves &moves)
Dispatches all units to a village, every unit can reach every village.
treachmap::iterator remove_unit(treachmap &reachmap, tmoves &moves, treachmap::iterator unit)
Removes a unit which can't reach any village anymore.
bool is_village(const map_location &loc) const
virtual const move_map & get_dstsrc() const override
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.
get_villages_phase(rca_context &context, const config &cfg)
virtual double get_aggression() const override
virtual void execute()
Execute the candidate action.
virtual void calculate_possible_moves(std::map< map_location, pathfind::paths > &possible_moves, move_map &srcdst, move_map &dstsrc, bool enemy, bool assume_full_movement=false, const terrain_filter *remove_destinations=nullptr) const override
const map_location & get_location() const
The current map location this unit is at.
bool contains(const map_location &) const
Standard logging facilities (interface).
const teleport_map get_teleport_locations(const unit &u, const team &viewing_team, bool see_all, bool ignore_units, bool check_vision)
Object which contains all the possible locations a unit can move to, with associated best routes to t...
static const map_location & null_location()
static const double BAD_SCORE
Container associating units to locations.
virtual bool is_keep_ignoring_leader(const std::string &id) const override
virtual void calculate_moves(const unit_map &units, std::map< map_location, pathfind::paths > &possible_moves, move_map &srcdst, move_map &dstsrc, bool enemy, bool assume_full_movement=false, const terrain_filter *remove_destinations=nullptr, bool see_all=false) const override
int side() const
The side this unit belongs to.
virtual const terrain_filter & get_avoid() const override
virtual double evaluate()
Evaluate the candidate action, resetting the internal state of the action.
virtual void execute()
Execute the candidate action.
plain_route a_star_search(const map_location &src, const map_location &dst, double stop_at, const cost_calculator &calc, const std::size_t width, const std::size_t height, const teleport_map *teleports, bool border)
A config object defines a single node in a WML file, with access to child nodes.
virtual move_result_ptr execute_move_action(const map_location &from, const map_location &to, bool remove_movement=true, bool unreach_is_ok=false) override
combat_phase(rca_context &context, const config &cfg)
virtual double get_caution() const override
static map_location::DIRECTION n
double get_score() const
Get the usual score of the candidate action without re-evaluation.
int h() const
Effective map height.
virtual void execute()
Execute the candidate action.
virtual void execute()
Execute the candidate action.
#define WRN_AI_TESTING_AI_DEFAULT
This module contains various pathfinding functions and utilities.
void remove_goal(const std::string &id)
virtual const moves_map & get_possible_moves() const override
std::string::const_iterator iterator
virtual config get_leader_goal() const override
void find_villages(treachmap &reachmap, tmoves &moves, const std::multimap< map_location, map_location > &dstsrc, const std::multimap< map_location, map_location > &enemy_dstsrc)
move_leader_to_goals_phase(rca_context &context, const config &cfg)
candidate action framework
attack_analysis best_analysis_