Search in sources :

Example 1 with ProOtherMoveOptions

use of games.strategy.triplea.ai.pro.data.ProOtherMoveOptions in project triplea by triplea-game.

the class ProPurchaseAi method prioritizeTerritoriesToDefend.

private List<ProPlaceTerritory> prioritizeTerritoriesToDefend(final Map<Territory, ProPurchaseTerritory> purchaseTerritories, final boolean isLand) {
    ProLogger.info("Prioritize territories to defend with isLand=" + isLand);
    final ProOtherMoveOptions enemyAttackOptions = territoryManager.getEnemyAttackOptions();
    // Determine which territories need defended
    final Set<ProPlaceTerritory> needToDefendTerritories = new HashSet<>();
    for (final ProPurchaseTerritory ppt : purchaseTerritories.values()) {
        // Check if any of the place territories can't be held with current defenders
        for (final ProPlaceTerritory placeTerritory : ppt.getCanPlaceTerritories()) {
            final Territory t = placeTerritory.getTerritory();
            if (enemyAttackOptions.getMax(t) == null || (t.isWater() && placeTerritory.getDefendingUnits().isEmpty()) || (isLand && t.isWater()) || (!isLand && !t.isWater())) {
                continue;
            }
            // Find current battle result
            final Set<Unit> enemyAttackingUnits = new HashSet<>(enemyAttackOptions.getMax(t).getMaxUnits());
            enemyAttackingUnits.addAll(enemyAttackOptions.getMax(t).getMaxAmphibUnits());
            final ProBattleResult result = calc.calculateBattleResults(t, new ArrayList<>(enemyAttackingUnits), placeTerritory.getDefendingUnits(), enemyAttackOptions.getMax(t).getMaxBombardUnits());
            placeTerritory.setMinBattleResult(result);
            double holdValue = 0;
            if (t.isWater()) {
                final double unitValue = TuvUtils.getTuv(CollectionUtils.getMatches(placeTerritory.getDefendingUnits(), Matches.unitIsOwnedBy(player)), ProData.unitValueMap);
                holdValue = unitValue / 8;
            }
            ProLogger.trace(t.getName() + " TUVSwing=" + result.getTuvSwing() + ", win%=" + result.getWinPercentage() + ", hasLandUnitRemaining=" + result.isHasLandUnitRemaining() + ", holdValue=" + holdValue + ", enemyAttackers=" + enemyAttackingUnits + ", defenders=" + placeTerritory.getDefendingUnits());
            // If it can't currently be held then add to list
            final boolean isLandAndCanOnlyBeAttackedByAir = !t.isWater() && !enemyAttackingUnits.isEmpty() && enemyAttackingUnits.stream().allMatch(Matches.unitIsAir());
            if ((!t.isWater() && result.isHasLandUnitRemaining()) || result.getTuvSwing() > holdValue || (t.equals(ProData.myCapital) && !isLandAndCanOnlyBeAttackedByAir && result.getWinPercentage() > (100 - ProData.winPercentage))) {
                needToDefendTerritories.add(placeTerritory);
            }
        }
    }
    // Calculate value of defending territory
    for (final ProPlaceTerritory placeTerritory : needToDefendTerritories) {
        final Territory t = placeTerritory.getTerritory();
        // Determine if it is my capital or adjacent to my capital
        int isMyCapital = 0;
        if (t.equals(ProData.myCapital)) {
            isMyCapital = 1;
        }
        // Determine if it has a factory
        int isFactory = 0;
        if (ProMatches.territoryHasInfraFactoryAndIsOwnedLand(player).test(t)) {
            isFactory = 1;
        }
        // Determine production value and if it is an enemy capital
        int production = 0;
        final TerritoryAttachment ta = TerritoryAttachment.get(t);
        if (ta != null) {
            production = ta.getProduction();
        }
        // Determine defending unit value
        double defendingUnitValue = TuvUtils.getTuv(placeTerritory.getDefendingUnits(), ProData.unitValueMap);
        if (t.isWater() && placeTerritory.getDefendingUnits().stream().noneMatch(Matches.unitIsOwnedBy(player))) {
            defendingUnitValue = 0;
        }
        // Calculate defense value for prioritization
        final double territoryValue = (2 * production + 4 * isFactory + 0.5 * defendingUnitValue) * (1 + isFactory) * (1 + 10 * isMyCapital);
        placeTerritory.setDefenseValue(territoryValue);
    }
    // Remove any territories with negative defense value
    needToDefendTerritories.removeIf(ppt -> ppt.getDefenseValue() <= 0);
    // Sort territories by value
    final List<ProPlaceTerritory> sortedTerritories = new ArrayList<>(needToDefendTerritories);
    sortedTerritories.sort(Comparator.comparingDouble(ProPlaceTerritory::getDefenseValue));
    for (final ProPlaceTerritory placeTerritory : sortedTerritories) {
        ProLogger.debug(placeTerritory.toString() + " defenseValue=" + placeTerritory.getDefenseValue());
    }
    return sortedTerritories;
}
Also used : ProPlaceTerritory(games.strategy.triplea.ai.pro.data.ProPlaceTerritory) ProPurchaseTerritory(games.strategy.triplea.ai.pro.data.ProPurchaseTerritory) Territory(games.strategy.engine.data.Territory) TerritoryAttachment(games.strategy.triplea.attachments.TerritoryAttachment) ArrayList(java.util.ArrayList) ProPurchaseTerritory(games.strategy.triplea.ai.pro.data.ProPurchaseTerritory) ProBattleResult(games.strategy.triplea.ai.pro.data.ProBattleResult) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) ProPlaceTerritory(games.strategy.triplea.ai.pro.data.ProPlaceTerritory) ProOtherMoveOptions(games.strategy.triplea.ai.pro.data.ProOtherMoveOptions) HashSet(java.util.HashSet)

Example 2 with ProOtherMoveOptions

use of games.strategy.triplea.ai.pro.data.ProOtherMoveOptions in project triplea by triplea-game.

the class ProPurchaseAi method purchaseSeaAndAmphibUnits.

