bool _try_resolve_loc()

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;
  }