use of games.strategy.engine.data.Route 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);
}
}
}
}
use of games.strategy.engine.data.Route in project triplea by triplea-game.
the class BattleDelegate method whereCanAirLand.
private static Collection<Territory> whereCanAirLand(final Collection<Unit> strandedAir, final Territory currentTerr, final PlayerID alliedPlayer, final GameData data, final BattleTracker battleTracker, final int carrierCostForCurrentTerr, final int allowedMovement, final boolean useMaxScrambleDistance) {
int maxDistance = allowedMovement;
if ((maxDistance > 1) || useMaxScrambleDistance) {
UnitType ut = null;
for (final Unit u : strandedAir) {
if (ut == null) {
ut = u.getType();
} else if (!ut.equals(u.getType())) {
throw new IllegalStateException("whereCanAirLand can only accept 1 UnitType if byMovementCost or scrambled is true");
}
}
if (useMaxScrambleDistance) {
maxDistance = UnitAttachment.get(ut).getMaxScrambleDistance();
}
}
if (maxDistance < 1 || strandedAir == null || strandedAir.isEmpty()) {
return Collections.singletonList(currentTerr);
}
final boolean areNeutralsPassableByAir = (Properties.getNeutralFlyoverAllowed(data) && !Properties.getNeutralsImpassable(data));
final HashSet<Territory> canNotLand = new HashSet<>();
canNotLand.addAll(battleTracker.getPendingBattleSites(false));
canNotLand.addAll(CollectionUtils.getMatches(data.getMap().getTerritories(), Matches.territoryHasEnemyUnits(alliedPlayer, data)));
final Collection<Territory> possibleTerrs = new ArrayList<>(data.getMap().getNeighbors(currentTerr, maxDistance));
if (maxDistance > 1) {
final Iterator<Territory> possibleIter = possibleTerrs.iterator();
while (possibleIter.hasNext()) {
final Route route = data.getMap().getRoute(currentTerr, possibleIter.next(), Matches.airCanFlyOver(alliedPlayer, data, areNeutralsPassableByAir));
if (route == null || route.getMovementCost(strandedAir.iterator().next()) > maxDistance) {
possibleIter.remove();
}
}
}
possibleTerrs.add(currentTerr);
final HashSet<Territory> availableLand = new HashSet<>(CollectionUtils.getMatches(possibleTerrs, Matches.isTerritoryAllied(alliedPlayer, data).and(Matches.territoryIsLand())));
availableLand.removeAll(canNotLand);
final HashSet<Territory> whereCanLand = new HashSet<>(availableLand);
// now for carrier-air-landing validation
if (!strandedAir.isEmpty() && strandedAir.stream().allMatch(Matches.unitCanLandOnCarrier())) {
final HashSet<Territory> availableWater = new HashSet<>(CollectionUtils.getMatches(possibleTerrs, Matches.territoryHasUnitsThatMatch(Matches.unitIsAlliedCarrier(alliedPlayer, data)).and(Matches.territoryIsWater())));
availableWater.removeAll(battleTracker.getPendingBattleSites(false));
// a rather simple calculation, either we can take all the air, or we can't, nothing in the middle
final int carrierCost = AirMovementValidator.carrierCost(strandedAir);
final Iterator<Territory> waterIter = availableWater.iterator();
while (waterIter.hasNext()) {
final Territory t = waterIter.next();
int carrierCapacity = AirMovementValidator.carrierCapacity(t.getUnits().getMatches(Matches.unitIsAlliedCarrier(alliedPlayer, data)), t);
if (!t.equals(currentTerr)) {
carrierCapacity -= AirMovementValidator.carrierCost(t.getUnits().getMatches(Matches.unitCanLandOnCarrier().and(Matches.alliedUnit(alliedPlayer, data))));
} else {
carrierCapacity -= carrierCostForCurrentTerr;
}
if (carrierCapacity < carrierCost) {
waterIter.remove();
}
}
whereCanLand.addAll(availableWater);
}
return whereCanLand;
}
use of games.strategy.engine.data.Route in project triplea by triplea-game.
the class AirMovementValidator method validateAirCaughtByMovingCarriersAndOwnedAndAlliedAir.
private static void validateAirCaughtByMovingCarriersAndOwnedAndAlliedAir(final MoveValidationResult result, final List<Territory> landingSpots, final Collection<Territory> potentialCarrierOrigins, final Map<Unit, Collection<Unit>> movedCarriersAndTheirFighters, final Collection<Unit> airThatMustLandOnCarriers, final Collection<Unit> airNotToConsider, final PlayerID player, final Route route, final GameData data) {
final Predicate<Unit> ownedCarrierMatch = Matches.unitIsOwnedBy(player).and(Matches.unitIsCarrier());
final Predicate<Unit> ownedAirMatch = Matches.unitIsOwnedBy(player).and(Matches.unitIsAir()).and(Matches.unitCanLandOnCarrier());
final Predicate<Unit> alliedNotOwnedAirMatch = Matches.unitIsOwnedBy(player).negate().and(Matches.isUnitAllied(player, data)).and(Matches.unitIsAir()).and(Matches.unitCanLandOnCarrier());
final Predicate<Unit> alliedNotOwnedCarrierMatch = Matches.unitIsOwnedBy(player).negate().and(Matches.isUnitAllied(player, data)).and(Matches.unitIsCarrier());
final Territory routeEnd = route.getEnd();
final boolean areNeutralsPassableByAir = areNeutralsPassableByAir(data);
final IntegerMap<Territory> landingSpotsWithCarrierCapacity = // fill our landing spot capacity with capacity from allied carriers and potential building of new carriers
populateStaticAlliedAndBuildingCarrierCapacity(landingSpots, movedCarriersAndTheirFighters, player, data);
final LinkedHashMap<Unit, Integer> movementLeftForAirToValidate = // calculate movement left only once
getMovementLeftForValidatingAir(airThatMustLandOnCarriers, player, route);
for (final Territory landingSpot : landingSpots) {
// since we are here, no point looking at this place twice
potentialCarrierOrigins.remove(landingSpot);
final List<Unit> airCanReach = new ArrayList<>();
for (final Unit air : airThatMustLandOnCarriers) {
if (canAirReachThisSpot(data, player, air, routeEnd, movementLeftForAirToValidate.get(air), landingSpot, areNeutralsPassableByAir)) {
// get all air that can reach this spot
airCanReach.add(air);
}
}
if (airCanReach.isEmpty()) {
continue;
}
final Collection<Unit> unitsInLandingSpot = landingSpot.getUnits().getUnits();
unitsInLandingSpot.removeAll(movedCarriersAndTheirFighters.keySet());
// make sure to remove any units we have already moved, or units that are excluded
unitsInLandingSpot.removeAll(airNotToConsider);
// because they are in our mouse selection
for (final Collection<Unit> ftrs : movedCarriersAndTheirFighters.values()) {
// also remove any fighters that are being moved with carriers that we have already moved
unitsInLandingSpot.removeAll(ftrs);
}
final Collection<Unit> ownedCarriersInLandingSpot = CollectionUtils.getMatches(unitsInLandingSpot, ownedCarrierMatch);
// get air we own here, but exclude any air that can fly to allied land
final Collection<Unit> airInLandingSpot = CollectionUtils.getMatches(CollectionUtils.getMatches(unitsInLandingSpot, ownedAirMatch), unitCanFindLand(data, landingSpot).negate());
// add allied air (it can't fly away)
airInLandingSpot.addAll(CollectionUtils.getMatches(unitsInLandingSpot, alliedNotOwnedAirMatch));
// make sure we don't count this again
// airNotToConsider.addAll(airInLandingSpot);
// get the current capacity
int landingSpotCapacity = landingSpotsWithCarrierCapacity.getInt(landingSpot);
// add capacity of owned carriers
landingSpotCapacity += carrierCapacity(ownedCarriersInLandingSpot, landingSpot);
// minus capacity of air in the territory
landingSpotCapacity -= carrierCost(airInLandingSpot);
if (!airCanReach.isEmpty()) {
final Iterator<Unit> airIter = airCanReach.iterator();
while (airIter.hasNext()) {
final Unit air = airIter.next();
final int carrierCost = carrierCost(air);
if (landingSpotCapacity >= carrierCost) {
landingSpotCapacity -= carrierCost;
// we can land this one here, yay
airThatMustLandOnCarriers.remove(air);
airIter.remove();
}
}
}
if (airThatMustLandOnCarriers.isEmpty()) {
// all can land here, so return
return;
}
// final int lowestCarrierCost = getLowestCarrierCost(airCanReach);
// now bring carriers here...
final Iterator<Territory> iter = potentialCarrierOrigins.iterator();
while (iter.hasNext()) {
final Territory carrierSpot = iter.next();
final Collection<Unit> unitsInCarrierSpot = carrierSpot.getUnits().getUnits();
// remove carriers we have already moved
unitsInCarrierSpot.removeAll(movedCarriersAndTheirFighters.keySet());
// remove units we do not want to consider because they are in our mouse selection
unitsInCarrierSpot.removeAll(airNotToConsider);
for (final Collection<Unit> ftrs : movedCarriersAndTheirFighters.values()) {
// remove the fighters that are moving with the carriers we have already moved
unitsInCarrierSpot.removeAll(ftrs);
}
final Collection<Unit> ownedCarriersInCarrierSpot = CollectionUtils.getMatches(unitsInCarrierSpot, ownedCarrierMatch);
if (ownedCarriersInCarrierSpot.isEmpty()) {
iter.remove();
continue;
}
final Collection<Unit> ownedAirInCarrierSpot = CollectionUtils.getMatches(// exclude any owned air that can fly to land
CollectionUtils.getMatches(unitsInCarrierSpot, ownedAirMatch), unitCanFindLand(data, carrierSpot).negate());
final Collection<Unit> alliedNotOwnedAirInCarrierSpot = CollectionUtils.getMatches(unitsInCarrierSpot, alliedNotOwnedAirMatch);
final Map<Unit, Collection<Unit>> mustMoveWithMap = // this only returns the allied cargo
MoveValidator.carrierMustMoveWith(ownedCarriersInCarrierSpot, carrierSpot, data, player);
// planes that MUST travel with the carrier
// get the current capacity for the carrier spot
int carrierSpotCapacity = landingSpotsWithCarrierCapacity.getInt(carrierSpot);
// we don't have it because this spot is not in the landing zone area.
if (!landingSpotsWithCarrierCapacity.containsKey(carrierSpot)) {
// we still have a capacity for allied carriers, but only to carry other allied or local owned units, not to
// carry our selected
// units.
carrierSpotCapacity = carrierCapacity(carrierSpot.getUnits().getMatches(alliedNotOwnedCarrierMatch), carrierSpot);
landingSpotsWithCarrierCapacity.put(carrierSpot, carrierSpotCapacity);
}
// we have allied air here, so we need to account for them before moving any carriers
if (!alliedNotOwnedAirInCarrierSpot.isEmpty() || !mustMoveWithMap.isEmpty()) {
// them
if (mustMoveWithMap.isEmpty()) {
// allied carriers can carry enough
carrierSpotCapacity -= carrierCost(alliedNotOwnedAirInCarrierSpot);
// we do not want to consider these units again
airNotToConsider.addAll(alliedNotOwnedAirInCarrierSpot);
if (carrierSpotCapacity > 0) {
// we can hold some of the owned air here too
final Iterator<Unit> ownedIter = ownedAirInCarrierSpot.iterator();
while (ownedIter.hasNext()) {
final Unit air = ownedIter.next();
final int carrierCost = carrierCost(air);
if (carrierSpotCapacity >= carrierCost) {
carrierSpotCapacity -= carrierCost;
// we do not want to consider this one again
airNotToConsider.add(air);
ownedIter.remove();
}
}
}
// put correct value for future reference now that we
// have considered the allied air
landingSpotsWithCarrierCapacity.put(carrierSpot, carrierSpotCapacity);
} else {
// carrierMustMoveWith does not account for any allied cargo already moved out.
for (final Collection<Unit> airMovingWith : mustMoveWithMap.values()) {
for (final Collection<Unit> ftrs : movedCarriersAndTheirFighters.values()) {
// remove the fighters that are moving with the carriers we have already moved
airMovingWith.removeAll(ftrs);
}
}
for (final Collection<Unit> airMovingWith : mustMoveWithMap.values()) {
// we will consider these as part of their moving carrier
alliedNotOwnedAirInCarrierSpot.removeAll(airMovingWith);
}
carrierSpotCapacity -= carrierCost(alliedNotOwnedAirInCarrierSpot);
// we do not want to consider these units again
airNotToConsider.addAll(alliedNotOwnedAirInCarrierSpot);
// put correct value for future reference now that we
// have considered the allied air
landingSpotsWithCarrierCapacity.put(carrierSpot, carrierSpotCapacity);
}
}
final Route toLandingSpot = data.getMap().getRoute(carrierSpot, landingSpot, Matches.seaCanMoveOver(player, data));
if (toLandingSpot == null) {
continue;
}
final List<Unit> carrierCanReach = CollectionUtils.getMatches(ownedCarriersInCarrierSpot, Matches.unitHasEnoughMovementForRoute(toLandingSpot));
if (carrierCanReach.isEmpty()) {
// none can reach
continue;
}
final List<Unit> carrierNotReach = new ArrayList<>(ownedCarriersInCarrierSpot);
// we want to see if the air units can be put on the carriers that cannot make it
// first, before taking up room on the carriers that can make it
carrierNotReach.removeAll(carrierCanReach);
final List<Unit> allCarriers = new ArrayList<>(carrierNotReach);
// so we remove them from the list then re-add them so that they will be at the end of the list
allCarriers.addAll(carrierCanReach);
// now we want to make a map of the carriers to the units they must carry with them (both allied and owned)
final Map<Unit, Collection<Unit>> carriersToMove = new HashMap<>();
final List<Unit> carrierFull = new ArrayList<>();
for (final Unit carrier : allCarriers) {
final Collection<Unit> airMovingWith = new ArrayList<>();
// first add allied cargo
final Collection<Unit> alliedMovingWith = mustMoveWithMap.get(carrier);
if (alliedMovingWith != null) {
airMovingWith.addAll(alliedMovingWith);
}
// now test if our carrier has any room for owned fighters
int carrierCapacity = carrierCapacity(carrier, carrierSpot);
carrierCapacity -= carrierCost(airMovingWith);
final Iterator<Unit> ownedIter = ownedAirInCarrierSpot.iterator();
while (ownedIter.hasNext()) {
final Unit air = ownedIter.next();
final int carrierCost = carrierCost(air);
if (carrierCapacity >= carrierCost) {
carrierCapacity -= carrierCost;
airMovingWith.add(air);
ownedIter.remove();
}
}
carriersToMove.put(carrier, airMovingWith);
if (carrierCapacity <= 0) {
carrierFull.add(carrier);
}
}
// if all carriers full, remove this carrier spot from consideration
if (carrierFull.containsAll(allCarriers)) {
iter.remove();
continue;
}
if (carrierFull.containsAll(carrierNotReach)) {
iter.remove();
}
// ok, now lets move them.
for (final Unit carrier : carrierCanReach) {
movedCarriersAndTheirFighters.put(carrier, carriersToMove.get(carrier));
landingSpotCapacity += carrierCapacity(carrier, carrierSpot);
landingSpotCapacity -= carrierCost(carriersToMove.get(carrier));
}
// optional for debugging
final Iterator<Unit> reachIter = airCanReach.iterator();
while (reachIter.hasNext()) {
final Unit air = reachIter.next();
final int carrierCost = carrierCost(air);
if (landingSpotCapacity >= carrierCost) {
landingSpotCapacity -= carrierCost;
// we can land this one here, yay
airThatMustLandOnCarriers.remove(air);
reachIter.remove();
}
}
if (airThatMustLandOnCarriers.isEmpty()) {
// all can land here, so return
return;
}
}
}
// anyone left over cannot land
for (final Unit air : airThatMustLandOnCarriers) {
result.addDisallowedUnit(NOT_ALL_AIR_UNITS_CAN_LAND, air);
}
}
use of games.strategy.engine.data.Route in project triplea by triplea-game.
the class MovePerformer method populateStack.
/**
* We assume that the move is valid.
*/
private void populateStack(final Collection<Unit> units, final Route route, final PlayerID id, final Collection<Unit> transportsToLoad) {
final IExecutable preAaFire = new IExecutable() {
private static final long serialVersionUID = -7945930782650355037L;
@Override
public void execute(final ExecutionStack stack, final IDelegateBridge bridge) {
// this can happen for air units moving out of a battle zone
for (final IBattle battle : getBattleTracker().getPendingBattles(route.getStart(), null)) {
for (final Unit unit : units) {
final Route routeUnitUsedToMove = moveDelegate.getRouteUsedToMoveInto(unit, route.getStart());
if (battle != null) {
battle.removeAttack(routeUnitUsedToMove, Collections.singleton(unit));
}
}
}
}
};
// hack to allow the executables to share state
final IExecutable fireAa = new IExecutable() {
private static final long serialVersionUID = -3780228078499895244L;
@Override
public void execute(final ExecutionStack stack, final IDelegateBridge bridge) {
final Collection<Unit> aaCasualties = fireAa(route, units);
final Set<Unit> aaCasualtiesWithDependents = new HashSet<>();
// need to remove any dependents here
if (aaCasualties != null) {
aaCasualtiesWithDependents.addAll(aaCasualties);
final Map<Unit, Collection<Unit>> dependencies = TransportTracker.transporting(units, units);
for (final Unit u : aaCasualties) {
final Collection<Unit> dependents = dependencies.get(u);
if (dependents != null) {
aaCasualtiesWithDependents.addAll(dependents);
}
// we might have new dependents too (ie: paratroopers)
final Collection<Unit> newDependents = m_newDependents.get(u);
if (newDependents != null) {
aaCasualtiesWithDependents.addAll(newDependents);
}
}
}
arrivingUnits = CollectionUtils.difference(units, aaCasualtiesWithDependents);
}
};
final IExecutable postAaFire = new IExecutable() {
private static final long serialVersionUID = 670783657414493643L;
@Override
public void execute(final ExecutionStack stack, final IDelegateBridge bridge) {
// if any non enemy territories on route
// or if any enemy units on route the
// battles on (note water could have enemy but its
// not owned)
final GameData data = bridge.getData();
final Predicate<Territory> mustFightThrough = getMustFightThroughMatch(id, data);
final Collection<Unit> arrived = Collections.unmodifiableList(CollectionUtils.intersection(units, arrivingUnits));
// Reset Optional
arrivingUnits = new ArrayList<>();
final Collection<Unit> arrivedCopyForBattles = new ArrayList<>(arrived);
final Map<Unit, Unit> transporting = TransportUtils.mapTransports(route, arrived, transportsToLoad);
// If we have paratrooper land units being carried by air units, they should be dropped off in the last
// territory. This means they
// are still dependent during the middle steps of the route.
final Collection<Unit> dependentOnSomethingTilTheEndOfRoute = new ArrayList<>();
final Collection<Unit> airTransports = CollectionUtils.getMatches(arrived, Matches.unitIsAirTransport());
final Collection<Unit> paratroops = CollectionUtils.getMatches(arrived, Matches.unitIsAirTransportable());
if (!airTransports.isEmpty() && !paratroops.isEmpty()) {
final Map<Unit, Unit> transportingAir = TransportUtils.mapTransportsToLoad(paratroops, airTransports);
dependentOnSomethingTilTheEndOfRoute.addAll(transportingAir.keySet());
}
final Collection<Unit> presentFromStartTilEnd = new ArrayList<>(arrived);
presentFromStartTilEnd.removeAll(dependentOnSomethingTilTheEndOfRoute);
final CompositeChange change = new CompositeChange();
// markFuelCostResourceChange must be done before we load/unload units
change.add(Route.getFuelChanges(units, route, id, data));
markTransportsMovement(arrived, transporting, route);
if (route.anyMatch(mustFightThrough) && arrived.size() != 0) {
boolean bombing = false;
boolean ignoreBattle = false;
// could it be a bombing raid
final Collection<Unit> enemyUnits = route.getEnd().getUnits().getMatches(Matches.enemyUnit(id, data));
final Collection<Unit> enemyTargetsTotal = CollectionUtils.getMatches(enemyUnits, Matches.unitCanBeDamaged().and(Matches.unitIsBeingTransported().negate()));
final boolean canCreateAirBattle = !enemyTargetsTotal.isEmpty() && Properties.getRaidsMayBePreceededByAirBattles(data) && AirBattle.territoryCouldPossiblyHaveAirBattleDefenders(route.getEnd(), id, data, true);
final Predicate<Unit> allBombingRaid = PredicateBuilder.of(Matches.unitIsStrategicBomber()).orIf(canCreateAirBattle, Matches.unitCanEscort()).build();
final boolean allCanBomb = !arrived.isEmpty() && arrived.stream().allMatch(allBombingRaid);
final Collection<Unit> enemyTargets = CollectionUtils.getMatches(enemyTargetsTotal, Matches.unitIsOfTypes(UnitAttachment.getAllowedBombingTargetsIntersection(CollectionUtils.getMatches(arrived, Matches.unitIsStrategicBomber()), data)));
final boolean targetsOrEscort = !enemyTargets.isEmpty() || (!enemyTargetsTotal.isEmpty() && canCreateAirBattle && !arrived.isEmpty() && arrived.stream().allMatch(Matches.unitCanEscort()));
boolean targetedAttack = false;
// if it's all bombers and there's something to bomb
if (allCanBomb && targetsOrEscort && GameStepPropertiesHelper.isCombatMove(data)) {
bombing = getRemotePlayer().shouldBomberBomb(route.getEnd());
// if bombing and there's something to target- ask what to bomb
if (bombing) {
// CompositeMatchOr<Unit> unitsToBeBombed = new CompositeMatchOr<Unit>(Matches.UnitIsFactory,
// Matches.UnitCanBeDamagedButIsNotFactory);
// determine which unit to bomb
final Unit target;
if (enemyTargets.size() > 1 && Properties.getDamageFromBombingDoneToUnitsInsteadOfTerritories(data) && !canCreateAirBattle) {
target = getRemotePlayer().whatShouldBomberBomb(route.getEnd(), enemyTargets, arrived);
} else if (!enemyTargets.isEmpty()) {
target = enemyTargets.iterator().next();
} else {
// in case we are escorts only
target = enemyTargetsTotal.iterator().next();
}
if (target == null) {
bombing = false;
targetedAttack = false;
} else {
targetedAttack = true;
final HashMap<Unit, HashSet<Unit>> targets = new HashMap<>();
targets.put(target, new HashSet<>(arrived));
// createdBattle = true;
getBattleTracker().addBattle(route, arrivedCopyForBattles, bombing, id, MovePerformer.this.bridge, m_currentMove, dependentOnSomethingTilTheEndOfRoute, targets, false);
}
}
}
// Ignore Trn on Trn forces.
if (isIgnoreTransportInMovement(bridge.getData())) {
final boolean allOwnedTransports = !arrived.isEmpty() && arrived.stream().allMatch(Matches.unitIsTransportButNotCombatTransport());
final boolean allEnemyTransports = !enemyUnits.isEmpty() && enemyUnits.stream().allMatch(Matches.unitIsTransportButNotCombatTransport());
// If everybody is a transport, don't create a battle
if (allOwnedTransports && allEnemyTransports) {
ignoreBattle = true;
}
}
if (!ignoreBattle && GameStepPropertiesHelper.isCombatMove(data) && !targetedAttack) {
// createdBattle = true;
if (bombing) {
getBattleTracker().addBombingBattle(route, arrivedCopyForBattles, id, MovePerformer.this.bridge, m_currentMove, dependentOnSomethingTilTheEndOfRoute);
} else {
getBattleTracker().addBattle(route, arrivedCopyForBattles, id, MovePerformer.this.bridge, m_currentMove, dependentOnSomethingTilTheEndOfRoute);
}
}
if (!ignoreBattle && GameStepPropertiesHelper.isNonCombatMove(data, false) && !targetedAttack) {
// difficult if we want these recorded in battle records).
for (final Territory t : route.getMatches(Matches.territoryIsOwnedByPlayerWhosRelationshipTypeCanTakeOverOwnedTerritoryAndPassableAndNotWater(id).and(Matches.territoryIsBlitzable(id, data)))) {
if (Matches.isTerritoryEnemy(id, data).test(t) || Matches.territoryHasEnemyUnits(id, data).test(t)) {
continue;
}
if ((t.equals(route.getEnd()) && !arrivedCopyForBattles.isEmpty() && arrivedCopyForBattles.stream().allMatch(Matches.unitIsAir())) || (!t.equals(route.getEnd()) && !presentFromStartTilEnd.isEmpty() && presentFromStartTilEnd.stream().allMatch(Matches.unitIsAir()))) {
continue;
}
// createdBattle = true;
getBattleTracker().takeOver(t, id, bridge, m_currentMove, arrivedCopyForBattles);
}
}
}
// mark movement
final Change moveChange = markMovementChange(arrived, route, id);
change.add(moveChange);
// actually move the units
if (route.getStart() != null && route.getEnd() != null) {
// ChangeFactory.addUnits(route.getEnd(), arrived);
final Change remove = ChangeFactory.removeUnits(route.getStart(), units);
final Change add = ChangeFactory.addUnits(route.getEnd(), arrived);
change.add(add, remove);
}
MovePerformer.this.bridge.addChange(change);
m_currentMove.addChange(change);
m_currentMove.setDescription(MyFormatter.unitsToTextNoOwner(arrived) + " moved from " + route.getStart().getName() + " to " + route.getEnd().getName());
moveDelegate.updateUndoableMoves(m_currentMove);
}
};
m_executionStack.push(postAaFire);
m_executionStack.push(fireAa);
m_executionStack.push(preAaFire);
m_executionStack.execute(bridge);
}
use of games.strategy.engine.data.Route in project triplea by triplea-game.
the class MustFightBattle method retreatFromDependents.
private Change retreatFromDependents(final Collection<Unit> units, final Territory retreatTo, final Collection<IBattle> dependentBattles) {
final CompositeChange change = new CompositeChange();
for (final IBattle dependent : dependentBattles) {
final Route route = new Route();
route.setStart(m_battleSite);
route.add(dependent.getTerritory());
final Collection<Unit> retreatedUnits = dependent.getDependentUnits(units);
dependent.removeAttack(route, retreatedUnits);
reLoadTransports(units, change);
change.add(ChangeFactory.moveUnits(dependent.getTerritory(), retreatTo, retreatedUnits));
}
return change;
}
Aggregations