Search in sources :

Example 86 with Territory

use of games.strategy.engine.data.Territory in project triplea by triplea-game.

the class ProPurchaseAi method purchaseLandUnits.

private void purchaseLandUnits(final Map<Territory, ProPurchaseTerritory> purchaseTerritories, final List<ProPlaceTerritory> prioritizedLandTerritories, final ProPurchaseOptionMap purchaseOptions, final Map<Territory, Double> territoryValueMap) {
    final List<Unit> unplacedUnits = player.getUnits().getMatches(Matches.unitIsNotSea());
    if (resourceTracker.isEmpty() && unplacedUnits.isEmpty()) {
        return;
    }
    ProLogger.info("Purchase land units with resources: " + resourceTracker);
    if (!unplacedUnits.isEmpty()) {
        ProLogger.info("Purchase land units with unplaced units=" + unplacedUnits);
    }
    // Loop through prioritized territories and purchase land units
    for (final ProPlaceTerritory placeTerritory : prioritizedLandTerritories) {
        final Territory t = placeTerritory.getTerritory();
        ProLogger.debug("Checking land place for " + t.getName());
        // Check remaining production
        int remainingUnitProduction = purchaseTerritories.get(t).getRemainingUnitProduction();
        ProLogger.debug(t + ", remainingUnitProduction=" + remainingUnitProduction);
        if (remainingUnitProduction <= 0) {
            continue;
        }
        // Determine most cost efficient units that can be produced in this territory
        final List<ProPurchaseOption> landFodderOptions = ProPurchaseUtils.findPurchaseOptionsForTerritory(player, purchaseOptions.getLandFodderOptions(), t, isBid);
        final List<ProPurchaseOption> landAttackOptions = ProPurchaseUtils.findPurchaseOptionsForTerritory(player, purchaseOptions.getLandAttackOptions(), t, isBid);
        final List<ProPurchaseOption> landDefenseOptions = ProPurchaseUtils.findPurchaseOptionsForTerritory(player, purchaseOptions.getLandDefenseOptions(), t, isBid);
        // Determine enemy distance and locally owned units
        int enemyDistance = ProUtils.getClosestEnemyOrNeutralLandTerritoryDistance(data, player, t, territoryValueMap);
        if (enemyDistance <= 0) {
            enemyDistance = 10;
        }
        final int fodderPercent = 80 - enemyDistance * 5;
        ProLogger.debug(t + ", enemyDistance=" + enemyDistance + ", fodderPercent=" + fodderPercent);
        final Set<Territory> neighbors = data.getMap().getNeighbors(t, 2, ProMatches.territoryCanMoveLandUnits(player, data, false));
        neighbors.add(t);
        final List<Unit> ownedLocalUnits = new ArrayList<>();
        for (final Territory neighbor : neighbors) {
            ownedLocalUnits.addAll(neighbor.getUnits().getMatches(Matches.unitIsOwnedBy(player)));
        }
        // Check for unplaced units
        final List<Unit> unitsToPlace = new ArrayList<>();
        for (final Iterator<Unit> it = unplacedUnits.iterator(); it.hasNext(); ) {
            final Unit u = it.next();
            if (remainingUnitProduction > 0 && ProPurchaseUtils.canUnitsBePlaced(Collections.singletonList(u), player, t, isBid)) {
                remainingUnitProduction--;
                unitsToPlace.add(u);
                it.remove();
                ProLogger.trace("Selected unplaced unit=" + u);
            }
        }
        // Purchase as many units as possible
        int addedFodderUnits = 0;
        double attackAndDefenseDifference = 0;
        boolean selectFodderUnit = true;
        while (true) {
            // Remove options that cost too much PUs or production
            ProPurchaseUtils.removeInvalidPurchaseOptions(player, startOfTurnData, landFodderOptions, resourceTracker, remainingUnitProduction, unitsToPlace, purchaseTerritories);
            ProPurchaseUtils.removeInvalidPurchaseOptions(player, startOfTurnData, landAttackOptions, resourceTracker, remainingUnitProduction, unitsToPlace, purchaseTerritories);
            ProPurchaseUtils.removeInvalidPurchaseOptions(player, startOfTurnData, landDefenseOptions, resourceTracker, remainingUnitProduction, unitsToPlace, purchaseTerritories);
            // Select purchase option
            Optional<ProPurchaseOption> optionalSelectedOption = Optional.empty();
            if (!selectFodderUnit && attackAndDefenseDifference > 0 && !landDefenseOptions.isEmpty()) {
                final Map<ProPurchaseOption, Double> defenseEfficiencies = new HashMap<>();
                for (final ProPurchaseOption ppo : landDefenseOptions) {
                    defenseEfficiencies.put(ppo, ppo.getDefenseEfficiency2(enemyDistance, data, ownedLocalUnits, unitsToPlace));
                }
                optionalSelectedOption = ProPurchaseUtils.randomizePurchaseOption(defenseEfficiencies, "Land Defense");
            } else if (!selectFodderUnit && !landAttackOptions.isEmpty()) {
                final Map<ProPurchaseOption, Double> attackEfficiencies = new HashMap<>();
                for (final ProPurchaseOption ppo : landAttackOptions) {
                    attackEfficiencies.put(ppo, ppo.getAttackEfficiency2(enemyDistance, data, ownedLocalUnits, unitsToPlace));
                }
                optionalSelectedOption = ProPurchaseUtils.randomizePurchaseOption(attackEfficiencies, "Land Attack");
            } else if (!landFodderOptions.isEmpty()) {
                final Map<ProPurchaseOption, Double> fodderEfficiencies = new HashMap<>();
                for (final ProPurchaseOption ppo : landFodderOptions) {
                    fodderEfficiencies.put(ppo, ppo.getFodderEfficiency(enemyDistance, data, ownedLocalUnits, unitsToPlace));
                }
                optionalSelectedOption = ProPurchaseUtils.randomizePurchaseOption(fodderEfficiencies, "Land Fodder");
                if (optionalSelectedOption.isPresent()) {
                    addedFodderUnits += optionalSelectedOption.get().getQuantity();
                }
            }
            if (!optionalSelectedOption.isPresent()) {
                break;
            }
            final ProPurchaseOption selectedOption = optionalSelectedOption.get();
            // Create new temp units
            resourceTracker.purchase(selectedOption);
            remainingUnitProduction -= selectedOption.getQuantity();
            unitsToPlace.addAll(selectedOption.getUnitType().create(selectedOption.getQuantity(), player, true));
            attackAndDefenseDifference += (selectedOption.getAttack() - selectedOption.getDefense());
            selectFodderUnit = ((double) addedFodderUnits / unitsToPlace.size() * 100) <= fodderPercent;
            ProLogger.trace("Selected unit=" + selectedOption.getUnitType().getName());
        }
        // Add units to place territory
        placeTerritory.getPlaceUnits().addAll(unitsToPlace);
        ProLogger.debug(t + ", placedUnits=" + unitsToPlace);
    }
}
Also used : ProPlaceTerritory(games.strategy.triplea.ai.pro.data.ProPlaceTerritory) ProPurchaseTerritory(games.strategy.triplea.ai.pro.data.ProPurchaseTerritory) Territory(games.strategy.engine.data.Territory) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) ProPlaceTerritory(games.strategy.triplea.ai.pro.data.ProPlaceTerritory) ProPurchaseOption(games.strategy.triplea.ai.pro.data.ProPurchaseOption) HashMap(java.util.HashMap) Map(java.util.Map) IntegerMap(games.strategy.util.IntegerMap) ProPurchaseOptionMap(games.strategy.triplea.ai.pro.data.ProPurchaseOptionMap)

