Search in sources :

Example 41 with GameData

use of games.strategy.engine.data.GameData in project triplea by triplea-game.

the class WeakAi method populateCombatMove.

private static void populateCombatMove(final GameData data, final List<Collection<Unit>> moveUnits, final List<Route> moveRoutes, final PlayerID player) {
    populateBomberCombat(data, moveUnits, moveRoutes, player);
    final Collection<Unit> unitsAlreadyMoved = new HashSet<>();
    // find the territories we can just walk into
    final Predicate<Territory> walkInto = Matches.isTerritoryEnemyAndNotUnownedWaterOrImpassableOrRestricted(player, data).or(Matches.isTerritoryFreeNeutral(data));
    final List<Territory> enemyOwned = CollectionUtils.getMatches(data.getMap().getTerritories(), walkInto);
    Collections.shuffle(enemyOwned);
    enemyOwned.sort((o1, o2) -> {
        // -1 means o1 goes first. 1 means o2 goes first. zero means they are equal.
        if (Objects.equals(o1, o2)) {
            return 0;
        }
        if (o1 == null) {
            return 1;
        }
        if (o2 == null) {
            return -1;
        }
        final TerritoryAttachment ta1 = TerritoryAttachment.get(o1);
        final TerritoryAttachment ta2 = TerritoryAttachment.get(o2);
        if (ta1 == null && ta2 == null) {
            return 0;
        }
        if (ta1 == null) {
            return 1;
        }
        if (ta2 == null) {
            return -1;
        }
        // take capitols first if we can
        if (ta1.isCapital() && !ta2.isCapital()) {
            return -1;
        }
        if (!ta1.isCapital() && ta2.isCapital()) {
            return 1;
        }
        final boolean factoryInT1 = o1.getUnits().anyMatch(Matches.unitCanProduceUnits());
        final boolean factoryInT2 = o2.getUnits().anyMatch(Matches.unitCanProduceUnits());
        // next take territories which can produce
        if (factoryInT1 && !factoryInT2) {
            return -1;
        }
        if (!factoryInT1 && factoryInT2) {
            return 1;
        }
        final boolean infrastructureInT1 = o1.getUnits().anyMatch(Matches.unitIsInfrastructure());
        final boolean infrastructureInT2 = o2.getUnits().anyMatch(Matches.unitIsInfrastructure());
        // next take territories with infrastructure
        if (infrastructureInT1 && !infrastructureInT2) {
            return -1;
        }
        if (!infrastructureInT1 && infrastructureInT2) {
            return 1;
        }
        // next take territories with largest PU value
        return ta2.getProduction() - ta1.getProduction();
    });
    final List<Territory> isWaterTerr = Utils.onlyWaterTerr(enemyOwned);
    enemyOwned.removeAll(isWaterTerr);
    // first find the territories we can just walk into
    for (final Territory enemy : enemyOwned) {
        if (AiUtils.strength(enemy.getUnits().getUnits(), false, false) == 0) {
            // only take it with 1 unit
            boolean taken = false;
            for (final Territory attackFrom : data.getMap().getNeighbors(enemy, Matches.territoryHasLandUnitsOwnedBy(player))) {
                if (taken) {
                    break;
                }
                // get the cheapest unit to move in
                final List<Unit> unitsSortedByCost = new ArrayList<>(attackFrom.getUnits().getUnits());
                unitsSortedByCost.sort(AiUtils.getCostComparator());
                for (final Unit unit : unitsSortedByCost) {
                    final Predicate<Unit> match = Matches.unitIsOwnedBy(player).and(Matches.unitIsLand()).and(Matches.unitIsNotInfrastructure()).and(Matches.unitCanMove()).and(Matches.unitIsNotAa()).and(Matches.unitCanNotMoveDuringCombatMove().negate());
                    if (!unitsAlreadyMoved.contains(unit) && match.test(unit)) {
                        moveRoutes.add(data.getMap().getRoute(attackFrom, enemy));
                        // number of units, to leave units free to move elsewhere
                        if (attackFrom.isWater()) {
                            final List<Unit> units = attackFrom.getUnits().getMatches(Matches.unitIsLandAndOwnedBy(player));
                            moveUnits.add(CollectionUtils.difference(units, unitsAlreadyMoved));
                            unitsAlreadyMoved.addAll(units);
                        } else {
                            moveUnits.add(Collections.singleton(unit));
                        }
                        unitsAlreadyMoved.add(unit);
                        taken = true;
                        break;
                    }
                }
            }
        }
    }
    // find the territories we can reasonably expect to take
    for (final Territory enemy : enemyOwned) {
        final float enemyStrength = AiUtils.strength(enemy.getUnits().getUnits(), false, false);
        if (enemyStrength > 0) {
            final Predicate<Unit> attackable = Matches.unitIsOwnedBy(player).and(Matches.unitIsStrategicBomber().negate()).and(o -> !unitsAlreadyMoved.contains(o)).and(Matches.unitIsNotAa()).and(Matches.unitCanMove()).and(Matches.unitIsNotInfrastructure()).and(Matches.unitCanNotMoveDuringCombatMove().negate()).and(Matches.unitIsNotSea());
            final Set<Territory> dontMoveFrom = new HashSet<>();
            // find our strength that we can attack with
            float ourStrength = 0;
            final Collection<Territory> attackFrom = data.getMap().getNeighbors(enemy, Matches.territoryHasLandUnitsOwnedBy(player));
            for (final Territory owned : attackFrom) {
                if (TerritoryAttachment.get(owned) != null && TerritoryAttachment.get(owned).isCapital() && (Utils.getStrengthOfPotentialAttackers(owned, data) > AiUtils.strength(owned.getUnits().getUnits(), false, false))) {
                    dontMoveFrom.add(owned);
                    continue;
                }
                ourStrength += AiUtils.strength(owned.getUnits().getMatches(attackable), true, false);
            }
            // prevents 2 infantry from attacking 1 infantry
            if (ourStrength > 1.37 * enemyStrength) {
                // this is all we need to take it, dont go overboard, since we may be able to use the units to attack
                // somewhere else
                double remainingStrengthNeeded = (2.5 * enemyStrength) + 4;
                for (final Territory owned : attackFrom) {
                    if (dontMoveFrom.contains(owned)) {
                        continue;
                    }
                    List<Unit> units = owned.getUnits().getMatches(attackable);
                    // 2) we can potentially attack another territory
                    if (!owned.isWater() && data.getMap().getNeighbors(owned, Matches.territoryHasEnemyLandUnits(player, data)).size() > 1) {
                        units = Utils.getUnitsUpToStrength(remainingStrengthNeeded, units, false);
                    }
                    remainingStrengthNeeded -= AiUtils.strength(units, true, false);
                    if (units.size() > 0) {
                        unitsAlreadyMoved.addAll(units);
                        moveUnits.add(units);
                        moveRoutes.add(data.getMap().getRoute(owned, enemy));
                    }
                }
            }
        }
    }
}
Also used : IPurchaseDelegate(games.strategy.triplea.delegate.remote.IPurchaseDelegate) Constants(games.strategy.triplea.Constants) UnitAttachment(games.strategy.triplea.attachments.UnitAttachment) HashMap(java.util.HashMap) NamedAttachable(games.strategy.engine.data.NamedAttachable) Properties(games.strategy.triplea.Properties) Resource(games.strategy.engine.data.Resource) ArrayList(java.util.ArrayList) PlaceableUnits(games.strategy.triplea.delegate.dataObjects.PlaceableUnits) HashSet(java.util.HashSet) Route(games.strategy.engine.data.Route) DelegateFinder(games.strategy.triplea.delegate.DelegateFinder) TransportTracker(games.strategy.triplea.delegate.TransportTracker) TerritoryAttachment(games.strategy.triplea.attachments.TerritoryAttachment) Map(java.util.Map) UnitType(games.strategy.engine.data.UnitType) TripleAUnit(games.strategy.triplea.TripleAUnit) AbstractAi(games.strategy.triplea.ai.AbstractAi) RepairRule(games.strategy.engine.data.RepairRule) CollectionUtils(games.strategy.util.CollectionUtils) IntegerMap(games.strategy.util.IntegerMap) Unit(games.strategy.engine.data.Unit) Iterator(java.util.Iterator) Predicate(java.util.function.Predicate) Collection(java.util.Collection) Set(java.util.Set) Territory(games.strategy.engine.data.Territory) Streams(com.google.common.collect.Streams) Objects(java.util.Objects) GameData(games.strategy.engine.data.GameData) List(java.util.List) PlayerID(games.strategy.engine.data.PlayerID) IMoveDelegate(games.strategy.triplea.delegate.remote.IMoveDelegate) Matches(games.strategy.triplea.delegate.Matches) BattleDelegate(games.strategy.triplea.delegate.BattleDelegate) IAbstractPlaceDelegate(games.strategy.triplea.delegate.remote.IAbstractPlaceDelegate) ITechDelegate(games.strategy.triplea.delegate.remote.ITechDelegate) ProductionRule(games.strategy.engine.data.ProductionRule) Collections(java.util.Collections) AiUtils(games.strategy.triplea.ai.AiUtils) Territory(games.strategy.engine.data.Territory) TerritoryAttachment(games.strategy.triplea.attachments.TerritoryAttachment) ArrayList(java.util.ArrayList) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) HashSet(java.util.HashSet)

