Search in sources :

Example 6 with ProBattleResult

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

Example 7 with ProBattleResult

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

the class ProSimulateTurnUtils method simulateBattles.

public static void simulateBattles(final GameData data, final PlayerID player, final IDelegateBridge delegateBridge, final ProOddsCalculator calc) {
    ProLogger.info("Starting battle simulation phase");
    final BattleDelegate battleDelegate = DelegateFinder.battleDelegate(data);
    final Map<BattleType, Collection<Territory>> battleTerritories = battleDelegate.getBattles().getBattles();
    for (final Entry<BattleType, Collection<Territory>> entry : battleTerritories.entrySet()) {
        for (final Territory t : entry.getValue()) {
            final IBattle battle = battleDelegate.getBattleTracker().getPendingBattle(t, entry.getKey().isBombingRun(), entry.getKey());
            final List<Unit> attackers = (List<Unit>) battle.getAttackingUnits();
            attackers.retainAll(t.getUnits().getUnits());
            final List<Unit> defenders = (List<Unit>) battle.getDefendingUnits();
            defenders.retainAll(t.getUnits().getUnits());
            final Set<Unit> bombardingUnits = new HashSet<>(battle.getBombardingUnits());
            ProLogger.debug("---" + t);
            ProLogger.debug("attackers=" + attackers);
            ProLogger.debug("defenders=" + defenders);
            ProLogger.debug("bombardingUnits=" + bombardingUnits);
            final ProBattleResult result = calc.callBattleCalculator(t, attackers, defenders, bombardingUnits);
            final List<Unit> remainingUnits = result.getAverageAttackersRemaining();
            ProLogger.debug("remainingUnits=" + remainingUnits);
            // Make updates to data
            final List<Unit> attackersToRemove = new ArrayList<>(attackers);
            attackersToRemove.removeAll(remainingUnits);
            final List<Unit> defendersToRemove = CollectionUtils.getMatches(defenders, Matches.unitIsInfrastructure().negate());
            final List<Unit> infrastructureToChangeOwner = CollectionUtils.getMatches(defenders, Matches.unitIsInfrastructure());
            ProLogger.debug("attackersToRemove=" + attackersToRemove);
            ProLogger.debug("defendersToRemove=" + defendersToRemove);
            ProLogger.debug("infrastructureToChangeOwner=" + infrastructureToChangeOwner);
            final Change attackerskilledChange = ChangeFactory.removeUnits(t, attackersToRemove);
            delegateBridge.addChange(attackerskilledChange);
            final Change defenderskilledChange = ChangeFactory.removeUnits(t, defendersToRemove);
            delegateBridge.addChange(defenderskilledChange);
            BattleTracker.captureOrDestroyUnits(t, player, player, delegateBridge, null);
            if (!checkIfCapturedTerritoryIsAlliedCapital(t, data, player, delegateBridge)) {
                delegateBridge.addChange(ChangeFactory.changeOwner(t, player));
            }
            battleDelegate.getBattleTracker().getConquered().add(t);
            battleDelegate.getBattleTracker().removeBattle(battle);
            final Territory updatedTerritory = data.getMap().getTerritory(t.getName());
            ProLogger.debug("after changes owner=" + updatedTerritory.getOwner() + ", units=" + updatedTerritory.getUnits().getUnits());
        }
    }
}
Also used : BattleDelegate(games.strategy.triplea.delegate.BattleDelegate) Territory(games.strategy.engine.data.Territory) ProTerritory(games.strategy.triplea.ai.pro.data.ProTerritory) ArrayList(java.util.ArrayList) BattleType(games.strategy.triplea.delegate.IBattle.BattleType) ProBattleResult(games.strategy.triplea.ai.pro.data.ProBattleResult) Change(games.strategy.engine.data.Change) Unit(games.strategy.engine.data.Unit) IBattle(games.strategy.triplea.delegate.IBattle) Collection(java.util.Collection) ArrayList(java.util.ArrayList) List(java.util.List) HashSet(java.util.HashSet)

