Skip to content

Commit

Permalink
Merge pull request #282 from triplea-game/AI_Consider_Enemy_Turn_Order
Browse files Browse the repository at this point in the history
AI consider enemy turn order
  • Loading branch information
ron-murhammer committed Nov 24, 2015
2 parents d62d12b + cc7b22d commit bd8cc09
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 44 deletions.
6 changes: 3 additions & 3 deletions src/games/strategy/triplea/ai/proAI/ProCombatMoveAI.java
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public Map<Territory, ProAttackTerritoryData> doCombatMove(final IMoveDelegate m
for (final ProAttackTerritoryData patd : prioritizedTerritories) {
territoriesToAttack.add(patd.getTerritory());
}
attackOptionsUtils.findMaxEnemyAttackUnits(player, territoriesToAttack, new ArrayList<Territory>(), enemyAttackMap);
attackOptionsUtils.findEnemyAttackOptions(player, territoriesToAttack, new ArrayList<Territory>(), enemyAttackMap);
Map<Territory, Double> territoryValueMap =
territoryValueUtils.findTerritoryValues(player, minCostPerHitPoint, new ArrayList<Territory>(),
territoriesToAttack);
Expand All @@ -153,7 +153,7 @@ public Map<Territory, ProAttackTerritoryData> doCombatMove(final IMoveDelegate m
possibleTransportTerritories.addAll(data.getMap().getNeighbors(patd.getTerritory(), Matches.TerritoryIsWater));
}
}
attackOptionsUtils.findMaxEnemyAttackUnits(player, territoriesToAttack, new ArrayList<Territory>(
attackOptionsUtils.findEnemyAttackOptions(player, territoriesToAttack, new ArrayList<Territory>(
possibleTransportTerritories), enemyAttackMap);
territoryValueMap =
territoryValueUtils.findTerritoryValues(player, minCostPerHitPoint, new ArrayList<Territory>(),
Expand Down Expand Up @@ -1488,7 +1488,7 @@ private void determineIfCapitalCanBeHeld(final Map<Territory, ProAttackTerritory
final List<Territory> territoriesToCheck = new ArrayList<Territory>();
territoriesToCheck.add(myCapital);
final Map<Territory, ProAttackTerritoryData> enemyAttackMap = new HashMap<Territory, ProAttackTerritoryData>();
attackOptionsUtils.findMaxEnemyAttackUnits(player, territoriesToAttack, territoriesToCheck, enemyAttackMap);
attackOptionsUtils.findEnemyAttackOptions(player, territoriesToAttack, territoriesToCheck, enemyAttackMap);
if (enemyAttackMap.get(myCapital) == null) {
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ public Map<Territory, ProAttackTerritoryData> doNonCombatMove(Map<Territory, Pro
moveOneDefenderToLandTerritoriesBorderingEnemy(moveMap, unitMoveMap);

// Determine max enemy attack units and if territories can be held
attackOptionsUtils.findMaxEnemyAttackUnits(player, movedOneDefenderToTerritories,
attackOptionsUtils.findEnemyAttackOptions(player, movedOneDefenderToTerritories,
new ArrayList<Territory>(moveMap.keySet()), enemyAttackMap);
determineIfMoveTerritoriesCanBeHeld(moveMap, enemyAttackMap);

Expand Down
10 changes: 5 additions & 5 deletions src/games/strategy/triplea/ai/proAI/ProPurchaseAI.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ public class ProPurchaseAI {
private double minCostPerHitPoint;
private ProResourceTracker resourceTracker;

public ProPurchaseAI(final ProUtils utils, final ProBattleUtils battleUtils,
final ProTransportUtils transportUtils, final ProAttackOptionsUtils attackOptionsUtils,
final ProTerritoryValueUtils territoryValueUtils, final ProPurchaseUtils purchaseUtils) {
public ProPurchaseAI(final ProUtils utils, final ProBattleUtils battleUtils, final ProTransportUtils transportUtils,
final ProAttackOptionsUtils attackOptionsUtils, final ProTerritoryValueUtils territoryValueUtils,
final ProPurchaseUtils purchaseUtils) {
this.utils = utils;
this.battleUtils = battleUtils;
this.transportUtils = transportUtils;
Expand Down Expand Up @@ -495,7 +495,7 @@ public Map<Territory, ProPurchaseTerritory> purchase(final IPurchaseDelegate pur

// Determine max enemy attack units and current allied defenders
final Map<Territory, ProAttackTerritoryData> enemyAttackMap = new HashMap<Territory, ProAttackTerritoryData>();
attackOptionsUtils.findMaxEnemyAttackUnits(player, new ArrayList<Territory>(), new ArrayList<Territory>(
attackOptionsUtils.findEnemyAttackOptions(player, new ArrayList<Territory>(), new ArrayList<Territory>(
placeTerritories), enemyAttackMap);
findDefendersInPlaceTerritories(purchaseTerritories);

Expand Down Expand Up @@ -878,7 +878,7 @@ public void place(final Map<Territory, ProPurchaseTerritory> purchaseTerritories

// Determine max enemy attack units and current allied defenders
final Map<Territory, ProAttackTerritoryData> enemyAttackMap = new HashMap<Territory, ProAttackTerritoryData>();
attackOptionsUtils.findMaxEnemyAttackUnits(player, new ArrayList<Territory>(), new ArrayList<Territory>(
attackOptionsUtils.findEnemyAttackOptions(player, new ArrayList<Territory>(), new ArrayList<Territory>(
placeNonConstructionTerritories.keySet()), enemyAttackMap);
findDefendersInPlaceTerritories(placeNonConstructionTerritories);

Expand Down
63 changes: 43 additions & 20 deletions src/games/strategy/triplea/ai/proAI/util/ProAttackOptionsUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,18 @@ public void findAttackOptions(final PlayerID player, final List<Territory> myUni
final Map<Territory, Set<Territory>> landRoutesMap, final List<ProAmphibData> transportMapList,
final List<Territory> enemyTerritories, final List<Territory> territoriesToCheck,
final boolean isCheckingEnemyAttacks, final boolean isIgnoringRelationships) {
findAttackOptions(player, myUnitTerritories, moveMap, unitMoveMap, transportMoveMap, bombardMap, landRoutesMap,
transportMapList, enemyTerritories, new ArrayList<Territory>(), territoriesToCheck, isCheckingEnemyAttacks,
isIgnoringRelationships);
}

public void findAttackOptions(final PlayerID player, final List<Territory> myUnitTerritories,
final Map<Territory, ProAttackTerritoryData> moveMap, final Map<Unit, Set<Territory>> unitMoveMap,
final Map<Unit, Set<Territory>> transportMoveMap, final Map<Unit, Set<Territory>> bombardMap,
final Map<Territory, Set<Territory>> landRoutesMap, final List<ProAmphibData> transportMapList,
final List<Territory> enemyTerritories, List<Territory> alliedTerritories,
final List<Territory> territoriesToCheck, final boolean isCheckingEnemyAttacks,
final boolean isIgnoringRelationships) {
final GameData data = ai.getGameData();

final List<Territory> territoriesThatCantBeHeld = new ArrayList<Territory>(enemyTerritories);
Expand All @@ -404,11 +416,11 @@ public void findAttackOptions(final PlayerID player, final List<Territory> myUni
ProMatches.territoryIsEnemyOrHasEnemyUnitsOrCantBeHeld(player, data, territoriesThatCantBeHeld),
enemyTerritories, true, isCheckingEnemyAttacks);
findLandMoveOptions(player, myUnitTerritories, moveMap, unitMoveMap, landRoutesMap,
ProMatches.territoryIsEnemyOrCantBeHeld(player, data, territoriesThatCantBeHeld), enemyTerritories, true,
isCheckingEnemyAttacks, isIgnoringRelationships);
ProMatches.territoryIsEnemyOrCantBeHeld(player, data, territoriesThatCantBeHeld), enemyTerritories,
alliedTerritories, true, isCheckingEnemyAttacks, isIgnoringRelationships);
findAirMoveOptions(player, myUnitTerritories, moveMap, unitMoveMap,
ProMatches.territoryHasEnemyUnitsOrCantBeHeld(player, data, territoriesThatCantBeHeld), enemyTerritories, true,
isCheckingEnemyAttacks, isIgnoringRelationships);
ProMatches.territoryHasEnemyUnitsOrCantBeHeld(player, data, territoriesThatCantBeHeld), enemyTerritories,
alliedTerritories, true, isCheckingEnemyAttacks, isIgnoringRelationships);
findAmphibMoveOptions(player, myUnitTerritories, moveMap, transportMapList, landRoutesMap,
ProMatches.territoryIsEnemyOrCantBeHeld(player, data, territoriesThatCantBeHeld), enemyTerritories, true,
isCheckingEnemyAttacks, isIgnoringRelationships);
Expand All @@ -426,10 +438,11 @@ public void findPotentialAttackOptions(final PlayerID player, final List<Territo
ProMatches.territoryIsPotentialEnemyOrHasPotentialEnemyUnits(player, data, otherPlayers),
new ArrayList<Territory>(), true, false);
findLandMoveOptions(player, myUnitTerritories, moveMap, unitMoveMap, landRoutesMap,
ProMatches.territoryIsPotentialEnemy(player, data, otherPlayers), new ArrayList<Territory>(), true, false, true);
ProMatches.territoryIsPotentialEnemy(player, data, otherPlayers), new ArrayList<Territory>(),
new ArrayList<Territory>(), true, false, true);
findAirMoveOptions(player, myUnitTerritories, moveMap, unitMoveMap,
ProMatches.territoryHasPotentialEnemyUnits(player, data, otherPlayers), new ArrayList<Territory>(), true,
false, true);
ProMatches.territoryHasPotentialEnemyUnits(player, data, otherPlayers), new ArrayList<Territory>(),
new ArrayList<Territory>(), true, false, true);
findAmphibMoveOptions(player, myUnitTerritories, moveMap, transportMapList, landRoutesMap,
ProMatches.territoryIsPotentialEnemy(player, data, otherPlayers), new ArrayList<Territory>(), true, false, true);
findBombardOptions(player, myUnitTerritories, moveMap, bombardMap, transportMapList, false);
Expand All @@ -445,23 +458,29 @@ public void findDefendOptions(final PlayerID player, final List<Territory> myUni
ProMatches.territoryHasNoEnemyUnitsOrCleared(player, data, clearedTerritories), clearedTerritories, false,
false);
findLandMoveOptions(player, myUnitTerritories, moveMap, unitMoveMap, landRoutesMap,
Matches.isTerritoryAllied(player, data), new ArrayList<Territory>(), false, false, false);
Matches.isTerritoryAllied(player, data), new ArrayList<Territory>(), new ArrayList<Territory>(), false, false,
false);
findAirMoveOptions(player, myUnitTerritories, moveMap, unitMoveMap,
ProMatches.territoryIsNotConqueredAlliedLand(player, data), new ArrayList<Territory>(), false, false, false);
ProMatches.territoryIsNotConqueredAlliedLand(player, data), new ArrayList<Territory>(),
new ArrayList<Territory>(), false, false, false);
findAmphibMoveOptions(player, myUnitTerritories, moveMap, transportMapList, landRoutesMap,
Matches.isTerritoryAllied(player, data), new ArrayList<Territory>(), false, false, false);
}

public void findMaxEnemyAttackUnits(final PlayerID player, final List<Territory> myConqueredTerritories,
public void findEnemyAttackOptions(final PlayerID player, final List<Territory> myConqueredTerritories,
final List<Territory> territoriesToCheck, final Map<Territory, ProAttackTerritoryData> enemyAttackMap) {
final GameData data = ai.getGameData();

// Loop through each enemy to determine the maximum number of enemy units that can attack each territory
// Get enemy players in order of turn
final List<PlayerID> enemyPlayers = utils.getEnemyPlayersInTurnOrder(player);
final List<Map<Territory, ProAttackTerritoryData>> enemyAttackMaps =
new ArrayList<Map<Territory, ProAttackTerritoryData>>();
final List<List<ProAmphibData>> enemyTransportMapLists = new ArrayList<List<ProAmphibData>>();
final List<PlayerID> enemyPlayers = utils.getEnemyPlayers(player);
final List<Territory> allTerritories = data.getMap().getTerritories();
Set<Territory> alliedTerritories = new HashSet<Territory>();
List<Territory> enemyTerritories = new ArrayList<Territory>(myConqueredTerritories);

// Loop through each enemy to determine the maximum number of enemy units that can attack each territory
for (final PlayerID enemyPlayer : enemyPlayers) {
final List<Territory> enemyUnitTerritories =
Match.getMatches(allTerritories, Matches.territoryHasUnitsOwnedBy(enemyPlayer));
Expand All @@ -475,7 +494,10 @@ public void findMaxEnemyAttackUnits(final PlayerID player, final List<Territory>
enemyAttackMaps.add(attackMap2);
enemyTransportMapLists.add(transportMapList2);
findAttackOptions(enemyPlayer, enemyUnitTerritories, attackMap2, unitAttackMap2, transportAttackMap2,
bombardMap2, landRoutesMap2, transportMapList2, myConqueredTerritories, territoriesToCheck, true, true);
bombardMap2, landRoutesMap2, transportMapList2, enemyTerritories,
new ArrayList<Territory>(alliedTerritories), territoriesToCheck, true, true);
alliedTerritories.addAll(Match.getMatches(attackMap2.keySet(), Matches.TerritoryIsLand));
enemyTerritories.removeAll(alliedTerritories);
}

// Consolidate enemy player attack maps into one attack map with max units a single enemy can attack with
Expand Down Expand Up @@ -633,8 +655,8 @@ private void findNavalMoveOptions(final PlayerID player, final List<Territory> m
private void findLandMoveOptions(final PlayerID player, final List<Territory> myUnitTerritories,
final Map<Territory, ProAttackTerritoryData> moveMap, final Map<Unit, Set<Territory>> unitMoveMap,
final Map<Territory, Set<Territory>> landRoutesMap, final Match<Territory> moveToTerritoryMatch,
final List<Territory> enemyTerritories, final boolean isCombatMove, final boolean isCheckingEnemyAttacks,
final boolean isIgnoringRelationships) {
final List<Territory> enemyTerritories, final List<Territory> alliedTerritories, final boolean isCombatMove,
final boolean isCheckingEnemyAttacks, final boolean isIgnoringRelationships) {
final GameData data = ai.getGameData();

final Map<Unit, Territory> unitTerritoryMap = utils.createUnitTerritoryMap(player);
Expand Down Expand Up @@ -677,7 +699,7 @@ private void findLandMoveOptions(final PlayerID player, final List<Territory> my
myUnitTerritory,
potentialTerritory,
ProMatches.territoryCanMoveLandUnitsThroughIgnoreEnemyUnits(player, data, myLandUnit,
startTerritory, isCombatMove, enemyTerritories));
startTerritory, isCombatMove, enemyTerritories, alliedTerritories));
}
if (myRoute == null) {
continue;
Expand Down Expand Up @@ -726,8 +748,9 @@ private void findLandMoveOptions(final PlayerID player, final List<Territory> my

private void findAirMoveOptions(final PlayerID player, final List<Territory> myUnitTerritories,
final Map<Territory, ProAttackTerritoryData> moveMap, final Map<Unit, Set<Territory>> unitMoveMap,
final Match<Territory> moveToTerritoryMatch, final List<Territory> enemyTerritories, final boolean isCombatMove,
final boolean isCheckingEnemyAttacks, final boolean isIgnoringRelationships) {
final Match<Territory> moveToTerritoryMatch, final List<Territory> enemyTerritories,
List<Territory> alliedTerritories, final boolean isCombatMove, final boolean isCheckingEnemyAttacks,
final boolean isIgnoringRelationships) {
final GameData data = ai.getGameData();

// TODO: add carriers to landing possibilities for non-enemy attacks
Expand Down Expand Up @@ -808,8 +831,8 @@ private void findAirMoveOptions(final PlayerID player, final List<Territory> myU
final Set<Territory> possibleLandingTerritories =
data.getMap().getNeighbors(potentialTerritory, remainingMoves, canFlyOverMatch);
final List<Territory> landingTerritories =
Match.getMatches(possibleLandingTerritories,
ProMatches.territoryCanLandAirUnits(player, data, isCombatMove, enemyTerritories));
Match.getMatches(possibleLandingTerritories, ProMatches.territoryCanLandAirUnits(player, data,
isCombatMove, enemyTerritories, alliedTerritories));
List<Territory> carrierTerritories = new ArrayList<Territory>();
if (Matches.UnitCanLandOnCarrier.match(myAirUnit)) {
carrierTerritories =
Expand Down
31 changes: 16 additions & 15 deletions src/games/strategy/triplea/ai/proAI/util/ProMatches.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@
public class ProMatches {

public static Match<Territory> territoryCanLandAirUnits(final PlayerID player, final GameData data,
final boolean isCombatMove, final List<Territory> enemyTerritories) {
final boolean isCombatMove, final List<Territory> enemyTerritories, final List<Territory> alliedTerritories) {
return new Match<Territory>() {
@Override
public boolean match(final Territory t) {
final Match<Territory> match =
new CompositeMatchAnd<Territory>(Matches.airCanLandOnThisAlliedNonConqueredLandTerritory(player, data),
Matches.TerritoryIsPassableAndNotRestrictedAndOkByRelationships(player, data, isCombatMove, false,
false, true, true), Matches.territoryIsInList(enemyTerritories).invert());
new CompositeMatchOr<Territory>(Matches.territoryIsInList(alliedTerritories),
new CompositeMatchAnd<Territory>(Matches.airCanLandOnThisAlliedNonConqueredLandTerritory(player, data),
Matches.TerritoryIsPassableAndNotRestrictedAndOkByRelationships(player, data, isCombatMove, false,
false, true, true), Matches.territoryIsInList(enemyTerritories).invert()));
return match.match(t);
}
};
Expand Down Expand Up @@ -185,22 +186,22 @@ public boolean match(final Territory t) {

public static Match<Territory> territoryCanMoveLandUnitsThroughIgnoreEnemyUnits(final PlayerID player,
final GameData data, final Unit u, final Territory startTerritory, final boolean isCombatMove,
final List<Territory> enemyTerritories) {
final List<Territory> enemyTerritories, final List<Territory> alliedTerritories) {
return new Match<Territory>() {
@Override
public boolean match(final Territory t) {
Match<Territory> match =
new CompositeMatchAnd<Territory>(
ProMatches.territoryCanMoveSpecificLandUnit(player, data, isCombatMove, u), Matches.isTerritoryAllied(
player, data), Matches.territoryIsInList(enemyTerritories).invert());
Match<Territory> alliedMatch =
new CompositeMatchOr<Territory>(Matches.isTerritoryAllied(player, data),
Matches.territoryIsInList(alliedTerritories));
if (isCombatMove && Matches.UnitCanBlitz.match(u) && TerritoryEffectHelper.unitKeepsBlitz(u, startTerritory)) {
final Match<Territory> alliedOrBlitzableMatch =
new CompositeMatchOr<Territory>(Matches.isTerritoryAllied(player, data), territoryIsBlitzable(player,
data, u));
match =
new CompositeMatchAnd<Territory>(ProMatches.territoryCanMoveSpecificLandUnit(player, data, isCombatMove,
u), alliedOrBlitzableMatch, Matches.territoryIsInList(enemyTerritories).invert());
alliedMatch =
new CompositeMatchOr<Territory>(Matches.isTerritoryAllied(player, data),
Matches.territoryIsInList(alliedTerritories), territoryIsBlitzable(player, data, u));
}
Match<Territory> match =
new CompositeMatchAnd<Territory>(
ProMatches.territoryCanMoveSpecificLandUnit(player, data, isCombatMove, u), alliedMatch, Matches
.territoryIsInList(enemyTerritories).invert());
return match.match(t);
}
};
Expand Down
21 changes: 21 additions & 0 deletions src/games/strategy/triplea/ai/proAI/util/ProUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.Set;

import games.strategy.engine.data.GameData;
import games.strategy.engine.data.GameSequence;
import games.strategy.engine.data.GameStep;
import games.strategy.engine.data.PlayerID;
import games.strategy.engine.data.RelationshipTracker;
Expand Down Expand Up @@ -46,6 +47,26 @@ public Map<Unit, Territory> createUnitTerritoryMap(final PlayerID player) {
return unitTerritoryMap;
}

public List<PlayerID> getEnemyPlayersInTurnOrder(final PlayerID player) {
final GameData data = ai.getGameData();
final List<PlayerID> enemyPlayers = new ArrayList<PlayerID>();
GameSequence sequence = data.getSequence();
int startIndex = sequence.getStepIndex();
for (int i = 0; i < sequence.size(); i++) {
int currentIndex = startIndex + i;
if (currentIndex >= sequence.size()) {
currentIndex -= sequence.size();
}
GameStep step = sequence.getStep(currentIndex);
PlayerID stepPlayer = step.getPlayerID();
if (step.getName().endsWith("CombatMove") && stepPlayer != null && !enemyPlayers.contains(stepPlayer)
&& !data.getRelationshipTracker().isAllied(player, stepPlayer)) {
enemyPlayers.add(step.getPlayerID());
}
}
return enemyPlayers;
}

public List<PlayerID> getEnemyPlayers(final PlayerID player) {
final GameData data = ai.getGameData();
final List<PlayerID> enemyPlayers = new ArrayList<PlayerID>();
Expand Down

0 comments on commit bd8cc09

Please sign in to comment.