use of games.strategy.triplea.attachments.TerritoryAttachment in project triplea by triplea-game.
the class WeakAi method populateCombatMove.
private static void populateCombatMove(final GameData data, final List<Collection<Unit>> moveUnits, final List<Route> moveRoutes, final PlayerID player) {
populateBomberCombat(data, moveUnits, moveRoutes, player);
final Collection<Unit> unitsAlreadyMoved = new HashSet<>();
// find the territories we can just walk into
final Predicate<Territory> walkInto = Matches.isTerritoryEnemyAndNotUnownedWaterOrImpassableOrRestricted(player, data).or(Matches.isTerritoryFreeNeutral(data));
final List<Territory> enemyOwned = CollectionUtils.getMatches(data.getMap().getTerritories(), walkInto);
Collections.shuffle(enemyOwned);
enemyOwned.sort((o1, o2) -> {
// -1 means o1 goes first. 1 means o2 goes first. zero means they are equal.
if (Objects.equals(o1, o2)) {
return 0;
}
if (o1 == null) {
return 1;
}
if (o2 == null) {
return -1;
}
final TerritoryAttachment ta1 = TerritoryAttachment.get(o1);
final TerritoryAttachment ta2 = TerritoryAttachment.get(o2);
if (ta1 == null && ta2 == null) {
return 0;
}
if (ta1 == null) {
return 1;
}
if (ta2 == null) {
return -1;
}
// take capitols first if we can
if (ta1.isCapital() && !ta2.isCapital()) {
return -1;
}
if (!ta1.isCapital() && ta2.isCapital()) {
return 1;
}
final boolean factoryInT1 = o1.getUnits().anyMatch(Matches.unitCanProduceUnits());
final boolean factoryInT2 = o2.getUnits().anyMatch(Matches.unitCanProduceUnits());
// next take territories which can produce
if (factoryInT1 && !factoryInT2) {
return -1;
}
if (!factoryInT1 && factoryInT2) {
return 1;
}
final boolean infrastructureInT1 = o1.getUnits().anyMatch(Matches.unitIsInfrastructure());
final boolean infrastructureInT2 = o2.getUnits().anyMatch(Matches.unitIsInfrastructure());
// next take territories with infrastructure
if (infrastructureInT1 && !infrastructureInT2) {
return -1;
}
if (!infrastructureInT1 && infrastructureInT2) {
return 1;
}
// next take territories with largest PU value
return ta2.getProduction() - ta1.getProduction();
});
final List<Territory> isWaterTerr = Utils.onlyWaterTerr(enemyOwned);
enemyOwned.removeAll(isWaterTerr);
// first find the territories we can just walk into
for (final Territory enemy : enemyOwned) {
if (AiUtils.strength(enemy.getUnits().getUnits(), false, false) == 0) {
// only take it with 1 unit
boolean taken = false;
for (final Territory attackFrom : data.getMap().getNeighbors(enemy, Matches.territoryHasLandUnitsOwnedBy(player))) {
if (taken) {
break;
}
// get the cheapest unit to move in
final List<Unit> unitsSortedByCost = new ArrayList<>(attackFrom.getUnits().getUnits());
unitsSortedByCost.sort(AiUtils.getCostComparator());
for (final Unit unit : unitsSortedByCost) {
final Predicate<Unit> match = Matches.unitIsOwnedBy(player).and(Matches.unitIsLand()).and(Matches.unitIsNotInfrastructure()).and(Matches.unitCanMove()).and(Matches.unitIsNotAa()).and(Matches.unitCanNotMoveDuringCombatMove().negate());
if (!unitsAlreadyMoved.contains(unit) && match.test(unit)) {
moveRoutes.add(data.getMap().getRoute(attackFrom, enemy));
// number of units, to leave units free to move elsewhere
if (attackFrom.isWater()) {
final List<Unit> units = attackFrom.getUnits().getMatches(Matches.unitIsLandAndOwnedBy(player));
moveUnits.add(CollectionUtils.difference(units, unitsAlreadyMoved));
unitsAlreadyMoved.addAll(units);
} else {
moveUnits.add(Collections.singleton(unit));
}
unitsAlreadyMoved.add(unit);
taken = true;
break;
}
}
}
}
}
// find the territories we can reasonably expect to take
for (final Territory enemy : enemyOwned) {
final float enemyStrength = AiUtils.strength(enemy.getUnits().getUnits(), false, false);
if (enemyStrength > 0) {
final Predicate<Unit> attackable = Matches.unitIsOwnedBy(player).and(Matches.unitIsStrategicBomber().negate()).and(o -> !unitsAlreadyMoved.contains(o)).and(Matches.unitIsNotAa()).and(Matches.unitCanMove()).and(Matches.unitIsNotInfrastructure()).and(Matches.unitCanNotMoveDuringCombatMove().negate()).and(Matches.unitIsNotSea());
final Set<Territory> dontMoveFrom = new HashSet<>();
// find our strength that we can attack with
float ourStrength = 0;
final Collection<Territory> attackFrom = data.getMap().getNeighbors(enemy, Matches.territoryHasLandUnitsOwnedBy(player));
for (final Territory owned : attackFrom) {
if (TerritoryAttachment.get(owned) != null && TerritoryAttachment.get(owned).isCapital() && (Utils.getStrengthOfPotentialAttackers(owned, data) > AiUtils.strength(owned.getUnits().getUnits(), false, false))) {
dontMoveFrom.add(owned);
continue;
}
ourStrength += AiUtils.strength(owned.getUnits().getMatches(attackable), true, false);
}
// prevents 2 infantry from attacking 1 infantry
if (ourStrength > 1.37 * enemyStrength) {
// this is all we need to take it, dont go overboard, since we may be able to use the units to attack
// somewhere else
double remainingStrengthNeeded = (2.5 * enemyStrength) + 4;
for (final Territory owned : attackFrom) {
if (dontMoveFrom.contains(owned)) {
continue;
}
List<Unit> units = owned.getUnits().getMatches(attackable);
// 2) we can potentially attack another territory
if (!owned.isWater() && data.getMap().getNeighbors(owned, Matches.territoryHasEnemyLandUnits(player, data)).size() > 1) {
units = Utils.getUnitsUpToStrength(remainingStrengthNeeded, units, false);
}
remainingStrengthNeeded -= AiUtils.strength(units, true, false);
if (units.size() > 0) {
unitsAlreadyMoved.addAll(units);
moveUnits.add(units);
moveRoutes.add(data.getMap().getRoute(owned, enemy));
}
}
}
}
}
}
use of games.strategy.triplea.attachments.TerritoryAttachment in project triplea by triplea-game.
the class ProPurchaseAi method prioritizeTerritoriesToDefend.
private List<ProPlaceTerritory> prioritizeTerritoriesToDefend(final Map<Territory, ProPurchaseTerritory> purchaseTerritories, final boolean isLand) {
ProLogger.info("Prioritize territories to defend with isLand=" + isLand);
final ProOtherMoveOptions enemyAttackOptions = territoryManager.getEnemyAttackOptions();
// Determine which territories need defended
final Set<ProPlaceTerritory> needToDefendTerritories = new HashSet<>();
for (final ProPurchaseTerritory ppt : purchaseTerritories.values()) {
// Check if any of the place territories can't be held with current defenders
for (final ProPlaceTerritory placeTerritory : ppt.getCanPlaceTerritories()) {
final Territory t = placeTerritory.getTerritory();
if (enemyAttackOptions.getMax(t) == null || (t.isWater() && placeTerritory.getDefendingUnits().isEmpty()) || (isLand && t.isWater()) || (!isLand && !t.isWater())) {
continue;
}
// Find current battle result
final Set<Unit> enemyAttackingUnits = new HashSet<>(enemyAttackOptions.getMax(t).getMaxUnits());
enemyAttackingUnits.addAll(enemyAttackOptions.getMax(t).getMaxAmphibUnits());
final ProBattleResult result = calc.calculateBattleResults(t, new ArrayList<>(enemyAttackingUnits), placeTerritory.getDefendingUnits(), enemyAttackOptions.getMax(t).getMaxBombardUnits());
placeTerritory.setMinBattleResult(result);
double holdValue = 0;
if (t.isWater()) {
final double unitValue = TuvUtils.getTuv(CollectionUtils.getMatches(placeTerritory.getDefendingUnits(), Matches.unitIsOwnedBy(player)), ProData.unitValueMap);
holdValue = unitValue / 8;
}
ProLogger.trace(t.getName() + " TUVSwing=" + result.getTuvSwing() + ", win%=" + result.getWinPercentage() + ", hasLandUnitRemaining=" + result.isHasLandUnitRemaining() + ", holdValue=" + holdValue + ", enemyAttackers=" + enemyAttackingUnits + ", defenders=" + placeTerritory.getDefendingUnits());
// If it can't currently be held then add to list
final boolean isLandAndCanOnlyBeAttackedByAir = !t.isWater() && !enemyAttackingUnits.isEmpty() && enemyAttackingUnits.stream().allMatch(Matches.unitIsAir());
if ((!t.isWater() && result.isHasLandUnitRemaining()) || result.getTuvSwing() > holdValue || (t.equals(ProData.myCapital) && !isLandAndCanOnlyBeAttackedByAir && result.getWinPercentage() > (100 - ProData.winPercentage))) {
needToDefendTerritories.add(placeTerritory);
}
}
}
// Calculate value of defending territory
for (final ProPlaceTerritory placeTerritory : needToDefendTerritories) {
final Territory t = placeTerritory.getTerritory();
// Determine if it is my capital or adjacent to my capital
int isMyCapital = 0;
if (t.equals(ProData.myCapital)) {
isMyCapital = 1;
}
// Determine if it has a factory
int isFactory = 0;
if (ProMatches.territoryHasInfraFactoryAndIsOwnedLand(player).test(t)) {
isFactory = 1;
}
// Determine production value and if it is an enemy capital
int production = 0;
final TerritoryAttachment ta = TerritoryAttachment.get(t);
if (ta != null) {
production = ta.getProduction();
}
// Determine defending unit value
double defendingUnitValue = TuvUtils.getTuv(placeTerritory.getDefendingUnits(), ProData.unitValueMap);
if (t.isWater() && placeTerritory.getDefendingUnits().stream().noneMatch(Matches.unitIsOwnedBy(player))) {
defendingUnitValue = 0;
}
// Calculate defense value for prioritization
final double territoryValue = (2 * production + 4 * isFactory + 0.5 * defendingUnitValue) * (1 + isFactory) * (1 + 10 * isMyCapital);
placeTerritory.setDefenseValue(territoryValue);
}
// Remove any territories with negative defense value
needToDefendTerritories.removeIf(ppt -> ppt.getDefenseValue() <= 0);
// Sort territories by value
final List<ProPlaceTerritory> sortedTerritories = new ArrayList<>(needToDefendTerritories);
sortedTerritories.sort(Comparator.comparingDouble(ProPlaceTerritory::getDefenseValue));
for (final ProPlaceTerritory placeTerritory : sortedTerritories) {
ProLogger.debug(placeTerritory.toString() + " defenseValue=" + placeTerritory.getDefenseValue());
}
return sortedTerritories;
}
use of games.strategy.triplea.attachments.TerritoryAttachment in project triplea by triplea-game.
the class ProCombatMoveAi method prioritizeAttackOptions.
private List<ProTerritory> prioritizeAttackOptions(final PlayerID player, final List<ProTerritory> attackOptions) {
ProLogger.info("Prioritizing territories to try to attack");
// Calculate value of attacking territory
for (final Iterator<ProTerritory> it = attackOptions.iterator(); it.hasNext(); ) {
final ProTerritory patd = it.next();
final Territory t = patd.getTerritory();
// Determine territory attack properties
final int isLand = !t.isWater() ? 1 : 0;
final int isNeutral = (!t.isWater() && t.getOwner().isNull()) ? 1 : 0;
final int isCanHold = patd.isCanHold() ? 1 : 0;
final int isAmphib = patd.isNeedAmphibUnits() ? 1 : 0;
final List<Unit> defendingUnits = CollectionUtils.getMatches(patd.getMaxEnemyDefenders(player, data), ProMatches.unitIsEnemyAndNotInfa(player, data));
final int isEmptyLand = (defendingUnits.isEmpty() && !patd.isNeedAmphibUnits()) ? 1 : 0;
final boolean isAdjacentToMyCapital = !data.getMap().getNeighbors(t, Matches.territoryIs(ProData.myCapital)).isEmpty();
final int isNotNeutralAdjacentToMyCapital = (isAdjacentToMyCapital && ProMatches.territoryIsEnemyNotNeutralLand(player, data).test(t)) ? 1 : 0;
final int isFactory = ProMatches.territoryHasInfraFactoryAndIsLand().test(t) ? 1 : 0;
final int isFfa = ProUtils.isFfa(data, player) ? 1 : 0;
// Determine production value and if it is an enemy capital
int production = 0;
int isEnemyCapital = 0;
final TerritoryAttachment ta = TerritoryAttachment.get(t);
if (ta != null) {
production = ta.getProduction();
if (ta.isCapital()) {
isEnemyCapital = 1;
}
}
// Calculate attack value for prioritization
double tuvSwing = patd.getMaxBattleResult().getTuvSwing();
if (isFfa == 1 && tuvSwing > 0) {
tuvSwing *= 0.5;
}
final double territoryValue = (1 + isLand + isCanHold * (1 + 2 * isFfa)) * (1 + isEmptyLand) * (1 + isFactory) * (1 - 0.5 * isAmphib) * production;
double attackValue = (tuvSwing + territoryValue) * (1 + 4 * isEnemyCapital) * (1 + 2 * isNotNeutralAdjacentToMyCapital) * (1 - 0.9 * isNeutral);
// Check if a negative value neutral territory should be attacked
if (attackValue <= 0 && !patd.isNeedAmphibUnits() && !t.isWater() && t.getOwner().isNull()) {
// Determine enemy neighbor territory production value for neutral land territories
double nearbyEnemyValue = 0;
final List<Territory> cantReachEnemyTerritories = new ArrayList<>();
final Set<Territory> nearbyTerritories = data.getMap().getNeighbors(t, ProMatches.territoryCanMoveLandUnits(player, data, true));
final List<Territory> nearbyEnemyTerritories = CollectionUtils.getMatches(nearbyTerritories, Matches.isTerritoryEnemy(player, data));
final List<Territory> nearbyTerritoriesWithOwnedUnits = CollectionUtils.getMatches(nearbyTerritories, Matches.territoryHasUnitsOwnedBy(player));
for (final Territory nearbyEnemyTerritory : nearbyEnemyTerritories) {
boolean allAlliedNeighborsHaveRoute = true;
for (final Territory nearbyAlliedTerritory : nearbyTerritoriesWithOwnedUnits) {
final int distance = data.getMap().getDistance_IgnoreEndForCondition(nearbyAlliedTerritory, nearbyEnemyTerritory, ProMatches.territoryIsEnemyNotNeutralOrAllied(player, data));
if (distance < 0 || distance > 2) {
allAlliedNeighborsHaveRoute = false;
break;
}
}
if (!allAlliedNeighborsHaveRoute) {
final double value = ProTerritoryValueUtils.findTerritoryAttackValue(player, nearbyEnemyTerritory);
if (value > 0) {
nearbyEnemyValue += value;
}
cantReachEnemyTerritories.add(nearbyEnemyTerritory);
}
}
ProLogger.debug(t.getName() + " calculated nearby enemy value=" + nearbyEnemyValue + " from " + cantReachEnemyTerritories);
if (nearbyEnemyValue > 0) {
ProLogger.trace(t.getName() + " updating negative neutral attack value=" + attackValue);
attackValue = nearbyEnemyValue * .001 / (1 - attackValue);
} else {
// Check if overwhelming attack strength (more than 5 times)
final double strengthDifference = ProBattleUtils.estimateStrengthDifference(t, patd.getMaxUnits(), patd.getMaxEnemyDefenders(player, data));
ProLogger.debug(t.getName() + " calculated strengthDifference=" + strengthDifference);
if (strengthDifference > 500) {
ProLogger.trace(t.getName() + " updating negative neutral attack value=" + attackValue);
attackValue = strengthDifference * .00001 / (1 - attackValue);
}
}
}
// Remove negative value territories
patd.setValue(attackValue);
if (attackValue <= 0 || (isDefensive && attackValue <= 8 && data.getMap().getDistance(ProData.myCapital, t) <= 3)) {
ProLogger.debug("Removing territory that has a negative attack value: " + t.getName() + ", AttackValue=" + patd.getValue());
it.remove();
}
}
// Sort attack territories by value
attackOptions.sort(Comparator.comparingDouble(ProTerritory::getValue));
// Log prioritized territories
for (final ProTerritory patd : attackOptions) {
ProLogger.debug("AttackValue=" + patd.getValue() + ", TUVSwing=" + patd.getMaxBattleResult().getTuvSwing() + ", isAmphib=" + patd.isNeedAmphibUnits() + ", " + patd.getTerritory().getName());
}
return attackOptions;
}
use of games.strategy.triplea.attachments.TerritoryAttachment in project triplea by triplea-game.
the class ProNonCombatMoveAi method moveOneDefenderToLandTerritoriesBorderingEnemy.
private List<Territory> moveOneDefenderToLandTerritoriesBorderingEnemy() {
ProLogger.info("Determine which territories to defend with one land unit");
final Map<Territory, ProTerritory> moveMap = territoryManager.getDefendOptions().getTerritoryMap();
final Map<Unit, Set<Territory>> unitMoveMap = territoryManager.getDefendOptions().getUnitMoveMap();
// Find land territories with no can't move units and adjacent to enemy land units
final List<Territory> territoriesToDefendWithOneUnit = new ArrayList<>();
for (final Territory t : moveMap.keySet()) {
final boolean hasAlliedLandUnits = moveMap.get(t).getCantMoveUnits().stream().anyMatch(ProMatches.unitIsAlliedLandAndNotInfra(player, data));
if (!t.isWater() && !hasAlliedLandUnits && ProMatches.territoryHasNeighborOwnedByAndHasLandUnit(data, ProUtils.getPotentialEnemyPlayers(player)).test(t)) {
territoriesToDefendWithOneUnit.add(t);
}
}
final List<Territory> result = new ArrayList<>(territoriesToDefendWithOneUnit);
// Sort units by number of defend options and cost
final Map<Unit, Set<Territory>> sortedUnitMoveOptions = ProSortMoveOptionsUtils.sortUnitMoveOptions(unitMoveMap);
// Set unit with the fewest move options in each territory
for (final Unit unit : sortedUnitMoveOptions.keySet()) {
if (Matches.unitIsLand().test(unit)) {
for (final Territory t : sortedUnitMoveOptions.get(unit)) {
final int unitValue = ProData.unitValueMap.getInt(unit.getType());
int production = 0;
final TerritoryAttachment ta = TerritoryAttachment.get(t);
if (ta != null) {
production = ta.getProduction();
}
// or where unit value is less than production + 3 (avoid sacrificing expensive units to block)
if (territoriesToDefendWithOneUnit.contains(t) && (unitValue <= (production + 3) || Matches.territoryHasUnitsOwnedBy(player).test(t))) {
moveMap.get(t).addUnit(unit);
unitMoveMap.remove(unit);
territoriesToDefendWithOneUnit.remove(t);
ProLogger.debug(t + ", added one land unit: " + unit);
break;
}
}
if (territoriesToDefendWithOneUnit.isEmpty()) {
break;
}
}
}
// Only return territories that received a defender
result.removeAll(territoriesToDefendWithOneUnit);
return result;
}
use of games.strategy.triplea.attachments.TerritoryAttachment in project triplea by triplea-game.
the class ProNonCombatMoveAi method prioritizeDefendOptions.
private List<ProTerritory> prioritizeDefendOptions(final Map<Territory, ProTerritory> factoryMoveMap, final Map<Territory, Double> territoryValueMap) {
ProLogger.info("Prioritizing territories to try to defend");
final Map<Territory, ProTerritory> moveMap = territoryManager.getDefendOptions().getTerritoryMap();
final ProOtherMoveOptions enemyAttackOptions = territoryManager.getEnemyAttackOptions();
// Calculate value of defending territory
for (final Territory t : moveMap.keySet()) {
// Determine if it is my capital or adjacent to my capital
int isMyCapital = 0;
if (t.equals(ProData.myCapital)) {
isMyCapital = 1;
}
// Determine if it has a factory
int isFactory = 0;
if (ProMatches.territoryHasInfraFactoryAndIsLand().test(t) || (factoryMoveMap != null && factoryMoveMap.containsKey(t))) {
isFactory = 1;
}
// Determine production value and if it is an enemy capital
int production = 0;
int isEnemyOrAlliedCapital = 0;
final TerritoryAttachment ta = TerritoryAttachment.get(t);
if (ta != null) {
production = ta.getProduction();
if (ta.isCapital() && !t.equals(ProData.myCapital)) {
isEnemyOrAlliedCapital = 1;
}
}
// Determine neighbor value
double neighborValue = 0;
if (!t.isWater()) {
final Set<Territory> landNeighbors = data.getMap().getNeighbors(t, Matches.territoryIsLand());
for (final Territory neighbor : landNeighbors) {
double neighborProduction = TerritoryAttachment.getProduction(neighbor);
if (Matches.isTerritoryAllied(player, data).test(neighbor)) {
neighborProduction = 0.1 * neighborProduction;
}
neighborValue += neighborProduction;
}
}
// Determine defending unit value
final int cantMoveUnitValue = TuvUtils.getTuv(moveMap.get(t).getCantMoveUnits(), ProData.unitValueMap);
double unitOwnerMultiplier = 1;
if (moveMap.get(t).getCantMoveUnits().stream().noneMatch(Matches.unitIsOwnedBy(player))) {
if (t.isWater() && moveMap.get(t).getCantMoveUnits().stream().noneMatch(Matches.unitIsTransportButNotCombatTransport())) {
unitOwnerMultiplier = 0;
} else {
unitOwnerMultiplier = 0.5;
}
}
// Calculate defense value for prioritization
final double territoryValue = unitOwnerMultiplier * (2 * production + 10 * isFactory + 0.5 * cantMoveUnitValue + 0.5 * neighborValue) * (1 + 10 * isMyCapital) * (1 + 4 * isEnemyOrAlliedCapital);
moveMap.get(t).setValue(territoryValue);
}
// Sort attack territories by value
final List<ProTerritory> prioritizedTerritories = new ArrayList<>(moveMap.values());
prioritizedTerritories.sort(Comparator.comparingDouble(ProTerritory::getValue));
// Remove territories that I'm not going to try to defend
for (final Iterator<ProTerritory> it = prioritizedTerritories.iterator(); it.hasNext(); ) {
final ProTerritory patd = it.next();
final Territory t = patd.getTerritory();
final boolean hasFactory = ProMatches.territoryHasInfraFactoryAndIsLand().test(t);
final ProBattleResult minResult = patd.getMinBattleResult();
final int cantMoveUnitValue = TuvUtils.getTuv(moveMap.get(t).getCantMoveUnits(), ProData.unitValueMap);
final List<Unit> maxEnemyUnits = patd.getMaxEnemyUnits();
final boolean isLandAndCanOnlyBeAttackedByAir = !t.isWater() && !maxEnemyUnits.isEmpty() && maxEnemyUnits.stream().allMatch(Matches.unitIsAir());
final boolean isNotFactoryAndShouldHold = !hasFactory && (minResult.getTuvSwing() <= 0 || !minResult.isHasLandUnitRemaining());
final boolean canAlreadyBeHeld = minResult.getTuvSwing() <= 0 && minResult.getWinPercentage() < (100 - ProData.winPercentage);
final boolean isNotFactoryAndHasNoEnemyNeighbors = !t.isWater() && !hasFactory && !ProMatches.territoryHasNeighborOwnedByAndHasLandUnit(data, ProUtils.getPotentialEnemyPlayers(player)).test(t);
final boolean isNotFactoryAndOnlyAmphib = !t.isWater() && !hasFactory && moveMap.get(t).getMaxUnits().stream().noneMatch(Matches.unitIsLand()) && cantMoveUnitValue < 5;
if (!patd.isCanHold() || patd.getValue() <= 0 || isLandAndCanOnlyBeAttackedByAir || isNotFactoryAndShouldHold || canAlreadyBeHeld || isNotFactoryAndHasNoEnemyNeighbors || isNotFactoryAndOnlyAmphib) {
final double tuvSwing = minResult.getTuvSwing();
final boolean hasRemainingLandUnit = minResult.isHasLandUnitRemaining();
ProLogger.debug("Removing territory=" + t.getName() + ", value=" + patd.getValue() + ", CanHold=" + patd.isCanHold() + ", isLandAndCanOnlyBeAttackedByAir=" + isLandAndCanOnlyBeAttackedByAir + ", isNotFactoryAndShouldHold=" + isNotFactoryAndShouldHold + ", canAlreadyBeHeld=" + canAlreadyBeHeld + ", isNotFactoryAndHasNoEnemyNeighbors=" + isNotFactoryAndHasNoEnemyNeighbors + ", isNotFactoryAndOnlyAmphib=" + isNotFactoryAndOnlyAmphib + ", tuvSwing=" + tuvSwing + ", hasRemainingLandUnit=" + hasRemainingLandUnit + ", maxEnemyUnits=" + patd.getMaxEnemyUnits().size());
it.remove();
}
}
// Add best sea production territory for sea factories
List<Territory> seaFactories = CollectionUtils.getMatches(data.getMap().getTerritories(), ProMatches.territoryHasInfraFactoryAndIsNotConqueredOwnedLand(player, data));
seaFactories = CollectionUtils.getMatches(seaFactories, ProMatches.territoryHasInfraFactoryAndIsOwnedLandAdjacentToSea(player, data));
for (final Territory t : seaFactories) {
if (territoryValueMap.get(t) >= 1) {
continue;
}
final Set<Territory> neighbors = data.getMap().getNeighbors(t, ProMatches.territoryCanMoveSeaUnits(player, data, true));
double maxValue = 0;
Territory maxTerritory = null;
for (final Territory neighbor : neighbors) {
if (moveMap.get(neighbor) != null && moveMap.get(neighbor).isCanHold() && territoryValueMap.get(neighbor) > maxValue) {
maxTerritory = neighbor;
maxValue = territoryValueMap.get(neighbor);
}
}
if (maxTerritory != null && enemyAttackOptions.getMax(maxTerritory) != null) {
boolean alreadyAdded = false;
for (final ProTerritory patd : prioritizedTerritories) {
if (patd.getTerritory().equals(maxTerritory)) {
alreadyAdded = true;
}
}
if (!alreadyAdded) {
prioritizedTerritories.add(moveMap.get(maxTerritory));
}
}
}
// Log prioritized territories
for (final ProTerritory attackTerritoryData : prioritizedTerritories) {
ProLogger.debug("Value=" + attackTerritoryData.getValue() + ", " + attackTerritoryData.getTerritory().getName());
}
return prioritizedTerritories;
}
Aggregations