use of games.strategy.triplea.ai.pro.data.ProPurchaseOptionMap in project triplea by triplea-game.
the class ProPurchaseAi method bid.
/**
* Default settings for bidding:
* 1) Limit one bid unit in a territory or sea zone (until set in all territories then 2, etc).
* 2) The nation placing a unit in a territory or sea zone must have started with a unit in said territory or sea zone
* prior to placing the bid.
*/
Map<Territory, ProPurchaseTerritory> bid(final int pus, final IPurchaseDelegate purchaseDelegate, final GameData startOfTurnData) {
// Current data fields
data = ProData.getData();
this.startOfTurnData = startOfTurnData;
player = ProData.getPlayer();
resourceTracker = new ProResourceTracker(pus, data);
territoryManager = new ProTerritoryManager(calc);
isBid = true;
final ProPurchaseOptionMap purchaseOptions = ProData.purchaseOptions;
ProLogger.info("Starting bid phase with resources: " + resourceTracker);
if (!player.getUnits().getUnits().isEmpty()) {
ProLogger.info("Starting bid phase with unplaced units=" + player.getUnits().getUnits());
}
// Find all purchase/place territories
final Map<Territory, ProPurchaseTerritory> purchaseTerritories = ProPurchaseUtils.findBidTerritories(player);
int previousNumUnits = 0;
while (true) {
// Determine max enemy attack units and current allied defenders
territoryManager.populateEnemyAttackOptions(new ArrayList<>(), new ArrayList<>(purchaseTerritories.keySet()));
findDefendersInPlaceTerritories(purchaseTerritories);
// Prioritize land territories that need defended and purchase additional defenders
final List<ProPlaceTerritory> needToDefendLandTerritories = prioritizeTerritoriesToDefend(purchaseTerritories, true);
purchaseDefenders(purchaseTerritories, needToDefendLandTerritories, purchaseOptions.getLandFodderOptions(), purchaseOptions.getAirOptions(), true);
// 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 : purchaseTerritories.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 options purchase AA then land units
final List<ProPlaceTerritory> prioritizedLandTerritories = prioritizeLandTerritories(purchaseTerritories);
purchaseAaUnits(purchaseTerritories, prioritizedLandTerritories, purchaseOptions.getAaOptions());
purchaseLandUnits(purchaseTerritories, prioritizedLandTerritories, purchaseOptions, territoryValueMap);
// Prioritize sea territories that need defended and purchase additional defenders
final List<ProPlaceTerritory> needToDefendSeaTerritories = prioritizeTerritoriesToDefend(purchaseTerritories, false);
purchaseDefenders(purchaseTerritories, needToDefendSeaTerritories, purchaseOptions.getSeaDefenseOptions(), purchaseOptions.getAirOptions(), false);
// Prioritize sea place options and purchase units
final List<ProPlaceTerritory> prioritizedSeaTerritories = prioritizeSeaTerritories(purchaseTerritories);
purchaseSeaAndAmphibUnits(purchaseTerritories, prioritizedSeaTerritories, territoryValueMap, purchaseOptions);
// Try to use any remaining PUs on high value units
purchaseUnitsWithRemainingProduction(purchaseTerritories, purchaseOptions.getLandOptions(), purchaseOptions.getAirOptions());
upgradeUnitsWithRemainingPUs(purchaseTerritories, purchaseOptions);
// Check if no remaining PUs or no unit built this iteration
final int numUnits = purchaseTerritories.values().stream().map(ProPurchaseTerritory::getCanPlaceTerritories).map(t -> t.get(0)).map(ProPlaceTerritory::getPlaceUnits).mapToInt(List::size).sum();
if (resourceTracker.isEmpty() || numUnits == previousNumUnits) {
break;
}
previousNumUnits = numUnits;
ProPurchaseUtils.incrementUnitProductionForBidTerritories(purchaseTerritories);
}
// Determine final count of each production rule
final IntegerMap<ProductionRule> purchaseMap = populateProductionRuleMap(purchaseTerritories, purchaseOptions);
// Purchase units
ProMetricUtils.collectPurchaseStats(purchaseMap);
final String error = purchaseDelegate.purchase(purchaseMap);
if (error != null) {
ProLogger.warn("Purchase error: " + error);
}
return purchaseTerritories;
}
use of games.strategy.triplea.ai.pro.data.ProPurchaseOptionMap 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.ProPurchaseOptionMap in project triplea by triplea-game.
the class ProData method hiddenInitialize.
private static void hiddenInitialize(final ProAi proAi, final GameData data, final PlayerID player, final boolean isSimulation) {
ProData.proAi = proAi;
ProData.data = data;
ProData.player = player;
ProData.isSimulation = isSimulation;
if (!Properties.getLowLuck(data)) {
winPercentage = 90;
minWinPercentage = 65;
}
myCapital = TerritoryAttachment.getFirstOwnedCapitalOrFirstUnownedCapital(player, data);
myUnitTerritories = CollectionUtils.getMatches(data.getMap().getTerritories(), Matches.territoryHasUnitsOwnedBy(player));
unitTerritoryMap = ProUtils.createUnitTerritoryMap();
unitValueMap = TuvUtils.getCostsForTuv(player, data);
purchaseOptions = new ProPurchaseOptionMap(player, data);
minCostPerHitPoint = getMinCostPerHitPoint(purchaseOptions.getLandOptions());
}
use of games.strategy.triplea.ai.pro.data.ProPurchaseOptionMap in project triplea by triplea-game.
the class ProPurchaseAi method populateProductionRuleMap.
private IntegerMap<ProductionRule> populateProductionRuleMap(final Map<Territory, ProPurchaseTerritory> purchaseTerritories, final ProPurchaseOptionMap purchaseOptions) {
ProLogger.info("Populate production rule map");
final List<Unit> unplacedUnits = player.getUnits().getMatches(Matches.unitIsNotSea());
final IntegerMap<ProductionRule> purchaseMap = new IntegerMap<>();
for (final ProPurchaseOption ppo : purchaseOptions.getAllOptions()) {
final int numUnits = (int) purchaseTerritories.values().stream().map(ProPurchaseTerritory::getCanPlaceTerritories).flatMap(Collection::stream).map(ProPlaceTerritory::getPlaceUnits).flatMap(Collection::stream).filter(u -> u.getType().equals(ppo.getUnitType())).filter(u -> !unplacedUnits.contains(u)).count();
if (numUnits > 0) {
final int numProductionRule = numUnits / ppo.getQuantity();
purchaseMap.put(ppo.getProductionRule(), numProductionRule);
ProLogger.info(numProductionRule + " " + ppo.getProductionRule());
}
}
return purchaseMap;
}
use of games.strategy.triplea.ai.pro.data.ProPurchaseOptionMap in project triplea by triplea-game.
the class ProPurchaseAi method purchase.
Map<Territory, ProPurchaseTerritory> purchase(final IPurchaseDelegate purchaseDelegate, final GameData startOfTurnData) {
// Current data fields
data = ProData.getData();
this.startOfTurnData = startOfTurnData;
player = ProData.getPlayer();
resourceTracker = new ProResourceTracker(player);
territoryManager = new ProTerritoryManager(calc);
isBid = false;
final ProPurchaseOptionMap purchaseOptions = ProData.purchaseOptions;
ProLogger.info("Starting purchase phase with resources: " + resourceTracker);
if (!player.getUnits().getUnits().isEmpty()) {
ProLogger.info("Starting purchase phase with unplaced units=" + player.getUnits().getUnits());
}
// Find all purchase/place territories
final Map<Territory, ProPurchaseTerritory> purchaseTerritories = ProPurchaseUtils.findPurchaseTerritories(player);
final Set<Territory> placeTerritories = new HashSet<>(CollectionUtils.getMatches(data.getMap().getTerritoriesOwnedBy(player), Matches.territoryIsLand()));
for (final Territory t : purchaseTerritories.keySet()) {
for (final ProPlaceTerritory ppt : purchaseTerritories.get(t).getCanPlaceTerritories()) {
placeTerritories.add(ppt.getTerritory());
}
}
// Determine max enemy attack units and current allied defenders
territoryManager.populateEnemyAttackOptions(new ArrayList<>(), new ArrayList<>(placeTerritories));
findDefendersInPlaceTerritories(purchaseTerritories);
// Prioritize land territories that need defended and purchase additional defenders
final List<ProPlaceTerritory> needToDefendLandTerritories = prioritizeTerritoriesToDefend(purchaseTerritories, true);
purchaseDefenders(purchaseTerritories, needToDefendLandTerritories, purchaseOptions.getLandFodderOptions(), purchaseOptions.getAirOptions(), true);
// 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 Territory t : purchaseTerritories.keySet()) {
for (final ProPlaceTerritory ppt : purchaseTerritories.get(t).getCanPlaceTerritories()) {
ppt.setStrategicValue(territoryValueMap.get(ppt.getTerritory()));
ProLogger.debug(ppt.getTerritory() + ", strategicValue=" + territoryValueMap.get(ppt.getTerritory()));
}
}
// Prioritize land place options purchase AA then land units
final List<ProPlaceTerritory> prioritizedLandTerritories = prioritizeLandTerritories(purchaseTerritories);
purchaseAaUnits(purchaseTerritories, prioritizedLandTerritories, purchaseOptions.getAaOptions());
purchaseLandUnits(purchaseTerritories, prioritizedLandTerritories, purchaseOptions, territoryValueMap);
// Prioritize sea territories that need defended and purchase additional defenders
final List<ProPlaceTerritory> needToDefendSeaTerritories = prioritizeTerritoriesToDefend(purchaseTerritories, false);
purchaseDefenders(purchaseTerritories, needToDefendSeaTerritories, purchaseOptions.getSeaDefenseOptions(), purchaseOptions.getAirOptions(), false);
// Determine whether to purchase new land factory
final Map<Territory, ProPurchaseTerritory> factoryPurchaseTerritories = new HashMap<>();
purchaseFactory(factoryPurchaseTerritories, purchaseTerritories, prioritizedLandTerritories, purchaseOptions, false);
// Prioritize sea place options and purchase units
final List<ProPlaceTerritory> prioritizedSeaTerritories = prioritizeSeaTerritories(purchaseTerritories);
purchaseSeaAndAmphibUnits(purchaseTerritories, prioritizedSeaTerritories, territoryValueMap, purchaseOptions);
// Try to use any remaining PUs on high value units
purchaseUnitsWithRemainingProduction(purchaseTerritories, purchaseOptions.getLandOptions(), purchaseOptions.getAirOptions());
upgradeUnitsWithRemainingPUs(purchaseTerritories, purchaseOptions);
// Try to purchase land/sea factory with extra PUs
purchaseFactory(factoryPurchaseTerritories, purchaseTerritories, prioritizedLandTerritories, purchaseOptions, true);
// Add factory purchase territory to list if not empty
if (!factoryPurchaseTerritories.isEmpty()) {
purchaseTerritories.putAll(factoryPurchaseTerritories);
}
// Determine final count of each production rule
final IntegerMap<ProductionRule> purchaseMap = populateProductionRuleMap(purchaseTerritories, purchaseOptions);
// Purchase units
ProMetricUtils.collectPurchaseStats(purchaseMap);
final String error = purchaseDelegate.purchase(purchaseMap);
if (error != null) {
ProLogger.warn("Purchase error: " + error);
}
return purchaseTerritories;
}
Aggregations