use of games.strategy.util.IntegerMap 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.util.IntegerMap in project triplea by triplea-game.
the class ProTechAi method findAttackers.
private static List<Unit> findAttackers(final Territory start, final int maxDistance, final HashSet<Integer> ignoreDistance, final PlayerID player, final GameData data, final Predicate<Unit> unitCondition, final Predicate<Territory> routeCondition, final List<Route> routes, final boolean sea) {
final IntegerMap<Territory> distance = new IntegerMap<>();
final Map<Territory, Territory> visited = new HashMap<>();
final List<Unit> units = new ArrayList<>();
final Queue<Territory> q = new ArrayDeque<>();
q.add(start);
Territory current;
distance.put(start, 0);
visited.put(start, null);
while (!q.isEmpty()) {
current = q.remove();
if (distance.getInt(current) == maxDistance) {
break;
}
for (final Territory neighbor : data.getMap().getNeighbors(current)) {
if (!distance.keySet().contains(neighbor)) {
if (!neighbor.getUnits().anyMatch(unitCondition)) {
if (!routeCondition.test(neighbor)) {
continue;
}
}
if (sea) {
final Route r = new Route();
r.setStart(neighbor);
r.add(current);
if (MoveValidator.validateCanal(r, null, player, data) != null) {
continue;
}
}
distance.put(neighbor, distance.getInt(current) + 1);
visited.put(neighbor, current);
q.add(neighbor);
final int dist = distance.getInt(neighbor);
if (ignoreDistance.contains(dist)) {
continue;
}
for (final Unit u : neighbor.getUnits()) {
if (unitCondition.test(u) && Matches.unitHasEnoughMovementForRoutes(routes).test(u)) {
units.add(u);
}
}
}
}
}
// pain in the ass, should just redesign stop blitz attack
for (final Territory t : visited.keySet()) {
final Route r = new Route();
Territory t2 = t;
r.setStart(t);
while (t2 != null) {
t2 = visited.get(t2);
if (t2 != null) {
r.add(t2);
}
}
routes.add(r);
}
return units;
}
use of games.strategy.util.IntegerMap in project triplea by triplea-game.
the class ProPurchaseOption method calculateSupportFactor.
// TODO: doesn't consider enemy support
private double calculateSupportFactor(final List<Unit> ownedLocalUnits, final List<Unit> unitsToPlace, final GameData data, final boolean defense) {
if ((!isAttackSupport && !defense) || (!isDefenseSupport && defense)) {
return 0;
}
final List<Unit> units = new ArrayList<>(ownedLocalUnits);
units.addAll(unitsToPlace);
units.addAll(unitType.create(1, player, true));
final Set<List<UnitSupportAttachment>> supportsAvailable = new HashSet<>();
final IntegerMap<UnitSupportAttachment> supportLeft = new IntegerMap<>();
DiceRoll.getSupport(units, supportsAvailable, supportLeft, new HashMap<>(), data, defense, true);
double totalSupportFactor = 0;
for (final UnitSupportAttachment usa : unitSupportAttachments) {
for (final List<UnitSupportAttachment> bonusType : supportsAvailable) {
if (!bonusType.contains(usa)) {
continue;
}
// Find number of support provided and supportable units
int numAddedSupport = usa.getNumber();
if (usa.getImpArtTech() && TechTracker.hasImprovedArtillerySupport(player)) {
numAddedSupport *= 2;
}
int numSupportProvided = -numAddedSupport;
final Set<Unit> supportableUnits = new HashSet<>();
for (final UnitSupportAttachment usa2 : bonusType) {
numSupportProvided += supportLeft.getInt(usa2);
supportableUnits.addAll(CollectionUtils.getMatches(units, Matches.unitIsOfTypes(usa2.getUnitType())));
}
final int numSupportableUnits = supportableUnits.size();
// Find ratio of supportable to support units (optimal 2 to 1)
final int numExtraSupportableUnits = Math.max(0, numSupportableUnits - numSupportProvided);
// Ranges from 0 to 1
final double ratio = Math.min(1, 2.0 * numExtraSupportableUnits / (numSupportableUnits + numAddedSupport));
// Find approximate strength bonus provided
double bonus = 0;
if (usa.getStrength()) {
bonus += usa.getBonus();
}
if (usa.getRoll()) {
bonus += (usa.getBonus() * data.getDiceSides() * 0.75);
}
// Find support factor value
final double supportFactor = Math.pow(numAddedSupport * 0.9, 0.9) * bonus * ratio;
totalSupportFactor += supportFactor;
ProLogger.trace(unitType.getName() + ", bonusType=" + usa.getBonusType() + ", supportFactor=" + supportFactor + ", numSupportProvided=" + numSupportProvided + ", numSupportableUnits=" + numSupportableUnits + ", numAddedSupport=" + numAddedSupport + ", ratio=" + ratio + ", bonus=" + bonus);
}
}
ProLogger.debug(unitType.getName() + ", defense=" + defense + ", totalSupportFactor=" + totalSupportFactor);
return totalSupportFactor;
}
use of games.strategy.util.IntegerMap in project triplea by triplea-game.
the class TripleAPlayer method purchase.
private void purchase(final boolean bid) {
if (getPlayerBridge().isGameOver()) {
return;
}
final PlayerID id = getPlayerId();
// play a sound for this phase
if (!bid && !soundPlayedAlreadyPurchase) {
ClipPlayer.play(SoundPath.CLIP_PHASE_PURCHASE, id);
soundPlayedAlreadyPurchase = true;
}
// Check if any factories need to be repaired
if (id.getRepairFrontier() != null && id.getRepairFrontier().getRules() != null && !id.getRepairFrontier().getRules().isEmpty()) {
final GameData data = getGameData();
if (isDamageFromBombingDoneToUnitsInsteadOfTerritories(data)) {
final Predicate<Unit> myDamaged = Matches.unitIsOwnedBy(id).and(Matches.unitHasTakenSomeBombingUnitDamage());
final Collection<Unit> damagedUnits = new ArrayList<>();
for (final Territory t : data.getMap().getTerritories()) {
damagedUnits.addAll(CollectionUtils.getMatches(t.getUnits().getUnits(), myDamaged));
}
if (damagedUnits.size() > 0) {
final HashMap<Unit, IntegerMap<RepairRule>> repair = ui.getRepair(id, bid, GameStepPropertiesHelper.getRepairPlayers(data, id));
if (repair != null) {
final IPurchaseDelegate purchaseDel;
try {
purchaseDel = (IPurchaseDelegate) getPlayerBridge().getRemoteDelegate();
} catch (final ClassCastException e) {
final String errorContext = "PlayerBridge step name: " + getPlayerBridge().getStepName() + ", Remote class name: " + getPlayerBridge().getRemoteDelegate().getClass();
// for some reason the client is not seeing or getting these errors, so print to err too
System.err.println(errorContext);
ClientLogger.logQuietly(errorContext, e);
throw new IllegalStateException(errorContext, e);
}
final String error = purchaseDel.purchaseRepair(repair);
if (error != null) {
ui.notifyError(error);
// dont give up, keep going
purchase(bid);
}
}
}
}
}
final IntegerMap<ProductionRule> prod = ui.getProduction(id, bid);
if (prod == null) {
return;
}
final IPurchaseDelegate purchaseDel;
try {
purchaseDel = (IPurchaseDelegate) getPlayerBridge().getRemoteDelegate();
} catch (final ClassCastException e) {
final String errorContext = "PlayerBridge step name: " + getPlayerBridge().getStepName() + ", Remote class name: " + getPlayerBridge().getRemoteDelegate().getClass();
// for some reason the client is not seeing or getting these errors, so print to err too
System.err.println(errorContext);
ClientLogger.logQuietly(errorContext, e);
throw new IllegalStateException(errorContext, e);
}
final String purchaseError = purchaseDel.purchase(prod);
if (purchaseError != null) {
ui.notifyError(purchaseError);
// dont give up, keep going
purchase(bid);
}
}
use of games.strategy.util.IntegerMap in project triplea by triplea-game.
the class TripleAUnit method getBiggestProducer.
public static Unit getBiggestProducer(final Collection<Unit> units, final Territory producer, final PlayerID player, final GameData data, final boolean accountForDamage) {
final Predicate<Unit> factoryMatch = Matches.unitIsOwnedAndIsFactoryOrCanProduceUnits(player).and(Matches.unitIsBeingTransported().negate()).and(producer.isWater() ? Matches.unitIsLand().negate() : Matches.unitIsSea().negate());
final Collection<Unit> factories = CollectionUtils.getMatches(units, factoryMatch);
if (factories.isEmpty()) {
return null;
}
final IntegerMap<Unit> productionPotential = new IntegerMap<>();
Unit highestUnit = factories.iterator().next();
int highestCapacity = Integer.MIN_VALUE;
for (final Unit u : factories) {
final int capacity = getHowMuchCanUnitProduce(u, producer, player, data, accountForDamage, false);
productionPotential.put(u, capacity);
if (capacity > highestCapacity) {
highestCapacity = capacity;
highestUnit = u;
}
}
return highestUnit;
}
Aggregations