in dipcc/dipcc/cc/adjudicator.cc [342:486]
bool _try_resolve_loc(Resolution &r, Loc dest,
map<Loc, LocCandidate> &loc_cands) {
if (map_contains(r.winners, dest)) {
// dest is already resolved
return false;
}
if (loc_cands.size() == 1) {
// Only one candidate for dest
auto only_cand_it = loc_cands.begin();
if (only_cand_it->second.min >= 1) {
// only candidate has min str >= 1, candidate wins
_resolve_winner(r, dest, only_cand_it->second);
return true;
}
} else {
// Multiple candidates for dest
// If this loc is the site of a h2h, try to resolve it first
auto h2h_it = unresolved_h2h_.find(dest);
if (h2h_it != unresolved_h2h_.end()) {
_try_resolve_h2h(dest, h2h_it->second);
}
// Loop through all candidate for dest, gathering data e.g. the
// largest min, largest max, and whether there is a unit engaging in
// a h2h
map<Loc, LocCandidate>::iterator largest_min_cand;
int largest_min = -1;
int largest_max = -1;
for (auto loc_cand_it = loc_cands.begin(); loc_cand_it != loc_cands.end();
loc_cand_it++) {
int min = loc_cand_it->second.min;
int max = loc_cand_it->second.max;
if (min > largest_min) {
largest_min = min;
largest_min_cand = loc_cand_it;
}
if (max > largest_max) {
largest_max = max;
}
if (loc_cand_it->second.src == dest) {
// maybe update holder prev str
_set_prev_str_to_max(dest, min);
}
}
// if the largest max is 0, this loc is empty
if (largest_max == 0) {
r.winners[dest] = NONE_LOC_CANDIDATE;
return true;
}
// check largest min/max against loc's prevent strength
if (largest_max <= loc_prev_str_[dest]) {
// no unit can beat the prev strength: either units holds, or we bounce
if (cands_[dest][dest].min > 0) {
_resolve_winner(r, dest, cands_[dest][dest]);
} else {
_resolve_bounce(r, dest);
}
return true;
}
if (largest_min < loc_prev_str_[dest]) {
// no unit's min beats prev strength, but >=1 units' max beats prev
// strength: we are undecided
return false;
}
// if largest min dominates other units' max, this unit wins
bool is_winner = true;
bool is_bounce = false;
int other_units_max = -1;
for (auto &loc_cand_it : loc_cands) {
if (loc_cand_it.first == root_loc(largest_min_cand->second.src)) {
continue;
}
int min = loc_cand_it.second.min;
int max = loc_cand_it.second.max;
if (max > other_units_max) {
other_units_max = max;
}
if (max >= largest_min) {
// largest min doesn't dominate this max, so no clear winner
is_winner = false;
if (max == min && max == largest_min && max == largest_max) {
// two top candidates have exact same min/max strength: bounce
is_bounce = true;
break;
}
}
}
if (is_winner) {
if (largest_min_cand->second.min -
largest_min_cand->second.dislodge_self_support <=
other_units_max) {
// Winning candidate does not win without self-power support. If
// this would cause a dislodge, remove support and recalculate to
// avoid self-dislodge. If the unit currently at dest
// successfully moves elsewhere, this is not a self-dislodge and
// the support holds. See DATC 6.E.9
return _handle_self_support_dislodge_support_winner(
r, largest_min_cand->second);
} else {
auto hold_cand_it = loc_cands.find(dest);
if (hold_cand_it != loc_cands.end() &&
hold_cand_it->second.src != largest_min_cand->second.src &&
hold_cand_it->second.power == largest_min_cand->second.power &&
hold_cand_it->second.max > 0) {
// unit of same power occupying dest; make sure we don't
// self-dislodge
if (hold_cand_it->second.min > 0) {
// this is a self-dislodge: prevent it
DLOG(INFO) << "Bounce to prevent self-dislodge: " << dest;
_resolve_bounce(r, dest);
return true;
} else {
// hold cand may still vacate: wait until that's resolved
unresolved_self_dislodges_.insert(make_pair(
root_loc(largest_min_cand->second.src), root_loc(dest)));
return false;
}
}
_resolve_winner(r, dest, largest_min_cand->second);
if (other_units_max == 0 &&
maybe_convoy_orders_by_dest_[dest].size() == 0) {
// no other unit managed to attack this loc: if the unit had an
// unresolved support, resolve it
_resolve_support_if_exists(r, dest);
}
return true;
}
} else if (is_bounce) {
_resolve_bounce(r, dest);
return true;
}
}
// no change was made
return false;
}