private void purchaseSeaAndAmphibUnits(final Map<Territory, ProPurchaseTerritory> purchaseTerritories, final List<ProPlaceTerritory> prioritizedSeaTerritories, final Map<Territory, Double> territoryValueMap, final ProPurchaseOptionMap purchaseOptions) {
    if (resourceTracker.isEmpty()) {
        return;
    }
    ProLogger.info("Purchase sea and amphib units with resources: " + resourceTracker);
    final ProOtherMoveOptions enemyAttackOptions = territoryManager.getEnemyAttackOptions();
    // Loop through prioritized territories and purchase sea units
    for (final ProPlaceTerritory placeTerritory : prioritizedSeaTerritories) {
        final Territory t = placeTerritory.getTerritory();
        ProLogger.debug("Checking sea place for " + t.getName());
        // Find all purchase territories for place territory
        final List<ProPurchaseTerritory> selectedPurchaseTerritories = getPurchaseTerritories(placeTerritory, purchaseTerritories);
        // Find local owned units
        final Set<Territory> neighbors = data.getMap().getNeighbors(t, 2, ProMatches.territoryCanMoveSeaUnits(player, data, false));
        neighbors.add(t);
        final List<Unit> ownedLocalUnits = new ArrayList<>();
        for (final Territory neighbor : neighbors) {
            ownedLocalUnits.addAll(neighbor.getUnits().getMatches(Matches.unitIsOwnedBy(player)));
        }
        int unusedCarrierCapacity = Math.min(0, ProTransportUtils.getUnusedCarrierCapacity(player, t, new ArrayList<>()));
        int unusedLocalCarrierCapacity = ProTransportUtils.getUnusedLocalCarrierCapacity(player, t, new ArrayList<>());
        ProLogger.trace(t + ", unusedCarrierCapacity=" + unusedCarrierCapacity + ", unusedLocalCarrierCapacity=" + unusedLocalCarrierCapacity);
        // If any enemy attackers then purchase sea defenders until it can be held
        boolean needDestroyer = false;
        if (enemyAttackOptions.getMax(t) != null) {
            // Determine if need destroyer
            if (enemyAttackOptions.getMax(t).getMaxUnits().stream().anyMatch(Matches.unitIsSub()) && t.getUnits().getMatches(Matches.unitIsOwnedBy(player)).stream().noneMatch(Matches.unitIsDestroyer())) {
                needDestroyer = true;
            }
            ProLogger.trace(t + ", needDestroyer=" + needDestroyer + ", checking defense since has enemy attackers: " + enemyAttackOptions.getMax(t).getMaxUnits());
            final List<Unit> initialDefendingUnits = new ArrayList<>(placeTerritory.getDefendingUnits());
            initialDefendingUnits.addAll(ProPurchaseUtils.getPlaceUnits(t, purchaseTerritories));
            ProBattleResult result = calc.calculateBattleResults(t, enemyAttackOptions.getMax(t).getMaxUnits(), initialDefendingUnits, enemyAttackOptions.getMax(t).getMaxBombardUnits());
            boolean hasOnlyRetreatingSubs = Properties.getSubRetreatBeforeBattle(data) && !initialDefendingUnits.isEmpty() && initialDefendingUnits.stream().allMatch(Matches.unitIsSub()) && enemyAttackOptions.getMax(t).getMaxUnits().stream().noneMatch(Matches.unitIsDestroyer());
            final List<Unit> unitsToPlace = new ArrayList<>();
            for (final ProPurchaseTerritory purchaseTerritory : selectedPurchaseTerritories) {
                // Check remaining production
                int remainingUnitProduction = purchaseTerritory.getRemainingUnitProduction();
                ProLogger.trace(t + ", purchaseTerritory=" + purchaseTerritory.getTerritory() + ", remainingUnitProduction=" + remainingUnitProduction);
                if (remainingUnitProduction <= 0) {
                    continue;
                }
                // Determine sea and transport units that can be produced in this territory
                final List<ProPurchaseOption> seaPurchaseOptionsForTerritory = ProPurchaseUtils.findPurchaseOptionsForTerritory(player, purchaseOptions.getSeaDefenseOptions(), t, isBid);
                seaPurchaseOptionsForTerritory.addAll(purchaseOptions.getAirOptions());
                // Purchase enough sea defenders to hold territory
                while (true) {
                    // If it can be held then break
                    if (!hasOnlyRetreatingSubs && (result.getTuvSwing() < -1 || result.getWinPercentage() < ProData.winPercentage)) {
                        break;
                    }
                    // Select purchase option
                    ProPurchaseUtils.removeInvalidPurchaseOptions(player, startOfTurnData, seaPurchaseOptionsForTerritory, resourceTracker, remainingUnitProduction, unitsToPlace, purchaseTerritories);
                    final Map<ProPurchaseOption, Double> defenseEfficiencies = new HashMap<>();
                    for (final ProPurchaseOption ppo : seaPurchaseOptionsForTerritory) {
                        defenseEfficiencies.put(ppo, ppo.getSeaDefenseEfficiency(data, ownedLocalUnits, unitsToPlace, needDestroyer, unusedCarrierCapacity, unusedLocalCarrierCapacity));
                    }
                    final Optional<ProPurchaseOption> optionalSelectedOption = ProPurchaseUtils.randomizePurchaseOption(defenseEfficiencies, "Sea Defense");
                    if (!optionalSelectedOption.isPresent()) {
                        break;
                    }
                    final ProPurchaseOption selectedOption = optionalSelectedOption.get();
                    if (selectedOption.isDestroyer()) {
                        needDestroyer = false;
                    }
                    // Create new temp defenders
                    resourceTracker.tempPurchase(selectedOption);
                    remainingUnitProduction -= selectedOption.getQuantity();
                    unitsToPlace.addAll(selectedOption.getUnitType().create(selectedOption.getQuantity(), player, true));
                    if (selectedOption.isCarrier() || selectedOption.isAir()) {
                        unusedCarrierCapacity = ProTransportUtils.getUnusedCarrierCapacity(player, t, unitsToPlace);
                        unusedLocalCarrierCapacity = ProTransportUtils.getUnusedLocalCarrierCapacity(player, t, unitsToPlace);
                    }
                    ProLogger.trace(t + ", added sea defender for defense: " + selectedOption.getUnitType().getName() + ", TUVSwing=" + result.getTuvSwing() + ", win%=" + result.getWinPercentage() + ", unusedCarrierCapacity=" + unusedCarrierCapacity + ", unusedLocalCarrierCapacity=" + unusedLocalCarrierCapacity);
                    // Find current battle result
                    final List<Unit> defendingUnits = new ArrayList<>(placeTerritory.getDefendingUnits());
                    defendingUnits.addAll(ProPurchaseUtils.getPlaceUnits(t, purchaseTerritories));
                    defendingUnits.addAll(unitsToPlace);
                    result = calc.estimateDefendBattleResults(t, enemyAttackOptions.getMax(t).getMaxUnits(), defendingUnits, enemyAttackOptions.getMax(t).getMaxBombardUnits());
                    hasOnlyRetreatingSubs = Properties.getSubRetreatBeforeBattle(data) && !defendingUnits.isEmpty() && defendingUnits.stream().allMatch(Matches.unitIsSub()) && enemyAttackOptions.getMax(t).getMaxUnits().stream().noneMatch(Matches.unitIsDestroyer());
                }
            }
            // Check to see if its worth trying to defend the territory
            if (result.getTuvSwing() < 0 || result.getWinPercentage() < ProData.winPercentage) {
                resourceTracker.confirmTempPurchases();
                ProLogger.trace(t + ", placedUnits=" + unitsToPlace + ", TUVSwing=" + result.getTuvSwing() + ", hasLandUnitRemaining=" + result.isHasLandUnitRemaining());
                addUnitsToPlaceTerritory(placeTerritory, unitsToPlace, purchaseTerritories);
            } else {
                resourceTracker.clearTempPurchases();
                setCantHoldPlaceTerritory(placeTerritory, purchaseTerritories);
                ProLogger.trace(t + ", can't defend TUVSwing=" + result.getTuvSwing() + ", win%=" + result.getWinPercentage() + ", tried to placeDefenders=" + unitsToPlace + ", enemyAttackers=" + enemyAttackOptions.getMax(t).getMaxUnits());
                continue;
            }
        }
        // TODO: update to use ProBattleUtils method
        // Check to see if local naval superiority
        int landDistance = ProUtils.getClosestEnemyLandTerritoryDistanceOverWater(data, player, t);
        if (landDistance <= 0) {
            landDistance = 10;
        }
        final int enemyDistance = Math.max(3, (landDistance + 1));
        final Set<Territory> nearbyTerritories = data.getMap().getNeighbors(t, enemyDistance, ProMatches.territoryCanMoveAirUnits(player, data, false));
        final List<Territory> nearbyLandTerritories = CollectionUtils.getMatches(nearbyTerritories, Matches.territoryIsLand());
        final Set<Territory> nearbyEnemySeaTerritories = data.getMap().getNeighbors(t, enemyDistance, Matches.territoryIsWater());
        nearbyEnemySeaTerritories.add(t);
        final int alliedDistance = (enemyDistance + 1) / 2;
        final Set<Territory> nearbyAlliedSeaTerritories = data.getMap().getNeighbors(t, alliedDistance, Matches.territoryIsWater());
        nearbyAlliedSeaTerritories.add(t);
        final List<Unit> enemyUnitsInLandTerritories = new ArrayList<>();
        for (final Territory nearbyLandTerritory : nearbyLandTerritories) {
            enemyUnitsInLandTerritories.addAll(nearbyLandTerritory.getUnits().getMatches(ProMatches.unitIsEnemyAir(player, data)));
        }
        final List<Unit> enemyUnitsInSeaTerritories = new ArrayList<>();
        for (final Territory nearbySeaTerritory : nearbyEnemySeaTerritories) {
            final List<Unit> enemySeaUnits = nearbySeaTerritory.getUnits().getMatches(ProMatches.unitIsEnemyNotLand(player, data));
            if (enemySeaUnits.isEmpty()) {
                continue;
            }
            final Route route = data.getMap().getRoute_IgnoreEnd(t, nearbySeaTerritory, Matches.territoryIsWater());
            if (route == null) {
                continue;
            }
            if (MoveValidator.validateCanal(route, enemySeaUnits, enemySeaUnits.get(0).getOwner(), data) != null) {
                continue;
            }
            final int routeLength = route.numberOfSteps();
            if (routeLength <= enemyDistance) {
                enemyUnitsInSeaTerritories.addAll(enemySeaUnits);
            }
        }
        final List<Unit> myUnitsInSeaTerritories = new ArrayList<>();
        for (final Territory nearbySeaTerritory : nearbyAlliedSeaTerritories) {
            myUnitsInSeaTerritories.addAll(nearbySeaTerritory.getUnits().getMatches(ProMatches.unitIsOwnedNotLand(player)));
            myUnitsInSeaTerritories.addAll(ProPurchaseUtils.getPlaceUnits(nearbySeaTerritory, purchaseTerritories));
        }
        // Check if destroyer is needed
        final int numEnemySubs = CollectionUtils.countMatches(enemyUnitsInSeaTerritories, Matches.unitIsSub());
        final int numMyDestroyers = CollectionUtils.countMatches(myUnitsInSeaTerritories, Matches.unitIsDestroyer());
        if (numEnemySubs > 2 * numMyDestroyers) {
            needDestroyer = true;
        }
        ProLogger.trace(t + ", enemyDistance=" + enemyDistance + ", alliedDistance=" + alliedDistance + ", enemyAirUnits=" + enemyUnitsInLandTerritories + ", enemySeaUnits=" + enemyUnitsInSeaTerritories + ", mySeaUnits=" + myUnitsInSeaTerritories + ", needDestroyer=" + needDestroyer);
        // Purchase naval defenders until I have local naval superiority
        final List<Unit> unitsToPlace = new ArrayList<>();
        for (final ProPurchaseTerritory purchaseTerritory : selectedPurchaseTerritories) {
            // Check remaining production
            int remainingUnitProduction = purchaseTerritory.getRemainingUnitProduction();
            ProLogger.trace(t + ", purchaseTerritory=" + purchaseTerritory.getTerritory() + ", remainingUnitProduction=" + remainingUnitProduction);
            if (remainingUnitProduction <= 0) {
                continue;
            }
            // Determine sea and transport units that can be produced in this territory
            final List<ProPurchaseOption> seaPurchaseOptionsForTerritory = ProPurchaseUtils.findPurchaseOptionsForTerritory(player, purchaseOptions.getSeaDefenseOptions(), t, isBid);
            seaPurchaseOptionsForTerritory.addAll(purchaseOptions.getAirOptions());
            while (true) {
                // If I have naval attack/defense superiority then break
                if (ProBattleUtils.territoryHasLocalNavalSuperiority(t, player, purchaseTerritories, unitsToPlace)) {
                    break;
                }
                // Select purchase option
                ProPurchaseUtils.removeInvalidPurchaseOptions(player, startOfTurnData, seaPurchaseOptionsForTerritory, resourceTracker, remainingUnitProduction, unitsToPlace, purchaseTerritories);
                final Map<ProPurchaseOption, Double> defenseEfficiencies = new HashMap<>();
                for (final ProPurchaseOption ppo : seaPurchaseOptionsForTerritory) {
                    defenseEfficiencies.put(ppo, ppo.getSeaDefenseEfficiency(data, ownedLocalUnits, unitsToPlace, needDestroyer, unusedCarrierCapacity, unusedLocalCarrierCapacity));
                }
                final Optional<ProPurchaseOption> optionalSelectedOption = ProPurchaseUtils.randomizePurchaseOption(defenseEfficiencies, "Sea Defense");
                if (!optionalSelectedOption.isPresent()) {
                    break;
                }
                final ProPurchaseOption selectedOption = optionalSelectedOption.get();
                if (selectedOption.isDestroyer()) {
                    needDestroyer = false;
                }
                // Create new temp units
                resourceTracker.purchase(selectedOption);
                remainingUnitProduction -= selectedOption.getQuantity();
                unitsToPlace.addAll(selectedOption.getUnitType().create(selectedOption.getQuantity(), player, true));
                if (selectedOption.isCarrier() || selectedOption.isAir()) {
                    unusedCarrierCapacity = ProTransportUtils.getUnusedCarrierCapacity(player, t, unitsToPlace);
                    unusedLocalCarrierCapacity = ProTransportUtils.getUnusedLocalCarrierCapacity(player, t, unitsToPlace);
                }
                ProLogger.trace(t + ", added sea defender for naval superiority: " + selectedOption.getUnitType().getName() + ", unusedCarrierCapacity=" + unusedCarrierCapacity + ", unusedLocalCarrierCapacity=" + unusedLocalCarrierCapacity);
            }
        }
        // Add sea defender units to place territory
        addUnitsToPlaceTerritory(placeTerritory, unitsToPlace, purchaseTerritories);
        // Loop through adjacent purchase territories and purchase transport/amphib units
        final int distance = ProTransportUtils.findMaxMovementForTransports(purchaseOptions.getSeaTransportOptions());
        ProLogger.trace(t + ", transportMovement=" + distance);
        for (final ProPurchaseTerritory purchaseTerritory : selectedPurchaseTerritories) {
            final Territory landTerritory = purchaseTerritory.getTerritory();
            // Check if territory can produce units and has remaining production
            int remainingUnitProduction = purchaseTerritory.getRemainingUnitProduction();
            ProLogger.trace(t + ", purchaseTerritory=" + landTerritory + ", remainingUnitProduction=" + remainingUnitProduction);
            if (remainingUnitProduction <= 0) {
                continue;
            }
            // Find local owned units
            final List<Unit> ownedLocalAmphibUnits = landTerritory.getUnits().getMatches(Matches.unitIsOwnedBy(player));
            // Determine sea and transport units that can be produced in this territory
            final List<ProPurchaseOption> seaTransportPurchaseOptionsForTerritory = ProPurchaseUtils.findPurchaseOptionsForTerritory(player, purchaseOptions.getSeaTransportOptions(), t, isBid);
            final List<ProPurchaseOption> amphibPurchaseOptionsForTerritory = ProPurchaseUtils.findPurchaseOptionsForTerritory(player, purchaseOptions.getLandOptions(), landTerritory, isBid);
            // Find transports that need loaded and units to ignore that are already paired up
            final List<Unit> transportsThatNeedUnits = new ArrayList<>();
            final Set<Unit> potentialUnitsToLoad = new HashSet<>();
            final Set<Territory> seaTerritories = data.getMap().getNeighbors(landTerritory, distance, ProMatches.territoryCanMoveSeaUnits(player, data, false));
            for (final Territory seaTerritory : seaTerritories) {
                final List<Unit> unitsInTerritory = ProPurchaseUtils.getPlaceUnits(seaTerritory, purchaseTerritories);
                unitsInTerritory.addAll(seaTerritory.getUnits().getUnits());
                final List<Unit> transports = CollectionUtils.getMatches(unitsInTerritory, ProMatches.unitIsOwnedTransport(player));
                for (final Unit transport : transports) {
                    transportsThatNeedUnits.add(transport);
                    final Set<Territory> territoriesToLoadFrom = new HashSet<>(data.getMap().getNeighbors(seaTerritory, distance));
                    territoriesToLoadFrom.removeIf(potentialTerritory -> potentialTerritory.isWater() || territoryValueMap.get(potentialTerritory) > 0.25);
                    final List<Unit> units = ProTransportUtils.getUnitsToTransportFromTerritories(player, transport, territoriesToLoadFrom, new ArrayList<>(potentialUnitsToLoad), ProMatches.unitIsOwnedCombatTransportableUnit(player));
                    potentialUnitsToLoad.addAll(units);
                }
            }
            // Determine whether transports, amphib units, or both are needed
            final Set<Territory> landNeighbors = data.getMap().getNeighbors(t, Matches.territoryIsLand());
            for (final Territory neighbor : landNeighbors) {
                if (territoryValueMap.get(neighbor) <= 0.25) {
                    final List<Unit> unitsInTerritory = new ArrayList<>(neighbor.getUnits().getUnits());
                    unitsInTerritory.addAll(ProPurchaseUtils.getPlaceUnits(neighbor, purchaseTerritories));
                    potentialUnitsToLoad.addAll(CollectionUtils.getMatches(unitsInTerritory, ProMatches.unitIsOwnedCombatTransportableUnit(player)));
                }
            }
            ProLogger.trace(t + ", potentialUnitsToLoad=" + potentialUnitsToLoad + ", transportsThatNeedUnits=" + transportsThatNeedUnits);
            // Purchase transports and amphib units
            final List<Unit> amphibUnitsToPlace = new ArrayList<>();
            final List<Unit> transportUnitsToPlace = new ArrayList<>();
            while (true) {
                if (!transportsThatNeedUnits.isEmpty()) {
                    // Get next empty transport and find its capacity
                    final Unit transport = transportsThatNeedUnits.get(0);
                    int transportCapacity = UnitAttachment.get(transport.getType()).getTransportCapacity();
                    // Find any existing units that can be transported
                    final List<Unit> selectedUnits = ProTransportUtils.selectUnitsToTransportFromList(transport, new ArrayList<>(potentialUnitsToLoad));
                    if (!selectedUnits.isEmpty()) {
                        potentialUnitsToLoad.removeAll(selectedUnits);
                        transportCapacity -= ProTransportUtils.findUnitsTransportCost(selectedUnits);
                    }
                    // Purchase units until transport is full
                    while (transportCapacity > 0) {
                        // Select amphib purchase option and add units
                        ProPurchaseUtils.removeInvalidPurchaseOptions(player, startOfTurnData, amphibPurchaseOptionsForTerritory, resourceTracker, remainingUnitProduction, amphibUnitsToPlace, purchaseTerritories);
                        final Map<ProPurchaseOption, Double> amphibEfficiencies = new HashMap<>();
                        for (final ProPurchaseOption ppo : amphibPurchaseOptionsForTerritory) {
                            if (ppo.getTransportCost() <= transportCapacity) {
                                amphibEfficiencies.put(ppo, ppo.getAmphibEfficiency(data, ownedLocalAmphibUnits, amphibUnitsToPlace));
                            }
                        }
                        final Optional<ProPurchaseOption> optionalSelectedOption = ProPurchaseUtils.randomizePurchaseOption(amphibEfficiencies, "Amphib");
                        if (!optionalSelectedOption.isPresent()) {
                            break;
                        }
                        final ProPurchaseOption ppo = optionalSelectedOption.get();
                        // Add amphib unit
                        final List<Unit> amphibUnits = ppo.getUnitType().create(ppo.getQuantity(), player, true);
                        amphibUnitsToPlace.addAll(amphibUnits);
                        resourceTracker.purchase(ppo);
                        remainingUnitProduction -= ppo.getQuantity();
                        transportCapacity -= ppo.getTransportCost();
                        ProLogger.trace("Selected unit=" + ppo.getUnitType().getName());
                    }
                    transportsThatNeedUnits.remove(transport);
                } else {
                    // Select purchase option
                    ProPurchaseUtils.removeInvalidPurchaseOptions(player, startOfTurnData, seaTransportPurchaseOptionsForTerritory, resourceTracker, remainingUnitProduction, transportUnitsToPlace, purchaseTerritories);
                    final Map<ProPurchaseOption, Double> transportEfficiencies = new HashMap<>();
                    for (final ProPurchaseOption ppo : seaTransportPurchaseOptionsForTerritory) {
                        transportEfficiencies.put(ppo, ppo.getTransportEfficiencyRatio());
                    }
                    final Optional<ProPurchaseOption> optionalSelectedOption = ProPurchaseUtils.randomizePurchaseOption(transportEfficiencies, "Sea Transport");
                    if (!optionalSelectedOption.isPresent()) {
                        break;
                    }
                    final ProPurchaseOption ppo = optionalSelectedOption.get();
                    // Add transports
                    final List<Unit> transports = ppo.getUnitType().create(ppo.getQuantity(), player, true);
                    transportUnitsToPlace.addAll(transports);
                    resourceTracker.purchase(ppo);
                    remainingUnitProduction -= ppo.getQuantity();
                    transportsThatNeedUnits.addAll(transports);
                    ProLogger.trace("Selected unit=" + ppo.getUnitType().getName() + ", potentialUnitsToLoad=" + potentialUnitsToLoad + ", transportsThatNeedUnits=" + transportsThatNeedUnits);
                }
            }
            // Add transport units to sea place territory and amphib units to land place territory
            for (final ProPlaceTerritory ppt : purchaseTerritory.getCanPlaceTerritories()) {
                if (landTerritory.equals(ppt.getTerritory())) {
                    ppt.getPlaceUnits().addAll(amphibUnitsToPlace);
                } else if (placeTerritory.equals(ppt)) {
                    ppt.getPlaceUnits().addAll(transportUnitsToPlace);
                }
            }
            ProLogger.trace(t + ", purchaseTerritory=" + landTerritory + ", transportUnitsToPlace=" + transportUnitsToPlace + ", amphibUnitsToPlace=" + amphibUnitsToPlace);
        }
    }
}
Also used : ProPlaceTerritory(games.strategy.triplea.ai.pro.data.ProPlaceTerritory) ProPurchaseTerritory(games.strategy.triplea.ai.pro.data.ProPurchaseTerritory) Territory(games.strategy.engine.data.Territory) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) ProPurchaseTerritory(games.strategy.triplea.ai.pro.data.ProPurchaseTerritory) ProBattleResult(games.strategy.triplea.ai.pro.data.ProBattleResult) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) ProPlaceTerritory(games.strategy.triplea.ai.pro.data.ProPlaceTerritory) ProPurchaseOption(games.strategy.triplea.ai.pro.data.ProPurchaseOption) ProOtherMoveOptions(games.strategy.triplea.ai.pro.data.ProOtherMoveOptions) Route(games.strategy.engine.data.Route) HashSet(java.util.HashSet)

