Search in sources :

Example 11 with PlayerAttachment

use of games.strategy.triplea.attachments.PlayerAttachment in project triplea by triplea-game.

the class AbstractEndTurnDelegate method getBlockadeProductionLoss.

// finds losses due to blockades, positive value returned.
private int getBlockadeProductionLoss(final PlayerID player, final GameData data, final IDelegateBridge bridge, final StringBuilder endTurnReport) {
    final PlayerAttachment playerRules = PlayerAttachment.get(player);
    if (playerRules != null && playerRules.getImmuneToBlockade()) {
        return 0;
    }
    final GameMap map = data.getMap();
    final Collection<Territory> blockable = CollectionUtils.getMatches(map.getTerritories(), Matches.territoryIsBlockadeZone());
    if (blockable.isEmpty()) {
        return 0;
    }
    final Predicate<Unit> enemyUnits = Matches.enemyUnit(player, data);
    int totalLoss = 0;
    final boolean rollDiceForBlockadeDamage = Properties.getConvoyBlockadesRollDiceForCost(data);
    final Collection<String> transcripts = new ArrayList<>();
    final HashMap<Territory, Tuple<Integer, List<Territory>>> damagePerBlockadeZone = new HashMap<>();
    boolean rolledDice = false;
    for (final Territory b : blockable) {
        // match will check for land, convoy zones, and also contested territories
        final List<Territory> viableNeighbors = CollectionUtils.getMatches(map.getNeighbors(b), Matches.isTerritoryOwnedBy(player).and(Matches.territoryCanCollectIncomeFrom(player, data)));
        final int maxLoss = getProduction(viableNeighbors);
        if (maxLoss <= 0) {
            continue;
        }
        final Collection<Unit> enemies = CollectionUtils.getMatches(b.getUnits().getUnits(), enemyUnits);
        if (enemies.isEmpty()) {
            continue;
        }
        int loss = 0;
        if (rollDiceForBlockadeDamage) {
            int numberOfDice = 0;
            for (final Unit u : enemies) {
                numberOfDice += UnitAttachment.get(u.getType()).getBlockade();
            }
            if (numberOfDice > 0) {
                // there is an issue with maps that have lots of rolls without any pause between them: they are causing the
                // cypted random source
                // (ie: live and pbem games) to lock up or error out
                // so we need to slow them down a bit, until we come up with a better solution (like aggregating all the
                // chances together, then
                // getting a ton of random numbers at once instead of one at a time)
                Interruptibles.sleep(100);
                final String transcript = "Rolling for Convoy Blockade Damage in " + b.getName();
                final int[] dice = bridge.getRandom(CONVOY_BLOCKADE_DICE_SIDES, numberOfDice, enemies.iterator().next().getOwner(), DiceType.BOMBING, transcript);
                transcripts.add(transcript + ". Rolls: " + MyFormatter.asDice(dice));
                rolledDice = true;
                for (final int d : dice) {
                    // we are zero based
                    final int roll = d + 1;
                    loss += (roll <= 3 ? roll : 0);
                }
            }
        } else {
            for (final Unit u : enemies) {
                loss += UnitAttachment.get(u.getType()).getBlockade();
            }
        }
        if (loss <= 0) {
            continue;
        }
        final int lossForBlockade = Math.min(maxLoss, loss);
        damagePerBlockadeZone.put(b, Tuple.of(lossForBlockade, viableNeighbors));
        totalLoss += lossForBlockade;
    }
    if (totalLoss <= 0 && !rolledDice) {
        return 0;
    }
    // now we need to make sure that we didn't deal more damage than the territories are worth, in the case of having
    // multiple sea zones
    // touching the same land zone.
    final List<Territory> blockadeZonesSorted = new ArrayList<>(damagePerBlockadeZone.keySet());
    blockadeZonesSorted.sort(getSingleBlockadeThenHighestToLowestBlockadeDamage(damagePerBlockadeZone));
    // we want to match highest damage to largest producer first, that is why we sort twice
    final IntegerMap<Territory> totalDamageTracker = new IntegerMap<>();
    for (final Territory b : blockadeZonesSorted) {
        final Tuple<Integer, List<Territory>> tuple = damagePerBlockadeZone.get(b);
        int damageForZone = tuple.getFirst();
        final List<Territory> terrsLosingIncome = new ArrayList<>(tuple.getSecond());
        terrsLosingIncome.sort(getSingleNeighborBlockadesThenHighestToLowestProduction(blockadeZonesSorted, map));
        final Iterator<Territory> iter = terrsLosingIncome.iterator();
        while (damageForZone > 0 && iter.hasNext()) {
            final Territory t = iter.next();
            final int maxProductionLessPreviousDamage = TerritoryAttachment.getProduction(t) - totalDamageTracker.getInt(t);
            final int damageToTerr = Math.min(damageForZone, maxProductionLessPreviousDamage);
            damageForZone -= damageToTerr;
            totalDamageTracker.put(t, damageToTerr + totalDamageTracker.getInt(t));
        }
    }
    final int realTotalLoss = Math.max(0, totalDamageTracker.totalValues());
    if (rollDiceForBlockadeDamage && (realTotalLoss > 0 || (rolledDice && !transcripts.isEmpty()))) {
        final String mainline = "Total Cost from Convoy Blockades: " + realTotalLoss;
        bridge.getHistoryWriter().startEvent(mainline);
        endTurnReport.append(mainline).append("<br />");
        for (final String t : transcripts) {
            bridge.getHistoryWriter().addChildToEvent(t);
            endTurnReport.append("* ").append(t).append("<br />");
        }
        endTurnReport.append("<br />");
    }
    return realTotalLoss;
}
Also used : IntegerMap(games.strategy.util.IntegerMap) Territory(games.strategy.engine.data.Territory) GameMap(games.strategy.engine.data.GameMap) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Unit(games.strategy.engine.data.Unit) PlayerAttachment(games.strategy.triplea.attachments.PlayerAttachment) ArrayList(java.util.ArrayList) List(java.util.List) Tuple(games.strategy.util.Tuple)

