use of games.strategy.engine.data.PlayerID in project triplea by triplea-game.
the class ProAi method selectCasualties.
@Override
public CasualtyDetails selectCasualties(final Collection<Unit> selectFrom, final Map<Unit, Collection<Unit>> dependents, final int count, final String message, final DiceRoll dice, final PlayerID hit, final Collection<Unit> friendlyUnits, final PlayerID enemyPlayer, final Collection<Unit> enemyUnits, final boolean amphibious, final Collection<Unit> amphibiousLandAttackers, final CasualtyList defaultCasualties, final GUID battleId, final Territory battlesite, final boolean allowMultipleHitsPerUnit) {
initializeData();
if (defaultCasualties.size() != count) {
throw new IllegalStateException("Select Casualties showing different numbers for number of hits to take vs total " + "size of default casualty selections");
}
if (defaultCasualties.getKilled().size() <= 0) {
return new CasualtyDetails(defaultCasualties, false);
}
// Consider unit cost
final CasualtyDetails myCasualties = new CasualtyDetails(false);
myCasualties.addToDamaged(defaultCasualties.getDamaged());
final List<Unit> selectFromSorted = new ArrayList<>(selectFrom);
if (enemyUnits.isEmpty()) {
selectFromSorted.sort(ProPurchaseUtils.getCostComparator());
} else {
// Get battle data
final GameData data = getGameData();
final PlayerID player = getPlayerId();
final BattleDelegate delegate = DelegateFinder.battleDelegate(data);
final IBattle battle = delegate.getBattleTracker().getPendingBattle(battleId);
// If defender and could lose battle then don't consider unit cost as just trying to survive
boolean needToCheck = true;
final boolean isAttacker = player.equals(battle.getAttacker());
if (!isAttacker) {
final List<Unit> attackers = (List<Unit>) battle.getAttackingUnits();
final List<Unit> defenders = (List<Unit>) battle.getDefendingUnits();
defenders.removeAll(defaultCasualties.getKilled());
final double strengthDifference = ProBattleUtils.estimateStrengthDifference(battlesite, attackers, defenders);
int minStrengthDifference = 60;
if (!Properties.getLowLuck(data)) {
minStrengthDifference = 55;
}
if (strengthDifference > minStrengthDifference) {
needToCheck = false;
}
}
// Use bubble sort to save expensive units
while (needToCheck) {
needToCheck = false;
for (int i = 0; i < selectFromSorted.size() - 1; i++) {
final Unit unit1 = selectFromSorted.get(i);
final Unit unit2 = selectFromSorted.get(i + 1);
final double unitCost1 = ProPurchaseUtils.getCost(unit1);
final double unitCost2 = ProPurchaseUtils.getCost(unit2);
if (unitCost1 > 1.5 * unitCost2) {
selectFromSorted.set(i, unit2);
selectFromSorted.set(i + 1, unit1);
needToCheck = true;
}
}
}
}
// Interleave carriers and planes
final List<Unit> interleavedTargetList = new ArrayList<>(ProTransportUtils.interleaveUnitsCarriersAndPlanes(selectFromSorted, 0));
for (int i = 0; i < defaultCasualties.getKilled().size(); ++i) {
myCasualties.addToKilled(interleavedTargetList.get(i));
}
if (count != myCasualties.size()) {
throw new IllegalStateException("AI chose wrong number of casualties");
}
return myCasualties;
}
use of games.strategy.engine.data.PlayerID in project triplea by triplea-game.
the class ProAi method selectAttackSubs.
@Override
public boolean selectAttackSubs(final Territory unitTerritory) {
initializeData();
// Get battle data
final GameData data = getGameData();
final PlayerID player = getPlayerId();
final BattleDelegate delegate = DelegateFinder.battleDelegate(data);
final IBattle battle = delegate.getBattleTracker().getPendingBattle(unitTerritory, false, BattleType.NORMAL);
// If battle is null then don't attack
if (battle == null) {
return false;
}
final List<Unit> attackers = (List<Unit>) battle.getAttackingUnits();
final List<Unit> defenders = (List<Unit>) battle.getDefendingUnits();
ProLogger.info(player.getName() + " checking sub attack in " + unitTerritory + ", attackers=" + attackers + ", defenders=" + defenders);
calc.setData(getGameData());
// Calculate battle results
final ProBattleResult result = calc.calculateBattleResults(unitTerritory, attackers, defenders, new HashSet<>());
ProLogger.debug(player.getName() + " sub attack TUVSwing=" + result.getTuvSwing());
return result.getTuvSwing() > 0;
}
use of games.strategy.engine.data.PlayerID in project triplea by triplea-game.
the class ProMoveUtils method calculateMoveRoutes.
public static void calculateMoveRoutes(final PlayerID player, final List<Collection<Unit>> moveUnits, final List<Route> moveRoutes, final Map<Territory, ProTerritory> attackMap, final boolean isCombatMove) {
final GameData data = ProData.getData();
// Find all amphib units
final Set<Unit> amphibUnits = attackMap.values().stream().map(ProTerritory::getAmphibAttackMap).map(Map::entrySet).flatMap(Collection::stream).flatMap(e -> Stream.concat(Stream.of(e.getKey()), e.getValue().stream())).collect(Collectors.toSet());
// Loop through all territories to attack
for (final Territory t : attackMap.keySet()) {
// Loop through each unit that is attacking the current territory
for (final Unit u : attackMap.get(t).getUnits()) {
// Skip amphib units
if (amphibUnits.contains(u)) {
continue;
}
// Skip if unit is already in move to territory
final Territory startTerritory = ProData.unitTerritoryMap.get(u);
if (startTerritory == null || startTerritory.equals(t)) {
continue;
}
// Add unit to move list
final List<Unit> unitList = new ArrayList<>();
unitList.add(u);
moveUnits.add(unitList);
// If carrier has dependent allied fighters then move them too
if (Matches.unitIsCarrier().test(u)) {
final Map<Unit, Collection<Unit>> carrierMustMoveWith = MoveValidator.carrierMustMoveWith(startTerritory.getUnits().getUnits(), startTerritory, data, player);
if (carrierMustMoveWith.containsKey(u)) {
unitList.addAll(carrierMustMoveWith.get(u));
}
}
// Determine route and add to move list
Route route = null;
if (unitList.stream().anyMatch(Matches.unitIsSea())) {
// Sea unit (including carriers with planes)
route = data.getMap().getRoute_IgnoreEnd(startTerritory, t, ProMatches.territoryCanMoveSeaUnitsThrough(player, data, isCombatMove));
} else if (!unitList.isEmpty() && unitList.stream().allMatch(Matches.unitIsLand())) {
// Land unit
route = data.getMap().getRoute_IgnoreEnd(startTerritory, t, ProMatches.territoryCanMoveLandUnitsThrough(player, data, u, startTerritory, isCombatMove, new ArrayList<>()));
} else if (!unitList.isEmpty() && unitList.stream().allMatch(Matches.unitIsAir())) {
// Air unit
route = data.getMap().getRoute_IgnoreEnd(startTerritory, t, ProMatches.territoryCanMoveAirUnitsAndNoAa(player, data, isCombatMove));
}
if (route == null) {
ProLogger.warn(data.getSequence().getRound() + "-" + data.getSequence().getStep().getName() + ": route is null " + startTerritory + " to " + t + ", units=" + unitList);
}
moveRoutes.add(route);
}
}
}
use of games.strategy.engine.data.PlayerID in project triplea by triplea-game.
the class ProOddsCalculator method callBattleCalculator.
public ProBattleResult callBattleCalculator(final Territory t, final List<Unit> attackingUnits, final List<Unit> defendingUnits, final Set<Unit> bombardingUnits, final boolean retreatWhenOnlyAirLeft) {
final GameData data = ProData.getData();
if (isCanceled || attackingUnits.isEmpty() || defendingUnits.isEmpty()) {
return new ProBattleResult();
}
final int minArmySize = Math.min(attackingUnits.size(), defendingUnits.size());
final int runCount = Math.max(16, 100 - minArmySize);
final PlayerID attacker = attackingUnits.get(0).getOwner();
final PlayerID defender = defendingUnits.get(0).getOwner();
if (retreatWhenOnlyAirLeft) {
calc.setRetreatWhenOnlyAirLeft(true);
}
final AggregateResults results = calc.setCalculateDataAndCalculate(attacker, defender, t, attackingUnits, defendingUnits, new ArrayList<>(bombardingUnits), TerritoryEffectHelper.getEffects(t), runCount);
if (retreatWhenOnlyAirLeft) {
calc.setRetreatWhenOnlyAirLeft(false);
}
// Find battle result statistics
final double winPercentage = results.getAttackerWinPercent() * 100;
final List<Unit> averageAttackersRemaining = results.getAverageAttackingUnitsRemaining();
final List<Unit> averageDefendersRemaining = results.getAverageDefendingUnitsRemaining();
final List<Unit> mainCombatAttackers = CollectionUtils.getMatches(attackingUnits, Matches.unitCanBeInBattle(true, !t.isWater(), 1, false, true, true));
final List<Unit> mainCombatDefenders = CollectionUtils.getMatches(defendingUnits, Matches.unitCanBeInBattle(false, !t.isWater(), 1, false, true, true));
double tuvSwing = results.getAverageTuvSwing(attacker, mainCombatAttackers, defender, mainCombatDefenders, data);
if (Matches.territoryIsNeutralButNotWater().test(t)) {
// Set TUV swing for neutrals
final double attackingUnitValue = TuvUtils.getTuv(mainCombatAttackers, ProData.unitValueMap);
final double remainingUnitValue = results.getAverageTuvOfUnitsLeftOver(ProData.unitValueMap, ProData.unitValueMap).getFirst();
tuvSwing = remainingUnitValue - attackingUnitValue;
}
final List<Unit> defendingTransportedUnits = CollectionUtils.getMatches(defendingUnits, Matches.unitIsBeingTransported());
if (t.isWater() && !defendingTransportedUnits.isEmpty()) {
// Add TUV swing for transported units
final double transportedUnitValue = TuvUtils.getTuv(defendingTransportedUnits, ProData.unitValueMap);
tuvSwing += transportedUnitValue * winPercentage / 100;
}
// Create battle result object
final List<Territory> territoryList = new ArrayList<>();
territoryList.add(t);
return (!territoryList.isEmpty() && territoryList.stream().allMatch(Matches.territoryIsLand())) ? new ProBattleResult(winPercentage, tuvSwing, averageAttackersRemaining.stream().anyMatch(Matches.unitIsLand()), averageAttackersRemaining, averageDefendersRemaining, results.getAverageBattleRoundsFought()) : new ProBattleResult(winPercentage, tuvSwing, !averageAttackersRemaining.isEmpty(), averageAttackersRemaining, averageDefendersRemaining, results.getAverageBattleRoundsFought());
}
use of games.strategy.engine.data.PlayerID in project triplea by triplea-game.
the class TripleAPlayer method battle.
private void battle() {
if (getPlayerBridge().isGameOver()) {
return;
}
final IBattleDelegate battleDel;
try {
battleDel = (IBattleDelegate) getPlayerBridge().getRemoteDelegate();
} catch (final ClassCastException e) {
final String errorContext = "PlayerBridge step name: " + getPlayerBridge().getStepName() + ", Remote class name: " + getPlayerBridge().getRemoteDelegate().getClass();
// TODO: this code is triplicated in the code..
ClientLogger.logQuietly(errorContext, e);
throw new IllegalStateException(errorContext, e);
}
final PlayerID id = getPlayerId();
while (true) {
if (getPlayerBridge().isGameOver()) {
return;
}
final BattleListing battles = battleDel.getBattles();
if (battles.isEmpty()) {
final IBattle battle = battleDel.getCurrentBattle();
if (battle != null) {
// this should never happen, but it happened once....
System.err.println("Current battle exists but is not on pending list: " + battle.toString());
battleDel.fightCurrentBattle();
}
return;
}
if (!soundPlayedAlreadyBattle) {
ClipPlayer.play(SoundPath.CLIP_PHASE_BATTLE, id);
soundPlayedAlreadyBattle = true;
}
final FightBattleDetails details = ui.getBattle(id, battles.getBattles());
if (getPlayerBridge().isGameOver()) {
return;
}
if (details != null) {
final String error = battleDel.fightBattle(details.getWhere(), details.isBombingRaid(), details.getBattleType());
if (error != null) {
ui.notifyError(error);
}
}
}
}
Aggregations