Search in sources :

Example 16 with TerritoryAttachment

use of games.strategy.triplea.attachments.TerritoryAttachment in project triplea by triplea-game.

the class WW2V3Year41Test method testOccupiedTerrOfAttachmentWithCapital.

@Test
public void testOccupiedTerrOfAttachmentWithCapital() throws GameParseException {
    // Set up test
    final PlayerID british = GameDataTestUtil.british(gameData);
    final ITestDelegateBridge delegateBridge = getDelegateBridge(british(gameData));
    // Set up the move delegate
    final MoveDelegate moveDelegate = moveDelegate(gameData);
    delegateBridge.setStepName("CombatMove");
    moveDelegate(gameData).setDelegateBridgeAndPlayer(delegateBridge);
    moveDelegate(gameData).start();
    // Set up the territories
    final Territory hupeh = territory("Hupeh", gameData);
    final Territory kiangsu = territory("Kiangsu", gameData);
    final Territory mongolia = territory("Mongolia", gameData);
    // Remove original capital
    final TerritoryAttachment taMongolia = TerritoryAttachment.get(mongolia);
    final TerritoryAttachment taKiangsu = TerritoryAttachment.get(kiangsu);
    taMongolia.setCapital(null);
    // Set as NEW capital
    taKiangsu.setCapital(Constants.PLAYER_NAME_CHINESE);
    // Remove all units
    removeFrom(kiangsu, kiangsu.getUnits().getUnits());
    removeFrom(hupeh, hupeh.getUnits().getUnits());
    // Set up the unit types
    addTo(hupeh, infantry(gameData).create(1, british));
    // Get units
    final Collection<Unit> moveUnits = hupeh.getUnits().getUnits();
    // Get Owner prior to battle
    final String preOwner = kiangsu.getOwner().getName();
    assertEquals(Constants.PLAYER_NAME_JAPANESE, preOwner);
    // add a VALID attack
    final String validResults = moveDelegate.move(moveUnits, new Route(hupeh, kiangsu));
    assertValid(validResults);
    // Ensure owner after attack doesn't match attacker
    final String postOwner = kiangsu.getOwner().getName();
    assertNotSame(Constants.PLAYER_NAME_BRITISH, postOwner);
    // Check that original owner is now owner
    assertEquals(Constants.PLAYER_NAME_CHINESE, postOwner);
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) Territory(games.strategy.engine.data.Territory) TerritoryAttachment(games.strategy.triplea.attachments.TerritoryAttachment) ITestDelegateBridge(games.strategy.engine.data.ITestDelegateBridge) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) Route(games.strategy.engine.data.Route) Test(org.junit.jupiter.api.Test)

Example 17 with TerritoryAttachment

use of games.strategy.triplea.attachments.TerritoryAttachment in project triplea by triplea-game.

the class LandTerritoryDrawable method draw.

@Override
public void draw(final Rectangle bounds, final GameData data, final Graphics2D graphics, final MapData mapData, final AffineTransform unscaled, final AffineTransform scaled) {
    final Territory territory = data.getMap().getTerritory(territoryName);
    final Color territoryColor;
    final TerritoryAttachment ta = TerritoryAttachment.get(territory);
    if (ta != null && ta.getIsImpassable()) {
        territoryColor = mapData.impassableColor();
    } else {
        territoryColor = mapData.getPlayerColor(territory.getOwner().getName());
    }
    draw(bounds, graphics, mapData, territory, territoryColor);
}
Also used : Territory(games.strategy.engine.data.Territory) TerritoryAttachment(games.strategy.triplea.attachments.TerritoryAttachment) Color(java.awt.Color)

Example 18 with TerritoryAttachment

use of games.strategy.triplea.attachments.TerritoryAttachment in project triplea by triplea-game.

the class MovePerformer method markMovementChange.