Example 3 with ProOtherMoveOptions

use of games.strategy.triplea.ai.pro.data.ProOtherMoveOptions in project triplea by triplea-game.

the class ProCombatMoveAi method removeAttacksUntilCapitalCanBeHeld.

private void removeAttacksUntilCapitalCanBeHeld(final List<ProTerritory> prioritizedTerritories, final List<ProPurchaseOption> landPurchaseOptions) {
    ProLogger.info("Check capital defenses after attack moves");
    final Map<Territory, ProTerritory> attackMap = territoryManager.getAttackOptions().getTerritoryMap();
    final Territory myCapital = ProData.myCapital;
    // Add max purchase defenders to capital for non-mobile factories (don't consider mobile factories since they may
    // move elsewhere)
    final List<Unit> placeUnits = new ArrayList<>();
    if (ProMatches.territoryHasNonMobileInfraFactoryAndIsNotConqueredOwnedLand(player, data).test(myCapital)) {
        placeUnits.addAll(ProPurchaseUtils.findMaxPurchaseDefenders(player, myCapital, landPurchaseOptions));
    }
    // Remove attack until capital can be defended
    while (true) {
        if (prioritizedTerritories.isEmpty()) {
            break;
        }
        // Determine max enemy counter attack units
        final List<Territory> territoriesToAttack = new ArrayList<>();
        for (final ProTerritory t : prioritizedTerritories) {
            territoriesToAttack.add(t.getTerritory());
        }
        ProLogger.trace("Remaining territories to attack=" + territoriesToAttack);
        final List<Territory> territoriesToCheck = new ArrayList<>();
        territoriesToCheck.add(myCapital);
        territoryManager.populateEnemyAttackOptions(territoriesToAttack, territoriesToCheck);
        final ProOtherMoveOptions enemyAttackOptions = territoryManager.getEnemyAttackOptions();
        if (enemyAttackOptions.getMax(myCapital) == null) {
            break;
        }
        // Find max remaining defenders
        final Set<Territory> territoriesAdjacentToCapital = data.getMap().getNeighbors(myCapital, Matches.territoryIsLand());
        final List<Unit> defenders = myCapital.getUnits().getMatches(Matches.isUnitAllied(player, data));
        defenders.addAll(placeUnits);
        for (final Territory t : territoriesAdjacentToCapital) {
            defenders.addAll(t.getUnits().getMatches(ProMatches.unitCanBeMovedAndIsOwnedLand(player, false)));
        }
        for (final ProTerritory t : attackMap.values()) {
            defenders.removeAll(t.getUnits());
        }
        // Determine counter attack results to see if I can hold it
        final Set<Unit> enemyAttackingUnits = new HashSet<>(enemyAttackOptions.getMax(myCapital).getMaxUnits());
        enemyAttackingUnits.addAll(enemyAttackOptions.getMax(myCapital).getMaxAmphibUnits());
        final ProBattleResult result = calc.estimateDefendBattleResults(myCapital, new ArrayList<>(enemyAttackingUnits), defenders, enemyAttackOptions.getMax(myCapital).getMaxBombardUnits());
        ProLogger.trace("Current capital result hasLandUnitRemaining=" + result.isHasLandUnitRemaining() + ", TUVSwing=" + result.getTuvSwing() + ", defenders=" + defenders.size() + ", attackers=" + enemyAttackingUnits.size());
        // Determine attack that uses the most units per value from capital and remove it
        if (result.isHasLandUnitRemaining()) {
            double maxUnitsNearCapitalPerValue = 0.0;
            Territory maxTerritory = null;
            final Set<Territory> territoriesNearCapital = data.getMap().getNeighbors(myCapital, Matches.territoryIsLand());
            territoriesNearCapital.add(myCapital);
            for (final Territory t : attackMap.keySet()) {
                int unitsNearCapital = 0;
                for (final Unit u : attackMap.get(t).getUnits()) {
                    if (territoriesNearCapital.contains(ProData.unitTerritoryMap.get(u))) {
                        unitsNearCapital++;
                    }
                }
                final double unitsNearCapitalPerValue = unitsNearCapital / attackMap.get(t).getValue();
                ProLogger.trace(t.getName() + " has unit near capital per value: " + unitsNearCapitalPerValue);
                if (unitsNearCapitalPerValue > maxUnitsNearCapitalPerValue) {
                    maxUnitsNearCapitalPerValue = unitsNearCapitalPerValue;
                    maxTerritory = t;
                }
            }
            if (maxTerritory != null) {
                prioritizedTerritories.remove(attackMap.get(maxTerritory));
                attackMap.get(maxTerritory).getUnits().clear();
                attackMap.get(maxTerritory).getAmphibAttackMap().clear();
                attackMap.get(maxTerritory).setBattleResult(null);
                ProLogger.debug("Removing territory to try to hold capital: " + maxTerritory.getName());
            } else {
                break;
            }
        } else {
            ProLogger.debug("Can hold capital: " + myCapital.getName());
            break;
        }
    }
}
Also used : Territory(games.strategy.engine.data.Territory) ProTerritory(games.strategy.triplea.ai.pro.data.ProTerritory) ProTerritory(games.strategy.triplea.ai.pro.data.ProTerritory) ArrayList(java.util.ArrayList) ProBattleResult(games.strategy.triplea.ai.pro.data.ProBattleResult) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) ProOtherMoveOptions(games.strategy.triplea.ai.pro.data.ProOtherMoveOptions) HashSet(java.util.HashSet)