Example 12 with PlayerAttachment

use of games.strategy.triplea.attachments.PlayerAttachment in project triplea by triplea-game.

the class TripleAPlayer method selectKamikazeSuicideAttacks.

@Override
public HashMap<Territory, HashMap<Unit, IntegerMap<Resource>>> selectKamikazeSuicideAttacks(final HashMap<Territory, Collection<Unit>> possibleUnitsToAttack) {
    final PlayerID id = getPlayerId();
    final PlayerAttachment pa = PlayerAttachment.get(id);
    if (pa == null) {
        return null;
    }
    final IntegerMap<Resource> resourcesAndAttackValues = pa.getSuicideAttackResources();
    if (resourcesAndAttackValues.size() <= 0) {
        return null;
    }
    final IntegerMap<Resource> playerResourceCollection = id.getResources().getResourcesCopy();
    final IntegerMap<Resource> attackTokens = new IntegerMap<>();
    for (final Resource possible : resourcesAndAttackValues.keySet()) {
        final int amount = playerResourceCollection.getInt(possible);
        if (amount > 0) {
            attackTokens.put(possible, amount);
        }
    }
    if (attackTokens.size() <= 0) {
        return null;
    }
    final HashMap<Territory, HashMap<Unit, IntegerMap<Resource>>> kamikazeSuicideAttacks = new HashMap<>();
    for (final Entry<Resource, Integer> entry : attackTokens.entrySet()) {
        final Resource resource = entry.getKey();
        final int max = entry.getValue();
        final Map<Territory, IntegerMap<Unit>> selection = ui.selectKamikazeSuicideAttacks(possibleUnitsToAttack, resource, max);
        for (final Entry<Territory, IntegerMap<Unit>> selectionEntry : selection.entrySet()) {
            final Territory territory = selectionEntry.getKey();
            final HashMap<Unit, IntegerMap<Resource>> currentTerr = kamikazeSuicideAttacks.getOrDefault(territory, new HashMap<>());
            for (final Entry<Unit, Integer> unitEntry : selectionEntry.getValue().entrySet()) {
                final Unit unit = unitEntry.getKey();
                final IntegerMap<Resource> currentUnit = currentTerr.getOrDefault(unit, new IntegerMap<>());
                currentUnit.add(resource, unitEntry.getValue());
                currentTerr.put(unit, currentUnit);
            }
            kamikazeSuicideAttacks.put(territory, currentTerr);
        }
    }
    return kamikazeSuicideAttacks;
}
Also used : IntegerMap(games.strategy.util.IntegerMap) PlayerID(games.strategy.engine.data.PlayerID) Territory(games.strategy.engine.data.Territory) HashMap(java.util.HashMap) Resource(games.strategy.engine.data.Resource) Unit(games.strategy.engine.data.Unit) PlayerAttachment(games.strategy.triplea.attachments.PlayerAttachment)

