use of games.strategy.triplea.ai.pro.data.ProTerritory 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.triplea.ai.pro.data.ProTerritory 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.triplea.ai.pro.data.ProTerritory 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.ai.pro.data.ProTerritory 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;
}
use of games.strategy.triplea.ai.pro.data.ProTerritory in project triplea by triplea-game.
the class ProNonCombatMoveAi method doNonCombatMove.
Map<Territory, ProTerritory> doNonCombatMove(Map<Territory, ProTerritory> factoryMoveMap, final Map<Territory, ProPurchaseTerritory> purchaseTerritories, final IMoveDelegate moveDel) {
ProLogger.info("Starting non-combat move phase");
// Current data at the start of non-combat move
data = ProData.getData();
player = ProData.getPlayer();
unitTerritoryMap = ProData.unitTerritoryMap;
territoryManager = new ProTerritoryManager(calc);
// Find the max number of units that can move to each allied territory
territoryManager.populateDefenseOptions(new ArrayList<>());
// Find number of units in each move territory that can't move and all infra units
findUnitsThatCantMove(purchaseTerritories, ProData.purchaseOptions.getLandOptions());
final Map<Unit, Set<Territory>> infraUnitMoveMap = findInfraUnitsThatCanMove();
// Try to have one land unit in each territory that is bordering an enemy territory
final List<Territory> movedOneDefenderToTerritories = moveOneDefenderToLandTerritoriesBorderingEnemy();
// Determine max enemy attack units and if territories can be held
territoryManager.populateEnemyAttackOptions(movedOneDefenderToTerritories, territoryManager.getDefendTerritories());
determineIfMoveTerritoriesCanBeHeld();
// Get list of territories that can't be held and find move value for each territory
final List<Territory> territoriesThatCantBeHeld = territoryManager.getCantHoldTerritories();
final Map<Territory, Double> territoryValueMap = ProTerritoryValueUtils.findTerritoryValues(player, territoriesThatCantBeHeld, new ArrayList<>());
final Map<Territory, Double> seaTerritoryValueMap = ProTerritoryValueUtils.findSeaTerritoryValues(player, territoriesThatCantBeHeld);
// Prioritize territories to defend
final List<ProTerritory> prioritizedTerritories = prioritizeDefendOptions(factoryMoveMap, territoryValueMap);
// Determine which territories to defend and how many units each one needs
final int enemyDistance = ProUtils.getClosestEnemyLandTerritoryDistance(data, player, ProData.myCapital);
moveUnitsToDefendTerritories(prioritizedTerritories, enemyDistance, territoryValueMap);
// Copy data in case capital defense needs increased
final ProTerritoryManager territoryManagerCopy = new ProTerritoryManager(calc, territoryManager);
// Use loop to ensure capital is protected after moves
if (ProData.myCapital != null) {
int defenseRange = -1;
while (true) {
// Add value to territories near capital if necessary
for (final Territory t : territoryManager.getDefendTerritories()) {
double value = territoryValueMap.get(t);
final int distance = data.getMap().getDistance(ProData.myCapital, t, ProMatches.territoryCanMoveLandUnits(player, data, false));
if (distance >= 0 && distance <= defenseRange) {
value *= 10;
}
territoryManager.getDefendOptions().getTerritoryMap().get(t).setValue(value);
if (t.isWater()) {
territoryManager.getDefendOptions().getTerritoryMap().get(t).setSeaValue(seaTerritoryValueMap.get(t));
}
}
moveUnitsToBestTerritories();
// Check if capital has local land superiority
ProLogger.info("Checking if capital has local land superiority with enemyDistance=" + enemyDistance);
if (enemyDistance >= 2 && enemyDistance <= 3 && defenseRange == -1 && !ProBattleUtils.territoryHasLocalLandSuperiorityAfterMoves(ProData.myCapital, enemyDistance, player, territoryManager.getDefendOptions().getTerritoryMap())) {
defenseRange = enemyDistance - 1;
territoryManager = territoryManagerCopy;
ProLogger.debug("Capital doesn't have local land superiority so setting defensive stance");
} else {
break;
}
}
} else {
moveUnitsToBestTerritories();
}
// Determine where to move infra units
factoryMoveMap = moveInfraUnits(factoryMoveMap, infraUnitMoveMap);
// Log a warning if any units not assigned to a territory (skip infrastructure for now)
for (final Unit u : territoryManager.getDefendOptions().getUnitMoveMap().keySet()) {
if (Matches.unitIsInfrastructure().negate().test(u)) {
ProLogger.warn(player + ": " + unitTerritoryMap.get(u) + " has unmoved unit: " + u + " with options: " + territoryManager.getDefendOptions().getUnitMoveMap().get(u));
}
}
// Calculate move routes and perform moves
doMove(territoryManager.getDefendOptions().getTerritoryMap(), moveDel, data, player);
// Log results
ProLogger.info("Logging results");
logAttackMoves(prioritizedTerritories);
return factoryMoveMap;
}
Aggregations