Search in sources :

Example 1 with CompositeChange

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

the class BattleDelegate method scramblingCleanup.

private void scramblingCleanup() {
    // return scrambled units to their original territories, or let them move 1 or x to a new territory.
    final GameData data = getData();
    if (!Properties.getScrambleRulesInEffect(data)) {
        return;
    }
    final boolean mustReturnToBase = Properties.getScrambledUnitsReturnToBase(data);
    for (final Territory t : data.getMap().getTerritories()) {
        int carrierCostOfCurrentTerr = 0;
        final Collection<Unit> wasScrambled = t.getUnits().getMatches(Matches.unitWasScrambled());
        for (final Unit u : wasScrambled) {
            final CompositeChange change = new CompositeChange();
            final Territory originatedFrom = TripleAUnit.get(u).getOriginatedFrom();
            Territory landingTerr = null;
            final String historyText;
            if (!mustReturnToBase || !Matches.isTerritoryAllied(u.getOwner(), data).test(originatedFrom)) {
                final Collection<Territory> possible = whereCanAirLand(Collections.singletonList(u), t, u.getOwner(), data, battleTracker, carrierCostOfCurrentTerr, 1, !mustReturnToBase);
                if (possible.size() > 1) {
                    landingTerr = getRemotePlayer(u.getOwner()).selectTerritoryForAirToLand(possible, t, "Select territory for air units to land. (Current territory is " + t.getName() + "): " + MyFormatter.unitsToText(Collections.singletonList(u)));
                } else if (possible.size() == 1) {
                    landingTerr = possible.iterator().next();
                }
                if (landingTerr == null || landingTerr.equals(t)) {
                    carrierCostOfCurrentTerr += AirMovementValidator.carrierCost(Collections.singletonList(u));
                    historyText = "Scrambled unit stays in territory " + t.getName();
                } else {
                    historyText = "Moving scrambled unit from " + t.getName() + " to " + landingTerr.getName();
                }
            } else {
                landingTerr = originatedFrom;
                historyText = "Moving scrambled unit from " + t.getName() + " back to originating territory: " + landingTerr.getName();
            }
            // if null, we leave it to die
            if (landingTerr != null) {
                change.add(ChangeFactory.moveUnits(t, landingTerr, Collections.singletonList(u)));
                change.add(Route.getFuelChanges(Collections.singleton(u), new Route(t, landingTerr), u.getOwner(), data));
            }
            change.add(ChangeFactory.unitPropertyChange(u, null, TripleAUnit.ORIGINATED_FROM));
            change.add(ChangeFactory.unitPropertyChange(u, false, TripleAUnit.WAS_SCRAMBLED));
            if (!change.isEmpty()) {
                bridge.getHistoryWriter().startEvent(historyText, u);
                bridge.addChange(change);
            }
        }
    }
}
Also used : Territory(games.strategy.engine.data.Territory) GameData(games.strategy.engine.data.GameData) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) CompositeChange(games.strategy.engine.data.CompositeChange) Route(games.strategy.engine.data.Route)

Example 2 with CompositeChange

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

the class BattleDelegate method resetMaxScrambleCount.

private static void resetMaxScrambleCount(final IDelegateBridge bridge) {
    // reset the tripleaUnit property for all airbases that were used
    final GameData data = bridge.getData();
    if (!Properties.getScrambleRulesInEffect(data)) {
        return;
    }
    final CompositeChange change = new CompositeChange();
    for (final Territory t : data.getMap().getTerritories()) {
        final Collection<Unit> airbases = t.getUnits().getMatches(Matches.unitIsAirBase());
        for (final Unit u : airbases) {
            final UnitAttachment ua = UnitAttachment.get(u.getType());
            final int currentMax = ((TripleAUnit) u).getMaxScrambleCount();
            final int allowedMax = ua.getMaxScrambleCount();
            if (currentMax != allowedMax) {
                change.add(ChangeFactory.unitPropertyChange(u, allowedMax, TripleAUnit.MAX_SCRAMBLE_COUNT));
            }
        }
    }
    if (!change.isEmpty()) {
        bridge.getHistoryWriter().startEvent("Preparing Airbases for Possible Scrambling");
        bridge.addChange(change);
    }
}
Also used : UnitAttachment(games.strategy.triplea.attachments.UnitAttachment) Territory(games.strategy.engine.data.Territory) GameData(games.strategy.engine.data.GameData) CompositeChange(games.strategy.engine.data.CompositeChange) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) TripleAUnit(games.strategy.triplea.TripleAUnit)

