use of games.strategy.engine.data.Territory in project triplea by triplea-game.
the class ProCombatMoveAi method removeTerritoriesThatArentWorthAttacking.
private void removeTerritoriesThatArentWorthAttacking(final List<ProTerritory> prioritizedTerritories) {
ProLogger.info("Remove territories that aren't worth attacking");
final ProOtherMoveOptions enemyAttackOptions = territoryManager.getEnemyAttackOptions();
// Loop through all prioritized territories
for (final Iterator<ProTerritory> it = prioritizedTerritories.iterator(); it.hasNext(); ) {
final ProTerritory patd = it.next();
final Territory t = patd.getTerritory();
ProLogger.debug("Checking territory=" + patd.getTerritory().getName() + " with isAmphib=" + patd.isNeedAmphibUnits());
// Remove empty convoy zones that can't be held
if (!patd.isCanHold() && enemyAttackOptions.getMax(t) != null && t.isWater() && !t.getUnits().anyMatch(Matches.enemyUnit(player, data))) {
ProLogger.debug("Removing convoy zone that can't be held: " + t.getName() + ", enemyAttackers=" + enemyAttackOptions.getMax(t).getMaxUnits());
it.remove();
continue;
}
// Remove neutral and low value amphib land territories that can't be held
final boolean isNeutral = t.getOwner().isNull();
final double strengthDifference = ProBattleUtils.estimateStrengthDifference(t, patd.getMaxUnits(), patd.getMaxEnemyDefenders(player, data));
if (!patd.isCanHold() && enemyAttackOptions.getMax(t) != null && !t.isWater()) {
if (isNeutral && strengthDifference <= 500) {
// Remove neutral territories that can't be held and don't have overwhelming attack strength
ProLogger.debug("Removing neutral territory that can't be held: " + t.getName() + ", enemyAttackers=" + enemyAttackOptions.getMax(t).getMaxUnits() + ", enemyAmphibAttackers=" + enemyAttackOptions.getMax(t).getMaxAmphibUnits() + ", strengthDifference=" + strengthDifference);
it.remove();
continue;
} else if (patd.isNeedAmphibUnits() && patd.getValue() < 2) {
// Remove amphib territories that aren't worth attacking
ProLogger.debug("Removing low value amphib territory that can't be held: " + t.getName() + ", enemyAttackers=" + enemyAttackOptions.getMax(t).getMaxUnits() + ", enemyAmphibAttackers=" + enemyAttackOptions.getMax(t).getMaxAmphibUnits());
it.remove();
continue;
}
}
// Remove neutral territories where attackers are adjacent to enemy territories that aren't being attacked
if (isNeutral && !t.isWater() && strengthDifference <= 500) {
// Get list of territories I'm attacking
final List<Territory> prioritizedTerritoryList = new ArrayList<>();
for (final ProTerritory prioritizedTerritory : prioritizedTerritories) {
prioritizedTerritoryList.add(prioritizedTerritory.getTerritory());
}
// Find all territories units are attacking from that are adjacent to territory
final Set<Territory> attackFromTerritories = new HashSet<>();
for (final Unit u : patd.getMaxUnits()) {
attackFromTerritories.add(ProData.unitTerritoryMap.get(u));
}
attackFromTerritories.retainAll(data.getMap().getNeighbors(t));
// Determine if any of the attacking from territories has enemy neighbors that aren't being attacked
boolean attackersHaveEnemyNeighbors = false;
Territory attackFromTerritoryWithEnemyNeighbors = null;
for (final Territory attackFromTerritory : attackFromTerritories) {
final Set<Territory> enemyNeighbors = data.getMap().getNeighbors(attackFromTerritory, ProMatches.territoryIsEnemyNotNeutralLand(player, data));
if (!prioritizedTerritoryList.containsAll(enemyNeighbors)) {
attackersHaveEnemyNeighbors = true;
attackFromTerritoryWithEnemyNeighbors = attackFromTerritory;
break;
}
}
if (attackersHaveEnemyNeighbors) {
ProLogger.debug("Removing neutral territory that has attackers that are adjacent to enemies: " + t.getName() + ", attackFromTerritory=" + attackFromTerritoryWithEnemyNeighbors);
it.remove();
}
}
}
}
use of games.strategy.engine.data.Territory in project triplea by triplea-game.
the class ProNonCombatMoveAi method logAttackMoves.
private void logAttackMoves(final List<ProTerritory> prioritizedTerritories) {
final Map<Territory, ProTerritory> moveMap = territoryManager.getDefendOptions().getTerritoryMap();
// Print prioritization
ProLogger.debug("Prioritized territories:");
for (final ProTerritory attackTerritoryData : prioritizedTerritories) {
ProLogger.trace(" " + attackTerritoryData.getValue() + " " + attackTerritoryData.getTerritory().getName());
}
// Print enemy territories with enemy units vs my units
ProLogger.debug("Territories that can be attacked:");
int count = 0;
for (final Territory t : moveMap.keySet()) {
count++;
ProLogger.trace(count + ". ---" + t.getName());
final Set<Unit> combinedUnits = new HashSet<>(moveMap.get(t).getMaxUnits());
combinedUnits.addAll(moveMap.get(t).getMaxAmphibUnits());
combinedUnits.addAll(moveMap.get(t).getCantMoveUnits());
ProLogger.trace(" --- My max units ---");
final Map<String, Integer> printMap = new HashMap<>();
for (final Unit unit : combinedUnits) {
if (printMap.containsKey(unit.toStringNoOwner())) {
printMap.put(unit.toStringNoOwner(), printMap.get(unit.toStringNoOwner()) + 1);
} else {
printMap.put(unit.toStringNoOwner(), 1);
}
}
for (final String key : printMap.keySet()) {
ProLogger.trace(" " + printMap.get(key) + " " + key);
}
ProLogger.trace(" --- My max amphib units ---");
final Map<String, Integer> printMap5 = new HashMap<>();
for (final Unit unit : moveMap.get(t).getMaxAmphibUnits()) {
if (printMap5.containsKey(unit.toStringNoOwner())) {
printMap5.put(unit.toStringNoOwner(), printMap5.get(unit.toStringNoOwner()) + 1);
} else {
printMap5.put(unit.toStringNoOwner(), 1);
}
}
for (final String key : printMap5.keySet()) {
ProLogger.trace(" " + printMap5.get(key) + " " + key);
}
final List<Unit> units3 = moveMap.get(t).getUnits();
ProLogger.trace(" --- My actual units ---");
final Map<String, Integer> printMap3 = new HashMap<>();
for (final Unit unit : units3) {
if (printMap3.containsKey(unit.toStringNoOwner())) {
printMap3.put(unit.toStringNoOwner(), printMap3.get(unit.toStringNoOwner()) + 1);
} else {
printMap3.put(unit.toStringNoOwner(), 1);
}
}
for (final String key : printMap3.keySet()) {
ProLogger.trace(" " + printMap3.get(key) + " " + key);
}
ProLogger.trace(" --- Enemy units ---");
final Map<String, Integer> printMap2 = new HashMap<>();
final List<Unit> units2 = moveMap.get(t).getMaxEnemyUnits();
for (final Unit unit : units2) {
if (printMap2.containsKey(unit.toStringNoOwner())) {
printMap2.put(unit.toStringNoOwner(), printMap2.get(unit.toStringNoOwner()) + 1);
} else {
printMap2.put(unit.toStringNoOwner(), 1);
}
}
for (final String key : printMap2.keySet()) {
ProLogger.trace(" " + printMap2.get(key) + " " + key);
}
ProLogger.trace(" --- Enemy bombard units ---");
final Map<String, Integer> printMap4 = new HashMap<>();
final Set<Unit> units4 = moveMap.get(t).getMaxEnemyBombardUnits();
for (final Unit unit : units4) {
if (printMap4.containsKey(unit.toStringNoOwner())) {
printMap4.put(unit.toStringNoOwner(), printMap4.get(unit.toStringNoOwner()) + 1);
} else {
printMap4.put(unit.toStringNoOwner(), 1);
}
}
for (final String key : printMap4.keySet()) {
ProLogger.trace(" " + printMap4.get(key) + " " + key);
}
}
}
use of games.strategy.engine.data.Territory in project triplea by triplea-game.
the class ProNonCombatMoveAi method findUnitsThatCantMove.
private void findUnitsThatCantMove(final Map<Territory, ProPurchaseTerritory> purchaseTerritories, final List<ProPurchaseOption> landPurchaseOptions) {
ProLogger.info("Find units that can't move");
final Map<Territory, ProTerritory> moveMap = territoryManager.getDefendOptions().getTerritoryMap();
final Map<Unit, Set<Territory>> unitMoveMap = territoryManager.getDefendOptions().getUnitMoveMap();
final List<ProTransport> transportMapList = territoryManager.getDefendOptions().getTransportList();
// Add all units that can't move (allied units, 0 move units, etc)
for (final Territory t : moveMap.keySet()) {
moveMap.get(t).getCantMoveUnits().addAll(t.getUnits().getMatches(ProMatches.unitCantBeMovedAndIsAlliedDefender(player, data, t)));
}
// Add all units that only have 1 move option and can't be transported
for (final Iterator<Unit> it = unitMoveMap.keySet().iterator(); it.hasNext(); ) {
final Unit u = it.next();
if (unitMoveMap.get(u).size() == 1) {
final Territory onlyTerritory = unitMoveMap.get(u).iterator().next();
if (onlyTerritory.equals(unitTerritoryMap.get(u))) {
boolean canBeTransported = false;
for (final ProTransport pad : transportMapList) {
for (final Territory t : pad.getTransportMap().keySet()) {
if (pad.getTransportMap().get(t).contains(onlyTerritory)) {
canBeTransported = true;
}
}
for (final Territory t : pad.getSeaTransportMap().keySet()) {
if (pad.getSeaTransportMap().get(t).contains(onlyTerritory)) {
canBeTransported = true;
}
}
}
if (!canBeTransported) {
moveMap.get(onlyTerritory).getCantMoveUnits().add(u);
it.remove();
}
}
}
}
// Check if purchase units are known yet
if (purchaseTerritories != null) {
// Add all units that will be purchased
for (final ProPurchaseTerritory ppt : purchaseTerritories.values()) {
for (final ProPlaceTerritory placeTerritory : ppt.getCanPlaceTerritories()) {
final Territory t = placeTerritory.getTerritory();
if (moveMap.get(t) != null) {
moveMap.get(t).getCantMoveUnits().addAll(placeTerritory.getPlaceUnits());
}
}
}
} else {
// Add max defenders that can be purchased to each territory
for (final Territory t : moveMap.keySet()) {
if (ProMatches.territoryHasNonMobileInfraFactoryAndIsNotConqueredOwnedLand(player, data).test(t)) {
moveMap.get(t).getCantMoveUnits().addAll(ProPurchaseUtils.findMaxPurchaseDefenders(player, t, landPurchaseOptions));
}
}
}
// Log can't move units per territory
for (final Territory t : moveMap.keySet()) {
if (!moveMap.get(t).getCantMoveUnits().isEmpty()) {
ProLogger.trace(t + " has units that can't move: " + moveMap.get(t).getCantMoveUnits());
}
}
}
use of games.strategy.engine.data.Territory 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.engine.data.Territory 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