Search in sources :

Example 1 with Change

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

the class BattleDelegate method moveAirAndLand.

private static void moveAirAndLand(final IDelegateBridge bridge, final Collection<Unit> defendingAirBeingMoved, final Collection<Unit> defendingAirTotal, final Territory newTerritory, final Territory battleSite) {
    bridge.getHistoryWriter().addChildToEvent(MyFormatter.unitsToText(defendingAirBeingMoved) + " forced to land in " + newTerritory.getName(), new ArrayList<>(defendingAirBeingMoved));
    final Change change = ChangeFactory.moveUnits(battleSite, newTerritory, defendingAirBeingMoved);
    bridge.addChange(change);
    // remove those that landed in case it was a carrier
    defendingAirTotal.removeAll(defendingAirBeingMoved);
}
Also used : CompositeChange(games.strategy.engine.data.CompositeChange) Change(games.strategy.engine.data.Change)

Example 2 with Change

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

the class BattleDelegate method createDamageChange.

private static Change createDamageChange(final IntegerMap<Unit> damagedMap, final IDelegateBridge bridge) {
    final Set<Unit> units = new HashSet<>(damagedMap.keySet());
    for (final Unit u : units) {
        damagedMap.add(u, u.getHits());
    }
    final Change damagedChange = ChangeFactory.unitsHit(damagedMap);
    bridge.getHistoryWriter().addChildToEvent("Units damaged: " + MyFormatter.unitsToText(units), units);
    return damagedChange;
}
Also used : CompositeChange(games.strategy.engine.data.CompositeChange) Change(games.strategy.engine.data.Change) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) HashSet(java.util.HashSet)

Example 3 with Change

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

the class BattleDelegate method checkDefendingPlanesCanLand.

private void checkDefendingPlanesCanLand() {
    final GameData data = getData();
    final Map<Territory, Collection<Unit>> defendingAirThatCanNotLand = battleTracker.getDefendingAirThatCanNotLand();
    final boolean isWW2v2orIsSurvivingAirMoveToLand = Properties.getWW2V2(data) || Properties.getSurvivingAirMoveToLand(data);
    final Predicate<Unit> alliedDefendingAir = Matches.unitIsAir().and(Matches.unitWasScrambled().negate());
    for (final Entry<Territory, Collection<Unit>> entry : defendingAirThatCanNotLand.entrySet()) {
        final Territory battleSite = entry.getKey();
        final Collection<Unit> defendingAir = entry.getValue();
        if (defendingAir == null || defendingAir.isEmpty()) {
            continue;
        }
        defendingAir.retainAll(battleSite.getUnits());
        if (defendingAir.isEmpty()) {
            continue;
        }
        final PlayerID defender = AbstractBattle.findDefender(battleSite, player, data);
        // Get all land territories where we can land
        final Set<Territory> neighbors = data.getMap().getNeighbors(battleSite);
        final Predicate<Territory> alliedLandTerritories = Matches.airCanLandOnThisAlliedNonConqueredLandTerritory(defender, data);
        // Get those that are neighbors
        final Collection<Territory> canLandHere = CollectionUtils.getMatches(neighbors, alliedLandTerritories);
        // Get all sea territories where there are allies
        final Predicate<Territory> neighboringSeaZonesWithAlliedUnits = Matches.territoryIsWater().and(Matches.territoryHasAlliedUnits(defender, data));
        // Get those that are neighbors
        final Collection<Territory> areSeaNeighbors = CollectionUtils.getMatches(neighbors, neighboringSeaZonesWithAlliedUnits);
        // Set up match criteria for allied carriers
        final Predicate<Unit> alliedCarrier = Matches.unitIsCarrier().and(Matches.alliedUnit(defender, data));
        // Set up match criteria for allied planes
        final Predicate<Unit> alliedPlane = Matches.unitIsAir().and(Matches.alliedUnit(defender, data));
        // See if neighboring carriers have any capacity available
        for (final Territory currentTerritory : areSeaNeighbors) {
            // get the capacity of the carriers and cost of fighters
            final Collection<Unit> alliedCarriers = currentTerritory.getUnits().getMatches(alliedCarrier);
            final Collection<Unit> alliedPlanes = currentTerritory.getUnits().getMatches(alliedPlane);
            final int alliedCarrierCapacity = AirMovementValidator.carrierCapacity(alliedCarriers, currentTerritory);
            final int alliedPlaneCost = AirMovementValidator.carrierCost(alliedPlanes);
            // if there is free capacity, add the territory to landing possibilities
            if (alliedCarrierCapacity - alliedPlaneCost >= 1) {
                canLandHere.add(currentTerritory);
            }
        }
        if (isWW2v2orIsSurvivingAirMoveToLand) {
            Territory territory;
            while (canLandHere.size() > 1 && defendingAir.size() > 0) {
                territory = getRemotePlayer(defender).selectTerritoryForAirToLand(canLandHere, battleSite, "Select territory for air units to land. (Current territory is " + battleSite.getName() + "): " + MyFormatter.unitsToText(defendingAir));
                // added for test script
                if (territory == null) {
                    territory = canLandHere.iterator().next();
                }
                if (territory.isWater()) {
                    landPlanesOnCarriers(bridge, alliedDefendingAir, defendingAir, alliedCarrier, alliedPlane, territory, battleSite);
                } else {
                    moveAirAndLand(bridge, defendingAir, defendingAir, territory, battleSite);
                    continue;
                }
                // remove the territory from those available
                canLandHere.remove(territory);
            }
            // Land in the last remaining territory
            if (canLandHere.size() > 0 && defendingAir.size() > 0) {
                territory = canLandHere.iterator().next();
                if (territory.isWater()) {
                    landPlanesOnCarriers(bridge, alliedDefendingAir, defendingAir, alliedCarrier, alliedPlane, territory, battleSite);
                } else {
                    moveAirAndLand(bridge, defendingAir, defendingAir, territory, battleSite);
                    continue;
                }
            }
        } else if (canLandHere.size() > 0) {
            // check for an island in this sea zone
            for (final Territory currentTerritory : canLandHere) {
                // only one neighbor, its an island.
                if (data.getMap().getNeighbors(currentTerritory).size() == 1) {
                    moveAirAndLand(bridge, defendingAir, defendingAir, currentTerritory, battleSite);
                }
            }
        }
        if (defendingAir.size() > 0) {
            // no where to go, they must die
            bridge.getHistoryWriter().addChildToEvent(MyFormatter.unitsToText(defendingAir) + " could not land and were killed", new ArrayList<>(defendingAir));
            final Change change = ChangeFactory.removeUnits(battleSite, defendingAir);
            bridge.addChange(change);
        }
    }
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) Territory(games.strategy.engine.data.Territory) GameData(games.strategy.engine.data.GameData) CompositeChange(games.strategy.engine.data.CompositeChange) Change(games.strategy.engine.data.Change) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) Collection(java.util.Collection) ResourceCollection(games.strategy.engine.data.ResourceCollection)