Example 8 with ProBattleResult

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

the class ProOddsCalculator method estimateDefendBattleResults.

public ProBattleResult estimateDefendBattleResults(final Territory t, final List<Unit> attackingUnits, final List<Unit> defendingUnits, final Set<Unit> bombardingUnits) {
    final ProBattleResult result = checkIfNoAttackersOrDefenders(t, attackingUnits, defendingUnits);
    if (result != null) {
        return result;
    }
    // Determine if defenders have no chance
    final double strengthDifference = ProBattleUtils.estimateStrengthDifference(t, attackingUnits, defendingUnits);
    if (strengthDifference > 55) {
        final boolean isLandAndCanOnlyBeAttackedByAir = !t.isWater() && !attackingUnits.isEmpty() && attackingUnits.stream().allMatch(Matches.unitIsAir());
        return new ProBattleResult(100 + strengthDifference, 999 + strengthDifference, !isLandAndCanOnlyBeAttackedByAir, attackingUnits, new ArrayList<>(), 1);
    }
    return callBattleCalculator(t, attackingUnits, defendingUnits, bombardingUnits);
}
Also used : ProBattleResult(games.strategy.triplea.ai.pro.data.ProBattleResult)

Example 9 with ProBattleResult

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

the class ProOddsCalculator method callBattleCalculator.

public ProBattleResult callBattleCalculator(final Territory t, final List<Unit> attackingUnits, final List<Unit> defendingUnits, final Set<Unit> bombardingUnits, final boolean retreatWhenOnlyAirLeft) {
    final GameData data = ProData.getData();
    if (isCanceled || attackingUnits.isEmpty() || defendingUnits.isEmpty()) {
        return new ProBattleResult();
    }
    final int minArmySize = Math.min(attackingUnits.size(), defendingUnits.size());
    final int runCount = Math.max(16, 100 - minArmySize);
    final PlayerID attacker = attackingUnits.get(0).getOwner();
    final PlayerID defender = defendingUnits.get(0).getOwner();
    if (retreatWhenOnlyAirLeft) {
        calc.setRetreatWhenOnlyAirLeft(true);
    }
    final AggregateResults results = calc.setCalculateDataAndCalculate(attacker, defender, t, attackingUnits, defendingUnits, new ArrayList<>(bombardingUnits), TerritoryEffectHelper.getEffects(t), runCount);
    if (retreatWhenOnlyAirLeft) {
        calc.setRetreatWhenOnlyAirLeft(false);
    }
    // Find battle result statistics
    final double winPercentage = results.getAttackerWinPercent() * 100;
    final List<Unit> averageAttackersRemaining = results.getAverageAttackingUnitsRemaining();
    final List<Unit> averageDefendersRemaining = results.getAverageDefendingUnitsRemaining();
    final List<Unit> mainCombatAttackers = CollectionUtils.getMatches(attackingUnits, Matches.unitCanBeInBattle(true, !t.isWater(), 1, false, true, true));
    final List<Unit> mainCombatDefenders = CollectionUtils.getMatches(defendingUnits, Matches.unitCanBeInBattle(false, !t.isWater(), 1, false, true, true));
    double tuvSwing = results.getAverageTuvSwing(attacker, mainCombatAttackers, defender, mainCombatDefenders, data);
    if (Matches.territoryIsNeutralButNotWater().test(t)) {
        // Set TUV swing for neutrals
        final double attackingUnitValue = TuvUtils.getTuv(mainCombatAttackers, ProData.unitValueMap);
        final double remainingUnitValue = results.getAverageTuvOfUnitsLeftOver(ProData.unitValueMap, ProData.unitValueMap).getFirst();
        tuvSwing = remainingUnitValue - attackingUnitValue;
    }
    final List<Unit> defendingTransportedUnits = CollectionUtils.getMatches(defendingUnits, Matches.unitIsBeingTransported());
    if (t.isWater() && !defendingTransportedUnits.isEmpty()) {
        // Add TUV swing for transported units
        final double transportedUnitValue = TuvUtils.getTuv(defendingTransportedUnits, ProData.unitValueMap);
        tuvSwing += transportedUnitValue * winPercentage / 100;
    }
    // Create battle result object
    final List<Territory> territoryList = new ArrayList<>();
    territoryList.add(t);
    return (!territoryList.isEmpty() && territoryList.stream().allMatch(Matches.territoryIsLand())) ? new ProBattleResult(winPercentage, tuvSwing, averageAttackersRemaining.stream().anyMatch(Matches.unitIsLand()), averageAttackersRemaining, averageDefendersRemaining, results.getAverageBattleRoundsFought()) : new ProBattleResult(winPercentage, tuvSwing, !averageAttackersRemaining.isEmpty(), averageAttackersRemaining, averageDefendersRemaining, results.getAverageBattleRoundsFought());
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) Territory(games.strategy.engine.data.Territory) GameData(games.strategy.engine.data.GameData) AggregateResults(games.strategy.triplea.oddsCalculator.ta.AggregateResults) ArrayList(java.util.ArrayList) ProBattleResult(games.strategy.triplea.ai.pro.data.ProBattleResult) Unit(games.strategy.engine.data.Unit)

