use of games.strategy.triplea.ai.pro.data.ProPlaceTerritory in project triplea by triplea-game.
the class ProPurchaseAi method purchaseLandUnits.
private void purchaseLandUnits(final Map<Territory, ProPurchaseTerritory> purchaseTerritories, final List<ProPlaceTerritory> prioritizedLandTerritories, final ProPurchaseOptionMap purchaseOptions, final Map<Territory, Double> territoryValueMap) {
final List<Unit> unplacedUnits = player.getUnits().getMatches(Matches.unitIsNotSea());
if (resourceTracker.isEmpty() && unplacedUnits.isEmpty()) {
return;
}
ProLogger.info("Purchase land units with resources: " + resourceTracker);
if (!unplacedUnits.isEmpty()) {
ProLogger.info("Purchase land units with unplaced units=" + unplacedUnits);
}
// Loop through prioritized territories and purchase land units
for (final ProPlaceTerritory placeTerritory : prioritizedLandTerritories) {
final Territory t = placeTerritory.getTerritory();
ProLogger.debug("Checking land place for " + t.getName());
// Check remaining production
int remainingUnitProduction = purchaseTerritories.get(t).getRemainingUnitProduction();
ProLogger.debug(t + ", remainingUnitProduction=" + remainingUnitProduction);
if (remainingUnitProduction <= 0) {
continue;
}
// Determine most cost efficient units that can be produced in this territory
final List<ProPurchaseOption> landFodderOptions = ProPurchaseUtils.findPurchaseOptionsForTerritory(player, purchaseOptions.getLandFodderOptions(), t, isBid);
final List<ProPurchaseOption> landAttackOptions = ProPurchaseUtils.findPurchaseOptionsForTerritory(player, purchaseOptions.getLandAttackOptions(), t, isBid);
final List<ProPurchaseOption> landDefenseOptions = ProPurchaseUtils.findPurchaseOptionsForTerritory(player, purchaseOptions.getLandDefenseOptions(), t, isBid);
// Determine enemy distance and locally owned units
int enemyDistance = ProUtils.getClosestEnemyOrNeutralLandTerritoryDistance(data, player, t, territoryValueMap);
if (enemyDistance <= 0) {
enemyDistance = 10;
}
final int fodderPercent = 80 - enemyDistance * 5;
ProLogger.debug(t + ", enemyDistance=" + enemyDistance + ", fodderPercent=" + fodderPercent);
final Set<Territory> neighbors = data.getMap().getNeighbors(t, 2, ProMatches.territoryCanMoveLandUnits(player, data, false));
neighbors.add(t);
final List<Unit> ownedLocalUnits = new ArrayList<>();
for (final Territory neighbor : neighbors) {
ownedLocalUnits.addAll(neighbor.getUnits().getMatches(Matches.unitIsOwnedBy(player)));
}
// Check for unplaced units
final List<Unit> unitsToPlace = new ArrayList<>();
for (final Iterator<Unit> it = unplacedUnits.iterator(); it.hasNext(); ) {
final Unit u = it.next();
if (remainingUnitProduction > 0 && ProPurchaseUtils.canUnitsBePlaced(Collections.singletonList(u), player, t, isBid)) {
remainingUnitProduction--;
unitsToPlace.add(u);
it.remove();
ProLogger.trace("Selected unplaced unit=" + u);
}
}
// Purchase as many units as possible
int addedFodderUnits = 0;
double attackAndDefenseDifference = 0;
boolean selectFodderUnit = true;
while (true) {
// Remove options that cost too much PUs or production
ProPurchaseUtils.removeInvalidPurchaseOptions(player, startOfTurnData, landFodderOptions, resourceTracker, remainingUnitProduction, unitsToPlace, purchaseTerritories);
ProPurchaseUtils.removeInvalidPurchaseOptions(player, startOfTurnData, landAttackOptions, resourceTracker, remainingUnitProduction, unitsToPlace, purchaseTerritories);
ProPurchaseUtils.removeInvalidPurchaseOptions(player, startOfTurnData, landDefenseOptions, resourceTracker, remainingUnitProduction, unitsToPlace, purchaseTerritories);
// Select purchase option
Optional<ProPurchaseOption> optionalSelectedOption = Optional.empty();
if (!selectFodderUnit && attackAndDefenseDifference > 0 && !landDefenseOptions.isEmpty()) {
final Map<ProPurchaseOption, Double> defenseEfficiencies = new HashMap<>();
for (final ProPurchaseOption ppo : landDefenseOptions) {
defenseEfficiencies.put(ppo, ppo.getDefenseEfficiency2(enemyDistance, data, ownedLocalUnits, unitsToPlace));
}
optionalSelectedOption = ProPurchaseUtils.randomizePurchaseOption(defenseEfficiencies, "Land Defense");
} else if (!selectFodderUnit && !landAttackOptions.isEmpty()) {
final Map<ProPurchaseOption, Double> attackEfficiencies = new HashMap<>();
for (final ProPurchaseOption ppo : landAttackOptions) {
attackEfficiencies.put(ppo, ppo.getAttackEfficiency2(enemyDistance, data, ownedLocalUnits, unitsToPlace));
}
optionalSelectedOption = ProPurchaseUtils.randomizePurchaseOption(attackEfficiencies, "Land Attack");
} else if (!landFodderOptions.isEmpty()) {
final Map<ProPurchaseOption, Double> fodderEfficiencies = new HashMap<>();
for (final ProPurchaseOption ppo : landFodderOptions) {
fodderEfficiencies.put(ppo, ppo.getFodderEfficiency(enemyDistance, data, ownedLocalUnits, unitsToPlace));
}
optionalSelectedOption = ProPurchaseUtils.randomizePurchaseOption(fodderEfficiencies, "Land Fodder");
if (optionalSelectedOption.isPresent()) {
addedFodderUnits += optionalSelectedOption.get().getQuantity();
}
}
if (!optionalSelectedOption.isPresent()) {
break;
}
final ProPurchaseOption selectedOption = optionalSelectedOption.get();
// Create new temp units
resourceTracker.purchase(selectedOption);
remainingUnitProduction -= selectedOption.getQuantity();
unitsToPlace.addAll(selectedOption.getUnitType().create(selectedOption.getQuantity(), player, true));
attackAndDefenseDifference += (selectedOption.getAttack() - selectedOption.getDefense());
selectFodderUnit = ((double) addedFodderUnits / unitsToPlace.size() * 100) <= fodderPercent;
ProLogger.trace("Selected unit=" + selectedOption.getUnitType().getName());
}
// Add units to place territory
placeTerritory.getPlaceUnits().addAll(unitsToPlace);
ProLogger.debug(t + ", placedUnits=" + unitsToPlace);
}
}
use of games.strategy.triplea.ai.pro.data.ProPlaceTerritory 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.ProPlaceTerritory in project triplea by triplea-game.
the class ProBattleUtils method territoryHasLocalLandSuperiority.
public static boolean territoryHasLocalLandSuperiority(final Territory t, final int distance, final PlayerID player, final Map<Territory, ProPurchaseTerritory> purchaseTerritories) {
final GameData data = ProData.getData();
if (t == null) {
return true;
}
for (int i = 2; i <= distance; i++) {
// Find enemy strength
final Set<Territory> nearbyTerritoriesForEnemy = data.getMap().getNeighbors(t, i, ProMatches.territoryCanMoveLandUnits(player, data, false));
nearbyTerritoriesForEnemy.add(t);
final List<Unit> enemyUnits = new ArrayList<>();
for (final Territory nearbyTerritory : nearbyTerritoriesForEnemy) {
enemyUnits.addAll(nearbyTerritory.getUnits().getMatches(ProMatches.unitIsEnemyNotNeutral(player, data)));
}
// Find allied strength
final Set<Territory> nearbyTerritoriesForAllied = data.getMap().getNeighbors(t, i - 1, ProMatches.territoryCanMoveLandUnits(player, data, false));
nearbyTerritoriesForAllied.add(t);
final List<Unit> alliedUnits = new ArrayList<>();
for (final Territory nearbyTerritory : nearbyTerritoriesForAllied) {
alliedUnits.addAll(nearbyTerritory.getUnits().getMatches(Matches.isUnitAllied(player, data)));
}
for (final ProPurchaseTerritory purchaseTerritory : purchaseTerritories.values()) {
for (final ProPlaceTerritory ppt : purchaseTerritory.getCanPlaceTerritories()) {
if (nearbyTerritoriesForAllied.contains(ppt.getTerritory())) {
alliedUnits.addAll(ppt.getPlaceUnits());
}
}
}
// Determine strength difference
final double strengthDifference = estimateStrengthDifference(t, enemyUnits, alliedUnits);
ProLogger.trace(t + ", current enemy land strengthDifference=" + strengthDifference + ", distance=" + i + ", enemySize=" + enemyUnits.size() + ", alliedSize=" + alliedUnits.size());
if (strengthDifference > 50) {
return false;
}
}
return true;
}
use of games.strategy.triplea.ai.pro.data.ProPlaceTerritory in project triplea by triplea-game.
the class ProPurchaseUtils method removeInvalidPurchaseOptions.
public static List<ProPurchaseOption> removeInvalidPurchaseOptions(final PlayerID player, final GameData data, final List<ProPurchaseOption> purchaseOptions, final ProResourceTracker resourceTracker, final int remainingUnitProduction, final List<Unit> unitsToPlace, final Map<Territory, ProPurchaseTerritory> purchaseTerritories) {
for (final Iterator<ProPurchaseOption> it = purchaseOptions.iterator(); it.hasNext(); ) {
final ProPurchaseOption purchaseOption = it.next();
// Check PU cost and production
if (!resourceTracker.hasEnough(purchaseOption) || purchaseOption.getQuantity() > remainingUnitProduction) {
it.remove();
continue;
}
// Check max unit limits (-1 is unlimited)
final int maxBuilt = purchaseOption.getMaxBuiltPerPlayer();
final UnitType type = purchaseOption.getUnitType();
if (maxBuilt == 0) {
it.remove();
} else if (maxBuilt > 0) {
// Find number of unit type that are already built and about to be placed
int currentlyBuilt = 0;
final Predicate<Unit> unitTypeOwnedBy = Matches.unitIsOfType(type).and(Matches.unitIsOwnedBy(player));
final List<Territory> allTerritories = data.getMap().getTerritories();
for (final Territory t : allTerritories) {
currentlyBuilt += t.getUnits().countMatches(unitTypeOwnedBy);
}
currentlyBuilt += CollectionUtils.countMatches(unitsToPlace, unitTypeOwnedBy);
for (final ProPurchaseTerritory t : purchaseTerritories.values()) {
for (final ProPlaceTerritory placeTerritory : t.getCanPlaceTerritories()) {
currentlyBuilt += CollectionUtils.countMatches(placeTerritory.getPlaceUnits(), unitTypeOwnedBy);
}
}
final int allowedBuild = maxBuilt - currentlyBuilt;
if (allowedBuild - purchaseOption.getQuantity() < 0) {
it.remove();
}
}
}
return purchaseOptions;
}
use of games.strategy.triplea.ai.pro.data.ProPlaceTerritory in project triplea by triplea-game.
the class ProPurchaseAi method place.
void place(final Map<Territory, ProPurchaseTerritory> purchaseTerritories, final IAbstractPlaceDelegate placeDelegate) {
ProLogger.info("Starting place phase");
data = ProData.getData();
player = ProData.getPlayer();
territoryManager = new ProTerritoryManager(calc);
if (purchaseTerritories != null) {
// Place all units calculated during purchase phase (land then sea to reduce failed placements)
for (final ProPurchaseTerritory t : purchaseTerritories.values()) {
for (final ProPlaceTerritory ppt : t.getCanPlaceTerritories()) {
if (!ppt.getTerritory().isWater()) {
final List<Unit> unitsToPlace = new ArrayList<>();
for (final Unit placeUnit : ppt.getPlaceUnits()) {
for (final Unit myUnit : player.getUnits()) {
if (myUnit.getType().equals(placeUnit.getType()) && !unitsToPlace.contains(myUnit)) {
unitsToPlace.add(myUnit);
break;
}
}
}
doPlace(data.getMap().getTerritory(ppt.getTerritory().getName()), unitsToPlace, placeDelegate);
ProLogger.debug(ppt.getTerritory() + " placed units: " + unitsToPlace);
}
}
}
for (final ProPurchaseTerritory t : purchaseTerritories.values()) {
for (final ProPlaceTerritory ppt : t.getCanPlaceTerritories()) {
if (ppt.getTerritory().isWater()) {
final List<Unit> unitsToPlace = new ArrayList<>();
for (final Unit placeUnit : ppt.getPlaceUnits()) {
for (final Unit myUnit : player.getUnits()) {
if (myUnit.getType().equals(placeUnit.getType()) && !unitsToPlace.contains(myUnit)) {
unitsToPlace.add(myUnit);
break;
}
}
}
doPlace(data.getMap().getTerritory(ppt.getTerritory().getName()), unitsToPlace, placeDelegate);
ProLogger.debug(ppt.getTerritory() + " placed units: " + unitsToPlace);
}
}
}
}
// Place remaining units (currently only implemented to handle land units, ex. WW2v3 China)
if (player.getUnits().getUnits().isEmpty()) {
return;
}
// Current data at the start of place
ProLogger.debug("Remaining units to place: " + player.getUnits().getUnits());
// Find all place territories
final Map<Territory, ProPurchaseTerritory> placeNonConstructionTerritories = ProPurchaseUtils.findPurchaseTerritories(player);
// Determine max enemy attack units and current allied defenders
findDefendersInPlaceTerritories(placeNonConstructionTerritories);
// Prioritize land territories that need defended and place additional defenders
final List<ProPlaceTerritory> needToDefendLandTerritories = prioritizeTerritoriesToDefend(placeNonConstructionTerritories, true);
placeDefenders(placeNonConstructionTerritories, needToDefendLandTerritories, placeDelegate);
// Find strategic value for each territory
ProLogger.info("Find strategic value for place territories");
final Map<Territory, Double> territoryValueMap = ProTerritoryValueUtils.findTerritoryValues(player, new ArrayList<>(), new ArrayList<>());
for (final ProPurchaseTerritory t : placeNonConstructionTerritories.values()) {
for (final ProPlaceTerritory ppt : t.getCanPlaceTerritories()) {
ppt.setStrategicValue(territoryValueMap.get(ppt.getTerritory()));
ProLogger.debug(ppt.getTerritory() + ", strategicValue=" + territoryValueMap.get(ppt.getTerritory()));
}
}
// Prioritize land place territories, add all territories, and then place units
final List<ProPlaceTerritory> prioritizedLandTerritories = prioritizeLandTerritories(placeNonConstructionTerritories);
for (final ProPurchaseTerritory ppt : placeNonConstructionTerritories.values()) {
for (final ProPlaceTerritory placeTerritory : ppt.getCanPlaceTerritories()) {
final Territory t = placeTerritory.getTerritory();
if (!t.isWater() && !prioritizedLandTerritories.contains(placeTerritory)) {
prioritizedLandTerritories.add(placeTerritory);
}
}
}
// Place regular land units
placeLandUnits(prioritizedLandTerritories, placeDelegate, false);
// Place isConstruction land units (needs separated since placeDelegate.getPlaceableUnits doesn't handle combined)
placeLandUnits(prioritizedLandTerritories, placeDelegate, true);
}
Aggregations