Example 87 with Territory

use of games.strategy.engine.data.Territory in project triplea by triplea-game.

the class ProTechAi method findAttackers.

private static List<Unit> findAttackers(final Territory start, final int maxDistance, final HashSet<Integer> ignoreDistance, final PlayerID player, final GameData data, final Predicate<Unit> unitCondition, final Predicate<Territory> routeCondition, final List<Route> routes, final boolean sea) {
    final IntegerMap<Territory> distance = new IntegerMap<>();
    final Map<Territory, Territory> visited = new HashMap<>();
    final List<Unit> units = new ArrayList<>();
    final Queue<Territory> q = new ArrayDeque<>();
    q.add(start);
    Territory current;
    distance.put(start, 0);
    visited.put(start, null);
    while (!q.isEmpty()) {
        current = q.remove();
        if (distance.getInt(current) == maxDistance) {
            break;
        }
        for (final Territory neighbor : data.getMap().getNeighbors(current)) {
            if (!distance.keySet().contains(neighbor)) {
                if (!neighbor.getUnits().anyMatch(unitCondition)) {
                    if (!routeCondition.test(neighbor)) {
                        continue;
                    }
                }
                if (sea) {
                    final Route r = new Route();
                    r.setStart(neighbor);
                    r.add(current);
                    if (MoveValidator.validateCanal(r, null, player, data) != null) {
                        continue;
                    }
                }
                distance.put(neighbor, distance.getInt(current) + 1);
                visited.put(neighbor, current);
                q.add(neighbor);
                final int dist = distance.getInt(neighbor);
                if (ignoreDistance.contains(dist)) {
                    continue;
                }
                for (final Unit u : neighbor.getUnits()) {
                    if (unitCondition.test(u) && Matches.unitHasEnoughMovementForRoutes(routes).test(u)) {
                        units.add(u);
                    }
                }
            }
        }
    }
    // pain in the ass, should just redesign stop blitz attack
    for (final Territory t : visited.keySet()) {
        final Route r = new Route();
        Territory t2 = t;
        r.setStart(t);
        while (t2 != null) {
            t2 = visited.get(t2);
            if (t2 != null) {
                r.add(t2);
            }
        }
        routes.add(r);
    }
    return units;
}
Also used : IntegerMap(games.strategy.util.IntegerMap) Territory(games.strategy.engine.data.Territory) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Unit(games.strategy.engine.data.Unit) ArrayDeque(java.util.ArrayDeque) Route(games.strategy.engine.data.Route)