Example 10 with ProBattleResult

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

the class ProOddsCalculator method checkIfNoAttackersOrDefenders.

private static ProBattleResult checkIfNoAttackersOrDefenders(final Territory t, final List<Unit> attackingUnits, final List<Unit> defendingUnits) {
    final GameData data = ProData.getData();
    final boolean hasNoDefenders = defendingUnits.stream().noneMatch(Matches.unitIsNotInfrastructure());
    final boolean isLandAndCanOnlyBeAttackedByAir = !t.isWater() && !attackingUnits.isEmpty() && attackingUnits.stream().allMatch(Matches.unitIsAir());
    if (attackingUnits.size() == 0 || hasNoDefenders && isLandAndCanOnlyBeAttackedByAir) {
        return new ProBattleResult();
    } else if (hasNoDefenders) {
        return new ProBattleResult(100, 0.1, true, attackingUnits, new ArrayList<>(), 0);
    } else if (Properties.getSubRetreatBeforeBattle(data) && !defendingUnits.isEmpty() && defendingUnits.stream().allMatch(Matches.unitIsSub()) && attackingUnits.stream().noneMatch(Matches.unitIsDestroyer())) {
        return new ProBattleResult();
    }
    return null;
}
Also used : GameData(games.strategy.engine.data.GameData) ArrayList(java.util.ArrayList) ProBattleResult(games.strategy.triplea.ai.pro.data.ProBattleResult)

Aggregations

ProBattleResult (games.strategy.triplea.ai.pro.data.ProBattleResult)24 ArrayList (java.util.ArrayList)21 Territory (games.strategy.engine.data.Territory)20 Unit (games.strategy.engine.data.Unit)20 TripleAUnit (games.strategy.triplea.TripleAUnit)15 HashSet (java.util.HashSet)15 ProOtherMoveOptions (games.strategy.triplea.ai.pro.data.ProOtherMoveOptions)12 ProTerritory (games.strategy.triplea.ai.pro.data.ProTerritory)12 ProPlaceTerritory (games.strategy.triplea.ai.pro.data.ProPlaceTerritory)10 ProPurchaseTerritory (games.strategy.triplea.ai.pro.data.ProPurchaseTerritory)10 HashMap (java.util.HashMap)7 List (java.util.List)6 GameData (games.strategy.engine.data.GameData)5 TerritoryAttachment (games.strategy.triplea.attachments.TerritoryAttachment)5 Collection (java.util.Collection)5 Set (java.util.Set)5 PlayerID (games.strategy.engine.data.PlayerID)4 BattleDelegate (games.strategy.triplea.delegate.BattleDelegate)4 IBattle (games.strategy.triplea.delegate.IBattle)4 TreeMap (java.util.TreeMap)4