private Change markMovementChange(final Collection<Unit> units, final Route route, final PlayerID id) {
    final GameData data = bridge.getData();
    final CompositeChange change = new CompositeChange();
    final Territory routeStart = route.getStart();
    final TerritoryAttachment taRouteStart = TerritoryAttachment.get(routeStart);
    final Territory routeEnd = route.getEnd();
    TerritoryAttachment taRouteEnd = null;
    if (routeEnd != null) {
        taRouteEnd = TerritoryAttachment.get(routeEnd);
    }
    // only units owned by us need to be marked
    final RelationshipTracker relationshipTracker = data.getRelationshipTracker();
    for (final Unit baseUnit : CollectionUtils.getMatches(units, Matches.unitIsOwnedBy(id))) {
        final TripleAUnit unit = (TripleAUnit) baseUnit;
        int moved = route.getMovementCost(unit);
        final UnitAttachment ua = UnitAttachment.get(unit.getType());
        if (ua.getIsAir()) {
            if (taRouteStart != null && taRouteStart.getAirBase() && relationshipTracker.isAllied(route.getStart().getOwner(), unit.getOwner())) {
                moved--;
            }
            if (taRouteEnd != null && taRouteEnd.getAirBase() && relationshipTracker.isAllied(route.getEnd().getOwner(), unit.getOwner())) {
                moved--;
            }
        }
        change.add(ChangeFactory.unitPropertyChange(unit, moved + unit.getAlreadyMoved(), TripleAUnit.ALREADY_MOVED));
    }
    // if entered a non blitzed conquered territory, mark with 0 movement
    if (GameStepPropertiesHelper.isCombatMove(data) && (MoveDelegate.getEmptyNeutral(route).size() != 0 || hasConqueredNonBlitzed(route))) {
        for (final Unit unit : CollectionUtils.getMatches(units, Matches.unitIsLand())) {
            change.add(ChangeFactory.markNoMovementChange(Collections.singleton(unit)));
        }
    }
    if (routeEnd != null && Properties.getSubsCanEndNonCombatMoveWithEnemies(data) && GameStepPropertiesHelper.isNonCombatMove(data, false) && routeEnd.getUnits().anyMatch(Matches.unitIsEnemyOf(data, id).and(Matches.unitIsDestroyer()))) {
        // if there is an enemy destroyer there
        for (final Unit unit : CollectionUtils.getMatches(units, Matches.unitIsSub().and(Matches.unitIsAir().negate()))) {
            change.add(ChangeFactory.markNoMovementChange(Collections.singleton(unit)));
        }
    }
    return change;
}
Also used : UnitAttachment(games.strategy.triplea.attachments.UnitAttachment) Territory(games.strategy.engine.data.Territory) GameData(games.strategy.engine.data.GameData) TerritoryAttachment(games.strategy.triplea.attachments.TerritoryAttachment) RelationshipTracker(games.strategy.engine.data.RelationshipTracker) CompositeChange(games.strategy.engine.data.CompositeChange) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) TripleAUnit(games.strategy.triplea.TripleAUnit)

Example 19 with TerritoryAttachment

use of games.strategy.triplea.attachments.TerritoryAttachment in project triplea by triplea-game.

the class BattleTracker method takeOver.