Example 88 with Territory

use of games.strategy.engine.data.Territory in project triplea by triplea-game.

the class ProTechAi method determineEnemyBlitzStrength.

/**
 * Determine the enemy potential for blitzing a territory - all enemies are combined.
 *
 * @param blitzHere
 *        - Territory expecting to be blitzed
 * @return actual strength of enemy units (armor)
 */
private static float determineEnemyBlitzStrength(final Territory blitzHere, final List<Route> blitzTerrRoutes, final GameData data, final PlayerID enemyPlayer) {
    final HashSet<Integer> ignore = new HashSet<>();
    ignore.add(1);
    final Predicate<Unit> blitzUnit = Matches.unitIsOwnedBy(enemyPlayer).and(Matches.unitCanBlitz()).and(Matches.unitCanMove());
    final Predicate<Territory> validBlitzRoute = Matches.territoryHasNoEnemyUnits(enemyPlayer, data).and(Matches.territoryIsNotImpassableToLandUnits(enemyPlayer, data));
    final List<Route> routes = new ArrayList<>();
    final List<Unit> blitzUnits = findAttackers(blitzHere, 2, ignore, enemyPlayer, data, blitzUnit, validBlitzRoute, routes, false);
    for (final Route r : routes) {
        if (r.numberOfSteps() == 2) {
            blitzTerrRoutes.add(r);
        }
    }
    return strength(blitzUnits, true, false, true);
}
Also used : Territory(games.strategy.engine.data.Territory) ArrayList(java.util.ArrayList) Unit(games.strategy.engine.data.Unit) Route(games.strategy.engine.data.Route) HashSet(java.util.HashSet)

Example 89 with Territory

use of games.strategy.engine.data.Territory in project triplea by triplea-game.

the class ProTechAi method getStrengthOfPotentialAttackers.

/**
 * Returns the strength of all attackers to a territory.
 * Differentiates between sea and land attack
 * Determines all transports within range of territory
 * Determines all air units within range of territory (using 2 for fighters and 3 for bombers)
 * Does not check for extended range fighters or bombers
 */
