Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some code clean ups. #12682

Merged
merged 3 commits into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,11 @@ public static int getProductionPotentialOfTerritory(
final Collection<Unit> unitsAtStartOfStepInTerritory,
final Territory producer,
final GamePlayer player,
final GameProperties properties,
final boolean accountForDamage,
final boolean mathMaxZero) {
return getHowMuchCanUnitProduce(
getBiggestProducer(
unitsAtStartOfStepInTerritory,
producer,
player,
player.getData().getTechTracker(),
properties,
accountForDamage),
getBiggestProducer(unitsAtStartOfStepInTerritory, producer, player, accountForDamage),
producer,
player.getData().getTechTracker(),
properties,
accountForDamage,
mathMaxZero);
}
Expand All @@ -69,8 +60,6 @@ public static int getProductionPotentialOfTerritory(
final Collection<Unit> units,
final Territory producer,
final GamePlayer player,
final TechTracker techTracker,
final GameProperties properties,
final boolean accountForDamage) {
final Predicate<Unit> factoryMatch =
Matches.unitIsOwnedAndIsFactoryOrCanProduceUnits(player)
Expand All @@ -84,8 +73,7 @@ public static int getProductionPotentialOfTerritory(
Unit highestUnit = CollectionUtils.getAny(factories);
int highestCapacity = Integer.MIN_VALUE;
for (final Unit u : factories) {
final int capacity =
getHowMuchCanUnitProduce(u, producer, techTracker, properties, accountForDamage, false);
final int capacity = getHowMuchCanUnitProduce(u, producer, accountForDamage, false);
productionPotential.put(u, capacity);
if (capacity > highestCapacity) {
highestCapacity = capacity;
Expand All @@ -106,8 +94,6 @@ public static int getProductionPotentialOfTerritory(
public static int getHowMuchCanUnitProduce(
final @Nullable Unit unit,
final Territory producer,
final TechTracker techTracker,
final GameProperties properties,
final boolean accountForDamage,
final boolean mathMaxZero) {
if (unit == null) {
Expand All @@ -125,6 +111,7 @@ public static int getHowMuchCanUnitProduce(
territoryUnitProduction = ta.getUnitProduction();
}
int productionCapacity;
final GameProperties properties = producer.getData().getProperties();
if (accountForDamage) {
if (Properties.getDamageFromBombingDoneToUnitsInsteadOfTerritories(properties)) {
if (ua.getCanProduceXUnits() < 0) {
Expand Down Expand Up @@ -158,6 +145,7 @@ public static int getHowMuchCanUnitProduce(
(Properties.getWW2V2(properties) || Properties.getWW2V3(properties)) ? 0 : 1;
}
}
final TechTracker techTracker = producer.getData().getTechTracker();
// Increase production if we have industrial technology
if (territoryProduction
>= techTracker.getMinimumTerritoryValueForProductionBonus(unit.getOwner())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,6 @@ void repair(
CollectionUtils.getMatches(fixTerr.getUnits(), ourFactories),
fixTerr,
player,
data.getTechTracker(),
data.getProperties(),
false);
if (Matches.unitHasTakenSomeBombingUnitDamage().test(possibleFactoryNeedingRepair)) {
unitsThatCanProduceNeedingRepair.put(possibleFactoryNeedingRepair, fixTerr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public static List<Unit> findMaxPurchaseDefenders(
final List<Unit> placeUnits = new ArrayList<>();
if (bestDefenseOption != null) {
ProLogger.debug("Best defense option: " + bestDefenseOption.getUnitType().getName());
int remainingUnitProduction = getUnitProduction(t, data, player);
int remainingUnitProduction = getUnitProduction(t, player);
int pusSpent = 0;
while (bestDefenseOption.getCost() <= (pusRemaining - pusSpent)
&& remainingUnitProduction >= bestDefenseOption.getQuantity()) {
Expand Down Expand Up @@ -190,16 +190,15 @@ public static Map<Territory, ProPurchaseTerritory> findPurchaseTerritories(
// Create purchase territory holder for each factory territory
final Map<Territory, ProPurchaseTerritory> purchaseTerritories = new HashMap<>();
for (final Territory t : ownedAndNotConqueredFactoryTerritories) {
final int unitProduction = getUnitProduction(t, data, player);
final int unitProduction = getUnitProduction(t, player);
final ProPurchaseTerritory ppt = new ProPurchaseTerritory(t, data, player, unitProduction);
purchaseTerritories.put(t, ppt);
ProLogger.debug(ppt.toString());
}
return purchaseTerritories;
}

private static int getUnitProduction(
final Territory territory, final GameState data, final GamePlayer player) {
private static int getUnitProduction(final Territory territory, final GamePlayer player) {
final Predicate<Unit> factoryMatch =
Matches.unitIsOwnedAndIsFactoryOrCanProduceUnits(player)
.and(Matches.unitIsBeingTransported().negate())
Expand All @@ -220,7 +219,7 @@ private static int getUnitProduction(
return Integer.MAX_VALUE;
}
return UnitUtils.getProductionPotentialOfTerritory(
territory.getUnits(), territory, player, data.getProperties(), true, true);
territory.getUnits(), territory, player, true, true);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ private static Route getAmphibRoute(final GamePlayer player, final GameState dat
}
final Predicate<Territory> endMatch =
o -> {
final boolean impassable =
TerritoryAttachment.get(o) != null && TerritoryAttachment.get(o).getIsImpassable();
final var ta = TerritoryAttachment.get(o);
final boolean impassable = ta != null && ta.getIsImpassable();
return !impassable
&& !o.isWater()
&& Utils.hasLandRouteToEnemyOwnedCapitol(o, player, data);
Expand Down Expand Up @@ -435,7 +435,8 @@ private List<MoveDescription> calculateNonCombat(final GameData data, final Game
if (t.isWater()) {
continue;
}
if (TerritoryAttachment.get(t) != null && TerritoryAttachment.get(t).isCapital()) {
final var ta = TerritoryAttachment.get(t);
if (ta != null && ta.isCapital()) {
// if they are a threat to take our capitol, dont move
// compare the strength of units we can place
final float ourStrength = AiUtils.strength(player.getUnits(), false, false);
Expand Down Expand Up @@ -651,8 +652,9 @@ private List<MoveDescription> calculateCombatMove(final GameState data, final Ga
final Collection<Territory> attackFrom =
data.getMap().getNeighbors(enemy, Matches.territoryHasLandUnitsOwnedBy(player));
for (final Territory owned : attackFrom) {
if (TerritoryAttachment.get(owned) != null
&& TerritoryAttachment.get(owned).isCapital()
final var ta = TerritoryAttachment.get(owned);
if (ta != null
&& ta.isCapital()
&& (Utils.getStrengthOfPotentialAttackers(owned, data)
> AiUtils.strength(owned.getUnits(), false, false))) {
dontMoveFrom.add(owned);
Expand Down Expand Up @@ -833,65 +835,43 @@ public void purchase(
CollectionUtils.getMatches(fixTerr.getUnits(), ourFactories),
fixTerr,
player,
data.getTechTracker(),
data.getProperties(),
false);
if (Matches.unitHasTakenSomeBombingUnitDamage().test(possibleFactoryNeedingRepair)) {
unitsThatCanProduceNeedingRepair.put(possibleFactoryNeedingRepair, fixTerr);
}
if (fixTerr.equals(capitol)) {
capProduction =
UnitUtils.getHowMuchCanUnitProduce(
possibleFactoryNeedingRepair,
fixTerr,
data.getTechTracker(),
data.getProperties(),
true,
true);
UnitUtils.getHowMuchCanUnitProduce(possibleFactoryNeedingRepair, fixTerr, true, true);
capUnit = possibleFactoryNeedingRepair;
capUnitTerritory = fixTerr;
}
currentProduction +=
UnitUtils.getHowMuchCanUnitProduce(
possibleFactoryNeedingRepair,
fixTerr,
data.getTechTracker(),
data.getProperties(),
true,
true);
UnitUtils.getHowMuchCanUnitProduce(possibleFactoryNeedingRepair, fixTerr, true, true);
}
repairFactories.remove(capitol);
unitsThatCanProduceNeedingRepair.remove(capUnit);
final var territoryIsOwnedAndHasOwnedUnitMatching =
Matches.territoryIsOwnedAndHasOwnedUnitMatching(
player, Matches.unitCanProduceUnitsAndCanBeDamaged());
// assume minimum unit price is 3, and that we are buying only that... if we over repair, oh
// well, that is better
// than under-repairing
// well, that is better than under-repairing
// goal is to be able to produce all our units, and at least half of that production in the
// capitol
//
// if capitol is super safe, we don't have to do this. and if capitol is under siege, we
// should repair enough to
// place all our units here
// should repair enough to place all our units here
int maxUnits = (totalPu - 1) / minimumUnitPrice;
if ((capProduction <= maxUnits / 2 || repairFactories.isEmpty()) && capUnit != null) {
for (final RepairRule rrule : repairRules) {
if (!capUnit.getType().equals(rrule.getAnyResultKey())) {
continue;
}
if (!Matches.territoryIsOwnedAndHasOwnedUnitMatching(
player, Matches.unitCanProduceUnitsAndCanBeDamaged())
.test(capitol)) {
if (!territoryIsOwnedAndHasOwnedUnitMatching.test(capitol)) {
continue;
}
diff = capUnit.getUnitDamage();
final int unitProductionAllowNegative =
UnitUtils.getHowMuchCanUnitProduce(
capUnit,
capUnitTerritory,
data.getTechTracker(),
data.getProperties(),
false,
true)
- diff;
UnitUtils.getHowMuchCanUnitProduce(capUnit, capUnitTerritory, false, true) - diff;
if (!repairFactories.isEmpty()) {
diff = Math.min(diff, (maxUnits / 2 - unitProductionAllowNegative) + 1);
} else {
Expand Down Expand Up @@ -922,9 +902,8 @@ public void purchase(
if (fixUnit == null || !fixUnit.getType().equals(rrule.getAnyResultKey())) {
continue;
}
if (!Matches.territoryIsOwnedAndHasOwnedUnitMatching(
player, Matches.unitCanProduceUnitsAndCanBeDamaged())
.test(unitsThatCanProduceNeedingRepair.get(fixUnit))) {
if (!territoryIsOwnedAndHasOwnedUnitMatching.test(
unitsThatCanProduceNeedingRepair.get(fixUnit))) {
continue;
}
// we will repair the first territories in the list as much as we can, until we fulfill
Expand All @@ -936,12 +915,7 @@ public void purchase(
diff = fixUnit.getUnitDamage();
final int unitProductionAllowNegative =
UnitUtils.getHowMuchCanUnitProduce(
fixUnit,
unitsThatCanProduceNeedingRepair.get(fixUnit),
data.getTechTracker(),
data.getProperties(),
false,
true)
fixUnit, unitsThatCanProduceNeedingRepair.get(fixUnit), false, true)
- diff;
if (i == 0) {
if (unitProductionAllowNegative < 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,7 @@ protected int getMaxUnitsToBePlacedFrom(
// maxConstructions
int production =
UnitUtils.getProductionPotentialOfTerritory(
unitsAtStartOfStepInTerritory(producer), producer, player, properties, true, true);
unitsAtStartOfStepInTerritory(producer), producer, player, true, true);
// increase the production by the number of constructions allowed
if (maxConstructions > 0) {
production += maxConstructions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -547,11 +547,13 @@ private Collection<TerritoryEffect> getTerritoryEffects() {

private void updateStats() {
Util.ensureOnEventDispatchThread();
final AtomicReference<AggregateResults> results = new AtomicReference<>();
final AtomicReference<AggregateResults> resultsRef = new AtomicReference<>();
final WaitDialog dialog =
new WaitDialog(this, "Calculating Odds... (this may take a while)", calculator::cancel);
final AtomicReference<Collection<Unit>> defenders = new AtomicReference<>();
final AtomicReference<Collection<Unit>> attackers = new AtomicReference<>();
final GamePlayer attacker = getAttacker();
final GamePlayer defender = getDefender();
ThreadRunner.runInNewThread(
() -> {
try {
Expand Down Expand Up @@ -585,10 +587,10 @@ private void updateStats() {
final Collection<TerritoryEffect> territoryEffects = getTerritoryEffects();
defenders.set(defending);
attackers.set(attacking);
results.set(
resultsRef.set(
calculator.calculate(
getAttacker(),
getDefender(),
attacker,
defender,
location,
attacking,
defending,
Expand All @@ -605,60 +607,53 @@ private void updateStats() {
}
});
// the runnable setting the dialog visible must run after this code executes, since this code is
// running on the
// swing event thread
// running on the swing event thread
dialog.setVisible(true);
// results.get() could be null if we cancelled to quickly or something weird like that.
if (results.get() == null) {
final var results = resultsRef.get();
if (results == null) {
setResultsToBlank();
} else {
// All AggregateResults method return NaN if there are no battle results to aggregate over.
// For "unrestricted" average methods, this cannot happen as we ensure that at least 1 round
// is simulated. However, the ...IfAbcWon() methods restrict that set of results which might
// become empty. In this case we display N/A (not applicable) instead of NaN (not a number).
attackerWin.setText(formatPercentage(results.get().getAttackerWinPercent()));
defenderWin.setText(formatPercentage(results.get().getDefenderWinPercent()));
draw.setText(formatPercentage(results.get().getDrawPercent()));
final boolean isLand = isLand();
final List<Unit> mainCombatAttackers =
CollectionUtils.getMatches(
attackers.get(), Matches.unitCanBeInBattle(true, isLand, 1, true));
final List<Unit> mainCombatDefenders =
CollectionUtils.getMatches(
defenders.get(), Matches.unitCanBeInBattle(false, isLand, 1, true));
final int attackersTotal = mainCombatAttackers.size();
final int defendersTotal = mainCombatDefenders.size();
defenderLeft.setText(
formatValue(results.get().getAverageDefendingUnitsLeft()) + " / " + defendersTotal);
attackerLeft.setText(
formatValue(results.get().getAverageAttackingUnitsLeft()) + " / " + attackersTotal);
final double avgDefIfDefWon = results.get().getAverageDefendingUnitsLeftWhenDefenderWon();
defenderLeftWhenDefenderWon.setText(
Double.isNaN(avgDefIfDefWon)
? "N/A"
: formatValue(avgDefIfDefWon) + " / " + defendersTotal);
final double avgAttIfAttWon = results.get().getAverageAttackingUnitsLeftWhenAttackerWon();
attackerLeftWhenAttackerWon.setText(
Double.isNaN(avgAttIfAttWon)
? "N/A"
: formatValue(avgAttIfAttWon) + " / " + attackersTotal);
roundsAverage.setText("" + formatValue(results.get().getAverageBattleRoundsFought()));
try (GameData.Unlocker ignored = data.acquireReadLock()) {
averageChangeInTuv.setText(
""
+ formatValue(
results
.get()
.getAverageTuvSwing(
getAttacker(),
mainCombatAttackers,
getDefender(),
mainCombatDefenders,
data)));
}
count.setText(results.get().getRollCount() + "");
time.setText(formatValue(results.get().getTime() / 1000.0) + " s");
return;
}
// All AggregateResults method return NaN if there are no battle results to aggregate over.
// For "unrestricted" average methods, this cannot happen as we ensure that at least 1 round
// is simulated. However, the ...IfAbcWon() methods restrict that set of results which might
// become empty. In this case we display N/A (not applicable) instead of NaN (not a number).
attackerWin.setText(formatPercentage(results.getAttackerWinPercent()));
defenderWin.setText(formatPercentage(results.getDefenderWinPercent()));
draw.setText(formatPercentage(results.getDrawPercent()));
final boolean isLand = isLand();
final List<Unit> mainCombatAttackers =
CollectionUtils.getMatches(
attackers.get(), Matches.unitCanBeInBattle(true, isLand, 1, true));
final List<Unit> mainCombatDefenders =
CollectionUtils.getMatches(
defenders.get(), Matches.unitCanBeInBattle(false, isLand, 1, true));
final int attackersTotal = mainCombatAttackers.size();
final int defendersTotal = mainCombatDefenders.size();
defenderLeft.setText(
formatValue(results.getAverageDefendingUnitsLeft()) + " / " + defendersTotal);
attackerLeft.setText(
formatValue(results.getAverageAttackingUnitsLeft()) + " / " + attackersTotal);
final double avgDefIfDefWon = results.getAverageDefendingUnitsLeftWhenDefenderWon();
defenderLeftWhenDefenderWon.setText(
Double.isNaN(avgDefIfDefWon)
? "N/A"
: formatValue(avgDefIfDefWon) + " / " + defendersTotal);
final double avgAttIfAttWon = results.getAverageAttackingUnitsLeftWhenAttackerWon();
attackerLeftWhenAttackerWon.setText(
Double.isNaN(avgAttIfAttWon)
? "N/A"
: formatValue(avgAttIfAttWon) + " / " + attackersTotal);
roundsAverage.setText(formatValue(results.getAverageBattleRoundsFought()));
try (GameData.Unlocker ignored = data.acquireReadLock()) {
double tuvSwing =
results.getAverageTuvSwing(
attacker, mainCombatAttackers, defender, mainCombatDefenders, data);
averageChangeInTuv.setText(formatValue(tuvSwing));
}
count.setText(results.getRollCount() + "");
time.setText(formatValue(results.getTime() / 1000.0) + " s");
}

private Territory findPotentialBattleSite() {
Expand Down
Loading