package games.strategy.triplea.ai.weakAI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import games.strategy.engine.data.GameData;
import games.strategy.engine.data.PlayerID;
import games.strategy.engine.data.Route;
import games.strategy.engine.data.Territory;
import games.strategy.engine.data.Unit;
import games.strategy.triplea.ai.AIUtils;
import games.strategy.triplea.attachments.TerritoryAttachment;
import games.strategy.triplea.delegate.Matches;
import games.strategy.util.CompositeMatch;
import games.strategy.util.CompositeMatchAnd;
import games.strategy.util.CompositeMatchOr;
import games.strategy.util.Match;
public class Utils {
/**
* All the territories that border one of our territories.
*/
public static List<Territory> getNeighboringEnemyLandTerritories(final GameData data, final PlayerID player) {
final ArrayList<Territory> rVal = new ArrayList<>();
for (final Territory t : data.getMap()) {
if (Matches.isTerritoryEnemy(player, data).match(t) && !t.getOwner().isNull()) {
if (!data.getMap().getNeighbors(t, Matches.isTerritoryOwnedBy(player)).isEmpty()) {
rVal.add(t);
}
}
}
return rVal;
}
public static List<Unit> getUnitsUpToStrength(final double maxStrength, final Collection<Unit> units,
final boolean sea) {
if (AIUtils.strength(units, true, sea) < maxStrength) {
return new ArrayList<>(units);
}
final ArrayList<Unit> rVal = new ArrayList<>();
for (final Unit u : units) {
rVal.add(u);
if (AIUtils.strength(rVal, true, sea) > maxStrength) {
return rVal;
}
}
return rVal;
}
public static float getStrengthOfPotentialAttackers(final Territory location, final GameData data) {
float strength = 0;
for (final Territory t : data.getMap().getNeighbors(location,
location.isWater() ? Matches.TerritoryIsWater : Matches.TerritoryIsLand)) {
final List<Unit> enemies = t.getUnits().getMatches(Matches.enemyUnit(location.getOwner(), data));
strength += AIUtils.strength(enemies, true, location.isWater());
}
return strength;
}
public static Route findNearest(final Territory start, final Match<Territory> endCondition,
final Match<Territory> routeCondition, final GameData data) {
Route shortestRoute = null;
for (final Territory t : data.getMap().getTerritories()) {
if (endCondition.match(t)) {
final CompositeMatchOr<Territory> routeOrEnd = new CompositeMatchOr<>(routeCondition, Matches.territoryIs(t));
final Route r = data.getMap().getRoute(start, t, routeOrEnd);
if (r != null) {
if (shortestRoute == null || r.numberOfSteps() < shortestRoute.numberOfSteps()) {
shortestRoute = r;
}
}
}
}
return shortestRoute;
}
public static boolean hasLandRouteToEnemyOwnedCapitol(final Territory t, final PlayerID us, final GameData data) {
for (final PlayerID player : Match.getMatches(data.getPlayerList().getPlayers(), Matches.isAtWar(us, data))) {
for (final Territory capital : TerritoryAttachment.getAllCurrentlyOwnedCapitals(player, data)) {
if (data.getMap().getDistance(t, capital, Matches.TerritoryIsLand) != -1) {
return true;
}
}
}
return false;
}
// returns all territories that are water territories (veqryn)
public static List<Territory> onlyWaterTerr(final GameData data, final List<Territory> allTerr) {
final List<Territory> water = new ArrayList<>(allTerr);
final Iterator<Territory> wFIter = water.iterator();
while (wFIter.hasNext()) {
final Territory waterFact = wFIter.next();
if (!Matches.TerritoryIsWater.match(waterFact)) {
wFIter.remove();
}
}
return water;
}
/**
* Return Territories containing any unit depending on unitCondition
* Differs from findCertainShips because it doesn't require the units be owned.
*/
public static List<Territory> findUnitTerr(final GameData data, final PlayerID player,
final Match<Unit> unitCondition) {
// Return territories containing a certain unit or set of Units
final CompositeMatch<Unit> limitShips = new CompositeMatchAnd<>(unitCondition);
final List<Territory> shipTerr = new ArrayList<>();
final Collection<Territory> tNeighbors = data.getMap().getTerritories();
for (final Territory t2 : tNeighbors) {
if (t2.getUnits().someMatch(limitShips)) {
shipTerr.add(t2);
}
}
return shipTerr;
}
}