private static float getStrengthOfPotentialAttackers(final Territory location, final GameData data, final PlayerID player) {
    final boolean transportsFirst = false;
    PlayerID enemyPlayer = null;
    final List<PlayerID> enemyPlayers = getEnemyPlayers(data, player);
    final HashMap<PlayerID, Float> enemyPlayerAttackMap = new HashMap<>();
    final Iterator<PlayerID> playerIter = enemyPlayers.iterator();
    if (location == null) {
        return -1000.0F;
    }
    boolean nonTransportsInAttack = false;
    final boolean onWater = location.isWater();
    if (!onWater) {
        nonTransportsInAttack = true;
    }
    final Set<Territory> waterTerr = data.getMap().getNeighbors(location, Matches.territoryIsWater());
    while (playerIter.hasNext()) {
        float seaStrength = 0.0F;
        float firstStrength = 0.0F;
        float secondStrength = 0.0F;
        float blitzStrength = 0.0F;
        float strength;
        enemyPlayer = playerIter.next();
        final Predicate<Unit> enemyPlane = Matches.unitIsAir().and(Matches.unitIsOwnedBy(enemyPlayer)).and(Matches.unitCanMove());
        final Predicate<Unit> enemyTransport = Matches.unitIsOwnedBy(enemyPlayer).and(Matches.unitIsSea()).and(Matches.unitIsTransport()).and(Matches.unitCanMove());
        final Predicate<Unit> enemyShip = Matches.unitIsOwnedBy(enemyPlayer).and(Matches.unitIsSea()).and(Matches.unitCanMove());
        final Predicate<Unit> enemyTransportable = Matches.unitIsOwnedBy(enemyPlayer).and(Matches.unitCanBeTransported()).and(Matches.unitIsNotAa()).and(Matches.unitCanMove());
        final Predicate<Unit> transport = Matches.unitIsSea().and(Matches.unitIsTransport()).and(Matches.unitCanMove());
        final List<Territory> enemyFighterTerritories = findUnitTerr(data, enemyPlane);
        int maxFighterDistance = 0;
        // and likely player will have at least 1 max move plane.
        for (final Territory enemyFighterTerritory : enemyFighterTerritories) {
            final List<Unit> enemyFighterUnits = enemyFighterTerritory.getUnits().getMatches(enemyPlane);
            maxFighterDistance = Math.max(maxFighterDistance, MoveValidator.getMaxMovement(enemyFighterUnits));
        }
        // must be able to land...we will miss fighters who have a Carrier that can reach same sea zone...C'est la vie
        maxFighterDistance--;
        if (maxFighterDistance < 0) {
            maxFighterDistance = 0;
        }
        final List<Territory> enemyTransportTerritories = findUnitTerr(data, transport);
        int maxTransportDistance = 0;
        for (final Territory enemyTransportTerritory : enemyTransportTerritories) {
            final List<Unit> enemyTransportUnits = enemyTransportTerritory.getUnits().getMatches(transport);
            maxTransportDistance = Math.max(maxTransportDistance, MoveValidator.getMaxMovement(enemyTransportUnits));
        }
        final List<Unit> alreadyLoaded = new ArrayList<>();
        final List<Route> blitzTerrRoutes = new ArrayList<>();
        final List<Territory> checked = new ArrayList<>();
        final List<Unit> enemyWaterUnits = new ArrayList<>();
        for (final Territory t : data.getMap().getNeighbors(location, onWater ? Matches.territoryIsWater() : Matches.territoryIsLand())) {
            final List<Unit> enemies = t.getUnits().getMatches(Matches.unitIsOwnedBy(enemyPlayer));
            enemyWaterUnits.addAll(enemies);
            firstStrength += strength(enemies, true, onWater, transportsFirst);
            checked.add(t);
        }
        if (Matches.territoryIsLand().test(location)) {
            blitzStrength = determineEnemyBlitzStrength(location, blitzTerrRoutes, data, enemyPlayer);
        } else {
            // get ships attack strength
            // old assumed fleets won't split up, new lets them. no biggie.
            // assumes max ship movement is 3.
            // note, both old and new implementations
            // allow units to be calculated that are in
            // territories we have already assaulted
            // this can be easily changed
            final HashSet<Integer> ignore = new HashSet<>();
            ignore.add(1);
            final List<Route> r = new ArrayList<>();
            final List<Unit> ships = findAttackers(location, 3, ignore, enemyPlayer, data, enemyShip, Matches.territoryIsBlockedSea(enemyPlayer, data), r, true);
            secondStrength = strength(ships, true, true, transportsFirst);
            enemyWaterUnits.addAll(ships);
        }
        final List<Unit> attackPlanes = findPlaneAttackersThatCanLand(location, maxFighterDistance, enemyPlayer, data, checked);
        final float airStrength = allAirStrength(attackPlanes);
        if (Matches.territoryHasWaterNeighbor(data).test(location) && Matches.territoryIsLand().test(location)) {
            for (final Territory t4 : data.getMap().getNeighbors(location, maxTransportDistance)) {
                if (!t4.isWater()) {
                    continue;
                }
                for (final Territory waterCheck : waterTerr) {
                    if (enemyPlayer == null) {
                        continue;
                    }
                    final List<Unit> transports = t4.getUnits().getMatches(enemyTransport);
                    if (transports.isEmpty()) {
                        continue;
                    }
                    if (!t4.equals(waterCheck)) {
                        final Route seaRoute = getMaxSeaRoute(data, t4, waterCheck, enemyPlayer, maxTransportDistance);
                        if (seaRoute == null || seaRoute.getEnd() == null || seaRoute.getEnd() != waterCheck) {
                            continue;
                        }
                    }
                    final List<Unit> loadedUnits = new ArrayList<>();
                    int availInf = 0;
                    int availOther = 0;
                    for (final Unit candidateTransport : transports) {
                        final Collection<Unit> thisTransUnits = TransportTracker.transporting(candidateTransport);
                        if (thisTransUnits == null) {
                            availInf += 2;
                            availOther += 1;
                            continue;
                        }
                        int inf = 2;
                        int other = 1;
                        for (final Unit checkUnit : thisTransUnits) {
                            if (Matches.unitIsLandTransportable().test(checkUnit)) {
                                inf--;
                            }
                            if (Matches.unitIsNotLandTransportable().test(checkUnit)) {
                                inf--;
                                other--;
                            }
                            loadedUnits.add(checkUnit);
                        }
                        availInf += inf;
                        availOther += other;
                    }
                    final Set<Territory> transNeighbors = data.getMap().getNeighbors(t4, Matches.isTerritoryAllied(enemyPlayer, data));
                    for (final Territory transNeighbor : transNeighbors) {
                        final List<Unit> transUnits = transNeighbor.getUnits().getMatches(enemyTransportable);
                        transUnits.removeAll(alreadyLoaded);
                        final List<Unit> availTransUnits = sortTransportUnits(transUnits);
                        for (final Unit transUnit : availTransUnits) {
                            if (availInf > 0 && Matches.unitIsLandTransportable().test(transUnit)) {
                                availInf--;
                                loadedUnits.add(transUnit);
                                alreadyLoaded.add(transUnit);
                            }
                            if (availInf > 0 && availOther > 0 && Matches.unitIsNotLandTransportable().test(transUnit)) {
                                availInf--;
                                availOther--;
                                loadedUnits.add(transUnit);
                                alreadyLoaded.add(transUnit);
                            }
                        }
                    }
                    seaStrength += strength(loadedUnits, true, false, transportsFirst);
                    break;
                }
            }
        }
        strength = seaStrength + blitzStrength + firstStrength + secondStrength;
        if (strength > 0.0F) {
            strength += airStrength;
        }
        if (onWater) {
            final Iterator<Unit> enemyWaterUnitsIter = enemyWaterUnits.iterator();
            while (enemyWaterUnitsIter.hasNext() && !nonTransportsInAttack) {
                if (Matches.unitIsNotTransport().test(enemyWaterUnitsIter.next())) {
                    nonTransportsInAttack = true;
                }
            }
        }
        if (!nonTransportsInAttack) {
            strength = 0.0F;
        }
        enemyPlayerAttackMap.put(enemyPlayer, strength);
    }
    float maxStrength = 0.0F;
    for (final PlayerID enemyPlayerCandidate : enemyPlayers) {
        if (enemyPlayerAttackMap.get(enemyPlayerCandidate) > maxStrength) {
            enemyPlayer = enemyPlayerCandidate;
            maxStrength = enemyPlayerAttackMap.get(enemyPlayerCandidate);
        }
    }
    for (final PlayerID enemyPlayerCandidate : enemyPlayers) {
        if (enemyPlayer != enemyPlayerCandidate) {
            // give 40% of other players...this is will affect a lot of decisions by AI
            maxStrength += enemyPlayerAttackMap.get(enemyPlayerCandidate) * 0.40F;
        }
    }
    return maxStrength;
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) Territory(games.strategy.engine.data.Territory) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Unit(games.strategy.engine.data.Unit) Route(games.strategy.engine.data.Route) HashSet(java.util.HashSet)

