use of games.strategy.engine.data.Territory 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);
}
}
}
use of games.strategy.engine.data.Territory in project triplea by triplea-game.
the class BattleDelegate method addBombardmentSources.
/**
* Add bombardment units to battles. Made public for test purposes only.
*/
void addBombardmentSources() {
final PlayerID attacker = bridge.getPlayerId();
final ITripleAPlayer remotePlayer = getRemotePlayer();
final Predicate<Unit> ownedAndCanBombard = Matches.unitCanBombard(attacker).and(Matches.unitIsOwnedBy(attacker));
final Map<Territory, Collection<IBattle>> adjBombardment = getPossibleBombardingTerritories();
final boolean shoreBombardPerGroundUnitRestricted = isShoreBombardPerGroundUnitRestricted(getData());
for (final Territory t : adjBombardment.keySet()) {
if (!battleTracker.hasPendingBattle(t, false)) {
Collection<IBattle> battles = adjBombardment.get(t);
battles = CollectionUtils.getMatches(battles, Matches.battleIsAmphibious());
if (!battles.isEmpty()) {
final Collection<Unit> bombardUnits = t.getUnits().getMatches(ownedAndCanBombard);
final List<Unit> listedBombardUnits = new ArrayList<>(bombardUnits);
sortUnitsToBombard(listedBombardUnits, attacker);
if (!bombardUnits.isEmpty()) {
// ask if they want to bombard
if (!remotePlayer.selectShoreBombard(t)) {
continue;
}
}
for (final Unit u : listedBombardUnits) {
final IBattle battle = selectBombardingBattle(u, t, battles);
if (battle != null) {
if (shoreBombardPerGroundUnitRestricted) {
if (battle.getAmphibiousLandAttackers().size() <= battle.getBombardingUnits().size()) {
battles.remove(battle);
break;
}
}
battle.addBombardingUnit(u);
}
}
}
}
}
}
use of games.strategy.engine.data.Territory in project triplea by triplea-game.
the class BattleDelegate method setupUnitsInSameTerritoryBattles.
/**
* Setup the battles where the battle occurs because units are in the
* same territory. This happens when subs emerge (after being submerged), and
* when naval units are placed in enemy occupied sea zones, and also
* when political relationships change and potentially leave units in now-hostile territories.
*/
private static void setupUnitsInSameTerritoryBattles(final BattleTracker battleTracker, final IDelegateBridge bridge) {
final PlayerID player = bridge.getPlayerId();
final GameData data = bridge.getData();
final boolean ignoreTransports = isIgnoreTransportInMovement(data);
final boolean ignoreSubs = isIgnoreSubInMovement(data);
final Predicate<Unit> seaTransports = Matches.unitIsTransportButNotCombatTransport().and(Matches.unitIsSea());
final Predicate<Unit> seaTranportsOrSubs = seaTransports.or(Matches.unitIsSub());
// we want to match all sea zones with our units and enemy units
final Predicate<Territory> anyTerritoryWithOwnAndEnemy = Matches.territoryHasUnitsOwnedBy(player).and(Matches.territoryHasEnemyUnits(player, data));
final Predicate<Territory> enemyTerritoryAndOwnUnits = Matches.isTerritoryEnemyAndNotUnownedWater(player, data).and(Matches.territoryHasUnitsOwnedBy(player));
final Predicate<Territory> enemyUnitsOrEnemyTerritory = anyTerritoryWithOwnAndEnemy.or(enemyTerritoryAndOwnUnits);
final List<Territory> battleTerritories = CollectionUtils.getMatches(data.getMap().getTerritories(), enemyUnitsOrEnemyTerritory);
for (final Territory territory : battleTerritories) {
final List<Unit> attackingUnits = territory.getUnits().getMatches(Matches.unitIsOwnedBy(player));
// now make sure to add any units that must move with these attacking units, so that they get included as
// dependencies
final Map<Unit, Collection<Unit>> transportMap = TransportTracker.transporting(territory.getUnits());
final HashSet<Unit> dependants = new HashSet<>();
for (final Entry<Unit, Collection<Unit>> entry : transportMap.entrySet()) {
// only consider those transports that we are attacking with. allied and enemy transports are not added.
if (attackingUnits.contains(entry.getKey())) {
dependants.addAll(entry.getValue());
}
}
// no duplicates
dependants.removeAll(attackingUnits);
// add the dependants to the attacking list
attackingUnits.addAll(dependants);
final List<Unit> enemyUnits = territory.getUnits().getMatches(Matches.enemyUnit(player, data));
final IBattle bombingBattle = battleTracker.getPendingBattle(territory, true, null);
if (bombingBattle != null) {
// we need to remove any units which are participating in bombing raids
attackingUnits.removeAll(bombingBattle.getAttackingUnits());
}
if (attackingUnits.stream().allMatch(Matches.unitIsInfrastructure())) {
continue;
}
IBattle battle = battleTracker.getPendingBattle(territory, false, BattleType.NORMAL);
if (battle == null) {
// fires)
if (enemyUnits.stream().allMatch(Matches.unitIsInfrastructure())) {
landParatroopers(player, territory, bridge);
}
bridge.getHistoryWriter().startEvent(player.getName() + " creates battle in territory " + territory.getName());
battleTracker.addBattle(new RouteScripted(territory), attackingUnits, player, bridge, null, null);
battle = battleTracker.getPendingBattle(territory, false, BattleType.NORMAL);
}
if (battle == null) {
continue;
}
if (bombingBattle != null) {
battleTracker.addDependency(battle, bombingBattle);
}
if (battle.isEmpty()) {
battle.addAttackChange(new RouteScripted(territory), attackingUnits, null);
}
if (!battle.getAttackingUnits().containsAll(attackingUnits)) {
List<Unit> attackingUnitsNeedToBeAdded = new ArrayList<>(attackingUnits);
attackingUnitsNeedToBeAdded.removeAll(battle.getAttackingUnits());
attackingUnitsNeedToBeAdded.removeAll(battle.getDependentUnits(battle.getAttackingUnits()));
if (territory.isWater()) {
attackingUnitsNeedToBeAdded = CollectionUtils.getMatches(attackingUnitsNeedToBeAdded, Matches.unitIsLand().negate());
} else {
attackingUnitsNeedToBeAdded = CollectionUtils.getMatches(attackingUnitsNeedToBeAdded, Matches.unitIsSea().negate());
}
if (!attackingUnitsNeedToBeAdded.isEmpty()) {
battle.addAttackChange(new RouteScripted(territory), attackingUnitsNeedToBeAdded, null);
}
}
// Reach stalemate if all attacking and defending units are transports
if ((ignoreTransports && !attackingUnits.isEmpty() && attackingUnits.stream().allMatch(seaTransports) && !enemyUnits.isEmpty() && enemyUnits.stream().allMatch(seaTransports)) || (!attackingUnits.isEmpty() && attackingUnits.stream().allMatch(Matches.unitHasAttackValueOfAtLeast(1).negate()) && !enemyUnits.isEmpty() && enemyUnits.stream().allMatch(Matches.unitHasDefendValueOfAtLeast(1).negate()))) {
final BattleResults results = new BattleResults(battle, WhoWon.DRAW, data);
battleTracker.getBattleRecords().addResultToBattle(player, battle.getBattleId(), null, 0, 0, BattleRecord.BattleResultDescription.STALEMATE, results);
battle.cancelBattle(bridge);
battleTracker.removeBattle(battle);
continue;
}
// possibility to ignore battle altogether
if (!attackingUnits.isEmpty()) {
final ITripleAPlayer remotePlayer = getRemotePlayer(bridge);
if (territory.isWater() && Properties.getSeaBattlesMayBeIgnored(data)) {
if (!remotePlayer.selectAttackUnits(territory)) {
final BattleResults results = new BattleResults(battle, WhoWon.NOTFINISHED, data);
battleTracker.getBattleRecords().addResultToBattle(player, battle.getBattleId(), null, 0, 0, BattleRecord.BattleResultDescription.NO_BATTLE, results);
battle.cancelBattle(bridge);
battleTracker.removeBattle(battle);
}
continue;
}
// Check for ignored units
if (ignoreTransports || ignoreSubs) {
// if only enemy transports... attack them?
if (ignoreTransports && !enemyUnits.isEmpty() && enemyUnits.stream().allMatch(seaTransports)) {
if (!remotePlayer.selectAttackTransports(territory)) {
final BattleResults results = new BattleResults(battle, WhoWon.NOTFINISHED, data);
battleTracker.getBattleRecords().addResultToBattle(player, battle.getBattleId(), null, 0, 0, BattleRecord.BattleResultDescription.NO_BATTLE, results);
battle.cancelBattle(bridge);
battleTracker.removeBattle(battle);
}
continue;
}
// if only enemy subs... attack them?
if (ignoreSubs && !enemyUnits.isEmpty() && enemyUnits.stream().allMatch(Matches.unitIsSub())) {
if (!remotePlayer.selectAttackSubs(territory)) {
final BattleResults results = new BattleResults(battle, WhoWon.NOTFINISHED, data);
battleTracker.getBattleRecords().addResultToBattle(player, battle.getBattleId(), null, 0, 0, BattleRecord.BattleResultDescription.NO_BATTLE, results);
battle.cancelBattle(bridge);
battleTracker.removeBattle(battle);
}
continue;
}
// if only enemy transports and subs... attack them?
if (ignoreSubs && ignoreTransports && !enemyUnits.isEmpty() && enemyUnits.stream().allMatch(seaTranportsOrSubs)) {
if (!remotePlayer.selectAttackUnits(territory)) {
final BattleResults results = new BattleResults(battle, WhoWon.NOTFINISHED, data);
battleTracker.getBattleRecords().addResultToBattle(player, battle.getBattleId(), null, 0, 0, BattleRecord.BattleResultDescription.NO_BATTLE, results);
battle.cancelBattle(bridge);
battleTracker.removeBattle(battle);
}
}
}
}
}
}
use of games.strategy.engine.data.Territory 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);
}
use of games.strategy.engine.data.Territory in project triplea by triplea-game.
the class AbstractPlaceDelegate method getUnitsToBePlacedAllDefault.
protected Collection<Unit> getUnitsToBePlacedAllDefault(final Territory to, final Collection<Unit> allUnits, final PlayerID player) {
final boolean water = to.isWater();
if (water && (!isWW2V2() && !isUnitPlacementInEnemySeas()) && to.getUnits().anyMatch(Matches.enemyUnit(player, getData()))) {
return null;
}
final Collection<Unit> units = new ArrayList<>(allUnits);
// if water, remove land. if land, remove water.
units.removeAll(CollectionUtils.getMatches(units, water ? Matches.unitIsLand() : Matches.unitIsSea()));
final Collection<Unit> placeableUnits = new ArrayList<>();
final Collection<Unit> unitsAtStartOfTurnInTo = unitsAtStartOfStepInTerritory(to);
final Collection<Unit> allProducedUnits = unitsPlacedInTerritorySoFar(to);
final boolean isBid = GameStepPropertiesHelper.isBid(getData());
final boolean wasFactoryThereAtStart = wasOwnedUnitThatCanProduceUnitsOrIsFactoryInTerritoryAtStartOfStep(to, player);
// we add factories and constructions later
if (water || wasFactoryThereAtStart || (!water && isPlayerAllowedToPlacementAnyTerritoryOwnedLand(player))) {
final Predicate<Unit> seaOrLandMatch = water ? Matches.unitIsSea() : Matches.unitIsLand();
placeableUnits.addAll(CollectionUtils.getMatches(units, seaOrLandMatch.and(Matches.unitIsNotConstruction())));
if (!water) {
placeableUnits.addAll(CollectionUtils.getMatches(units, Matches.unitIsAir().and(Matches.unitIsNotConstruction())));
} else if (((isBid || canProduceFightersOnCarriers() || AirThatCantLandUtil.isLhtrCarrierProduction(getData())) && allProducedUnits.stream().anyMatch(Matches.unitIsCarrier())) || ((isBid || canProduceNewFightersOnOldCarriers() || AirThatCantLandUtil.isLhtrCarrierProduction(getData())) && to.getUnits().anyMatch(Matches.unitIsCarrier()))) {
placeableUnits.addAll(CollectionUtils.getMatches(units, Matches.unitIsAir().and(Matches.unitCanLandOnCarrier())));
}
}
if (units.stream().anyMatch(Matches.unitIsConstruction())) {
final IntegerMap<String> constructionsMap = howManyOfEachConstructionCanPlace(to, to, units, player);
final Collection<Unit> skipUnits = new ArrayList<>();
for (final Unit currentUnit : CollectionUtils.getMatches(units, Matches.unitIsConstruction())) {
final int maxUnits = howManyOfConstructionUnit(currentUnit, constructionsMap);
if (maxUnits > 0) {
// max placement by constructionType of each unitType
if (skipUnits.contains(currentUnit)) {
continue;
}
placeableUnits.addAll(CollectionUtils.getNMatches(units, maxUnits, Matches.unitIsOfType(currentUnit.getType())));
skipUnits.addAll(CollectionUtils.getMatches(units, Matches.unitIsOfType(currentUnit.getType())));
}
}
}
// remove any units that require other units to be consumed on creation, if we don't have enough to consume (veqryn)
if (placeableUnits.stream().anyMatch(Matches.unitConsumesUnitsOnCreation())) {
final Collection<Unit> unitsWhichConsume = CollectionUtils.getMatches(placeableUnits, Matches.unitConsumesUnitsOnCreation());
for (final Unit unit : unitsWhichConsume) {
if (Matches.unitWhichConsumesUnitsHasRequiredUnits(unitsAtStartOfTurnInTo).negate().test(unit)) {
placeableUnits.remove(unit);
}
}
}
// now check stacking limits
final Collection<Unit> placeableUnits2 = new ArrayList<>();
final Collection<UnitType> typesAlreadyChecked = new ArrayList<>();
for (final Unit currentUnit : placeableUnits) {
final UnitType ut = currentUnit.getType();
if (typesAlreadyChecked.contains(ut)) {
continue;
}
typesAlreadyChecked.add(ut);
placeableUnits2.addAll(CollectionUtils.getNMatches(placeableUnits, UnitAttachment.getMaximumNumberOfThisUnitTypeToReachStackingLimit("placementLimit", ut, to, player, getData()), Matches.unitIsOfType(ut)));
}
if (!isUnitPlacementRestrictions()) {
return placeableUnits2;
}
final Collection<Unit> placeableUnits3 = new ArrayList<>();
for (final Unit currentUnit : placeableUnits2) {
final UnitAttachment ua = UnitAttachment.get(currentUnit.getType());
// Can be null!
final TerritoryAttachment ta = TerritoryAttachment.get(to);
if (ua.getCanOnlyBePlacedInTerritoryValuedAtX() != -1 && ua.getCanOnlyBePlacedInTerritoryValuedAtX() > (ta == null ? 0 : ta.getProduction())) {
continue;
}
if (unitWhichRequiresUnitsHasRequiredUnits(to, false).negate().test(currentUnit)) {
continue;
}
if (Matches.unitCanOnlyPlaceInOriginalTerritories().test(currentUnit) && !Matches.territoryIsOriginallyOwnedBy(player).test(to)) {
continue;
}
// account for any unit placement restrictions by territory
final String[] terrs = ua.getUnitPlacementRestrictions();
final Collection<Territory> listedTerrs = getListedTerritories(terrs);
if (!listedTerrs.contains(to)) {
placeableUnits3.add(currentUnit);
}
}
return placeableUnits3;
}
Aggregations