use of games.strategy.triplea.delegate.UnitBattleComparator in project triplea by triplea-game.
the class ProBattleUtils method checkForOverwhelmingWin.
public static boolean checkForOverwhelmingWin(final Territory t, final List<Unit> attackingUnits, final List<Unit> defendingUnits) {
final GameData data = ProData.getData();
if (defendingUnits.isEmpty() && !attackingUnits.isEmpty()) {
return true;
}
// Check that defender has at least 1 power
final double power = estimatePower(t, defendingUnits, attackingUnits, false);
if (power == 0 && !attackingUnits.isEmpty()) {
return true;
}
// Determine if enough attack power to win in 1 round
final List<Unit> sortedUnitsList = new ArrayList<>(attackingUnits);
sortedUnitsList.sort(new UnitBattleComparator(false, ProData.unitValueMap, TerritoryEffectHelper.getEffects(t), data, false, false));
Collections.reverse(sortedUnitsList);
final int attackPower = DiceRoll.getTotalPower(DiceRoll.getUnitPowerAndRollsForNormalBattles(sortedUnitsList, defendingUnits, false, false, data, t, TerritoryEffectHelper.getEffects(t), false, null), data);
final List<Unit> defendersWithHitPoints = CollectionUtils.getMatches(defendingUnits, Matches.unitIsInfrastructure().negate());
final int totalDefenderHitPoints = BattleCalculator.getTotalHitpointsLeft(defendersWithHitPoints);
return ((attackPower / data.getDiceSides()) >= totalDefenderHitPoints);
}
use of games.strategy.triplea.delegate.UnitBattleComparator in project triplea by triplea-game.
the class ProBattleUtils method estimatePower.
private static double estimatePower(final Territory t, final List<Unit> myUnits, final List<Unit> enemyUnits, final boolean attacking) {
final GameData data = ProData.getData();
final List<Unit> unitsThatCanFight = CollectionUtils.getMatches(myUnits, Matches.unitCanBeInBattle(attacking, !t.isWater(), 1, false, true, true));
final List<Unit> sortedUnitsList = new ArrayList<>(unitsThatCanFight);
sortedUnitsList.sort(new UnitBattleComparator(!attacking, ProData.unitValueMap, TerritoryEffectHelper.getEffects(t), data, false, false));
Collections.reverse(sortedUnitsList);
final int myPower = DiceRoll.getTotalPower(DiceRoll.getUnitPowerAndRollsForNormalBattles(sortedUnitsList, enemyUnits, !attacking, false, data, t, TerritoryEffectHelper.getEffects(t), false, null), data);
return (myPower * 6.0 / data.getDiceSides());
}
use of games.strategy.triplea.delegate.UnitBattleComparator in project triplea by triplea-game.
the class ProSortMoveOptionsUtils method sortUnitNeededOptionsThenAttack.
public static Map<Unit, Set<Territory>> sortUnitNeededOptionsThenAttack(final PlayerID player, final Map<Unit, Set<Territory>> unitAttackOptions, final Map<Territory, ProTerritory> attackMap, final Map<Unit, Territory> unitTerritoryMap, final ProOddsCalculator calc) {
final GameData data = ProData.getData();
final List<Map.Entry<Unit, Set<Territory>>> list = new ArrayList<>(unitAttackOptions.entrySet());
list.sort((o1, o2) -> {
// Sort by number of territories that still need units
int numOptions1 = 0;
for (final Territory t : o1.getValue()) {
final ProTerritory patd = attackMap.get(t);
if (patd.getBattleResult() == null) {
patd.setBattleResult(calc.estimateAttackBattleResults(t, patd.getUnits(), patd.getMaxEnemyDefenders(player, data), patd.getBombardTerritoryMap().keySet()));
}
if (!patd.isCurrentlyWins()) {
numOptions1++;
}
}
int numOptions2 = 0;
for (final Territory t : o2.getValue()) {
final ProTerritory patd = attackMap.get(t);
if (patd.getBattleResult() == null) {
patd.setBattleResult(calc.estimateAttackBattleResults(t, patd.getUnits(), patd.getMaxEnemyDefenders(player, data), patd.getBombardTerritoryMap().keySet()));
}
if (!patd.isCurrentlyWins()) {
numOptions2++;
}
}
if (numOptions1 != numOptions2) {
return (numOptions1 - numOptions2);
}
if (numOptions1 == 0) {
return 0;
}
// Sort by attack efficiency
int minPower1 = Integer.MAX_VALUE;
for (final Territory t : o1.getValue()) {
if (!attackMap.get(t).isCurrentlyWins()) {
final List<Unit> defendingUnits = t.getUnits().getMatches(Matches.enemyUnit(player, data));
final List<Unit> sortedUnitsList = new ArrayList<>(attackMap.get(t).getUnits());
sortedUnitsList.sort(new UnitBattleComparator(false, ProData.unitValueMap, TerritoryEffectHelper.getEffects(t), data, false, false));
Collections.reverse(sortedUnitsList);
final int powerWithout = DiceRoll.getTotalPower(DiceRoll.getUnitPowerAndRollsForNormalBattles(sortedUnitsList, defendingUnits, false, false, data, t, TerritoryEffectHelper.getEffects(t), false, null), data);
sortedUnitsList.add(o1.getKey());
sortedUnitsList.sort(new UnitBattleComparator(false, ProData.unitValueMap, TerritoryEffectHelper.getEffects(t), data, false, false));
Collections.reverse(sortedUnitsList);
final int powerWith = DiceRoll.getTotalPower(DiceRoll.getUnitPowerAndRollsForNormalBattles(sortedUnitsList, defendingUnits, false, false, data, t, TerritoryEffectHelper.getEffects(t), false, null), data);
final int power = powerWith - powerWithout;
if (power < minPower1) {
minPower1 = power;
}
}
}
final UnitAttachment ua1 = UnitAttachment.get(o1.getKey().getType());
if (ua1.getIsAir()) {
minPower1 *= 10;
}
final double attackEfficiency1 = (double) minPower1 / ProData.unitValueMap.getInt(o1.getKey().getType());
int minPower2 = Integer.MAX_VALUE;
for (final Territory t : o2.getValue()) {
if (!attackMap.get(t).isCurrentlyWins()) {
final List<Unit> defendingUnits = t.getUnits().getMatches(Matches.enemyUnit(player, data));
final List<Unit> sortedUnitsList = new ArrayList<>(attackMap.get(t).getUnits());
sortedUnitsList.sort(new UnitBattleComparator(false, ProData.unitValueMap, TerritoryEffectHelper.getEffects(t), data, false, false));
Collections.reverse(sortedUnitsList);
final int powerWithout = DiceRoll.getTotalPower(DiceRoll.getUnitPowerAndRollsForNormalBattles(sortedUnitsList, defendingUnits, false, false, data, t, TerritoryEffectHelper.getEffects(t), false, null), data);
sortedUnitsList.add(o2.getKey());
sortedUnitsList.sort(new UnitBattleComparator(false, ProData.unitValueMap, TerritoryEffectHelper.getEffects(t), data, false, false));
Collections.reverse(sortedUnitsList);
final int powerWith = DiceRoll.getTotalPower(DiceRoll.getUnitPowerAndRollsForNormalBattles(sortedUnitsList, defendingUnits, false, false, data, t, TerritoryEffectHelper.getEffects(t), false, null), data);
final int power = powerWith - powerWithout;
if (power < minPower2) {
minPower2 = power;
}
}
}
final UnitAttachment ua2 = UnitAttachment.get(o2.getKey().getType());
if (ua2.getIsAir()) {
minPower2 *= 10;
}
final double attackEfficiency2 = (double) minPower2 / ProData.unitValueMap.getInt(o2.getKey().getType());
if (attackEfficiency1 != attackEfficiency2) {
return (attackEfficiency1 < attackEfficiency2) ? 1 : -1;
}
// Check if unit types are equal and is air then sort by average distance
if (o1.getKey().getType().equals(o2.getKey().getType())) {
final boolean isAirUnit = UnitAttachment.get(o1.getKey().getType()).getIsAir();
if (isAirUnit) {
int distance1 = 0;
for (final Territory t : o1.getValue()) {
if (!attackMap.get(t).isCurrentlyWins()) {
distance1 += data.getMap().getDistance_IgnoreEndForCondition(unitTerritoryMap.get(o1.getKey()), t, ProMatches.territoryCanMoveAirUnitsAndNoAa(player, data, true));
}
}
int distance2 = 0;
for (final Territory t : o2.getValue()) {
if (!attackMap.get(t).isCurrentlyWins()) {
distance2 += data.getMap().getDistance_IgnoreEndForCondition(unitTerritoryMap.get(o2.getKey()), t, ProMatches.territoryCanMoveAirUnitsAndNoAa(player, data, true));
}
}
if (distance1 != distance2) {
return distance1 - distance2;
}
}
}
return o1.getKey().getType().getName().compareTo(o2.getKey().getType().getName());
});
final Map<Unit, Set<Territory>> sortedUnitAttackOptions = new LinkedHashMap<>();
for (final Map.Entry<Unit, Set<Territory>> entry : list) {
sortedUnitAttackOptions.put(entry.getKey(), entry.getValue());
}
return sortedUnitAttackOptions;
}
use of games.strategy.triplea.delegate.UnitBattleComparator in project triplea by triplea-game.
the class TripleAFrame method selectKamikazeSuicideAttacks.
public Map<Territory, IntegerMap<Unit>> selectKamikazeSuicideAttacks(final HashMap<Territory, Collection<Unit>> possibleUnitsToAttack, final Resource attackResourceToken, final int maxNumberOfAttacksAllowed) {
if (SwingUtilities.isEventDispatchThread()) {
throw new IllegalStateException("Should not be called from dispatch thread");
}
final Map<Territory, IntegerMap<Unit>> selection = new HashMap<>();
if (possibleUnitsToAttack == null || possibleUnitsToAttack.isEmpty() || attackResourceToken == null || maxNumberOfAttacksAllowed <= 0 || messageAndDialogThreadPool == null) {
return selection;
}
messageAndDialogThreadPool.waitForAll();
final CountDownLatch continueLatch = new CountDownLatch(1);
final Collection<IndividualUnitPanelGrouped> unitPanels = new ArrayList<>();
SwingUtilities.invokeLater(() -> {
final Map<String, Collection<Unit>> possibleUnitsToAttackStringForm = new HashMap<>();
for (final Entry<Territory, Collection<Unit>> entry : possibleUnitsToAttack.entrySet()) {
final List<Unit> units = new ArrayList<>(entry.getValue());
units.sort(new UnitBattleComparator(false, TuvUtils.getCostsForTuv(units.get(0).getOwner(), data), TerritoryEffectHelper.getEffects(entry.getKey()), data, true, false));
Collections.reverse(units);
possibleUnitsToAttackStringForm.put(entry.getKey().getName(), units);
}
mapPanel.centerOn(data.getMap().getTerritory(possibleUnitsToAttackStringForm.keySet().iterator().next()));
final IndividualUnitPanelGrouped unitPanel = new IndividualUnitPanelGrouped(possibleUnitsToAttackStringForm, uiContext, "Select Units to Suicide Attack using " + attackResourceToken.getName(), maxNumberOfAttacksAllowed, true, false);
unitPanels.add(unitPanel);
final String optionAttack = "Attack";
final String optionNone = "None";
final Object[] options = { optionAttack, optionNone };
final JOptionPane optionPane = new JOptionPane(unitPanel, JOptionPane.PLAIN_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[1]);
final JDialog dialog = new JDialog((Frame) getParent(), "Select units to Suicide Attack using " + attackResourceToken.getName());
dialog.setContentPane(optionPane);
dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
dialog.setLocationRelativeTo(getParent());
dialog.setAlwaysOnTop(true);
dialog.pack();
dialog.setVisible(true);
dialog.requestFocusInWindow();
optionPane.addPropertyChangeListener(e -> {
if (!dialog.isVisible()) {
return;
}
final String option = ((String) optionPane.getValue());
if (option.equals(optionNone)) {
unitPanels.clear();
selection.clear();
dialog.setVisible(false);
dialog.removeAll();
dialog.dispose();
continueLatch.countDown();
} else if (option.equals(optionAttack)) {
if (unitPanels.size() != 1) {
throw new IllegalStateException("unitPanels should only contain 1 entry");
}
for (final IndividualUnitPanelGrouped terrChooser : unitPanels) {
for (final Entry<String, IntegerMap<Unit>> entry : terrChooser.getSelected().entrySet()) {
selection.put(data.getMap().getTerritory(entry.getKey()), entry.getValue());
}
}
dialog.setVisible(false);
dialog.removeAll();
dialog.dispose();
continueLatch.countDown();
}
});
});
mapPanel.getUiContext().addShutdownLatch(continueLatch);
Interruptibles.await(continueLatch);
mapPanel.getUiContext().removeShutdownLatch(continueLatch);
return selection;
}
use of games.strategy.triplea.delegate.UnitBattleComparator in project triplea by triplea-game.
the class OddsCalculatorPanel method setWidgetActivation.
private void setWidgetActivation() {
keepOneAttackingLandUnitCheckBox.setEnabled(landBattleCheckBox.isSelected());
amphibiousCheckBox.setEnabled(landBattleCheckBox.isSelected());
final boolean isLand = isLand();
try {
data.acquireReadLock();
// do not include bombardment and aa guns in our "total" labels
final List<Unit> attackers = CollectionUtils.getMatches(attackingUnitsPanel.getUnits(), Matches.unitCanBeInBattle(true, isLand, 1, false, true, true));
final List<Unit> defenders = CollectionUtils.getMatches(defendingUnitsPanel.getUnits(), Matches.unitCanBeInBattle(false, isLand, 1, false, true, true));
attackerUnitsTotalNumber.setText("Units: " + attackers.size());
defenderUnitsTotalNumber.setText("Units: " + defenders.size());
attackerUnitsTotalTuv.setText("TUV: " + TuvUtils.getTuv(attackers, getAttacker(), TuvUtils.getCostsForTuv(getAttacker(), data), data));
defenderUnitsTotalTuv.setText("TUV: " + TuvUtils.getTuv(defenders, getDefender(), TuvUtils.getCostsForTuv(getDefender(), data), data));
final int attackHitPoints = BattleCalculator.getTotalHitpointsLeft(attackers);
final int defenseHitPoints = BattleCalculator.getTotalHitpointsLeft(defenders);
attackerUnitsTotalHitpoints.setText("HP: " + attackHitPoints);
defenderUnitsTotalHitpoints.setText("HP: " + defenseHitPoints);
final boolean isAmphibiousBattle = isAmphibiousBattle();
final Collection<TerritoryEffect> territoryEffects = getTerritoryEffects();
final IntegerMap<UnitType> costs = TuvUtils.getCostsForTuv(getAttacker(), data);
attackers.sort(new UnitBattleComparator(false, costs, territoryEffects, data, false, false));
Collections.reverse(attackers);
final int attackPower = DiceRoll.getTotalPower(DiceRoll.getUnitPowerAndRollsForNormalBattles(attackers, defenders, false, false, data, location, territoryEffects, isAmphibiousBattle, (isAmphibiousBattle ? attackers : new ArrayList<>())), data);
// defender is never amphibious
final int defensePower = DiceRoll.getTotalPower(DiceRoll.getUnitPowerAndRollsForNormalBattles(defenders, attackers, true, false, data, location, territoryEffects, isAmphibiousBattle, new ArrayList<>()), data);
attackerUnitsTotalPower.setText("Power: " + attackPower);
defenderUnitsTotalPower.setText("Power: " + defensePower);
} finally {
data.releaseReadLock();
}
}
Aggregations