Example 4 with ProOtherMoveOptions

use of games.strategy.triplea.ai.pro.data.ProOtherMoveOptions in project triplea by triplea-game.

the class ProCombatMoveAi method removeTerritoriesThatArentWorthAttacking.

private void removeTerritoriesThatArentWorthAttacking(final List<ProTerritory> prioritizedTerritories) {
    ProLogger.info("Remove territories that aren't worth attacking");
    final ProOtherMoveOptions enemyAttackOptions = territoryManager.getEnemyAttackOptions();
    // Loop through all prioritized territories
    for (final Iterator<ProTerritory> it = prioritizedTerritories.iterator(); it.hasNext(); ) {
        final ProTerritory patd = it.next();
        final Territory t = patd.getTerritory();
        ProLogger.debug("Checking territory=" + patd.getTerritory().getName() + " with isAmphib=" + patd.isNeedAmphibUnits());
        // Remove empty convoy zones that can't be held
        if (!patd.isCanHold() && enemyAttackOptions.getMax(t) != null && t.isWater() && !t.getUnits().anyMatch(Matches.enemyUnit(player, data))) {
            ProLogger.debug("Removing convoy zone that can't be held: " + t.getName() + ", enemyAttackers=" + enemyAttackOptions.getMax(t).getMaxUnits());
            it.remove();
            continue;
        }
        // Remove neutral and low value amphib land territories that can't be held
        final boolean isNeutral = t.getOwner().isNull();
        final double strengthDifference = ProBattleUtils.estimateStrengthDifference(t, patd.getMaxUnits(), patd.getMaxEnemyDefenders(player, data));
        if (!patd.isCanHold() && enemyAttackOptions.getMax(t) != null && !t.isWater()) {
            if (isNeutral && strengthDifference <= 500) {
                // Remove neutral territories that can't be held and don't have overwhelming attack strength
                ProLogger.debug("Removing neutral territory that can't be held: " + t.getName() + ", enemyAttackers=" + enemyAttackOptions.getMax(t).getMaxUnits() + ", enemyAmphibAttackers=" + enemyAttackOptions.getMax(t).getMaxAmphibUnits() + ", strengthDifference=" + strengthDifference);
                it.remove();
                continue;
            } else if (patd.isNeedAmphibUnits() && patd.getValue() < 2) {
                // Remove amphib territories that aren't worth attacking
                ProLogger.debug("Removing low value amphib territory that can't be held: " + t.getName() + ", enemyAttackers=" + enemyAttackOptions.getMax(t).getMaxUnits() + ", enemyAmphibAttackers=" + enemyAttackOptions.getMax(t).getMaxAmphibUnits());
                it.remove();
                continue;
            }
        }
        // Remove neutral territories where attackers are adjacent to enemy territories that aren't being attacked
        if (isNeutral && !t.isWater() && strengthDifference <= 500) {
            // Get list of territories I'm attacking
            final List<Territory> prioritizedTerritoryList = new ArrayList<>();
            for (final ProTerritory prioritizedTerritory : prioritizedTerritories) {
                prioritizedTerritoryList.add(prioritizedTerritory.getTerritory());
            }
            // Find all territories units are attacking from that are adjacent to territory
            final Set<Territory> attackFromTerritories = new HashSet<>();
            for (final Unit u : patd.getMaxUnits()) {
                attackFromTerritories.add(ProData.unitTerritoryMap.get(u));
            }
            attackFromTerritories.retainAll(data.getMap().getNeighbors(t));
            // Determine if any of the attacking from territories has enemy neighbors that aren't being attacked
            boolean attackersHaveEnemyNeighbors = false;
            Territory attackFromTerritoryWithEnemyNeighbors = null;
            for (final Territory attackFromTerritory : attackFromTerritories) {
                final Set<Territory> enemyNeighbors = data.getMap().getNeighbors(attackFromTerritory, ProMatches.territoryIsEnemyNotNeutralLand(player, data));
                if (!prioritizedTerritoryList.containsAll(enemyNeighbors)) {
                    attackersHaveEnemyNeighbors = true;
                    attackFromTerritoryWithEnemyNeighbors = attackFromTerritory;
                    break;
                }
            }
            if (attackersHaveEnemyNeighbors) {
                ProLogger.debug("Removing neutral territory that has attackers that are adjacent to enemies: " + t.getName() + ", attackFromTerritory=" + attackFromTerritoryWithEnemyNeighbors);
                it.remove();
            }
        }
    }
}
Also used : Territory(games.strategy.engine.data.Territory) ProTerritory(games.strategy.triplea.ai.pro.data.ProTerritory) ProTerritory(games.strategy.triplea.ai.pro.data.ProTerritory) ArrayList(java.util.ArrayList) ProOtherMoveOptions(games.strategy.triplea.ai.pro.data.ProOtherMoveOptions) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) HashSet(java.util.HashSet)