Example 42 with GameData

use of games.strategy.engine.data.GameData in project triplea by triplea-game.

the class WeakAi method getAmphibRoute.

private static Route getAmphibRoute(final PlayerID player, final GameData data) {
    if (!isAmphibAttack(player, data)) {
        return null;
    }
    final Territory ourCapitol = TerritoryAttachment.getFirstOwnedCapitalOrFirstUnownedCapital(player, data);
    final Predicate<Territory> endMatch = o -> {
        final boolean impassable = TerritoryAttachment.get(o) != null && TerritoryAttachment.get(o).getIsImpassable();
        return !impassable && !o.isWater() && Utils.hasLandRouteToEnemyOwnedCapitol(o, player, data);
    };
    final Predicate<Territory> routeCond = Matches.territoryIsWater().and(Matches.territoryHasNoEnemyUnits(player, data));
    final Route withNoEnemy = Utils.findNearest(ourCapitol, endMatch, routeCond, data);
    if (withNoEnemy != null && withNoEnemy.numberOfSteps() > 0) {
        return withNoEnemy;
    }
    // this will fail if our capitol is not next to water, c'est la vie.
    final Route route = Utils.findNearest(ourCapitol, endMatch, Matches.territoryIsWater(), data);
    if (route != null && route.numberOfSteps() == 0) {
        return null;
    }
    return route;
}
Also used : IPurchaseDelegate(games.strategy.triplea.delegate.remote.IPurchaseDelegate) Constants(games.strategy.triplea.Constants) UnitAttachment(games.strategy.triplea.attachments.UnitAttachment) HashMap(java.util.HashMap) NamedAttachable(games.strategy.engine.data.NamedAttachable) Properties(games.strategy.triplea.Properties) Resource(games.strategy.engine.data.Resource) ArrayList(java.util.ArrayList) PlaceableUnits(games.strategy.triplea.delegate.dataObjects.PlaceableUnits) HashSet(java.util.HashSet) Route(games.strategy.engine.data.Route) DelegateFinder(games.strategy.triplea.delegate.DelegateFinder) TransportTracker(games.strategy.triplea.delegate.TransportTracker) TerritoryAttachment(games.strategy.triplea.attachments.TerritoryAttachment) Map(java.util.Map) UnitType(games.strategy.engine.data.UnitType) TripleAUnit(games.strategy.triplea.TripleAUnit) AbstractAi(games.strategy.triplea.ai.AbstractAi) RepairRule(games.strategy.engine.data.RepairRule) CollectionUtils(games.strategy.util.CollectionUtils) IntegerMap(games.strategy.util.IntegerMap) Unit(games.strategy.engine.data.Unit) Iterator(java.util.Iterator) Predicate(java.util.function.Predicate) Collection(java.util.Collection) Set(java.util.Set) Territory(games.strategy.engine.data.Territory) Streams(com.google.common.collect.Streams) Objects(java.util.Objects) GameData(games.strategy.engine.data.GameData) List(java.util.List) PlayerID(games.strategy.engine.data.PlayerID) IMoveDelegate(games.strategy.triplea.delegate.remote.IMoveDelegate) Matches(games.strategy.triplea.delegate.Matches) BattleDelegate(games.strategy.triplea.delegate.BattleDelegate) IAbstractPlaceDelegate(games.strategy.triplea.delegate.remote.IAbstractPlaceDelegate) ITechDelegate(games.strategy.triplea.delegate.remote.ITechDelegate) ProductionRule(games.strategy.engine.data.ProductionRule) Collections(java.util.Collections) AiUtils(games.strategy.triplea.ai.AiUtils) Territory(games.strategy.engine.data.Territory) Route(games.strategy.engine.data.Route)

