269 for(u = units_.
begin(); u != units_.
end(); ++u) {
271 if (u->get_state(
"guardian")) {
272 LOG_AI << u->type_id() <<
" is guardian, staying still";
273 return std::pair(u->get_location(), u->get_location());
279 for(u = units_.
begin(); u != units_.
end(); ++u) {
285 if(u == units_.
end()) {
286 LOG_AI <<
"no eligible units found";
287 return std::pair<map_location,map_location>();
300 std::vector<rated_target> rated_targets;
301 for(std::vector<target>::iterator tg = targets.begin(); tg != targets.end(); ++tg) {
303 double max_rating =
rate_target(*tg, u, dstsrc, enemy_dstsrc, dummy_route);
304 rated_targets.emplace_back(tg, max_rating);
314 double best_rating = -1.0;
316 std::vector<rated_target>::iterator best_rated_target = rated_targets.end();
318 std::vector<rated_target>::iterator rated_tg = rated_targets.begin();
320 for(; rated_tg != rated_targets.end(); ++rated_tg) {
321 const target& tg = *(rated_tg->tg);
323 LOG_AI <<
"Considering target at: " << tg.
loc;
331 const double locStopValue = 500.0;
333 pathfind::plain_route real_route = a_star_search(u->get_location(), tg.
loc, locStopValue, cost_calc, map_.
w(), map_.
h(), &allowed_teleports);
335 if(real_route.
steps.empty()) {
336 LOG_AI <<
"Can't reach target: " << locStopValue <<
" = " << tg.
value <<
"/" << best_rating;
340 double real_rating =
rate_target(tg, u, dstsrc, enemy_dstsrc, real_route);
344 if(real_rating > best_rating){
345 best_rating = real_rating;
346 best_rated_target = rated_tg;
347 best_route = real_route;
352 best_rating = 0.000000001;
357 if(rated_tg+1 != rated_targets.end() && best_rating >= (rated_tg+1)->max_rating)
362 LOG_AI <<
"choose target...";
364 if(best_rated_target == rated_targets.end()) {
365 LOG_AI <<
"no eligible targets found for unit at " << u->get_location();
366 return std::pair(u->get_location(), u->get_location());
369 assert(best_rating >= 0);
370 std::vector<target>::iterator best_target = best_rated_target->tg;
377 if(simple_targeting ==
false) {
378 LOG_AI <<
"complex targeting...";
380 for(++u; u != units_.
end(); ++u) {
382 u->movement_left() <= 0 || u->get_state(
"guardian") ||
395 const double locStopValue = 500.0;
399 if(cur_route.
steps.empty()) {
403 double rating =
rate_target(*best_target, u, dstsrc, enemy_dstsrc, cur_route);
405 if(best == units_.
end() || rating > best_rating) {
406 best_rating = rating;
408 best_route = cur_route;
412 LOG_AI <<
"done complex targeting...";
417 LOG_AI <<
"best unit: " << best->get_location();
419 assert(best_target != targets.end());
424 if(best_target->type == ai_target::type::support) {
427 std::vector<map_location> locs;
428 access_points(srcdst, best->get_location(), best_target->loc, locs);
430 if(locs.empty() ==
false) {
431 LOG_AI <<
"supporting unit at " << best_target->loc.wml_x() <<
"," << best_target->loc.wml_y();
433 int best_defense = 0;
434 double best_vulnerability = 0.0;
436 for(std::vector<map_location>::const_iterator
i = locs.begin();
i != locs.end(); ++
i) {
437 const int defense = best->defense_modifier(map_.
get_terrain(*
i));
441 if(best_loc.
valid() ==
false || defense < best_defense || (defense == best_defense && vulnerability < best_vulnerability)) {
443 best_defense = defense;
444 best_vulnerability = vulnerability;
448 LOG_AI <<
"returning support...";
449 return std::pair(best->get_location(), best_loc);
453 std::map<map_location,pathfind::paths> dummy_possible_moves;
458 bool dangerous =
false;
463 int movement = best->movement_left();
465 const bool defensive_grouping =
get_grouping() ==
"defensive";
470 for(std::vector<map_location>::const_iterator
i = best_route.
steps.begin();
i != best_route.
steps.end() && movement > 0; ++
i) {
475 if ((threat >= best->hitpoints() && threat >
power_projection(*
i,fullmove_dstsrc)) ||
481 if(!defensive_grouping) {
486 LOG_AI <<
"done grouping...";
490 LOG_AI <<
"dangerous path";
491 std::set<map_location> group, enemies;
503 LOG_AI <<
"group didn't move " << group.size();
506 return std::pair(best->get_location(), best->get_location());
510 LOG_AI <<
"massing to attack " << best_target->loc.wml_x() <<
"," << best_target->loc.wml_y()
511 <<
" " << our_strength;
513 const double value = best_target->value;
516 const unit& un = *best;
518 targets.erase(best_target);
522 double best_threat = 0.0;
523 int best_distance = 0;
525 const double max_acceptable_threat = un.
hitpoints() / 4.0;
527 std::set<map_location> mass_locations;
529 const auto itors = srcdst.equal_range(
loc);
530 for(move_map::const_iterator
i = itors.first;
i != itors.second; ++
i) {
536 if(best_loc.
valid() ==
false || (threat < std::max<double>(best_threat,max_acceptable_threat) && distance < best_distance)) {
537 best_loc =
i->second;
538 best_threat = threat;
539 best_distance = distance;
542 if(threat < max_acceptable_threat) {
543 mass_locations.insert(
i->second);
547 for(std::set<map_location>::const_iterator j = mass_locations.begin(); j != mass_locations.end(); ++j) {
549 LOG_AI <<
"found mass-to-attack target... " << *j <<
" with value: " <<
value*4.0;
550 targets.emplace_back(*j,
value*4.0,ai_target::type::mass);
551 best_target = targets.end() - 1;
555 return std::pair<map_location,map_location>(
loc,best_loc);
559 for(std::vector<map_location>::reverse_iterator ri =
560 best_route.
steps.rbegin(); ri != best_route.
steps.rend(); ++ri) {
564 bool is_dangerous =
false;
566 auto its = dstsrc.equal_range(*ri);
567 while(its.first != its.second) {
568 if (its.first->second == best->get_location()) {
569 if(!
should_retreat(its.first->first,best,fullmove_srcdst,fullmove_dstsrc,enemy_dstsrc,
571 double value = best_target->value - best->cost() / 20.0;
573 if(
value > 0.0 && best_target->type != ai_target::type::mass) {
577 LOG_AI <<
"found reinforcement target... " << its.first->first <<
" with value: " <<
value*2.0;
578 targets.emplace_back(its.first->first,
value*2.0,ai_target::type::battle_aid);
581 best_target->value =
value;
583 targets.erase(best_target);
586 LOG_AI <<
"Moving to " << its.first->first.wml_x() <<
"," << its.first->first.wml_y();
588 return std::pair<map_location,map_location>(its.first->second,its.first->first);
599 if(best != units_.
end()) {
600 LOG_AI <<
"Could not make good move, staying still";
604 targets.emplace_back(best->get_location(), best_target->value);
605 best_target = targets.end() - 1;
606 return std::pair(best->get_location(), best->get_location());
609 LOG_AI <<
"Could not find anywhere to move!";
610 return std::pair<map_location,map_location>();
704 const std::vector<map_location>::const_iterator itor = std::find(route.begin(),route.end(),
dst);
705 if(itor == route.end()) {
709 LOG_AI <<
"group has " << units.size() <<
" members";
713 std::size_t direction = 0;
716 if(itor+1 != route.end()) {
718 }
else if(itor != route.begin()) {
724 direction = std::distance(adj.begin(), std::find(adj.begin(), adj.end(), next));
727 std::deque<map_location> preferred_moves;
728 preferred_moves.push_back(
dst);
730 std::map<map_location,pathfind::paths> possible_moves;
734 bool gamestate_changed =
false;
736 for(std::set<map_location>::const_iterator
i = units.begin();
i != units.end(); ++
i) {
738 if(un == units_.
end()) {
743 int best_defense = -1;
744 for(std::deque<map_location>::const_iterator j = preferred_moves.begin(); j != preferred_moves.end(); ++j) {
745 if(units_.
count(*j)) {
749 const auto itors = dstsrc.equal_range(*j);
750 move_map::const_iterator m;
751 for(m = itors.first; m != itors.second; ++m) {
752 if(m->second == *
i) {
757 if(m == itors.second) {
761 int defense = un->defense_modifier(map_.
get_terrain(*j));
762 if(best_loc.
valid() ==
false || defense < best_defense) {
764 best_defense = defense;
768 if(best_loc.
valid()) {
770 gamestate_changed |= move_res->is_gamestate_changed();
773 if (!move_res->is_ok()) {
774 return gamestate_changed;
777 preferred_moves.erase(std::find(preferred_moves.begin(),preferred_moves.end(),best_loc));
781 for(std::size_t
n = 0;
n < adj.size(); ++
n) {
782 if(
n != direction && ((
n+3)%6) != direction && map_.
on_board(adj[
n]) &&
783 units_.
count(adj[
n]) == 0 && std::count(preferred_moves.begin(),preferred_moves.end(),adj[
n]) == 0) {
784 preferred_moves.push_front(adj[
n]);
785 LOG_AI <<
"added moves: " << adj[
n].wml_x() <<
"," << adj[
n].wml_y();
789 LOG_AI <<
"Could not move group member to any of " << preferred_moves.size() <<
" locations";
793 return gamestate_changed;
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
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
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.
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