package games.strategy.triplea.ai.proAI.data; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import games.strategy.engine.data.PlayerID; import games.strategy.engine.data.Territory; import games.strategy.engine.data.Unit; import games.strategy.triplea.ai.proAI.ProData; import games.strategy.triplea.ai.proAI.util.ProBattleUtils; import games.strategy.triplea.ai.proAI.util.ProUtils; import games.strategy.triplea.delegate.Matches; import games.strategy.util.Match; public class ProOtherMoveOptions { private final Map<Territory, ProTerritory> maxMoveMap; private final Map<Territory, List<ProTerritory>> moveMaps; public ProOtherMoveOptions() { maxMoveMap = new HashMap<>(); moveMaps = new HashMap<>(); } public ProOtherMoveOptions(final List<Map<Territory, ProTerritory>> moveMapList, final PlayerID player, final boolean isAttacker) { maxMoveMap = createMaxMoveMap(moveMapList, player, isAttacker); moveMaps = createMoveMaps(moveMapList); } public ProTerritory getMax(final Territory t) { return maxMoveMap.get(t); } public List<ProTerritory> getAll(final Territory t) { final List<ProTerritory> result = moveMaps.get(t); if (result != null) { return result; } return new ArrayList<>(); } @Override public String toString() { return maxMoveMap.toString(); } private static Map<Territory, ProTerritory> createMaxMoveMap(final List<Map<Territory, ProTerritory>> moveMaps, final PlayerID player, final boolean isAttacker) { final Map<Territory, ProTerritory> result = new HashMap<>(); final List<PlayerID> players = ProUtils.getOtherPlayersInTurnOrder(player); for (final Map<Territory, ProTerritory> moveMap : moveMaps) { for (final Territory t : moveMap.keySet()) { // Get current player PlayerID movePlayer = null; final Set<Unit> currentUnits = new HashSet<>(moveMap.get(t).getMaxUnits()); currentUnits.addAll(moveMap.get(t).getMaxAmphibUnits()); if (!currentUnits.isEmpty()) { movePlayer = currentUnits.iterator().next().getOwner(); } else { continue; } // Skip if checking allied moves and their turn doesn't come before territory owner's if (ProData.getData().getRelationshipTracker().isAllied(player, movePlayer) && !ProUtils.isPlayersTurnFirst(players, movePlayer, t.getOwner())) { continue; } // Add to max move map if its empty or its strength is greater than existing if (!result.containsKey(t)) { result.put(t, moveMap.get(t)); } else { final Set<Unit> maxUnits = new HashSet<>(result.get(t).getMaxUnits()); maxUnits.addAll(result.get(t).getMaxAmphibUnits()); double maxStrength = 0; if (!maxUnits.isEmpty()) { maxStrength = ProBattleUtils.estimateStrength(t, new ArrayList<>(maxUnits), new ArrayList<>(), isAttacker); } final double currentStrength = ProBattleUtils.estimateStrength(t, new ArrayList<>(currentUnits), new ArrayList<>(), isAttacker); final boolean currentHasLandUnits = Match.someMatch(currentUnits, Matches.UnitIsLand); final boolean maxHasLandUnits = Match.someMatch(maxUnits, Matches.UnitIsLand); if ((currentHasLandUnits && ((!maxHasLandUnits && !t.isWater()) || currentStrength > maxStrength)) || ((!maxHasLandUnits || t.isWater()) && currentStrength > maxStrength)) { result.put(t, moveMap.get(t)); } } } } return result; } private static Map<Territory, List<ProTerritory>> createMoveMaps( final List<Map<Territory, ProTerritory>> moveMapList) { final Map<Territory, List<ProTerritory>> result = new HashMap<>(); for (final Map<Territory, ProTerritory> moveMap : moveMapList) { for (final Territory t : moveMap.keySet()) { if (!result.containsKey(t)) { final List<ProTerritory> list = new ArrayList<>(); list.add(moveMap.get(t)); result.put(t, list); } else { result.get(t).add(moveMap.get(t)); } } } return result; } }