Search in sources :

Example 76 with IntegerMap

use of games.strategy.util.IntegerMap in project triplea by triplea-game.

the class DiceRoll method getUnitPowerAndRollsForNormalBattles.

/**
 * @param unitsGettingPowerFor
 *        should be sorted from weakest to strongest, before the method is called, for the actual battle.
 */
protected static Map<Unit, Tuple<Integer, Integer>> getUnitPowerAndRollsForNormalBattles(final List<Unit> unitsGettingPowerFor, final List<Unit> allEnemyUnitsAliveOrWaitingToDie, final boolean defending, final boolean bombing, final GameData data, final Territory location, final Collection<TerritoryEffect> territoryEffects, final boolean isAmphibiousBattle, final Collection<Unit> amphibiousLandAttackers, final Map<Unit, IntegerMap<Unit>> unitSupportPowerMap, final Map<Unit, IntegerMap<Unit>> unitSupportRollsMap) {
    final Map<Unit, Tuple<Integer, Integer>> unitPowerAndRolls = new HashMap<>();
    if (unitsGettingPowerFor == null || unitsGettingPowerFor.isEmpty()) {
        return unitPowerAndRolls;
    }
    // get all supports, friendly and enemy
    final Set<List<UnitSupportAttachment>> supportRulesFriendly = new HashSet<>();
    final IntegerMap<UnitSupportAttachment> supportLeftFriendly = new IntegerMap<>();
    final Map<UnitSupportAttachment, LinkedIntegerMap<Unit>> supportUnitsLeftFriendly = new HashMap<>();
    getSupport(unitsGettingPowerFor, supportRulesFriendly, supportLeftFriendly, supportUnitsLeftFriendly, data, defending, true);
    final Set<List<UnitSupportAttachment>> supportRulesEnemy = new HashSet<>();
    final IntegerMap<UnitSupportAttachment> supportLeftEnemy = new IntegerMap<>();
    final Map<UnitSupportAttachment, LinkedIntegerMap<Unit>> supportUnitsLeftEnemy = new HashMap<>();
    getSupport(allEnemyUnitsAliveOrWaitingToDie, supportRulesEnemy, supportLeftEnemy, supportUnitsLeftEnemy, data, !defending, false);
    // copy for rolls
    final IntegerMap<UnitSupportAttachment> supportLeftFriendlyRolls = new IntegerMap<>(supportLeftFriendly);
    final IntegerMap<UnitSupportAttachment> supportLeftEnemyRolls = new IntegerMap<>(supportLeftEnemy);
    final Map<UnitSupportAttachment, LinkedIntegerMap<Unit>> supportUnitsLeftFriendlyRolls = new HashMap<>();
    for (final UnitSupportAttachment usa : supportUnitsLeftFriendly.keySet()) {
        supportUnitsLeftFriendlyRolls.put(usa, new LinkedIntegerMap<>(supportUnitsLeftFriendly.get(usa)));
    }
    final Map<UnitSupportAttachment, LinkedIntegerMap<Unit>> supportUnitsLeftEnemyRolls = new HashMap<>();
    for (final UnitSupportAttachment usa : supportUnitsLeftEnemy.keySet()) {
        supportUnitsLeftEnemyRolls.put(usa, new LinkedIntegerMap<>(supportUnitsLeftEnemy.get(usa)));
    }
    final int diceSides = data.getDiceSides();
    for (final Unit current : unitsGettingPowerFor) {
        // find our initial strength
        int strength;
        final UnitAttachment ua = UnitAttachment.get(current.getType());
        if (defending) {
            strength = ua.getDefense(current.getOwner());
            if (isFirstTurnLimitedRoll(current.getOwner(), data)) {
                strength = Math.min(1, strength);
            } else {
                strength += getSupport(current, supportRulesFriendly, supportLeftFriendly, supportUnitsLeftFriendly, unitSupportPowerMap, true, false);
            }
            strength += getSupport(current, supportRulesEnemy, supportLeftEnemy, supportUnitsLeftEnemy, unitSupportPowerMap, true, false);
        } else {
            strength = ua.getAttack(current.getOwner());
            if (ua.getIsMarine() != 0 && isAmphibiousBattle) {
                if (amphibiousLandAttackers.contains(current)) {
                    strength += ua.getIsMarine();
                }
            }
            if (ua.getIsSea() && isAmphibiousBattle && Matches.territoryIsLand().test(location)) {
                // change the strength to be bombard, not attack/defense, because this is a
                strength = ua.getBombard();
            // bombarding naval unit
            }
            strength += getSupport(current, supportRulesFriendly, supportLeftFriendly, supportUnitsLeftFriendly, unitSupportPowerMap, true, false);
            strength += getSupport(current, supportRulesEnemy, supportLeftEnemy, supportUnitsLeftEnemy, unitSupportPowerMap, true, false);
        }
        strength += TerritoryEffectHelper.getTerritoryCombatBonus(current.getType(), territoryEffects, defending);
        strength = Math.min(Math.max(strength, 0), diceSides);
        // now determine our rolls
        int rolls;
        if (!bombing && strength == 0) {
            rolls = 0;
        } else {
            if (defending) {
                rolls = ua.getDefenseRolls(current.getOwner());
            } else {
                rolls = ua.getAttackRolls(current.getOwner());
            }
            rolls += getSupport(current, supportRulesFriendly, supportLeftFriendlyRolls, supportUnitsLeftFriendlyRolls, unitSupportRollsMap, false, true);
            rolls += getSupport(current, supportRulesEnemy, supportLeftEnemyRolls, supportUnitsLeftEnemyRolls, unitSupportRollsMap, false, true);
            rolls = Math.max(0, rolls);
            if (rolls == 0) {
                strength = 0;
            }
        }
        unitPowerAndRolls.put(current, Tuple.of(strength, rolls));
    }
    return unitPowerAndRolls;
}
Also used : LinkedIntegerMap(games.strategy.util.LinkedIntegerMap) IntegerMap(games.strategy.util.IntegerMap) HashMap(java.util.HashMap) UnitSupportAttachment(games.strategy.triplea.attachments.UnitSupportAttachment) Unit(games.strategy.engine.data.Unit) UnitAttachment(games.strategy.triplea.attachments.UnitAttachment) LinkedIntegerMap(games.strategy.util.LinkedIntegerMap) ArrayList(java.util.ArrayList) List(java.util.List) Tuple(games.strategy.util.Tuple) HashSet(java.util.HashSet)