Example 3 with CompositeChange

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

the class BattleDelegate method landParatroopers.

private static void landParatroopers(final PlayerID player, final Territory battleSite, final IDelegateBridge bridge) {
    if (TechTracker.hasParatroopers(player)) {
        final Collection<Unit> airTransports = CollectionUtils.getMatches(battleSite.getUnits(), Matches.unitIsAirTransport());
        final Collection<Unit> paratroops = CollectionUtils.getMatches(battleSite.getUnits(), Matches.unitIsAirTransportable());
        if (!airTransports.isEmpty() && !paratroops.isEmpty()) {
            final CompositeChange change = new CompositeChange();
            for (final Unit u : paratroops) {
                final TripleAUnit taUnit = (TripleAUnit) u;
                final Unit transport = taUnit.getTransportedBy();
                if (transport == null || !airTransports.contains(transport)) {
                    continue;
                }
                change.add(TransportTracker.unloadAirTransportChange(taUnit, battleSite, false));
            }
            if (!change.isEmpty()) {
                bridge.getHistoryWriter().startEvent(player.getName() + " lands units in " + battleSite.getName());
                bridge.addChange(change);
            }
        }
    }
}
Also used : TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) CompositeChange(games.strategy.engine.data.CompositeChange) TripleAUnit(games.strategy.triplea.TripleAUnit)

Example 4 with CompositeChange

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

the class BattleTracker method undoBattle.

void undoBattle(final Route route, final Collection<Unit> units, final PlayerID player, final IDelegateBridge bridge) {
    for (final IBattle battle : new ArrayList<>(m_pendingBattles)) {
        if (battle.getTerritory().equals(route.getEnd())) {
            battle.removeAttack(route, units);
            if (battle.isEmpty()) {
                removeBattleForUndo(player, battle);
            }
        }
    }
    final RelationshipTracker relationshipTracker = bridge.getData().getRelationshipTracker();
    // because we could have conquered the end territory if there are no units there
    for (final Territory current : route.getAllTerritories()) {
        if (!relationshipTracker.isAllied(current.getOwner(), player) && m_conquered.contains(current)) {
            m_conquered.remove(current);
            m_blitzed.remove(current);
        }
    }
    // say they weren't in combat
    final CompositeChange change = new CompositeChange();
    for (final Unit unit : units) {
        change.add(ChangeFactory.unitPropertyChange(unit, false, TripleAUnit.WAS_IN_COMBAT));
    }
    bridge.addChange(change);
}
Also used : Territory(games.strategy.engine.data.Territory) ArrayList(java.util.ArrayList) RelationshipTracker(games.strategy.engine.data.RelationshipTracker) CompositeChange(games.strategy.engine.data.CompositeChange) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit)

Example 5 with CompositeChange

use of games.strategy.engine.data.CompositeChange 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

CompositeChange (games.strategy.engine.data.CompositeChange)74 Unit (games.strategy.engine.data.Unit)48 TripleAUnit (games.strategy.triplea.TripleAUnit)40 GameData (games.strategy.engine.data.GameData)31 Territory (games.strategy.engine.data.Territory)25 ArrayList (java.util.ArrayList)22 PlayerID (games.strategy.engine.data.PlayerID)21 Change (games.strategy.engine.data.Change)17 UnitType (games.strategy.engine.data.UnitType)14 Resource (games.strategy.engine.data.Resource)9 HashSet (java.util.HashSet)9 UnitAttachment (games.strategy.triplea.attachments.UnitAttachment)8 IntegerMap (games.strategy.util.IntegerMap)8 Tuple (games.strategy.util.Tuple)7 Collection (java.util.Collection)7 RelationshipType (games.strategy.engine.data.RelationshipType)6 Set (java.util.Set)6 ProductionFrontier (games.strategy.engine.data.ProductionFrontier)4 ProductionRule (games.strategy.engine.data.ProductionRule)4 HashMap (java.util.HashMap)4