Example 13 with PlayerAttachment

use of games.strategy.triplea.attachments.PlayerAttachment in project triplea by triplea-game.

the class AbstractAi method selectKamikazeSuicideAttacks.

@Override
public HashMap<Territory, HashMap<Unit, IntegerMap<Resource>>> selectKamikazeSuicideAttacks(final HashMap<Territory, Collection<Unit>> possibleUnitsToAttack) {
    final PlayerID id = getPlayerId();
    // we are going to just assign random attacks to each unit randomly, til we run out of tokens to attack with.
    final PlayerAttachment pa = PlayerAttachment.get(id);
    if (pa == null) {
        return null;
    }
    final IntegerMap<Resource> resourcesAndAttackValues = pa.getSuicideAttackResources();
    if (resourcesAndAttackValues.size() <= 0) {
        return null;
    }
    final IntegerMap<Resource> playerResourceCollection = id.getResources().getResourcesCopy();
    final IntegerMap<Resource> attackTokens = new IntegerMap<>();
    for (final Resource possible : resourcesAndAttackValues.keySet()) {
        final int amount = playerResourceCollection.getInt(possible);
        if (amount > 0) {
            attackTokens.put(possible, amount);
        }
    }
    if (attackTokens.size() <= 0) {
        return null;
    }
    final HashMap<Territory, HashMap<Unit, IntegerMap<Resource>>> kamikazeSuicideAttacks = new HashMap<>();
    for (final Entry<Territory, Collection<Unit>> entry : possibleUnitsToAttack.entrySet()) {
        if (attackTokens.size() <= 0) {
            continue;
        }
        final Territory t = entry.getKey();
        final List<Unit> targets = new ArrayList<>(entry.getValue());
        Collections.shuffle(targets);
        for (final Unit u : targets) {
            if (attackTokens.size() <= 0) {
                continue;
            }
            final IntegerMap<Resource> resourceMap = new IntegerMap<>();
            final Resource resource = attackTokens.keySet().iterator().next();
            final int num = Math.min(attackTokens.getInt(resource), (UnitAttachment.get(u.getType()).getHitPoints() * (Math.random() < .3 ? 1 : (Math.random() < .5 ? 2 : 3))));
            resourceMap.put(resource, num);
            final HashMap<Unit, IntegerMap<Resource>> attMap = kamikazeSuicideAttacks.getOrDefault(t, new HashMap<>());
            attMap.put(u, resourceMap);
            kamikazeSuicideAttacks.put(t, attMap);
            attackTokens.add(resource, -num);
            if (attackTokens.getInt(resource) <= 0) {
                attackTokens.removeKey(resource);
            }
        }
    }
    return kamikazeSuicideAttacks;
}
Also used : IntegerMap(games.strategy.util.IntegerMap) PlayerID(games.strategy.engine.data.PlayerID) Territory(games.strategy.engine.data.Territory) HashMap(java.util.HashMap) Resource(games.strategy.engine.data.Resource) ArrayList(java.util.ArrayList) Unit(games.strategy.engine.data.Unit) PlayerAttachment(games.strategy.triplea.attachments.PlayerAttachment) Collection(java.util.Collection)

Aggregations

PlayerAttachment (games.strategy.triplea.attachments.PlayerAttachment)13 PlayerID (games.strategy.engine.data.PlayerID)9 Territory (games.strategy.engine.data.Territory)8 Unit (games.strategy.engine.data.Unit)8 Resource (games.strategy.engine.data.Resource)7 GameData (games.strategy.engine.data.GameData)5 ArrayList (java.util.ArrayList)5 CompositeChange (games.strategy.engine.data.CompositeChange)4 TerritoryAttachment (games.strategy.triplea.attachments.TerritoryAttachment)4 IntegerMap (games.strategy.util.IntegerMap)4 HashMap (java.util.HashMap)4 Change (games.strategy.engine.data.Change)3 TripleAUnit (games.strategy.triplea.TripleAUnit)3 Collection (java.util.Collection)3 UnitType (games.strategy.engine.data.UnitType)2 Tuple (games.strategy.util.Tuple)2 GameMap (games.strategy.engine.data.GameMap)1 PlayerList (games.strategy.engine.data.PlayerList)1 RelationshipTracker (games.strategy.engine.data.RelationshipTracker)1 Relationship (games.strategy.engine.data.RelationshipTracker.Relationship)1