Example 77 with IntegerMap

use of games.strategy.util.IntegerMap in project triplea by triplea-game.

the class RulesAttachment method checkUnitExclusions.

/**
 * Checks for the collection of territories to see if they have units owned by the exclType alliance.
 * It doesn't yet threshold the data
 */
private boolean checkUnitExclusions(final Collection<Territory> territories, final String exclType, final int numberNeeded, final List<PlayerID> players, final GameData data) {
    boolean useSpecific = false;
    if (getUnitPresence() != null && !getUnitPresence().keySet().isEmpty()) {
        useSpecific = true;
    }
    // Go through the owned territories and see if there are any units owned by allied/enemy based on exclType
    boolean satisfied = false;
    int numberMet = 0;
    for (final Territory terr : territories) {
        // get all the units in the territory
        final Collection<Unit> allUnits = new ArrayList<>(terr.getUnits().getUnits());
        if (exclType.equals("allied")) {
            // any allied units in the territory. (does not include owned units)
            allUnits.removeAll(CollectionUtils.getMatches(allUnits, Matches.unitIsOwnedByOfAnyOfThesePlayers(players)));
            allUnits.retainAll(CollectionUtils.getMatches(allUnits, Matches.alliedUnitOfAnyOfThesePlayers(players, data)));
        } else if (exclType.equals("direct")) {
            allUnits.removeAll(CollectionUtils.getMatches(allUnits, Matches.unitIsOwnedByOfAnyOfThesePlayers(players).negate()));
        } else if (exclType.equals("enemy")) {
            // any enemy units in the territory
            allUnits.retainAll(CollectionUtils.getMatches(allUnits, Matches.enemyUnitOfAnyOfThesePlayers(players, data)));
        } else if (exclType.equals("enemy_surface")) {
            // any enemy units (not trn/sub) in the territory
            allUnits.retainAll(CollectionUtils.getMatches(allUnits, Matches.enemyUnitOfAnyOfThesePlayers(players, data).and(Matches.unitIsNotSub()).and(Matches.unitIsNotTransportButCouldBeCombatTransport())));
        } else {
            return false;
        }
        if (allUnits.size() == 0) {
            numberMet += 1;
            if (numberMet >= numberNeeded) {
                satisfied = true;
                if (!getCountEach()) {
                    break;
                }
            }
        } else if (useSpecific) {
            final IntegerMap<String> unitComboMap = getUnitPresence();
            final Set<String> unitCombos = unitComboMap.keySet();
            boolean hasLess = false;
            for (final String uc : unitCombos) {
                final int unitsMax = unitComboMap.getInt(uc);
                if (uc == null || uc.equals("ANY") || uc.equals("any")) {
                    hasLess = allUnits.size() <= unitsMax;
                } else {
                    final Set<UnitType> typesAllowed = data.getUnitTypeList().getUnitTypes(uc.split(":"));
                    hasLess = CollectionUtils.getMatches(allUnits, Matches.unitIsOfTypes(typesAllowed)).size() <= unitsMax;
                }
                if (!hasLess) {
                    break;
                }
            }
            if (hasLess) {
                numberMet += 1;
                if (numberMet >= numberNeeded) {
                    satisfied = true;
                    if (!getCountEach()) {
                        break;
                    }
                }
            }
        }
    }
    if (getCountEach()) {
        m_eachMultiple = numberMet;
    }
    return satisfied;
}
Also used : IntegerMap(games.strategy.util.IntegerMap) Territory(games.strategy.engine.data.Territory) HashSet(java.util.HashSet) Set(java.util.Set) ArrayList(java.util.ArrayList) Unit(games.strategy.engine.data.Unit)