Example 4 with Change

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

the class BattleTracker method addBombingBattle.

private void addBombingBattle(final Route route, final Collection<Unit> units, final PlayerID attacker, final GameData data, final HashMap<Unit, HashSet<Unit>> targets) {
    IBattle battle = getPendingBattle(route.getEnd(), true, BattleType.BOMBING_RAID);
    if (battle == null) {
        battle = new StrategicBombingRaidBattle(route.getEnd(), data, attacker, this);
        m_pendingBattles.add(battle);
        getBattleRecords().addBattle(attacker, battle.getBattleId(), route.getEnd(), battle.getBattleType());
    }
    final Change change = battle.addAttackChange(route, units, targets);
    // when state is moved to the game data, this will change
    if (!change.isEmpty()) {
        throw new IllegalStateException("Non empty change");
    }
    // dont let land battles in the same territory occur before bombing battles
    final IBattle dependent = getPendingBattle(route.getEnd(), false, BattleType.NORMAL);
    if (dependent != null) {
        addDependency(dependent, battle);
    }
    final IBattle dependentAirBattle = getPendingBattle(route.getEnd(), false, BattleType.AIR_BATTLE);
    if (dependentAirBattle != null) {
        addDependency(dependentAirBattle, battle);
    }
}
Also used : CompositeChange(games.strategy.engine.data.CompositeChange) Change(games.strategy.engine.data.Change)

Example 5 with Change

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

the class BattleTracker method captureOrDestroyUnits.

/**
 * Called when a territory is conquered to determine if remaining enemy units should be
 * captured, destroyed, or take damage.
 */