public void takeOver(final Territory territory, final PlayerID id, final IDelegateBridge bridge, final UndoableMove changeTracker, final Collection<Unit> arrivingUnits) {
    // This could be NULL if unowned water
    final TerritoryAttachment ta = TerritoryAttachment.get(territory);
    if (ta == null) {
        // TODO: allow capture/destroy of infrastructure on unowned water
        return;
    }
    final GameData data = bridge.getData();
    final Collection<Unit> arrivedUnits = (arrivingUnits == null ? null : new ArrayList<>(arrivingUnits));
    final RelationshipTracker relationshipTracker = data.getRelationshipTracker();
    final boolean isTerritoryOwnerAnEnemy = relationshipTracker.canTakeOverOwnedTerritory(id, territory.getOwner());
    // check to make sure attackers have more than just transports. If they don't, exit here.
    if (territory.isWater() && arrivedUnits != null) {
        // Total Attacking Sea units = all units - land units - air units - submerged subs
        // Also subtract transports & subs (if they can't control sea zones)
        int totalMatches = arrivedUnits.size() - CollectionUtils.countMatches(arrivedUnits, Matches.unitIsLand()) - CollectionUtils.countMatches(arrivedUnits, Matches.unitIsAir()) - CollectionUtils.countMatches(arrivedUnits, Matches.unitIsSubmerged());
        // If transports are restricted from controlling sea zones, subtract them
        final Predicate<Unit> transportsCanNotControl = Matches.unitIsTransportAndNotDestroyer().and(Matches.unitIsTransportButNotCombatTransport());
        if (!Properties.getTransportControlSeaZone(data)) {
            totalMatches -= CollectionUtils.countMatches(arrivedUnits, transportsCanNotControl);
        }
        // If subs are restricted from controlling sea zones, subtract them
        if (Properties.getSubControlSeaZoneRestricted(data)) {
            totalMatches -= CollectionUtils.countMatches(arrivedUnits, Matches.unitIsSub());
        }
        if (totalMatches == 0) {
            return;
        }
    }
    // If it was a Convoy Route- check ownership of the associated neighboring territory and set message
    if (ta.getConvoyRoute()) {
        // we could be part of a convoy route for another territory
        final Collection<Territory> attachedConvoyTo = TerritoryAttachment.getWhatTerritoriesThisIsUsedInConvoysFor(territory, data);
        for (final Territory convoy : attachedConvoyTo) {
            final TerritoryAttachment cta = TerritoryAttachment.get(convoy);
            if (!cta.getConvoyRoute()) {
                continue;
            }
            final PlayerID convoyOwner = convoy.getOwner();
            if (relationshipTracker.isAllied(id, convoyOwner)) {
                if (CollectionUtils.getMatches(cta.getConvoyAttached(), Matches.isTerritoryAllied(convoyOwner, data)).size() <= 0) {
                    bridge.getHistoryWriter().addChildToEvent(convoyOwner.getName() + " gains " + cta.getProduction() + " production in " + convoy.getName() + " for the liberation the convoy route in " + territory.getName());
                }
            } else if (relationshipTracker.isAtWar(id, convoyOwner)) {
                if (CollectionUtils.getMatches(cta.getConvoyAttached(), Matches.isTerritoryAllied(convoyOwner, data)).size() == 1) {
                    bridge.getHistoryWriter().addChildToEvent(convoyOwner.getName() + " loses " + cta.getProduction() + " production in " + convoy.getName() + " due to the capture of the convoy route in " + territory.getName());
                }
            }
        }
    }
    // if neutral, we may charge money to enter
    if (territory.getOwner().isNull() && !territory.isWater() && Properties.getNeutralCharge(data) >= 0) {
        final Resource pus = data.getResourceList().getResource(Constants.PUS);
        final int puChargeIdeal = -Properties.getNeutralCharge(data);
        final int puChargeReal = Math.min(0, Math.max(puChargeIdeal, -id.getResources().getQuantity(pus)));
        final Change neutralFee = ChangeFactory.changeResourcesChange(id, pus, puChargeReal);
        bridge.addChange(neutralFee);
        if (changeTracker != null) {
            changeTracker.addChange(neutralFee);
        }
        if (puChargeIdeal == puChargeReal) {
            bridge.getHistoryWriter().addChildToEvent(id.getName() + " loses " + -puChargeReal + " " + MyFormatter.pluralize("PU", -puChargeReal) + " for violating " + territory.getName() + "s neutrality.");
        } else {
            System.out.println("Player, " + id.getName() + " attacks a Neutral territory, and should have had to pay " + puChargeIdeal + ", but did not have enough PUs to pay! This is a bug.");
            bridge.getHistoryWriter().addChildToEvent(id.getName() + " loses " + -puChargeReal + " " + MyFormatter.pluralize("PU", -puChargeReal) + " for violating " + territory.getName() + "s neutrality.  Correct amount to charge is: " + puChargeIdeal + ".  Player should not have been able to make this attack!");
        }
    }
    // instead it is relying on the fact that the capital should be owned by the person it is attached to
    if (isTerritoryOwnerAnEnemy && ta.getCapital() != null) {
        // if the capital is owned by the capitols player take the money
        final PlayerID whoseCapital = data.getPlayerList().getPlayerId(ta.getCapital());
        final PlayerAttachment pa = PlayerAttachment.get(id);
        final PlayerAttachment paWhoseCapital = PlayerAttachment.get(whoseCapital);
        final List<Territory> capitalsList = new ArrayList<>(TerritoryAttachment.getAllCurrentlyOwnedCapitals(whoseCapital, data));
        // we are losing one right now, so it is < not <=
        if (paWhoseCapital != null && paWhoseCapital.getRetainCapitalNumber() < capitalsList.size()) {
            // do nothing, we keep our money since we still control enough capitals
            bridge.getHistoryWriter().addChildToEvent(id.getName() + " captures one of " + whoseCapital.getName() + " capitals");
        } else if (whoseCapital.equals(territory.getOwner())) {
            final Resource pus = data.getResourceList().getResource(Constants.PUS);
            final int capturedPuCount = whoseCapital.getResources().getQuantity(pus);
            if (pa != null) {
                if (isPacificTheater(data)) {
                    final Change changeVp = ChangeFactory.attachmentPropertyChange(pa, (capturedPuCount + pa.getCaptureVps()), "captureVps");
                    bridge.addChange(changeVp);
                    if (changeTracker != null) {
                        changeTracker.addChange(changeVp);
                    }
                }
            }
            final Change remove = ChangeFactory.changeResourcesChange(whoseCapital, pus, -capturedPuCount);
            bridge.addChange(remove);
            if (paWhoseCapital != null && paWhoseCapital.getDestroysPUs()) {
                bridge.getHistoryWriter().addChildToEvent(id.getName() + " destroys " + capturedPuCount + MyFormatter.pluralize("PU", capturedPuCount) + " while taking " + whoseCapital.getName() + " capital");
                if (changeTracker != null) {
                    changeTracker.addChange(remove);
                }
            } else {
                bridge.getHistoryWriter().addChildToEvent(id.getName() + " captures " + capturedPuCount + MyFormatter.pluralize("PU", capturedPuCount) + " while taking " + whoseCapital.getName() + " capital");
                if (changeTracker != null) {
                    changeTracker.addChange(remove);
                }
                final Change add = ChangeFactory.changeResourcesChange(id, pus, capturedPuCount);
                bridge.addChange(add);
                if (changeTracker != null) {
                    changeTracker.addChange(add);
                }
            }
            // remove all the tokens of the captured player
            final Resource tokens = data.getResourceList().getResource(Constants.TECH_TOKENS);
            if (tokens != null) {
                final int currTokens = whoseCapital.getResources().getQuantity(Constants.TECH_TOKENS);
                final Change removeTokens = ChangeFactory.changeResourcesChange(whoseCapital, tokens, -currTokens);
                bridge.addChange(removeTokens);
                if (changeTracker != null) {
                    changeTracker.addChange(removeTokens);
                }
            }
        }
    }
    // is this an allied territory, revert to original owner if it is, unless they dont own there captital
    final PlayerID terrOrigOwner = OriginalOwnerTracker.getOriginalOwner(territory);
    PlayerID newOwner = id;
    // then we do not worry about this.
    if (isTerritoryOwnerAnEnemy && terrOrigOwner != null && relationshipTracker.isAllied(terrOrigOwner, id) && !terrOrigOwner.equals(territory.getOwner())) {
        final List<Territory> capitalsListOwned = new ArrayList<>(TerritoryAttachment.getAllCurrentlyOwnedCapitals(terrOrigOwner, data));
        if (!capitalsListOwned.isEmpty()) {
            newOwner = terrOrigOwner;
        } else {
            newOwner = id;
            final List<Territory> capitalsListOriginal = new ArrayList<>(TerritoryAttachment.getAllCapitals(terrOrigOwner, data));
            for (final Territory current : capitalsListOriginal) {
                if (territory.equals(current) || current.getOwner().equals(PlayerID.NULL_PLAYERID)) {
                    // if a neutral controls our capital, our territories get liberated (ie: china in ww2v3)
                    newOwner = terrOrigOwner;
                }
            }
        }
    }
    // then we set that here (except we don't set it if we are liberating allied owned territory)
    if (isTerritoryOwnerAnEnemy && newOwner.equals(id) && Matches.territoryHasWhenCapturedByGoesTo().test(territory)) {
        for (final String value : ta.getWhenCapturedByGoesTo()) {
            final String[] s = value.split(":");
            final PlayerID capturingPlayer = data.getPlayerList().getPlayerId(s[0]);
            final PlayerID goesToPlayer = data.getPlayerList().getPlayerId(s[1]);
            if (capturingPlayer.equals(goesToPlayer)) {
                continue;
            }
            if (capturingPlayer.equals(id)) {
                newOwner = goesToPlayer;
                break;
            }
        }
    }
    if (isTerritoryOwnerAnEnemy) {
        final Change takeOver = ChangeFactory.changeOwner(territory, newOwner);
        bridge.getHistoryWriter().addChildToEvent(takeOver.toString());
        bridge.addChange(takeOver);
        if (changeTracker != null) {
            changeTracker.addChange(takeOver);
            changeTracker.addToConquered(territory);
        }
        // play a sound
        if (territory.isWater()) {
            // should probably see if there is something actually happening for water
            bridge.getSoundChannelBroadcaster().playSoundForAll(SoundPath.CLIP_TERRITORY_CAPTURE_SEA, id);
        } else if (ta.getCapital() != null) {
            bridge.getSoundChannelBroadcaster().playSoundForAll(SoundPath.CLIP_TERRITORY_CAPTURE_CAPITAL, id);
        } else if (m_blitzed.contains(territory) && arrivedUnits.stream().anyMatch(Matches.unitCanBlitz())) {
            bridge.getSoundChannelBroadcaster().playSoundForAll(SoundPath.CLIP_TERRITORY_CAPTURE_BLITZ, id);
        } else {
            bridge.getSoundChannelBroadcaster().playSoundForAll(SoundPath.CLIP_TERRITORY_CAPTURE_LAND, id);
        }
    }
    // TODO: see if necessary
    if (territory.getUnits().anyMatch(Matches.unitIsEnemyOf(data, id).and(Matches.unitCanBeDamaged()))) {
        final IBattle bombingBattle = getPendingBattle(territory, true, null);
        if (bombingBattle != null) {
            final BattleResults results = new BattleResults(bombingBattle, WhoWon.DRAW, data);
            getBattleRecords().addResultToBattle(id, bombingBattle.getBattleId(), null, 0, 0, BattleRecord.BattleResultDescription.NO_BATTLE, results);
            bombingBattle.cancelBattle(bridge);
            removeBattle(bombingBattle);
            throw new IllegalStateException("Bombing Raids should be dealt with first! Be sure the battle has dependencies set correctly!");
        }
    }
    captureOrDestroyUnits(territory, id, newOwner, bridge, changeTracker);
    // Also check to make sure playerAttachment even HAS a capital to fix abend
    if (isTerritoryOwnerAnEnemy && terrOrigOwner != null && ta.getCapital() != null && TerritoryAttachment.getAllCapitals(terrOrigOwner, data).contains(territory) && relationshipTracker.isAllied(terrOrigOwner, id)) {
        // if it is give it back to the original owner
        final Collection<Territory> originallyOwned = OriginalOwnerTracker.getOriginallyOwned(data, terrOrigOwner);
        final List<Territory> friendlyTerritories = CollectionUtils.getMatches(originallyOwned, Matches.isTerritoryAllied(terrOrigOwner, data));
        // give back the factories as well.
        for (final Territory item : friendlyTerritories) {
            if (item.getOwner() == terrOrigOwner) {
                continue;
            }
            final Change takeOverFriendlyTerritories = ChangeFactory.changeOwner(item, terrOrigOwner);
            bridge.addChange(takeOverFriendlyTerritories);
            bridge.getHistoryWriter().addChildToEvent(takeOverFriendlyTerritories.toString());
            if (changeTracker != null) {
                changeTracker.addChange(takeOverFriendlyTerritories);
            }
            final Collection<Unit> units = CollectionUtils.getMatches(item.getUnits().getUnits(), Matches.unitIsInfrastructure());
            if (!units.isEmpty()) {
                final Change takeOverNonComUnits = ChangeFactory.changeOwner(units, terrOrigOwner, territory);
                bridge.addChange(takeOverNonComUnits);
                if (changeTracker != null) {
                    changeTracker.addChange(takeOverNonComUnits);
                }
            }
        }
    }
    // (they may want to unload from the transport and attack)
    if (Matches.territoryIsWater().test(territory) && arrivedUnits != null) {
        arrivedUnits.removeAll(CollectionUtils.getMatches(arrivedUnits, Matches.unitIsLand()));
    }
    markWasInCombat(arrivedUnits, bridge, changeTracker);
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) Territory(games.strategy.engine.data.Territory) GameData(games.strategy.engine.data.GameData) TerritoryAttachment(games.strategy.triplea.attachments.TerritoryAttachment) BattleResults(games.strategy.triplea.oddsCalculator.ta.BattleResults) ArrayList(java.util.ArrayList) Resource(games.strategy.engine.data.Resource) CompositeChange(games.strategy.engine.data.CompositeChange) Change(games.strategy.engine.data.Change) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) PlayerAttachment(games.strategy.triplea.attachments.PlayerAttachment) RelationshipTracker(games.strategy.engine.data.RelationshipTracker)