Example 5 with ProOtherMoveOptions

use of games.strategy.triplea.ai.pro.data.ProOtherMoveOptions in project triplea by triplea-game.

the class ProNonCombatMoveAi method prioritizeDefendOptions.

private List<ProTerritory> prioritizeDefendOptions(final Map<Territory, ProTerritory> factoryMoveMap, final Map<Territory, Double> territoryValueMap) {
    ProLogger.info("Prioritizing territories to try to defend");
    final Map<Territory, ProTerritory> moveMap = territoryManager.getDefendOptions().getTerritoryMap();
    final ProOtherMoveOptions enemyAttackOptions = territoryManager.getEnemyAttackOptions();
    // Calculate value of defending territory
    for (final Territory t : moveMap.keySet()) {
        // Determine if it is my capital or adjacent to my capital
        int isMyCapital = 0;
        if (t.equals(ProData.myCapital)) {
            isMyCapital = 1;
        }
        // Determine if it has a factory
        int isFactory = 0;
        if (ProMatches.territoryHasInfraFactoryAndIsLand().test(t) || (factoryMoveMap != null && factoryMoveMap.containsKey(t))) {
            isFactory = 1;
        }
        // Determine production value and if it is an enemy capital
        int production = 0;
        int isEnemyOrAlliedCapital = 0;
        final TerritoryAttachment ta = TerritoryAttachment.get(t);
        if (ta != null) {
            production = ta.getProduction();
            if (ta.isCapital() && !t.equals(ProData.myCapital)) {
                isEnemyOrAlliedCapital = 1;
            }
        }
        // Determine neighbor value
        double neighborValue = 0;
        if (!t.isWater()) {
            final Set<Territory> landNeighbors = data.getMap().getNeighbors(t, Matches.territoryIsLand());
            for (final Territory neighbor : landNeighbors) {
                double neighborProduction = TerritoryAttachment.getProduction(neighbor);
                if (Matches.isTerritoryAllied(player, data).test(neighbor)) {
                    neighborProduction = 0.1 * neighborProduction;
                }
                neighborValue += neighborProduction;
            }
        }
        // Determine defending unit value
        final int cantMoveUnitValue = TuvUtils.getTuv(moveMap.get(t).getCantMoveUnits(), ProData.unitValueMap);
        double unitOwnerMultiplier = 1;
        if (moveMap.get(t).getCantMoveUnits().stream().noneMatch(Matches.unitIsOwnedBy(player))) {
            if (t.isWater() && moveMap.get(t).getCantMoveUnits().stream().noneMatch(Matches.unitIsTransportButNotCombatTransport())) {
                unitOwnerMultiplier = 0;
            } else {
                unitOwnerMultiplier = 0.5;
            }
        }
        // Calculate defense value for prioritization
        final double territoryValue = unitOwnerMultiplier * (2 * production + 10 * isFactory + 0.5 * cantMoveUnitValue + 0.5 * neighborValue) * (1 + 10 * isMyCapital) * (1 + 4 * isEnemyOrAlliedCapital);
        moveMap.get(t).setValue(territoryValue);
    }
    // Sort attack territories by value
    final List<ProTerritory> prioritizedTerritories = new ArrayList<>(moveMap.values());
    prioritizedTerritories.sort(Comparator.comparingDouble(ProTerritory::getValue));
    // Remove territories that I'm not going to try to defend
    for (final Iterator<ProTerritory> it = prioritizedTerritories.iterator(); it.hasNext(); ) {
        final ProTerritory patd = it.next();
        final Territory t = patd.getTerritory();
        final boolean hasFactory = ProMatches.territoryHasInfraFactoryAndIsLand().test(t);
        final ProBattleResult minResult = patd.getMinBattleResult();
        final int cantMoveUnitValue = TuvUtils.getTuv(moveMap.get(t).getCantMoveUnits(), ProData.unitValueMap);
        final List<Unit> maxEnemyUnits = patd.getMaxEnemyUnits();
        final boolean isLandAndCanOnlyBeAttackedByAir = !t.isWater() && !maxEnemyUnits.isEmpty() && maxEnemyUnits.stream().allMatch(Matches.unitIsAir());
        final boolean isNotFactoryAndShouldHold = !hasFactory && (minResult.getTuvSwing() <= 0 || !minResult.isHasLandUnitRemaining());
        final boolean canAlreadyBeHeld = minResult.getTuvSwing() <= 0 && minResult.getWinPercentage() < (100 - ProData.winPercentage);
        final boolean isNotFactoryAndHasNoEnemyNeighbors = !t.isWater() && !hasFactory && !ProMatches.territoryHasNeighborOwnedByAndHasLandUnit(data, ProUtils.getPotentialEnemyPlayers(player)).test(t);
        final boolean isNotFactoryAndOnlyAmphib = !t.isWater() && !hasFactory && moveMap.get(t).getMaxUnits().stream().noneMatch(Matches.unitIsLand()) && cantMoveUnitValue < 5;
        if (!patd.isCanHold() || patd.getValue() <= 0 || isLandAndCanOnlyBeAttackedByAir || isNotFactoryAndShouldHold || canAlreadyBeHeld || isNotFactoryAndHasNoEnemyNeighbors || isNotFactoryAndOnlyAmphib) {
            final double tuvSwing = minResult.getTuvSwing();
            final boolean hasRemainingLandUnit = minResult.isHasLandUnitRemaining();
            ProLogger.debug("Removing territory=" + t.getName() + ", value=" + patd.getValue() + ", CanHold=" + patd.isCanHold() + ", isLandAndCanOnlyBeAttackedByAir=" + isLandAndCanOnlyBeAttackedByAir + ", isNotFactoryAndShouldHold=" + isNotFactoryAndShouldHold + ", canAlreadyBeHeld=" + canAlreadyBeHeld + ", isNotFactoryAndHasNoEnemyNeighbors=" + isNotFactoryAndHasNoEnemyNeighbors + ", isNotFactoryAndOnlyAmphib=" + isNotFactoryAndOnlyAmphib + ", tuvSwing=" + tuvSwing + ", hasRemainingLandUnit=" + hasRemainingLandUnit + ", maxEnemyUnits=" + patd.getMaxEnemyUnits().size());
            it.remove();
        }
    }
    // Add best sea production territory for sea factories
    List<Territory> seaFactories = CollectionUtils.getMatches(data.getMap().getTerritories(), ProMatches.territoryHasInfraFactoryAndIsNotConqueredOwnedLand(player, data));
    seaFactories = CollectionUtils.getMatches(seaFactories, ProMatches.territoryHasInfraFactoryAndIsOwnedLandAdjacentToSea(player, data));
    for (final Territory t : seaFactories) {
        if (territoryValueMap.get(t) >= 1) {
            continue;
        }
        final Set<Territory> neighbors = data.getMap().getNeighbors(t, ProMatches.territoryCanMoveSeaUnits(player, data, true));
        double maxValue = 0;
        Territory maxTerritory = null;
        for (final Territory neighbor : neighbors) {
            if (moveMap.get(neighbor) != null && moveMap.get(neighbor).isCanHold() && territoryValueMap.get(neighbor) > maxValue) {
                maxTerritory = neighbor;
                maxValue = territoryValueMap.get(neighbor);
            }
        }
        if (maxTerritory != null && enemyAttackOptions.getMax(maxTerritory) != null) {
            boolean alreadyAdded = false;
            for (final ProTerritory patd : prioritizedTerritories) {
                if (patd.getTerritory().equals(maxTerritory)) {
                    alreadyAdded = true;
                }
            }
            if (!alreadyAdded) {
                prioritizedTerritories.add(moveMap.get(maxTerritory));
            }
        }
    }
    // Log prioritized territories
    for (final ProTerritory attackTerritoryData : prioritizedTerritories) {
        ProLogger.debug("Value=" + attackTerritoryData.getValue() + ", " + attackTerritoryData.getTerritory().getName());
    }
    return prioritizedTerritories;
}
Also used : ProPlaceTerritory(games.strategy.triplea.ai.pro.data.ProPlaceTerritory) ProPurchaseTerritory(games.strategy.triplea.ai.pro.data.ProPurchaseTerritory) ProTerritory(games.strategy.triplea.ai.pro.data.ProTerritory) Territory(games.strategy.engine.data.Territory) ProTerritory(games.strategy.triplea.ai.pro.data.ProTerritory) TerritoryAttachment(games.strategy.triplea.attachments.TerritoryAttachment) ArrayList(java.util.ArrayList) ProBattleResult(games.strategy.triplea.ai.pro.data.ProBattleResult) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) ProOtherMoveOptions(games.strategy.triplea.ai.pro.data.ProOtherMoveOptions)