Example 43 with GameData

use of games.strategy.engine.data.GameData in project triplea by triplea-game.

the class ProPurchaseAi method bid.

/**
 * Default settings for bidding:
 * 1) Limit one bid unit in a territory or sea zone (until set in all territories then 2, etc).
 * 2) The nation placing a unit in a territory or sea zone must have started with a unit in said territory or sea zone
 * prior to placing the bid.
 */
Map<Territory, ProPurchaseTerritory> bid(final int pus, final IPurchaseDelegate purchaseDelegate, final GameData startOfTurnData) {
    // Current data fields
    data = ProData.getData();
    this.startOfTurnData = startOfTurnData;
    player = ProData.getPlayer();
    resourceTracker = new ProResourceTracker(pus, data);
    territoryManager = new ProTerritoryManager(calc);
    isBid = true;
    final ProPurchaseOptionMap purchaseOptions = ProData.purchaseOptions;
    ProLogger.info("Starting bid phase with resources: " + resourceTracker);
    if (!player.getUnits().getUnits().isEmpty()) {
        ProLogger.info("Starting bid phase with unplaced units=" + player.getUnits().getUnits());
    }
    // Find all purchase/place territories
    final Map<Territory, ProPurchaseTerritory> purchaseTerritories = ProPurchaseUtils.findBidTerritories(player);
    int previousNumUnits = 0;
    while (true) {
        // Determine max enemy attack units and current allied defenders
        territoryManager.populateEnemyAttackOptions(new ArrayList<>(), new ArrayList<>(purchaseTerritories.keySet()));
        findDefendersInPlaceTerritories(purchaseTerritories);
        // Prioritize land territories that need defended and purchase additional defenders
        final List<ProPlaceTerritory> needToDefendLandTerritories = prioritizeTerritoriesToDefend(purchaseTerritories, true);
        purchaseDefenders(purchaseTerritories, needToDefendLandTerritories, purchaseOptions.getLandFodderOptions(), purchaseOptions.getAirOptions(), true);
        // Find strategic value for each territory
        ProLogger.info("Find strategic value for place territories");
        final Map<Territory, Double> territoryValueMap = ProTerritoryValueUtils.findTerritoryValues(player, new ArrayList<>(), new ArrayList<>());
        for (final ProPurchaseTerritory t : purchaseTerritories.values()) {
            for (final ProPlaceTerritory ppt : t.getCanPlaceTerritories()) {
                ppt.setStrategicValue(territoryValueMap.get(ppt.getTerritory()));
                ProLogger.debug(ppt.getTerritory() + ", strategicValue=" + territoryValueMap.get(ppt.getTerritory()));
            }
        }
        // Prioritize land place options purchase AA then land units
        final List<ProPlaceTerritory> prioritizedLandTerritories = prioritizeLandTerritories(purchaseTerritories);
        purchaseAaUnits(purchaseTerritories, prioritizedLandTerritories, purchaseOptions.getAaOptions());
        purchaseLandUnits(purchaseTerritories, prioritizedLandTerritories, purchaseOptions, territoryValueMap);
        // Prioritize sea territories that need defended and purchase additional defenders
        final List<ProPlaceTerritory> needToDefendSeaTerritories = prioritizeTerritoriesToDefend(purchaseTerritories, false);
        purchaseDefenders(purchaseTerritories, needToDefendSeaTerritories, purchaseOptions.getSeaDefenseOptions(), purchaseOptions.getAirOptions(), false);
        // Prioritize sea place options and purchase units
        final List<ProPlaceTerritory> prioritizedSeaTerritories = prioritizeSeaTerritories(purchaseTerritories);
        purchaseSeaAndAmphibUnits(purchaseTerritories, prioritizedSeaTerritories, territoryValueMap, purchaseOptions);
        // Try to use any remaining PUs on high value units
        purchaseUnitsWithRemainingProduction(purchaseTerritories, purchaseOptions.getLandOptions(), purchaseOptions.getAirOptions());
        upgradeUnitsWithRemainingPUs(purchaseTerritories, purchaseOptions);
        // Check if no remaining PUs or no unit built this iteration
        final int numUnits = purchaseTerritories.values().stream().map(ProPurchaseTerritory::getCanPlaceTerritories).map(t -> t.get(0)).map(ProPlaceTerritory::getPlaceUnits).mapToInt(List::size).sum();
        if (resourceTracker.isEmpty() || numUnits == previousNumUnits) {
            break;
        }
        previousNumUnits = numUnits;
        ProPurchaseUtils.incrementUnitProductionForBidTerritories(purchaseTerritories);
    }
    // Determine final count of each production rule
    final IntegerMap<ProductionRule> purchaseMap = populateProductionRuleMap(purchaseTerritories, purchaseOptions);
    // Purchase units
    ProMetricUtils.collectPurchaseStats(purchaseMap);
    final String error = purchaseDelegate.purchase(purchaseMap);
    if (error != null) {
        ProLogger.warn("Purchase error: " + error);
    }
    return purchaseTerritories;
}
Also used : ProPlaceTerritory(games.strategy.triplea.ai.pro.data.ProPlaceTerritory) ProBattleResult(games.strategy.triplea.ai.pro.data.ProBattleResult) ProPurchaseOption(games.strategy.triplea.ai.pro.data.ProPurchaseOption) ProUtils(games.strategy.triplea.ai.pro.util.ProUtils) IPurchaseDelegate(games.strategy.triplea.delegate.remote.IPurchaseDelegate) UnitAttachment(games.strategy.triplea.attachments.UnitAttachment) HashMap(java.util.HashMap) ProResourceTracker(games.strategy.triplea.ai.pro.data.ProResourceTracker) ProBattleUtils(games.strategy.triplea.ai.pro.util.ProBattleUtils) Properties(games.strategy.triplea.Properties) ProTransportUtils(games.strategy.triplea.ai.pro.util.ProTransportUtils) TuvUtils(games.strategy.triplea.util.TuvUtils) ArrayList(java.util.ArrayList) ProLogger(games.strategy.triplea.ai.pro.logging.ProLogger) PlaceableUnits(games.strategy.triplea.delegate.dataObjects.PlaceableUnits) HashSet(java.util.HashSet) Route(games.strategy.engine.data.Route) TerritoryAttachment(games.strategy.triplea.attachments.TerritoryAttachment) ProTerritoryManager(games.strategy.triplea.ai.pro.data.ProTerritoryManager) ProPurchaseTerritory(games.strategy.triplea.ai.pro.data.ProPurchaseTerritory) MoveValidator(games.strategy.triplea.delegate.MoveValidator) Map(java.util.Map) TripleAUnit(games.strategy.triplea.TripleAUnit) ProOtherMoveOptions(games.strategy.triplea.ai.pro.data.ProOtherMoveOptions) RepairRule(games.strategy.engine.data.RepairRule) CollectionUtils(games.strategy.util.CollectionUtils) IntegerMap(games.strategy.util.IntegerMap) ProPurchaseOptionMap(games.strategy.triplea.ai.pro.data.ProPurchaseOptionMap) Unit(games.strategy.engine.data.Unit) Iterator(java.util.Iterator) Predicate(java.util.function.Predicate) Collection(java.util.Collection) Set(java.util.Set) Territory(games.strategy.engine.data.Territory) ProMetricUtils(games.strategy.triplea.ai.pro.logging.ProMetricUtils) ProTerritoryValueUtils(games.strategy.triplea.ai.pro.util.ProTerritoryValueUtils) ProPurchaseUtils(games.strategy.triplea.ai.pro.util.ProPurchaseUtils) GameData(games.strategy.engine.data.GameData) List(java.util.List) PlayerID(games.strategy.engine.data.PlayerID) ProMatches(games.strategy.triplea.ai.pro.util.ProMatches) Matches(games.strategy.triplea.delegate.Matches) IAbstractPlaceDelegate(games.strategy.triplea.delegate.remote.IAbstractPlaceDelegate) Optional(java.util.Optional) ProOddsCalculator(games.strategy.triplea.ai.pro.util.ProOddsCalculator) ProductionRule(games.strategy.engine.data.ProductionRule) Comparator(java.util.Comparator) Collections(java.util.Collections) ProPlaceTerritory(games.strategy.triplea.ai.pro.data.ProPlaceTerritory) ProPurchaseTerritory(games.strategy.triplea.ai.pro.data.ProPurchaseTerritory) Territory(games.strategy.engine.data.Territory) ProTerritoryManager(games.strategy.triplea.ai.pro.data.ProTerritoryManager) ProPurchaseOptionMap(games.strategy.triplea.ai.pro.data.ProPurchaseOptionMap) ProPurchaseTerritory(games.strategy.triplea.ai.pro.data.ProPurchaseTerritory) ProductionRule(games.strategy.engine.data.ProductionRule) ProPlaceTerritory(games.strategy.triplea.ai.pro.data.ProPlaceTerritory) ProResourceTracker(games.strategy.triplea.ai.pro.data.ProResourceTracker)