Example 20 with TerritoryAttachment

use of games.strategy.triplea.attachments.TerritoryAttachment in project triplea by triplea-game.

the class ProTerritoryManager method removeTerritoriesThatCantBeConquered.

private List<ProTerritory> removeTerritoriesThatCantBeConquered(final PlayerID player, final Map<Territory, ProTerritory> attackMap, final Map<Unit, Set<Territory>> unitAttackMap, final Map<Unit, Set<Territory>> transportAttackMap, final ProOtherMoveOptions alliedAttackOptions, final ProOtherMoveOptions enemyDefendOptions, final boolean isIgnoringRelationships) {
    ProLogger.info("Removing territories that can't be conquered");
    final GameData data = ProData.getData();
    // Determine if territory can be successfully attacked with max possible attackers
    final List<Territory> territoriesToRemove = new ArrayList<>();
    for (final Territory t : attackMap.keySet()) {
        final ProTerritory patd = attackMap.get(t);
        // Check if I can win without amphib units and ignore AA since max units might have lots of planes
        List<Unit> defenders = CollectionUtils.getMatches(patd.getMaxEnemyDefenders(player, data), ProMatches.unitIsEnemyAndNotAa(player, data));
        if (isIgnoringRelationships) {
            defenders = new ArrayList<>(t.getUnits());
        }
        patd.setMaxBattleResult(calc.estimateAttackBattleResults(t, patd.getMaxUnits(), defenders, new HashSet<>()));
        // Add in amphib units if I can't win without them
        if (patd.getMaxBattleResult().getWinPercentage() < ProData.winPercentage && !patd.getMaxAmphibUnits().isEmpty()) {
            final Set<Unit> combinedUnits = new HashSet<>(patd.getMaxUnits());
            combinedUnits.addAll(patd.getMaxAmphibUnits());
            patd.setMaxBattleResult(calc.estimateAttackBattleResults(t, new ArrayList<>(combinedUnits), defenders, patd.getMaxBombardUnits()));
            patd.setNeedAmphibUnits(true);
        }
        // Check strafing and using allied attack if enemy capital/factory
        boolean isEnemyCapitalOrFactory = false;
        final TerritoryAttachment ta = TerritoryAttachment.get(t);
        if (!t.getOwner().isNull() && ((ta != null && ta.isCapital()) || ProMatches.territoryHasInfraFactoryAndIsLand().test(t))) {
            isEnemyCapitalOrFactory = true;
        }
        if (patd.getMaxBattleResult().getWinPercentage() < ProData.minWinPercentage && isEnemyCapitalOrFactory && alliedAttackOptions.getMax(t) != null) {
            // Check for allied attackers
            final ProTerritory alliedAttack = alliedAttackOptions.getMax(t);
            final Set<Unit> alliedUnits = new HashSet<>(alliedAttack.getMaxUnits());
            alliedUnits.addAll(alliedAttack.getMaxAmphibUnits());
            if (!alliedUnits.isEmpty()) {
                // Make sure allies' capital isn't next to territory
                final PlayerID alliedPlayer = alliedUnits.iterator().next().getOwner();
                final Territory capital = TerritoryAttachment.getFirstOwnedCapitalOrFirstUnownedCapital(alliedPlayer, data);
                if (capital != null && !data.getMap().getNeighbors(capital).contains(t)) {
                    // Get max enemy defenders
                    final Set<Unit> additionalEnemyDefenders = new HashSet<>();
                    final List<PlayerID> players = ProUtils.getOtherPlayersInTurnOrder(player);
                    for (final ProTerritory enemyDefendOption : enemyDefendOptions.getAll(t)) {
                        final Set<Unit> enemyUnits = new HashSet<>(enemyDefendOption.getMaxUnits());
                        enemyUnits.addAll(enemyDefendOption.getMaxAmphibUnits());
                        if (!enemyUnits.isEmpty()) {
                            final PlayerID enemyPlayer = enemyUnits.iterator().next().getOwner();
                            if (ProUtils.isPlayersTurnFirst(players, enemyPlayer, alliedPlayer)) {
                                additionalEnemyDefenders.addAll(enemyUnits);
                            }
                        }
                    }
                    // Check allied result without strafe
                    final Set<Unit> enemyDefendersBeforeStrafe = new HashSet<>(defenders);
                    enemyDefendersBeforeStrafe.addAll(additionalEnemyDefenders);
                    final ProBattleResult result = calc.estimateAttackBattleResults(t, new ArrayList<>(alliedUnits), new ArrayList<>(enemyDefendersBeforeStrafe), alliedAttack.getMaxBombardUnits());
                    if (result.getWinPercentage() < ProData.winPercentage) {
                        patd.setStrafing(true);
                        // Try to strafe to allow allies to conquer territory
                        final Set<Unit> combinedUnits = new HashSet<>(patd.getMaxUnits());
                        combinedUnits.addAll(patd.getMaxAmphibUnits());
                        final ProBattleResult strafeResult = calc.callBattleCalculator(t, new ArrayList<>(combinedUnits), defenders, patd.getMaxBombardUnits(), true);
                        // Check allied result with strafe
                        final Set<Unit> enemyDefendersAfterStrafe = new HashSet<>(strafeResult.getAverageDefendersRemaining());
                        enemyDefendersAfterStrafe.addAll(additionalEnemyDefenders);
                        patd.setMaxBattleResult(calc.estimateAttackBattleResults(t, new ArrayList<>(alliedUnits), new ArrayList<>(enemyDefendersAfterStrafe), alliedAttack.getMaxBombardUnits()));
                        ProLogger.debug("Checking strafing territory: " + t + ", alliedPlayer=" + alliedUnits.iterator().next().getOwner().getName() + ", maxWin%=" + patd.getMaxBattleResult().getWinPercentage() + ", maxAttackers=" + alliedUnits.size() + ", maxDefenders=" + enemyDefendersAfterStrafe.size());
                    }
                }
            }
        }
        if (patd.getMaxBattleResult().getWinPercentage() < ProData.minWinPercentage || (patd.isStrafing() && (patd.getMaxBattleResult().getWinPercentage() < ProData.winPercentage || !patd.getMaxBattleResult().isHasLandUnitRemaining()))) {
            territoriesToRemove.add(t);
        }
    }
    // Remove territories that can't be successfully attacked
    Collections.sort(territoriesToRemove);
    final List<ProTerritory> result = new ArrayList<>(attackMap.values());
    for (final Territory t : territoriesToRemove) {
        final ProTerritory proTerritoryToRemove = attackMap.get(t);
        final Set<Unit> combinedUnits = new HashSet<>(proTerritoryToRemove.getMaxUnits());
        combinedUnits.addAll(proTerritoryToRemove.getMaxAmphibUnits());
        ProLogger.debug("Removing territory that we can't successfully attack: " + t + ", maxWin%=" + proTerritoryToRemove.getMaxBattleResult().getWinPercentage() + ", maxAttackers=" + combinedUnits.size());
        result.remove(proTerritoryToRemove);
        for (final Set<Territory> territories : unitAttackMap.values()) {
            territories.remove(t);
        }
        for (final Set<Territory> territories : transportAttackMap.values()) {
            territories.remove(t);
        }
    }
    return result;
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) Territory(games.strategy.engine.data.Territory) GameData(games.strategy.engine.data.GameData) 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)