Example 90 with Territory

use of games.strategy.engine.data.Territory in project triplea by triplea-game.

the class ProTechAi method tech.

static void tech(final ITechDelegate techDelegate, final GameData data, final PlayerID player) {
    if (!Properties.getWW2V3TechModel(data)) {
        return;
    }
    final Territory myCapitol = TerritoryAttachment.getFirstOwnedCapitalOrFirstUnownedCapital(player, data);
    final float enemyStrength = getStrengthOfPotentialAttackers(myCapitol, data, player);
    float myStrength = (myCapitol == null || myCapitol.getUnits() == null) ? 0.0F : strength(myCapitol.getUnits().getUnits(), false, false, false);
    final List<Territory> areaStrength = getNeighboringLandTerritories(data, player, myCapitol);
    for (final Territory areaTerr : areaStrength) {
        myStrength += strength(areaTerr.getUnits().getUnits(), false, false, false) * 0.75F;
    }
    final boolean capDanger = myStrength < (enemyStrength * 1.25F + 3.0F);
    final Resource pus = data.getResourceList().getResource(Constants.PUS);
    final int pusRemaining = player.getResources().getQuantity(pus);
    final Resource techtokens = data.getResourceList().getResource(Constants.TECH_TOKENS);
    final int techTokensQuantity = player.getResources().getQuantity(techtokens);
    int tokensToBuy = 0;
    if (!capDanger && techTokensQuantity < 3 && pusRemaining > Math.random() * 160) {
        tokensToBuy = 1;
    }
    if (techTokensQuantity > 0 || tokensToBuy > 0) {
        final List<TechnologyFrontier> cats = TechAdvance.getPlayerTechCategories(player);
        // retaining 65% chance of choosing land advances using basic ww2v3 model.
        if (data.getTechnologyFrontier().isEmpty()) {
            if (Math.random() > 0.35) {
                techDelegate.rollTech(techTokensQuantity + tokensToBuy, cats.get(1), tokensToBuy, null);
            } else {
                techDelegate.rollTech(techTokensQuantity + tokensToBuy, cats.get(0), tokensToBuy, null);
            }
        } else {
            final int rand = (int) (Math.random() * cats.size());
            techDelegate.rollTech(techTokensQuantity + tokensToBuy, cats.get(rand), tokensToBuy, null);
        }
    }
}
Also used : Territory(games.strategy.engine.data.Territory) Resource(games.strategy.engine.data.Resource) TechnologyFrontier(games.strategy.engine.data.TechnologyFrontier)

Aggregations

Territory (games.strategy.engine.data.Territory)420 Unit (games.strategy.engine.data.Unit)254 TripleAUnit (games.strategy.triplea.TripleAUnit)195 PlayerID (games.strategy.engine.data.PlayerID)164 ArrayList (java.util.ArrayList)160 Test (org.junit.jupiter.api.Test)140 Route (games.strategy.engine.data.Route)137 ITestDelegateBridge (games.strategy.engine.data.ITestDelegateBridge)118 GameData (games.strategy.engine.data.GameData)94 HashSet (java.util.HashSet)87 UnitType (games.strategy.engine.data.UnitType)65 HashMap (java.util.HashMap)65 ScriptedRandomSource (games.strategy.engine.random.ScriptedRandomSource)50 Collection (java.util.Collection)47 IntegerMap (games.strategy.util.IntegerMap)45 Set (java.util.Set)41 ProTerritory (games.strategy.triplea.ai.pro.data.ProTerritory)39 TerritoryAttachment (games.strategy.triplea.attachments.TerritoryAttachment)37 List (java.util.List)36 ProPurchaseTerritory (games.strategy.triplea.ai.pro.data.ProPurchaseTerritory)34