use of games.strategy.triplea.attachments.TerritoryAttachment in project triplea by triplea-game.
the class ProSimulateTurnUtils method checkIfCapturedTerritoryIsAlliedCapital.
private static boolean checkIfCapturedTerritoryIsAlliedCapital(final Territory t, final GameData data, final PlayerID player, final IDelegateBridge delegateBridge) {
final PlayerID terrOrigOwner = OriginalOwnerTracker.getOriginalOwner(t);
final RelationshipTracker relationshipTracker = data.getRelationshipTracker();
final TerritoryAttachment ta = TerritoryAttachment.get(t);
if (ta != null && ta.getCapital() != null && terrOrigOwner != null && TerritoryAttachment.getAllCapitals(terrOrigOwner, data).contains(t) && relationshipTracker.isAllied(terrOrigOwner, player)) {
// Give capital and any allied territories back to original owner
final Collection<Territory> originallyOwned = OriginalOwnerTracker.getOriginallyOwned(data, terrOrigOwner);
final List<Territory> friendlyTerritories = CollectionUtils.getMatches(originallyOwned, Matches.isTerritoryAllied(terrOrigOwner, data));
friendlyTerritories.add(t);
for (final Territory item : friendlyTerritories) {
if (item.getOwner() == terrOrigOwner) {
continue;
}
final Change takeOverFriendlyTerritories = ChangeFactory.changeOwner(item, terrOrigOwner);
delegateBridge.addChange(takeOverFriendlyTerritories);
final Collection<Unit> units = CollectionUtils.getMatches(item.getUnits().getUnits(), Matches.unitIsInfrastructure());
if (!units.isEmpty()) {
final Change takeOverNonComUnits = ChangeFactory.changeOwner(units, terrOrigOwner, t);
delegateBridge.addChange(takeOverNonComUnits);
}
}
return true;
}
return false;
}
use of games.strategy.triplea.attachments.TerritoryAttachment in project triplea by triplea-game.
the class ProPurchaseUtils method getUnitProduction.
private static int getUnitProduction(final Territory territory, final GameData data, final PlayerID player) {
final Predicate<Unit> factoryMatch = Matches.unitIsOwnedAndIsFactoryOrCanProduceUnits(player).and(Matches.unitIsBeingTransported().negate()).and((territory.isWater() ? Matches.unitIsLand() : Matches.unitIsSea()).negate());
final Collection<Unit> factoryUnits = territory.getUnits().getMatches(factoryMatch);
final TerritoryAttachment ta = TerritoryAttachment.get(territory);
final boolean originalFactory = (ta != null && ta.getOriginalFactory());
final boolean playerIsOriginalOwner = factoryUnits.size() > 0 && player.equals(getOriginalFactoryOwner(territory, player));
final RulesAttachment ra = player.getRulesAttachment();
if (originalFactory && playerIsOriginalOwner) {
if (ra != null && ra.getMaxPlacePerTerritory() != -1) {
return Math.max(0, ra.getMaxPlacePerTerritory());
}
return Integer.MAX_VALUE;
}
if (ra != null && ra.getPlacementAnyTerritory()) {
return Integer.MAX_VALUE;
}
return TripleAUnit.getProductionPotentialOfTerritory(territory.getUnits().getUnits(), territory, player, data, true, true);
}
use of games.strategy.triplea.attachments.TerritoryAttachment in project triplea by triplea-game.
the class AbstractEndTurnDelegate method changeUnitOwnership.
private static void changeUnitOwnership(final IDelegateBridge bridge) {
final PlayerID player = bridge.getPlayerId();
final PlayerAttachment pa = PlayerAttachment.get(player);
final Collection<PlayerID> possibleNewOwners = pa.getGiveUnitControl();
final Collection<Territory> territories = bridge.getData().getMap().getTerritories();
final CompositeChange change = new CompositeChange();
final Collection<Tuple<Territory, Collection<Unit>>> changeList = new ArrayList<>();
for (final Territory currTerritory : territories) {
final TerritoryAttachment ta = TerritoryAttachment.get(currTerritory);
// if ownership should change in this territory
if (ta != null && ta.getChangeUnitOwners() != null && !ta.getChangeUnitOwners().isEmpty()) {
final Collection<PlayerID> terrNewOwners = ta.getChangeUnitOwners();
for (final PlayerID terrNewOwner : terrNewOwners) {
if (possibleNewOwners.contains(terrNewOwner)) {
// PlayerOwnerChange
final Collection<Unit> units = currTerritory.getUnits().getMatches(Matches.unitOwnedBy(player).and(Matches.unitCanBeGivenByTerritoryTo(terrNewOwner)));
if (!units.isEmpty()) {
change.add(ChangeFactory.changeOwner(units, terrNewOwner, currTerritory));
changeList.add(Tuple.of(currTerritory, units));
}
}
}
}
}
if (!change.isEmpty() && !changeList.isEmpty()) {
if (changeList.size() == 1) {
final Tuple<Territory, Collection<Unit>> tuple = changeList.iterator().next();
bridge.getHistoryWriter().startEvent("Some Units in " + tuple.getFirst().getName() + " change ownership: " + MyFormatter.unitsToTextNoOwner(tuple.getSecond()), tuple.getSecond());
} else {
bridge.getHistoryWriter().startEvent("Units Change Ownership");
for (final Tuple<Territory, Collection<Unit>> tuple : changeList) {
bridge.getHistoryWriter().addChildToEvent("Some Units in " + tuple.getFirst().getName() + " change ownership: " + MyFormatter.unitsToTextNoOwner(tuple.getSecond()), tuple.getSecond());
}
}
bridge.addChange(change);
}
}
use of games.strategy.triplea.attachments.TerritoryAttachment in project triplea by triplea-game.
the class WW2V3Year41Test method testFactoryPlace.
@Test
public void testFactoryPlace() {
// Set up game
final PlayerID british = GameDataTestUtil.british(gameData);
final ITestDelegateBridge delegateBridge = getDelegateBridge(british(gameData));
// Set up the territories
final Territory egypt = territory("Union of South Africa", gameData);
// Set up the unit types
final UnitType factoryType = GameDataTestUtil.factory(gameData);
// Set up the move delegate
final PlaceDelegate placeDelegate = placeDelegate(gameData);
delegateBridge.setStepName("Place");
delegateBridge.setPlayerId(british);
placeDelegate.setDelegateBridgeAndPlayer(delegateBridge);
placeDelegate.start();
// Add the factory
final IntegerMap<UnitType> map = new IntegerMap<>();
map.add(factoryType, 1);
addTo(british(gameData), factory(gameData).create(1, british(gameData)), gameData);
// Place the factory
final String response = placeDelegate.placeUnits(GameDataTestUtil.getUnits(map, british), egypt);
assertValid(response);
// placeUnits performPlace
// get production and unit production values
final TerritoryAttachment ta = TerritoryAttachment.get(egypt);
assertEquals(ta.getUnitProduction(), ta.getProduction());
}
use of games.strategy.triplea.attachments.TerritoryAttachment in project triplea by triplea-game.
the class ProCombatMoveAi method determineUnitsToAttackWith.
private void determineUnitsToAttackWith(final List<ProTerritory> prioritizedTerritories, final List<Unit> alreadyMovedUnits) {
ProLogger.info("Determine units to attack each territory with");
final Map<Territory, ProTerritory> attackMap = territoryManager.getAttackOptions().getTerritoryMap();
final ProOtherMoveOptions enemyAttackOptions = territoryManager.getEnemyAttackOptions();
final Map<Unit, Set<Territory>> unitAttackMap = territoryManager.getAttackOptions().getUnitMoveMap();
// Assign units to territories by prioritization
while (true) {
Map<Unit, Set<Territory>> sortedUnitAttackOptions = tryToAttackTerritories(prioritizedTerritories, alreadyMovedUnits);
// Clear bombers
for (final ProTerritory t : attackMap.values()) {
t.getBombers().clear();
}
// Get all units that have already moved
final Set<Unit> alreadyAttackedWithUnits = new HashSet<>();
for (final ProTerritory t : attackMap.values()) {
alreadyAttackedWithUnits.addAll(t.getUnits());
alreadyAttackedWithUnits.addAll(t.getAmphibAttackMap().keySet());
}
// Check to see if any territories can be bombed
final Map<Unit, Set<Territory>> bomberMoveMap = territoryManager.getAttackOptions().getBomberMoveMap();
for (final Unit unit : bomberMoveMap.keySet()) {
if (alreadyAttackedWithUnits.contains(unit)) {
continue;
}
Optional<Territory> maxBombingTerritory = Optional.empty();
int maxBombingScore = MIN_BOMBING_SCORE;
for (final Territory t : bomberMoveMap.get(unit)) {
final boolean territoryCanBeBombed = t.getUnits().anyMatch(Matches.unitCanProduceUnitsAndCanBeDamaged());
if (territoryCanBeBombed && canAirSafelyLandAfterAttack(unit, t)) {
final int noAaBombingDefense = t.getUnits().anyMatch(Matches.unitIsAaForBombingThisUnitOnly()) ? 0 : 1;
int maxDamage = 0;
final TerritoryAttachment ta = TerritoryAttachment.get(t);
if (ta != null) {
maxDamage = ta.getProduction();
}
final int numExistingBombers = attackMap.get(t).getBombers().size();
final int remainingDamagePotential = maxDamage - 3 * numExistingBombers;
final int bombingScore = (1 + 9 * noAaBombingDefense) * remainingDamagePotential;
if (bombingScore >= maxBombingScore) {
maxBombingScore = bombingScore;
maxBombingTerritory = Optional.of(t);
}
}
}
if (maxBombingTerritory.isPresent()) {
final Territory t = maxBombingTerritory.get();
attackMap.get(t).getBombers().add(unit);
sortedUnitAttackOptions.remove(unit);
ProLogger.debug("Add bomber (" + unit + ") to " + t);
}
}
// Re-sort attack options
sortedUnitAttackOptions = ProSortMoveOptionsUtils.sortUnitNeededOptionsThenAttack(player, sortedUnitAttackOptions, attackMap, ProData.unitTerritoryMap, calc);
// Set air units in any territory with no AA (don't move planes to empty territories)
for (final Iterator<Unit> it = sortedUnitAttackOptions.keySet().iterator(); it.hasNext(); ) {
final Unit unit = it.next();
final boolean isAirUnit = UnitAttachment.get(unit.getType()).getIsAir();
if (!isAirUnit) {
// skip non-air units
continue;
}
Territory minWinTerritory = null;
double minWinPercentage = Double.MAX_VALUE;
for (final Territory t : sortedUnitAttackOptions.get(unit)) {
final ProTerritory patd = attackMap.get(t);
// Check if air unit should avoid this territory due to no guaranteed safe landing location
final boolean isEnemyFactory = ProMatches.territoryHasInfraFactoryAndIsEnemyLand(player, data).test(t);
if (!isEnemyFactory && !canAirSafelyLandAfterAttack(unit, t)) {
continue;
}
if (patd.getBattleResult() == null) {
patd.setBattleResult(calc.estimateAttackBattleResults(t, patd.getUnits(), patd.getMaxEnemyDefenders(player, data), patd.getBombardTerritoryMap().keySet()));
}
final ProBattleResult result = patd.getBattleResult();
if (result.getWinPercentage() < minWinPercentage || (!result.isHasLandUnitRemaining() && minWinTerritory == null)) {
final List<Unit> attackingUnits = patd.getUnits();
final List<Unit> defendingUnits = patd.getMaxEnemyDefenders(player, data);
final boolean isOverwhelmingWin = ProBattleUtils.checkForOverwhelmingWin(t, attackingUnits, defendingUnits);
final boolean hasAa = defendingUnits.stream().anyMatch(Matches.unitIsAaForAnything());
if (!hasAa && !isOverwhelmingWin) {
minWinPercentage = result.getWinPercentage();
minWinTerritory = t;
}
}
}
if (minWinTerritory != null) {
attackMap.get(minWinTerritory).addUnit(unit);
attackMap.get(minWinTerritory).setBattleResult(null);
it.remove();
}
}
// Re-sort attack options
sortedUnitAttackOptions = ProSortMoveOptionsUtils.sortUnitNeededOptionsThenAttack(player, sortedUnitAttackOptions, attackMap, ProData.unitTerritoryMap, calc);
// Find territory that we can try to hold that needs unit
for (final Iterator<Unit> it = sortedUnitAttackOptions.keySet().iterator(); it.hasNext(); ) {
final Unit unit = it.next();
Territory minWinTerritory = null;
for (final Territory t : sortedUnitAttackOptions.get(unit)) {
final ProTerritory patd = attackMap.get(t);
if (patd.isCanHold()) {
// Check if I already have enough attack units to win in 2 rounds
if (patd.getBattleResult() == null) {
patd.setBattleResult(calc.estimateAttackBattleResults(t, patd.getUnits(), patd.getMaxEnemyDefenders(player, data), patd.getBombardTerritoryMap().keySet()));
}
final ProBattleResult result = patd.getBattleResult();
final List<Unit> attackingUnits = patd.getUnits();
final List<Unit> defendingUnits = patd.getMaxEnemyDefenders(player, data);
final boolean isOverwhelmingWin = ProBattleUtils.checkForOverwhelmingWin(t, attackingUnits, defendingUnits);
if (!isOverwhelmingWin && result.getBattleRounds() > 2) {
minWinTerritory = t;
break;
}
}
}
if (minWinTerritory != null) {
attackMap.get(minWinTerritory).addUnit(unit);
attackMap.get(minWinTerritory).setBattleResult(null);
it.remove();
}
}
// Re-sort attack options
sortedUnitAttackOptions = ProSortMoveOptionsUtils.sortUnitNeededOptionsThenAttack(player, sortedUnitAttackOptions, attackMap, ProData.unitTerritoryMap, calc);
// Add sea units to any territory that significantly increases TUV gain
for (final Iterator<Unit> it = sortedUnitAttackOptions.keySet().iterator(); it.hasNext(); ) {
final Unit unit = it.next();
final boolean isSeaUnit = UnitAttachment.get(unit.getType()).getIsSea();
if (!isSeaUnit) {
// skip non-sea units
continue;
}
for (final Territory t : sortedUnitAttackOptions.get(unit)) {
final ProTerritory patd = attackMap.get(t);
if (attackMap.get(t).getBattleResult() == null) {
attackMap.get(t).setBattleResult(calc.estimateAttackBattleResults(t, patd.getUnits(), patd.getMaxEnemyDefenders(player, data), patd.getBombardTerritoryMap().keySet()));
}
final ProBattleResult result = attackMap.get(t).getBattleResult();
final List<Unit> attackers = new ArrayList<>(patd.getUnits());
attackers.add(unit);
final ProBattleResult result2 = calc.estimateAttackBattleResults(t, attackers, patd.getMaxEnemyDefenders(player, data), patd.getBombardTerritoryMap().keySet());
final double unitValue = ProData.unitValueMap.getInt(unit.getType());
if ((result2.getTuvSwing() - unitValue / 3) > result.getTuvSwing()) {
attackMap.get(t).addUnit(unit);
attackMap.get(t).setBattleResult(null);
it.remove();
break;
}
}
}
// Determine if all attacks are worth it
final List<Unit> usedUnits = new ArrayList<>();
for (final ProTerritory patd : prioritizedTerritories) {
usedUnits.addAll(patd.getUnits());
}
ProTerritory territoryToRemove = null;
for (final ProTerritory patd : prioritizedTerritories) {
final Territory t = patd.getTerritory();
// Find battle result
if (patd.getBattleResult() == null) {
patd.setBattleResult(calc.estimateAttackBattleResults(t, patd.getUnits(), patd.getMaxEnemyDefenders(player, data), patd.getBombardTerritoryMap().keySet()));
}
final ProBattleResult result = patd.getBattleResult();
// Determine enemy counter attack results
boolean canHold = true;
double enemyCounterTuvSwing = 0;
if (enemyAttackOptions.getMax(t) != null && !ProMatches.territoryIsWaterAndAdjacentToOwnedFactory(player, data).test(t)) {
List<Unit> remainingUnitsToDefendWith = CollectionUtils.getMatches(result.getAverageAttackersRemaining(), Matches.unitIsAir().negate());
ProBattleResult result2 = calc.calculateBattleResults(t, patd.getMaxEnemyUnits(), remainingUnitsToDefendWith, patd.getMaxBombardUnits());
if (patd.isCanHold() && result2.getTuvSwing() > 0) {
final List<Unit> unusedUnits = new ArrayList<>(patd.getMaxUnits());
unusedUnits.addAll(patd.getMaxAmphibUnits());
unusedUnits.removeAll(usedUnits);
unusedUnits.addAll(remainingUnitsToDefendWith);
final ProBattleResult result3 = calc.calculateBattleResults(t, patd.getMaxEnemyUnits(), unusedUnits, patd.getMaxBombardUnits());
if (result3.getTuvSwing() < result2.getTuvSwing()) {
result2 = result3;
remainingUnitsToDefendWith = unusedUnits;
}
}
canHold = (!result2.isHasLandUnitRemaining() && !t.isWater()) || (result2.getTuvSwing() < 0) || (result2.getWinPercentage() < ProData.minWinPercentage);
if (result2.getTuvSwing() > 0) {
enemyCounterTuvSwing = result2.getTuvSwing();
}
ProLogger.trace("Territory=" + t.getName() + ", CanHold=" + canHold + ", MyDefenders=" + remainingUnitsToDefendWith.size() + ", EnemyAttackers=" + patd.getMaxEnemyUnits().size() + ", win%=" + result2.getWinPercentage() + ", EnemyTUVSwing=" + result2.getTuvSwing() + ", hasLandUnitRemaining=" + result2.isHasLandUnitRemaining());
}
// Find attack value
final boolean isNeutral = (!t.isWater() && t.getOwner().isNull());
final int isLand = !t.isWater() ? 1 : 0;
final int isCanHold = canHold ? 1 : 0;
final int isCantHoldAmphib = !canHold && !patd.getAmphibAttackMap().isEmpty() ? 1 : 0;
final int isFactory = ProMatches.territoryHasInfraFactoryAndIsLand().test(t) ? 1 : 0;
final int isFfa = ProUtils.isFfa(data, player) ? 1 : 0;
final int production = TerritoryAttachment.getProduction(t);
double capitalValue = 0;
final TerritoryAttachment ta = TerritoryAttachment.get(t);
if (ta != null && ta.isCapital()) {
capitalValue = ProUtils.getPlayerProduction(t.getOwner(), data);
}
final double territoryValue = (1 + isLand - isCantHoldAmphib + isFactory + isCanHold * (1 + 2 * isFfa + 2 * isFactory)) * production + capitalValue;
double tuvSwing = result.getTuvSwing();
if (isFfa == 1 && tuvSwing > 0) {
tuvSwing *= 0.5;
}
final double attackValue = tuvSwing + territoryValue * result.getWinPercentage() / 100 - enemyCounterTuvSwing * 2 / 3;
boolean allUnitsCanAttackOtherTerritory = true;
if (isNeutral && attackValue < 0) {
for (final Unit u : patd.getUnits()) {
boolean canAttackOtherTerritory = false;
for (final ProTerritory patd2 : prioritizedTerritories) {
if (!patd.equals(patd2) && unitAttackMap.get(u) != null && unitAttackMap.get(u).contains(patd2.getTerritory())) {
canAttackOtherTerritory = true;
break;
}
}
if (!canAttackOtherTerritory) {
allUnitsCanAttackOtherTerritory = false;
break;
}
}
}
// Determine whether to remove attack
if (!patd.isStrafing() && (result.getWinPercentage() < ProData.minWinPercentage || !result.isHasLandUnitRemaining() || (isNeutral && !canHold) || (attackValue < 0 && (!isNeutral || allUnitsCanAttackOtherTerritory || result.getBattleRounds() >= 4)))) {
territoryToRemove = patd;
}
ProLogger.debug(patd.getResultString() + ", attackValue=" + attackValue + ", territoryValue=" + territoryValue + ", allUnitsCanAttackOtherTerritory=" + allUnitsCanAttackOtherTerritory + " with attackers=" + patd.getUnits());
}
// Determine whether all attacks are successful or try to hold fewer territories
if (territoryToRemove == null) {
break;
}
prioritizedTerritories.remove(territoryToRemove);
ProLogger.debug("Removing " + territoryToRemove.getTerritory().getName());
}
}
Aggregations