public static void captureOrDestroyUnits(final Territory territory, final PlayerID id, final PlayerID newOwner, final IDelegateBridge bridge, final UndoableMove changeTracker) {
    final GameData data = bridge.getData();
    // destroy any units that should be destroyed on capture
    if (Properties.getUnitsCanBeDestroyedInsteadOfCaptured(data)) {
        final Predicate<Unit> enemyToBeDestroyed = Matches.enemyUnit(id, data).and(Matches.unitDestroyedWhenCapturedByOrFrom(id));
        final Collection<Unit> destroyed = territory.getUnits().getMatches(enemyToBeDestroyed);
        if (!destroyed.isEmpty()) {
            final Change destroyUnits = ChangeFactory.removeUnits(territory, destroyed);
            bridge.getHistoryWriter().addChildToEvent("Some non-combat units are destroyed: ", destroyed);
            bridge.addChange(destroyUnits);
            if (changeTracker != null) {
                changeTracker.addChange(destroyUnits);
            }
        }
    }
    // destroy any capture on entering units, IF the property to destroy them instead of capture is turned on
    if (Properties.getOnEnteringUnitsDestroyedInsteadOfCaptured(data)) {
        final Collection<Unit> destroyed = territory.getUnits().getMatches(Matches.unitCanBeCapturedOnEnteringToInThisTerritory(id, territory, data));
        if (!destroyed.isEmpty()) {
            final Change destroyUnits = ChangeFactory.removeUnits(territory, destroyed);
            bridge.getHistoryWriter().addChildToEvent(id.getName() + " destroys some units instead of capturing them", destroyed);
            bridge.addChange(destroyUnits);
            if (changeTracker != null) {
                changeTracker.addChange(destroyUnits);
            }
        }
    }
    // destroy any disabled units owned by the enemy that are NOT infrastructure or factories
    final Predicate<Unit> enemyToBeDestroyed = Matches.enemyUnit(id, data).and(Matches.unitIsDisabled()).and(Matches.unitIsInfrastructure().negate());
    final Collection<Unit> destroyed = territory.getUnits().getMatches(enemyToBeDestroyed);
    if (!destroyed.isEmpty()) {
        final Change destroyUnits = ChangeFactory.removeUnits(territory, destroyed);
        bridge.getHistoryWriter().addChildToEvent(id.getName() + " destroys some disabled combat units", destroyed);
        bridge.addChange(destroyUnits);
        if (changeTracker != null) {
            changeTracker.addChange(destroyUnits);
        }
    }
    // take over non combatants
    final Predicate<Unit> enemyNonCom = Matches.enemyUnit(id, data).and(Matches.unitIsInfrastructure());
    final Predicate<Unit> willBeCaptured = enemyNonCom.or(Matches.unitCanBeCapturedOnEnteringToInThisTerritory(id, territory, data));
    final Collection<Unit> nonCom = territory.getUnits().getMatches(willBeCaptured);
    // change any units that change unit types on capture
    if (Properties.getUnitsCanBeChangedOnCapture(data)) {
        final Collection<Unit> toReplace = CollectionUtils.getMatches(nonCom, Matches.unitWhenCapturedChangesIntoDifferentUnitType());
        for (final Unit u : toReplace) {
            final Map<String, Tuple<String, IntegerMap<UnitType>>> map = UnitAttachment.get(u.getType()).getWhenCapturedChangesInto();
            final PlayerID currentOwner = u.getOwner();
            for (final String value : map.keySet()) {
                final String[] s = value.split(":");
                if (!(s[0].equals("any") || data.getPlayerList().getPlayerId(s[0]).equals(currentOwner))) {
                    continue;
                }
                // we could use "id" or "newOwner" here... not sure which to use
                if (!(s[1].equals("any") || data.getPlayerList().getPlayerId(s[1]).equals(id))) {
                    continue;
                }
                final CompositeChange changes = new CompositeChange();
                final Collection<Unit> toAdd = new ArrayList<>();
                final Tuple<String, IntegerMap<UnitType>> toCreate = map.get(value);
                final boolean translateAttributes = toCreate.getFirst().equalsIgnoreCase("true");
                for (final UnitType ut : toCreate.getSecond().keySet()) {
                    toAdd.addAll(ut.create(toCreate.getSecond().getInt(ut), newOwner));
                }
                if (!toAdd.isEmpty()) {
                    if (translateAttributes) {
                        final Change translate = TripleAUnit.translateAttributesToOtherUnits(u, toAdd, territory);
                        if (!translate.isEmpty()) {
                            changes.add(translate);
                        }
                    }
                    changes.add(ChangeFactory.removeUnits(territory, Collections.singleton(u)));
                    changes.add(ChangeFactory.addUnits(territory, toAdd));
                    changes.add(ChangeFactory.markNoMovementChange(toAdd));
                    bridge.getHistoryWriter().addChildToEvent(id.getName() + " converts " + u.toStringNoOwner() + " into different units", toAdd);
                    bridge.addChange(changes);
                    if (changeTracker != null) {
                        changeTracker.addChange(changes);
                    }
                    // don't forget to remove this unit from the list
                    nonCom.remove(u);
                    break;
                }
            }
        }
    }
    if (!nonCom.isEmpty()) {
        // FYI: a dummy delegate will not do anything with this change,
        // meaning that the battle calculator will think this unit lived,
        // even though it died or was captured, etc!
        final Change capture = ChangeFactory.changeOwner(nonCom, newOwner, territory);
        bridge.addChange(capture);
        if (changeTracker != null) {
            changeTracker.addChange(capture);
        }
        final Change noMovementChange = ChangeFactory.markNoMovementChange(nonCom);
        bridge.addChange(noMovementChange);
        if (changeTracker != null) {
            changeTracker.addChange(noMovementChange);
        }
        final IntegerMap<Unit> damageMap = new IntegerMap<>();
        for (final Unit unit : CollectionUtils.getMatches(nonCom, Matches.unitWhenCapturedSustainsDamage())) {
            final TripleAUnit taUnit = (TripleAUnit) unit;
            final int damageLimit = taUnit.getHowMuchMoreDamageCanThisUnitTake(unit, territory);
            final int sustainedDamage = UnitAttachment.get(unit.getType()).getWhenCapturedSustainsDamage();
            final int actualDamage = Math.max(0, Math.min(sustainedDamage, damageLimit));
            final int totalDamage = taUnit.getUnitDamage() + actualDamage;
            damageMap.put(unit, totalDamage);
        }
        if (!damageMap.isEmpty()) {
            final Change damageChange = ChangeFactory.bombingUnitDamage(damageMap);
            bridge.addChange(damageChange);
            if (changeTracker != null) {
                changeTracker.addChange(damageChange);
            }
            // Kill any units that can die if they have reached max damage
            if (damageMap.keySet().stream().anyMatch(Matches.unitCanDieFromReachingMaxDamage())) {
                final List<Unit> unitsCanDie = CollectionUtils.getMatches(damageMap.keySet(), Matches.unitCanDieFromReachingMaxDamage());
                unitsCanDie.retainAll(CollectionUtils.getMatches(unitsCanDie, Matches.unitIsAtMaxDamageOrNotCanBeDamaged(territory)));
                if (!unitsCanDie.isEmpty()) {
                    final Change removeDead = ChangeFactory.removeUnits(territory, unitsCanDie);
                    bridge.addChange(removeDead);
                    if (changeTracker != null) {
                        changeTracker.addChange(removeDead);
                    }
                }
            }
        }
    }
}
Also used : IntegerMap(games.strategy.util.IntegerMap) PlayerID(games.strategy.engine.data.PlayerID) GameData(games.strategy.engine.data.GameData) ArrayList(java.util.ArrayList) CompositeChange(games.strategy.engine.data.CompositeChange) Change(games.strategy.engine.data.Change) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) TripleAUnit(games.strategy.triplea.TripleAUnit) UnitType(games.strategy.engine.data.UnitType) CompositeChange(games.strategy.engine.data.CompositeChange) Tuple(games.strategy.util.Tuple)

Aggregations

Change (games.strategy.engine.data.Change)70 CompositeChange (games.strategy.engine.data.CompositeChange)44 Unit (games.strategy.engine.data.Unit)40 TripleAUnit (games.strategy.triplea.TripleAUnit)29 PlayerID (games.strategy.engine.data.PlayerID)25 Territory (games.strategy.engine.data.Territory)23 ArrayList (java.util.ArrayList)20 GameData (games.strategy.engine.data.GameData)19 UnitType (games.strategy.engine.data.UnitType)16 Resource (games.strategy.engine.data.Resource)12 Test (org.junit.jupiter.api.Test)11 ITestDelegateBridge (games.strategy.engine.data.ITestDelegateBridge)9 Route (games.strategy.engine.data.Route)9 HashSet (java.util.HashSet)8 UnitAttachment (games.strategy.triplea.attachments.UnitAttachment)6 Collection (java.util.Collection)6 IntegerMap (games.strategy.util.IntegerMap)5 Tuple (games.strategy.util.Tuple)4 ProductionFrontier (games.strategy.engine.data.ProductionFrontier)3 ITripleAPlayer (games.strategy.triplea.player.ITripleAPlayer)3