public static Map<Territory, Double> findSeaTerritoryValues( final PlayerID player, final List<Territory> territoriesThatCantBeHeld) { final GameData data = ProData.getData(); final List<Territory> allTerritories = data.getMap().getTerritories(); // Determine value for water territories final Map<Territory, Double> territoryValueMap = new HashMap<Territory, Double>(); for (final Territory t : allTerritories) { if (!territoriesThatCantBeHeld.contains(t) && t.isWater() && !data.getMap().getNeighbors(t, Matches.TerritoryIsWater).isEmpty()) { // Determine sea value based on nearby convoy production double nearbySeaProductionValue = 0; final Set<Territory> nearbySeaTerritories = data.getMap() .getNeighbors(t, 4, ProMatches.territoryCanMoveSeaUnits(player, data, true)); final List<Territory> nearbyEnemySeaTerritories = Match.getMatches( nearbySeaTerritories, ProMatches.territoryIsEnemyOrCantBeHeld(player, data, territoriesThatCantBeHeld)); for (final Territory nearbyEnemySeaTerritory : nearbyEnemySeaTerritories) { final Route route = data.getMap() .getRoute_IgnoreEnd( t, nearbyEnemySeaTerritory, ProMatches.territoryCanMoveSeaUnits(player, data, true)); if (route == null || MoveValidator.validateCanal(route, null, player, data) != null) { continue; } final int distance = route.numberOfSteps(); if (distance > 0) { nearbySeaProductionValue += TerritoryAttachment.getProduction(nearbyEnemySeaTerritory) / Math.pow(2, distance); } } // Determine sea value based on nearby enemy sea units double nearbyEnemySeaUnitValue = 0; final List<Territory> nearbyEnemySeaUnitTerritories = Match.getMatches(nearbySeaTerritories, Matches.territoryHasEnemyUnits(player, data)); for (final Territory nearbyEnemySeaTerritory : nearbyEnemySeaUnitTerritories) { final Route route = data.getMap() .getRoute_IgnoreEnd( t, nearbyEnemySeaTerritory, ProMatches.territoryCanMoveSeaUnits(player, data, true)); if (route == null || MoveValidator.validateCanal(route, null, player, data) != null) { continue; } final int distance = route.numberOfSteps(); if (distance > 0) { nearbyEnemySeaUnitValue += nearbyEnemySeaTerritory.getUnits().countMatches(Matches.unitIsEnemyOf(data, player)) / Math.pow(2, distance); } } // Set final values final double value = 100 * nearbySeaProductionValue + nearbyEnemySeaUnitValue; territoryValueMap.put(t, value); } else if (t.isWater()) { territoryValueMap.put(t, 0.0); } } return territoryValueMap; }