Example 44 with GameData

use of games.strategy.engine.data.GameData in project triplea by triplea-game.

the class ProAi method retreatQuery.

@Override
public Territory retreatQuery(final GUID battleId, final boolean submerge, final Territory battleTerritory, final Collection<Territory> possibleTerritories, final String message) {
    initializeData();
    // Get battle data
    final GameData data = getGameData();
    final PlayerID player = getPlayerId();
    final BattleDelegate delegate = DelegateFinder.battleDelegate(data);
    final IBattle battle = delegate.getBattleTracker().getPendingBattle(battleId);
    // If battle is null or amphibious then don't retreat
    if (battle == null || battleTerritory == null || battle.isAmphibious()) {
        return null;
    }
    // If attacker with more unit strength or strafing and isn't land battle with only air left then don't retreat
    final boolean isAttacker = player.equals(battle.getAttacker());
    final List<Unit> attackers = (List<Unit>) battle.getAttackingUnits();
    final List<Unit> defenders = (List<Unit>) battle.getDefendingUnits();
    final double strengthDifference = ProBattleUtils.estimateStrengthDifference(battleTerritory, attackers, defenders);
    final boolean isStrafing = isAttacker && storedStrafingTerritories.contains(battleTerritory);
    ProLogger.info(player.getName() + " checking retreat from territory " + battleTerritory + ", attackers=" + attackers.size() + ", defenders=" + defenders.size() + ", submerge=" + submerge + ", attacker=" + isAttacker + ", isStrafing=" + isStrafing);
    if ((isStrafing || (isAttacker && strengthDifference > 50)) && (battleTerritory.isWater() || attackers.stream().anyMatch(Matches.unitIsLand()))) {
        return null;
    }
    calc.setData(getGameData());
    return retreatAi.retreatQuery(battleId, battleTerritory, possibleTerritories);
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) BattleDelegate(games.strategy.triplea.delegate.BattleDelegate) GameData(games.strategy.engine.data.GameData) IBattle(games.strategy.triplea.delegate.IBattle) List(java.util.List) ArrayList(java.util.ArrayList) CasualtyList(games.strategy.triplea.delegate.dataObjects.CasualtyList) Unit(games.strategy.engine.data.Unit)

