Search in sources :

Example 1 with ProTerritory

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

the class ProTransportUtils method getUnitsToTransportThatCantMoveToHigherValue.

public static List<Unit> getUnitsToTransportThatCantMoveToHigherValue(final PlayerID player, final Unit transport, final Set<Territory> territoriesToLoadFrom, final List<Unit> unitsToIgnore, final Map<Territory, ProTerritory> moveMap, final Map<Unit, Set<Territory>> unitMoveMap, final double value) {
    final List<Unit> unitsToIgnoreOrHaveBetterLandMove = new ArrayList<>(unitsToIgnore);
    if (!TransportTracker.isTransporting(transport)) {
        // Get all units that can be transported
        final List<Unit> units = new ArrayList<>();
        for (final Territory loadFrom : territoriesToLoadFrom) {
            units.addAll(loadFrom.getUnits().getMatches(ProMatches.unitIsOwnedTransportableUnitAndCanBeLoaded(player, transport, true)));
        }
        units.removeAll(unitsToIgnore);
        // Check to see which have higher land move value
        for (final Unit u : units) {
            if (unitMoveMap.get(u) != null) {
                for (final Territory t : unitMoveMap.get(u)) {
                    if (moveMap.get(t) != null && moveMap.get(t).getValue() > value) {
                        unitsToIgnoreOrHaveBetterLandMove.add(u);
                        break;
                    }
                }
            }
        }
    }
    return getUnitsToTransportFromTerritories(player, transport, territoriesToLoadFrom, unitsToIgnoreOrHaveBetterLandMove);
}
Also used : Territory(games.strategy.engine.data.Territory) ProTerritory(games.strategy.triplea.ai.pro.data.ProTerritory) ArrayList(java.util.ArrayList) Unit(games.strategy.engine.data.Unit)

Example 2 with ProTerritory

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

the class ProCombatMoveAi method prioritizeAttackOptions.