Aggregations

Territory (games.strategy.engine.data.Territory)15 Unit (games.strategy.engine.data.Unit)15 TripleAUnit (games.strategy.triplea.TripleAUnit)15 ProOtherMoveOptions (games.strategy.triplea.ai.pro.data.ProOtherMoveOptions)15 ArrayList (java.util.ArrayList)13 HashSet (java.util.HashSet)13 ProBattleResult (games.strategy.triplea.ai.pro.data.ProBattleResult)12 ProPlaceTerritory (games.strategy.triplea.ai.pro.data.ProPlaceTerritory)9 ProPurchaseTerritory (games.strategy.triplea.ai.pro.data.ProPurchaseTerritory)9 ProTerritory (games.strategy.triplea.ai.pro.data.ProTerritory)8 ProPurchaseOption (games.strategy.triplea.ai.pro.data.ProPurchaseOption)4 TerritoryAttachment (games.strategy.triplea.attachments.TerritoryAttachment)4 HashMap (java.util.HashMap)4 Set (java.util.Set)2 TreeMap (java.util.TreeMap)2 Route (games.strategy.engine.data.Route)1 ProTransport (games.strategy.triplea.ai.pro.data.ProTransport)1 PlaceableUnits (games.strategy.triplea.delegate.dataObjects.PlaceableUnits)1 Collection (java.util.Collection)1 LinkedHashSet (java.util.LinkedHashSet)1