Example 78 with IntegerMap

use of games.strategy.util.IntegerMap in project triplea by triplea-game.

the class AbstractBattle method findPlayerWithMostUnits.

static PlayerID findPlayerWithMostUnits(final Collection<Unit> units) {
    final IntegerMap<PlayerID> playerUnitCount = new IntegerMap<>();
    for (final Unit unit : units) {
        playerUnitCount.add(unit.getOwner(), 1);
    }
    int max = -1;
    PlayerID player = null;
    for (final PlayerID current : playerUnitCount.keySet()) {
        final int count = playerUnitCount.getInt(current);
        if (count > max) {
            max = count;
            player = current;
        }
    }
    return player;
}
Also used : IntegerMap(games.strategy.util.IntegerMap) PlayerID(games.strategy.engine.data.PlayerID) Unit(games.strategy.engine.data.Unit)

Example 79 with IntegerMap

use of games.strategy.util.IntegerMap 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 80 with IntegerMap

use of games.strategy.util.IntegerMap in project triplea by triplea-game.

the class PacificTest method testCanMoveNavalBase.

@Test
public void testCanMoveNavalBase() {
    bridge.setStepName("americanNonCombatMove");
    final Route route = new Route();
    route.setStart(sz5);
    route.add(sz7);
    route.add(sz8);
    route.add(sz20);
    final IntegerMap<UnitType> map = new IntegerMap<>();
    map.put(fighter, 1);
    final String results = delegate.move(GameDataTestUtil.getUnits(map, route.getStart()), route);
    assertValid(results);
}
Also used : IntegerMap(games.strategy.util.IntegerMap) UnitType(games.strategy.engine.data.UnitType) Route(games.strategy.engine.data.Route) Test(org.junit.jupiter.api.Test)

Aggregations

IntegerMap (games.strategy.util.IntegerMap)132 UnitType (games.strategy.engine.data.UnitType)87 Test (org.junit.jupiter.api.Test)73 Route (games.strategy.engine.data.Route)66 Unit (games.strategy.engine.data.Unit)53 Territory (games.strategy.engine.data.Territory)39 ArrayList (java.util.ArrayList)35 PlayerID (games.strategy.engine.data.PlayerID)26 TripleAUnit (games.strategy.triplea.TripleAUnit)24 HashMap (java.util.HashMap)23 HashSet (java.util.HashSet)19 Resource (games.strategy.engine.data.Resource)16 GameData (games.strategy.engine.data.GameData)15 ProductionRule (games.strategy.engine.data.ProductionRule)14 Collection (java.util.Collection)12 List (java.util.List)12 UnitAttachment (games.strategy.triplea.attachments.UnitAttachment)10 Set (java.util.Set)10 RepairRule (games.strategy.engine.data.RepairRule)9 NamedAttachable (games.strategy.engine.data.NamedAttachable)7