Aggregations

TerritoryAttachment (games.strategy.triplea.attachments.TerritoryAttachment)36 Territory (games.strategy.engine.data.Territory)29 Unit (games.strategy.engine.data.Unit)24 TripleAUnit (games.strategy.triplea.TripleAUnit)19 ArrayList (java.util.ArrayList)14 PlayerID (games.strategy.engine.data.PlayerID)13 GameData (games.strategy.engine.data.GameData)9 HashSet (java.util.HashSet)8 UnitAttachment (games.strategy.triplea.attachments.UnitAttachment)7 ProTerritory (games.strategy.triplea.ai.pro.data.ProTerritory)6 UnitType (games.strategy.engine.data.UnitType)5 ProBattleResult (games.strategy.triplea.ai.pro.data.ProBattleResult)5 CompositeChange (games.strategy.engine.data.CompositeChange)4 Resource (games.strategy.engine.data.Resource)4 ProOtherMoveOptions (games.strategy.triplea.ai.pro.data.ProOtherMoveOptions)4 PlayerAttachment (games.strategy.triplea.attachments.PlayerAttachment)4 IntegerMap (games.strategy.util.IntegerMap)4 RelationshipTracker (games.strategy.engine.data.RelationshipTracker)3 ProPlaceTerritory (games.strategy.triplea.ai.pro.data.ProPlaceTerritory)3 ProPurchaseTerritory (games.strategy.triplea.ai.pro.data.ProPurchaseTerritory)3