private List<ProTerritory> prioritizeAttackOptions(final PlayerID player, final List<ProTerritory> attackOptions) {
    ProLogger.info("Prioritizing territories to try to attack");
    // Calculate value of attacking territory
    for (final Iterator<ProTerritory> it = attackOptions.iterator(); it.hasNext(); ) {
        final ProTerritory patd = it.next();
        final Territory t = patd.getTerritory();
        // Determine territory attack properties
        final int isLand = !t.isWater() ? 1 : 0;
        final int isNeutral = (!t.isWater() && t.getOwner().isNull()) ? 1 : 0;
        final int isCanHold = patd.isCanHold() ? 1 : 0;
        final int isAmphib = patd.isNeedAmphibUnits() ? 1 : 0;
        final List<Unit> defendingUnits = CollectionUtils.getMatches(patd.getMaxEnemyDefenders(player, data), ProMatches.unitIsEnemyAndNotInfa(player, data));
        final int isEmptyLand = (defendingUnits.isEmpty() && !patd.isNeedAmphibUnits()) ? 1 : 0;
        final boolean isAdjacentToMyCapital = !data.getMap().getNeighbors(t, Matches.territoryIs(ProData.myCapital)).isEmpty();
        final int isNotNeutralAdjacentToMyCapital = (isAdjacentToMyCapital && ProMatches.territoryIsEnemyNotNeutralLand(player, data).test(t)) ? 1 : 0;
        final int isFactory = ProMatches.territoryHasInfraFactoryAndIsLand().test(t) ? 1 : 0;
        final int isFfa = ProUtils.isFfa(data, player) ? 1 : 0;
        // Determine production value and if it is an enemy capital
        int production = 0;
        int isEnemyCapital = 0;
        final TerritoryAttachment ta = TerritoryAttachment.get(t);
        if (ta != null) {
            production = ta.getProduction();
            if (ta.isCapital()) {
                isEnemyCapital = 1;
            }
        }
        // Calculate attack value for prioritization
        double tuvSwing = patd.getMaxBattleResult().getTuvSwing();
        if (isFfa == 1 && tuvSwing > 0) {
            tuvSwing *= 0.5;
        }
        final double territoryValue = (1 + isLand + isCanHold * (1 + 2 * isFfa)) * (1 + isEmptyLand) * (1 + isFactory) * (1 - 0.5 * isAmphib) * production;
        double attackValue = (tuvSwing + territoryValue) * (1 + 4 * isEnemyCapital) * (1 + 2 * isNotNeutralAdjacentToMyCapital) * (1 - 0.9 * isNeutral);
        // Check if a negative value neutral territory should be attacked
        if (attackValue <= 0 && !patd.isNeedAmphibUnits() && !t.isWater() && t.getOwner().isNull()) {
            // Determine enemy neighbor territory production value for neutral land territories
            double nearbyEnemyValue = 0;
            final List<Territory> cantReachEnemyTerritories = new ArrayList<>();
            final Set<Territory> nearbyTerritories = data.getMap().getNeighbors(t, ProMatches.territoryCanMoveLandUnits(player, data, true));
            final List<Territory> nearbyEnemyTerritories = CollectionUtils.getMatches(nearbyTerritories, Matches.isTerritoryEnemy(player, data));
            final List<Territory> nearbyTerritoriesWithOwnedUnits = CollectionUtils.getMatches(nearbyTerritories, Matches.territoryHasUnitsOwnedBy(player));
            for (final Territory nearbyEnemyTerritory : nearbyEnemyTerritories) {
                boolean allAlliedNeighborsHaveRoute = true;
                for (final Territory nearbyAlliedTerritory : nearbyTerritoriesWithOwnedUnits) {
                    final int distance = data.getMap().getDistance_IgnoreEndForCondition(nearbyAlliedTerritory, nearbyEnemyTerritory, ProMatches.territoryIsEnemyNotNeutralOrAllied(player, data));
                    if (distance < 0 || distance > 2) {
                        allAlliedNeighborsHaveRoute = false;
                        break;
                    }
                }
                if (!allAlliedNeighborsHaveRoute) {
                    final double value = ProTerritoryValueUtils.findTerritoryAttackValue(player, nearbyEnemyTerritory);
                    if (value > 0) {
                        nearbyEnemyValue += value;
                    }
                    cantReachEnemyTerritories.add(nearbyEnemyTerritory);
                }
            }
            ProLogger.debug(t.getName() + " calculated nearby enemy value=" + nearbyEnemyValue + " from " + cantReachEnemyTerritories);
            if (nearbyEnemyValue > 0) {
                ProLogger.trace(t.getName() + " updating negative neutral attack value=" + attackValue);
                attackValue = nearbyEnemyValue * .001 / (1 - attackValue);
            } else {
                // Check if overwhelming attack strength (more than 5 times)
                final double strengthDifference = ProBattleUtils.estimateStrengthDifference(t, patd.getMaxUnits(), patd.getMaxEnemyDefenders(player, data));
                ProLogger.debug(t.getName() + " calculated strengthDifference=" + strengthDifference);
                if (strengthDifference > 500) {
                    ProLogger.trace(t.getName() + " updating negative neutral attack value=" + attackValue);
                    attackValue = strengthDifference * .00001 / (1 - attackValue);
                }
            }
        }
        // Remove negative value territories
        patd.setValue(attackValue);
        if (attackValue <= 0 || (isDefensive && attackValue <= 8 && data.getMap().getDistance(ProData.myCapital, t) <= 3)) {
            ProLogger.debug("Removing territory that has a negative attack value: " + t.getName() + ", AttackValue=" + patd.getValue());
            it.remove();
        }
    }
    // Sort attack territories by value
    attackOptions.sort(Comparator.comparingDouble(ProTerritory::getValue));
    // Log prioritized territories
    for (final ProTerritory patd : attackOptions) {
        ProLogger.debug("AttackValue=" + patd.getValue() + ", TUVSwing=" + patd.getMaxBattleResult().getTuvSwing() + ", isAmphib=" + patd.isNeedAmphibUnits() + ", " + patd.getTerritory().getName());
    }
    return attackOptions;
}
Also used : Territory(games.strategy.engine.data.Territory) ProTerritory(games.strategy.triplea.ai.pro.data.ProTerritory) ProTerritory(games.strategy.triplea.ai.pro.data.ProTerritory) TerritoryAttachment(games.strategy.triplea.attachments.TerritoryAttachment) ArrayList(java.util.ArrayList) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit)

Example 3 with ProTerritory

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

the class ProCombatMoveAi method determineTerritoriesToAttack.