Example 45 with GameData

use of games.strategy.engine.data.GameData in project triplea by triplea-game.

the class ProAi method selectCasualties.

@Override
public CasualtyDetails selectCasualties(final Collection<Unit> selectFrom, final Map<Unit, Collection<Unit>> dependents, final int count, final String message, final DiceRoll dice, final PlayerID hit, final Collection<Unit> friendlyUnits, final PlayerID enemyPlayer, final Collection<Unit> enemyUnits, final boolean amphibious, final Collection<Unit> amphibiousLandAttackers, final CasualtyList defaultCasualties, final GUID battleId, final Territory battlesite, final boolean allowMultipleHitsPerUnit) {
    initializeData();
    if (defaultCasualties.size() != count) {
        throw new IllegalStateException("Select Casualties showing different numbers for number of hits to take vs total " + "size of default casualty selections");
    }
    if (defaultCasualties.getKilled().size() <= 0) {
        return new CasualtyDetails(defaultCasualties, false);
    }
    // Consider unit cost
    final CasualtyDetails myCasualties = new CasualtyDetails(false);
    myCasualties.addToDamaged(defaultCasualties.getDamaged());
    final List<Unit> selectFromSorted = new ArrayList<>(selectFrom);
    if (enemyUnits.isEmpty()) {
        selectFromSorted.sort(ProPurchaseUtils.getCostComparator());
    } else {
        // Get battle data
        final GameData data = getGameData();
        final PlayerID player = getPlayerId();
        final BattleDelegate delegate = DelegateFinder.battleDelegate(data);
        final IBattle battle = delegate.getBattleTracker().getPendingBattle(battleId);
        // If defender and could lose battle then don't consider unit cost as just trying to survive
        boolean needToCheck = true;
        final boolean isAttacker = player.equals(battle.getAttacker());
        if (!isAttacker) {
            final List<Unit> attackers = (List<Unit>) battle.getAttackingUnits();
            final List<Unit> defenders = (List<Unit>) battle.getDefendingUnits();
            defenders.removeAll(defaultCasualties.getKilled());
            final double strengthDifference = ProBattleUtils.estimateStrengthDifference(battlesite, attackers, defenders);
            int minStrengthDifference = 60;
            if (!Properties.getLowLuck(data)) {
                minStrengthDifference = 55;
            }
            if (strengthDifference > minStrengthDifference) {
                needToCheck = false;
            }
        }
        // Use bubble sort to save expensive units
        while (needToCheck) {
            needToCheck = false;
            for (int i = 0; i < selectFromSorted.size() - 1; i++) {
                final Unit unit1 = selectFromSorted.get(i);
                final Unit unit2 = selectFromSorted.get(i + 1);
                final double unitCost1 = ProPurchaseUtils.getCost(unit1);
                final double unitCost2 = ProPurchaseUtils.getCost(unit2);
                if (unitCost1 > 1.5 * unitCost2) {
                    selectFromSorted.set(i, unit2);
                    selectFromSorted.set(i + 1, unit1);
                    needToCheck = true;
                }
            }
        }
    }
    // Interleave carriers and planes
    final List<Unit> interleavedTargetList = new ArrayList<>(ProTransportUtils.interleaveUnitsCarriersAndPlanes(selectFromSorted, 0));
    for (int i = 0; i < defaultCasualties.getKilled().size(); ++i) {
        myCasualties.addToKilled(interleavedTargetList.get(i));
    }
    if (count != myCasualties.size()) {
        throw new IllegalStateException("AI chose wrong number of casualties");
    }
    return myCasualties;
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) BattleDelegate(games.strategy.triplea.delegate.BattleDelegate) GameData(games.strategy.engine.data.GameData) ArrayList(java.util.ArrayList) Unit(games.strategy.engine.data.Unit) IBattle(games.strategy.triplea.delegate.IBattle) CasualtyDetails(games.strategy.triplea.delegate.dataObjects.CasualtyDetails) List(java.util.List) ArrayList(java.util.ArrayList) CasualtyList(games.strategy.triplea.delegate.dataObjects.CasualtyList)

Aggregations

GameData (games.strategy.engine.data.GameData)204 Unit (games.strategy.engine.data.Unit)100 PlayerID (games.strategy.engine.data.PlayerID)92 Territory (games.strategy.engine.data.Territory)92 ArrayList (java.util.ArrayList)83 TripleAUnit (games.strategy.triplea.TripleAUnit)64 HashSet (java.util.HashSet)50 CompositeChange (games.strategy.engine.data.CompositeChange)40 List (java.util.List)36 HashMap (java.util.HashMap)32 Set (java.util.Set)32 Route (games.strategy.engine.data.Route)31 UnitAttachment (games.strategy.triplea.attachments.UnitAttachment)30 Collection (java.util.Collection)29 UnitType (games.strategy.engine.data.UnitType)26 Change (games.strategy.engine.data.Change)24 Test (org.junit.jupiter.api.Test)23 Resource (games.strategy.engine.data.Resource)22 TestMapGameData (games.strategy.triplea.xml.TestMapGameData)22 Map (java.util.Map)21