private void determineTerritoriesToAttack(final List<ProTerritory> prioritizedTerritories) {
    ProLogger.info("Determine which territories to attack");
    // Assign units to territories by prioritization
    int numToAttack = Math.min(1, prioritizedTerritories.size());
    boolean haveRemovedAllAmphibTerritories = false;
    while (true) {
        final List<ProTerritory> territoriesToTryToAttack = prioritizedTerritories.subList(0, numToAttack);
        ProLogger.debug("Current number of territories: " + numToAttack);
        tryToAttackTerritories(territoriesToTryToAttack, new ArrayList<>());
        // Determine if all attacks are successful
        boolean areSuccessful = true;
        for (final ProTerritory patd : territoriesToTryToAttack) {
            final Territory t = patd.getTerritory();
            if (patd.getBattleResult() == null) {
                patd.setBattleResult(calc.estimateAttackBattleResults(t, patd.getUnits(), patd.getMaxEnemyDefenders(player, data), patd.getBombardTerritoryMap().keySet()));
            }
            ProLogger.trace(patd.getResultString() + " with attackers: " + patd.getUnits());
            final double estimate = ProBattleUtils.estimateStrengthDifference(t, patd.getUnits(), patd.getMaxEnemyDefenders(player, data));
            final ProBattleResult result = patd.getBattleResult();
            if (!patd.isStrafing() && estimate < patd.getStrengthEstimate() && (result.getWinPercentage() < ProData.minWinPercentage || !result.isHasLandUnitRemaining())) {
                areSuccessful = false;
            }
        }
        // Determine whether to try more territories, remove a territory, or end
        if (areSuccessful) {
            for (final ProTerritory patd : territoriesToTryToAttack) {
                patd.setCanAttack(true);
                final double estimate = ProBattleUtils.estimateStrengthDifference(patd.getTerritory(), patd.getUnits(), patd.getMaxEnemyDefenders(player, data));
                if (estimate < patd.getStrengthEstimate()) {
                    patd.setStrengthEstimate(estimate);
                }
            }
            // If already used all transports then remove any remaining amphib territories
            if (!haveRemovedAllAmphibTerritories) {
                if (territoryManager.haveUsedAllAttackTransports()) {
                    final List<ProTerritory> amphibTerritoriesToRemove = new ArrayList<>();
                    for (int i = numToAttack; i < prioritizedTerritories.size(); i++) {
                        if (prioritizedTerritories.get(i).isNeedAmphibUnits()) {
                            amphibTerritoriesToRemove.add(prioritizedTerritories.get(i));
                            ProLogger.debug("Removing amphib territory since already used all transports: " + prioritizedTerritories.get(i).getTerritory().getName());
                        }
                    }
                    prioritizedTerritories.removeAll(amphibTerritoriesToRemove);
                    haveRemovedAllAmphibTerritories = true;
                }
            }
            // Can attack all territories in list so end
            numToAttack++;
            if (numToAttack > prioritizedTerritories.size()) {
                break;
            }
        } else {
            ProLogger.debug("Removing territory: " + prioritizedTerritories.get(numToAttack - 1).getTerritory().getName());
            prioritizedTerritories.remove(numToAttack - 1);
            if (numToAttack > prioritizedTerritories.size()) {
                numToAttack--;
            }
        }
    }
    ProLogger.debug("Final number of territories: " + (numToAttack - 1));
}
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)

Example 4 with ProTerritory

use of games.strategy.triplea.ai.pro.data.ProTerritory 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 5 with ProTerritory

use of games.strategy.triplea.ai.pro.data.ProTerritory 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)

Aggregations

ProTerritory (games.strategy.triplea.ai.pro.data.ProTerritory)32 Territory (games.strategy.engine.data.Territory)31 Unit (games.strategy.engine.data.Unit)29 ArrayList (java.util.ArrayList)26 TripleAUnit (games.strategy.triplea.TripleAUnit)24 HashSet (java.util.HashSet)16 ProBattleResult (games.strategy.triplea.ai.pro.data.ProBattleResult)11 ProPurchaseTerritory (games.strategy.triplea.ai.pro.data.ProPurchaseTerritory)11 Set (java.util.Set)11 ProPlaceTerritory (games.strategy.triplea.ai.pro.data.ProPlaceTerritory)10 GameData (games.strategy.engine.data.GameData)9 HashMap (java.util.HashMap)9 ProOtherMoveOptions (games.strategy.triplea.ai.pro.data.ProOtherMoveOptions)8 LinkedHashSet (java.util.LinkedHashSet)7 Route (games.strategy.engine.data.Route)6 List (java.util.List)6 Map (java.util.Map)6 TerritoryAttachment (games.strategy.triplea.attachments.TerritoryAttachment)5 ProTransport (games.strategy.triplea.ai.pro.data.ProTransport)4 Collection (java.util.Collection)4