Search in sources :

Example 1 with Unit

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

the class BattleCalculator method categorizeLowLuckAirUnits.

/**
 * http://triplea.sourceforge.net/mywiki/Forum#nabble-td4658925%7Ca4658925
 * returns two lists, the first list is the air units that can be evenly divided into groups of 3 or 6 (depending on
 * radar)
 * the second list is all the air units that do not fit in the first list
 */
private static Tuple<List<List<Unit>>, List<Unit>> categorizeLowLuckAirUnits(final Collection<Unit> units, final int groupSize) {
    final Collection<UnitCategory> categorizedAir = UnitSeperator.categorize(units, null, false, true);
    final List<List<Unit>> groupsOfSize = new ArrayList<>();
    final List<Unit> toRoll = new ArrayList<>();
    for (final UnitCategory uc : categorizedAir) {
        final int remainder = uc.getUnits().size() % groupSize;
        final int splitPosition = uc.getUnits().size() - remainder;
        final List<Unit> group = new ArrayList<>(uc.getUnits().subList(0, splitPosition));
        if (!group.isEmpty()) {
            for (int i = 0; i < splitPosition; i += groupSize) {
                final List<Unit> miniGroup = new ArrayList<>(uc.getUnits().subList(i, i + groupSize));
                if (!miniGroup.isEmpty()) {
                    groupsOfSize.add(miniGroup);
                }
            }
        }
        toRoll.addAll(uc.getUnits().subList(splitPosition, uc.getUnits().size()));
    }
    return Tuple.of(groupsOfSize, toRoll);
}
Also used : ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) CasualtyList(games.strategy.triplea.delegate.dataObjects.CasualtyList) List(java.util.List) Unit(games.strategy.engine.data.Unit) UnitCategory(games.strategy.triplea.util.UnitCategory)

Example 2 with Unit

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

the class BattleCalculator method getTotalHitpointsLeft.

public static int getTotalHitpointsLeft(final Collection<Unit> units) {
    if (units == null || units.isEmpty()) {
        return 0;
    }
    int totalHitPoints = 0;
    for (final Unit u : units) {
        final UnitAttachment ua = UnitAttachment.get(u.getType());
        totalHitPoints += ua.getHitPoints();
        totalHitPoints -= u.getHits();
    }
    return totalHitPoints;
}
Also used : UnitAttachment(games.strategy.triplea.attachments.UnitAttachment) Unit(games.strategy.engine.data.Unit)

Example 3 with Unit

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

the class BattleCalculator method sortUnitsForCasualtiesWithSupport.

/**
 * The purpose of this is to return a list in the PERFECT order of which units should be selected to die first,
 * And that means that certain units MUST BE INTERLEAVED.
 * This list assumes that you have already taken any extra hit points away from any 2 hitpoint units.
 * Example: You have a 1 attack Artillery unit that supports, and a 1 attack infantry unit that can receive support.
 * The best selection of units to die is first to take whichever unit has excess, then cut that down til they are both
 * the same size,
 * then to take 1 artillery followed by 1 infantry, followed by 1 artillery, then 1 inf, etc, until everyone is dead.
 * If you just return all infantry followed by all artillery, or the other way around, you will be missing out on some
 * important support
 * provided.
 * (Veqryn)
 */
private static List<Unit> sortUnitsForCasualtiesWithSupport(final Collection<Unit> targetsToPickFrom, final boolean defending, final PlayerID player, final Collection<Unit> enemyUnits, final boolean amphibious, final Collection<Unit> amphibiousLandAttackers, final Territory battlesite, final IntegerMap<UnitType> costs, final Collection<TerritoryEffect> territoryEffects, final GameData data, final boolean bonus) {
    // Convert unit lists to unit type lists
    final List<UnitType> targetTypes = new ArrayList<>();
    for (final Unit u : targetsToPickFrom) {
        targetTypes.add(u.getType());
    }
    final List<UnitType> amphibTypes = new ArrayList<>();
    if (amphibiousLandAttackers != null) {
        for (final Unit u : amphibiousLandAttackers) {
            amphibTypes.add(u.getType());
        }
    }
    // Calculate hashes and cache key
    int targetsHashCode = 1;
    for (final UnitType ut : targetTypes) {
        targetsHashCode += ut.hashCode();
    }
    targetsHashCode *= 31;
    int amphibHashCode = 1;
    for (final UnitType ut : amphibTypes) {
        amphibHashCode += ut.hashCode();
    }
    amphibHashCode *= 31;
    String key = player.getName() + "|" + battlesite.getName() + "|" + defending + "|" + amphibious + "|" + targetsHashCode + "|" + amphibHashCode;
    // Check OOL cache
    final List<UnitType> stored = oolCache.get(key);
    if (stored != null) {
        // System.out.println("Hit with cacheSize=" + oolCache.size() + ", key=" + key);
        final List<Unit> result = new ArrayList<>();
        final List<Unit> selectFrom = new ArrayList<>(targetsToPickFrom);
        for (final UnitType ut : stored) {
            for (final Iterator<Unit> it = selectFrom.iterator(); it.hasNext(); ) {
                final Unit u = it.next();
                if (ut.equals(u.getType())) {
                    result.add(u);
                    it.remove();
                }
            }
        }
        return result;
    }
    // System.out.println("Miss with cacheSize=" + oolCache.size() + ", key=" + key);
    // Sort enough units to kill off
    final List<Unit> sortedUnitsList = new ArrayList<>(targetsToPickFrom);
    sortedUnitsList.sort(new UnitBattleComparator(defending, costs, territoryEffects, data, bonus, false));
    // Sort units starting with strongest so that support gets added to them first
    Collections.reverse(sortedUnitsList);
    final UnitBattleComparator unitComparatorWithoutPrimaryPower = new UnitBattleComparator(defending, costs, territoryEffects, data, bonus, true);
    final Map<Unit, IntegerMap<Unit>> unitSupportPowerMap = new HashMap<>();
    final Map<Unit, IntegerMap<Unit>> unitSupportRollsMap = new HashMap<>();
    final Map<Unit, Tuple<Integer, Integer>> unitPowerAndRollsMap = DiceRoll.getUnitPowerAndRollsForNormalBattles(sortedUnitsList, new ArrayList<>(enemyUnits), defending, false, data, battlesite, territoryEffects, amphibious, amphibiousLandAttackers, unitSupportPowerMap, unitSupportRollsMap);
    // Sort units starting with weakest for finding the worst units
    Collections.reverse(sortedUnitsList);
    final List<Unit> sortedWellEnoughUnitsList = new ArrayList<>();
    for (int i = 0; i < sortedUnitsList.size(); ++i) {
        // Loop through all target units to find the best unit to take as casualty
        Unit worstUnit = null;
        int minPower = Integer.MAX_VALUE;
        final Set<UnitType> unitTypes = new HashSet<>();
        for (final Unit u : sortedUnitsList) {
            if (unitTypes.contains(u.getType())) {
                continue;
            }
            unitTypes.add(u.getType());
            // Find unit power
            final Map<Unit, Tuple<Integer, Integer>> currentUnitMap = new HashMap<>();
            currentUnitMap.put(u, unitPowerAndRollsMap.get(u));
            int power = DiceRoll.getTotalPower(currentUnitMap, data);
            // Add any support power that it provides to other units
            final IntegerMap<Unit> unitSupportPowerMapForUnit = unitSupportPowerMap.get(u);
            if (unitSupportPowerMapForUnit != null) {
                for (final Unit supportedUnit : unitSupportPowerMapForUnit.keySet()) {
                    Tuple<Integer, Integer> strengthAndRolls = unitPowerAndRollsMap.get(supportedUnit);
                    if (strengthAndRolls == null) {
                        continue;
                    }
                    // Remove any rolls provided by this support so they aren't counted twice
                    final IntegerMap<Unit> unitSupportRollsMapForUnit = unitSupportRollsMap.get(u);
                    if (unitSupportRollsMapForUnit != null) {
                        strengthAndRolls = Tuple.of(strengthAndRolls.getFirst(), strengthAndRolls.getSecond() - unitSupportRollsMapForUnit.getInt(supportedUnit));
                    }
                    // If one roll then just add the power
                    if (strengthAndRolls.getSecond() == 1) {
                        power += unitSupportPowerMapForUnit.getInt(supportedUnit);
                        continue;
                    }
                    // Find supported unit power with support
                    final Map<Unit, Tuple<Integer, Integer>> supportedUnitMap = new HashMap<>();
                    supportedUnitMap.put(supportedUnit, strengthAndRolls);
                    final int powerWithSupport = DiceRoll.getTotalPower(supportedUnitMap, data);
                    // Find supported unit power without support
                    final int strengthWithoutSupport = strengthAndRolls.getFirst() - unitSupportPowerMapForUnit.getInt(supportedUnit);
                    final Tuple<Integer, Integer> strengthAndRollsWithoutSupport = Tuple.of(strengthWithoutSupport, strengthAndRolls.getSecond());
                    supportedUnitMap.put(supportedUnit, strengthAndRollsWithoutSupport);
                    final int powerWithoutSupport = DiceRoll.getTotalPower(supportedUnitMap, data);
                    // Add the actual power provided by the support
                    final int addedPower = powerWithSupport - powerWithoutSupport;
                    power += addedPower;
                }
            }
            // Add any power from support rolls that it provides to other units
            final IntegerMap<Unit> unitSupportRollsMapForUnit = unitSupportRollsMap.get(u);
            if (unitSupportRollsMapForUnit != null) {
                for (final Unit supportedUnit : unitSupportRollsMapForUnit.keySet()) {
                    final Tuple<Integer, Integer> strengthAndRolls = unitPowerAndRollsMap.get(supportedUnit);
                    if (strengthAndRolls == null) {
                        continue;
                    }
                    // Find supported unit power with support
                    final Map<Unit, Tuple<Integer, Integer>> supportedUnitMap = new HashMap<>();
                    supportedUnitMap.put(supportedUnit, strengthAndRolls);
                    final int powerWithSupport = DiceRoll.getTotalPower(supportedUnitMap, data);
                    // Find supported unit power without support
                    final int rollsWithoutSupport = strengthAndRolls.getSecond() - unitSupportRollsMap.get(u).getInt(supportedUnit);
                    final Tuple<Integer, Integer> strengthAndRollsWithoutSupport = Tuple.of(strengthAndRolls.getFirst(), rollsWithoutSupport);
                    supportedUnitMap.put(supportedUnit, strengthAndRollsWithoutSupport);
                    final int powerWithoutSupport = DiceRoll.getTotalPower(supportedUnitMap, data);
                    // Add the actual power provided by the support
                    final int addedPower = powerWithSupport - powerWithoutSupport;
                    power += addedPower;
                }
            }
            // Check if unit has lower power
            if (power < minPower || (power == minPower && unitComparatorWithoutPrimaryPower.compare(u, worstUnit) < 0)) {
                worstUnit = u;
                minPower = power;
            }
        }
        // Add worst unit to sorted list, update any units it supported, and remove from other collections
        final IntegerMap<Unit> unitSupportPowerMapForUnit = unitSupportPowerMap.get(worstUnit);
        if (unitSupportPowerMapForUnit != null) {
            for (final Unit supportedUnit : unitSupportPowerMapForUnit.keySet()) {
                final Tuple<Integer, Integer> strengthAndRolls = unitPowerAndRollsMap.get(supportedUnit);
                if (strengthAndRolls == null) {
                    continue;
                }
                final int strengthWithoutSupport = strengthAndRolls.getFirst() - unitSupportPowerMapForUnit.getInt(supportedUnit);
                final Tuple<Integer, Integer> strengthAndRollsWithoutSupport = Tuple.of(strengthWithoutSupport, strengthAndRolls.getSecond());
                unitPowerAndRollsMap.put(supportedUnit, strengthAndRollsWithoutSupport);
                sortedUnitsList.remove(supportedUnit);
                sortedUnitsList.add(0, supportedUnit);
            }
        }
        final IntegerMap<Unit> unitSupportRollsMapForUnit = unitSupportRollsMap.get(worstUnit);
        if (unitSupportRollsMapForUnit != null) {
            for (final Unit supportedUnit : unitSupportRollsMapForUnit.keySet()) {
                final Tuple<Integer, Integer> strengthAndRolls = unitPowerAndRollsMap.get(supportedUnit);
                if (strengthAndRolls == null) {
                    continue;
                }
                final int rollsWithoutSupport = strengthAndRolls.getSecond() - unitSupportRollsMapForUnit.getInt(supportedUnit);
                final Tuple<Integer, Integer> strengthAndRollsWithoutSupport = Tuple.of(strengthAndRolls.getFirst(), rollsWithoutSupport);
                unitPowerAndRollsMap.put(supportedUnit, strengthAndRollsWithoutSupport);
                sortedUnitsList.remove(supportedUnit);
                sortedUnitsList.add(0, supportedUnit);
            }
        }
        sortedWellEnoughUnitsList.add(worstUnit);
        sortedUnitsList.remove(worstUnit);
        unitPowerAndRollsMap.remove(worstUnit);
        unitSupportPowerMap.remove(worstUnit);
        unitSupportRollsMap.remove(worstUnit);
    }
    sortedWellEnoughUnitsList.addAll(sortedUnitsList);
    // Cache result and all subsets of the result
    final List<UnitType> unitTypes = new ArrayList<>();
    for (final Unit u : sortedWellEnoughUnitsList) {
        unitTypes.add(u.getType());
    }
    for (final Iterator<UnitType> it = unitTypes.iterator(); it.hasNext(); ) {
        oolCache.put(key, new ArrayList<>(unitTypes));
        final UnitType unitTypeToRemove = it.next();
        targetTypes.remove(unitTypeToRemove);
        if (Collections.frequency(targetTypes, unitTypeToRemove) < Collections.frequency(amphibTypes, unitTypeToRemove)) {
            amphibTypes.remove(unitTypeToRemove);
        }
        targetsHashCode = 1;
        for (final UnitType ut : targetTypes) {
            targetsHashCode += ut.hashCode();
        }
        targetsHashCode *= 31;
        amphibHashCode = 1;
        for (final UnitType ut : amphibTypes) {
            amphibHashCode += ut.hashCode();
        }
        amphibHashCode *= 31;
        key = player.getName() + "|" + battlesite.getName() + "|" + defending + "|" + amphibious + "|" + targetsHashCode + "|" + amphibHashCode;
        it.remove();
    }
    return sortedWellEnoughUnitsList;
}
Also used : LinkedIntegerMap(games.strategy.util.LinkedIntegerMap) IntegerMap(games.strategy.util.IntegerMap) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) ArrayList(java.util.ArrayList) Unit(games.strategy.engine.data.Unit) UnitType(games.strategy.engine.data.UnitType) Tuple(games.strategy.util.Tuple) HashSet(java.util.HashSet)

Example 4 with Unit

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

the class BattleCalculator method selectCasualties.

/**
 * @param battleId
 *        may be null if we are not in a battle (eg, if this is an aa fire due to moving).
 */
public static CasualtyDetails selectCasualties(final String step, final PlayerID player, final Collection<Unit> targetsToPickFrom, final Collection<Unit> friendlyUnits, final PlayerID enemyPlayer, final Collection<Unit> enemyUnits, final boolean amphibious, final Collection<Unit> amphibiousLandAttackers, final Territory battlesite, final Collection<TerritoryEffect> territoryEffects, final IDelegateBridge bridge, final String text, final DiceRoll dice, final boolean defending, final GUID battleId, final boolean headLess, final int extraHits, final boolean allowMultipleHitsPerUnit) {
    if (targetsToPickFrom.isEmpty()) {
        return new CasualtyDetails();
    }
    if (!friendlyUnits.containsAll(targetsToPickFrom)) {
        throw new IllegalStateException("friendlyUnits should but does not contain all units from targetsToPickFrom");
    }
    final GameData data = bridge.getData();
    final boolean isEditMode = BaseEditDelegate.getEditMode(data);
    final ITripleAPlayer tripleaPlayer = player.isNull() ? new WeakAi(player.getName(), TripleA.WEAK_COMPUTER_PLAYER_TYPE) : (ITripleAPlayer) bridge.getRemotePlayer(player);
    final Map<Unit, Collection<Unit>> dependents = headLess ? Collections.emptyMap() : getDependents(targetsToPickFrom);
    if (isEditMode && !headLess) {
        final CasualtyDetails editSelection = tripleaPlayer.selectCasualties(targetsToPickFrom, dependents, 0, text, dice, player, friendlyUnits, enemyPlayer, enemyUnits, amphibious, amphibiousLandAttackers, new CasualtyList(), battleId, battlesite, allowMultipleHitsPerUnit);
        final List<Unit> killed = editSelection.getKilled();
        // if partial retreat is possible, kill amphibious units first
        if (isPartialAmphibiousRetreat(data)) {
            killAmphibiousFirst(killed, targetsToPickFrom);
        }
        return editSelection;
    }
    if (dice.getHits() == 0) {
        return new CasualtyDetails(Collections.emptyList(), Collections.emptyList(), true);
    }
    int hitsRemaining = dice.getHits();
    if (isTransportCasualtiesRestricted(data)) {
        hitsRemaining = extraHits;
    }
    if (!isEditMode && allTargetsOneTypeOneHitPoint(targetsToPickFrom, dependents)) {
        final List<Unit> killed = new ArrayList<>();
        final Iterator<Unit> iter = targetsToPickFrom.iterator();
        for (int i = 0; i < hitsRemaining; i++) {
            if (i >= targetsToPickFrom.size()) {
                break;
            }
            killed.add(iter.next());
        }
        return new CasualtyDetails(killed, Collections.emptyList(), true);
    }
    // Create production cost map, Maybe should do this elsewhere, but in case prices change, we do it here.
    final IntegerMap<UnitType> costs = TuvUtils.getCostsForTuv(player, data);
    final Tuple<CasualtyList, List<Unit>> defaultCasualtiesAndSortedTargets = getDefaultCasualties(targetsToPickFrom, hitsRemaining, defending, player, enemyUnits, amphibious, amphibiousLandAttackers, battlesite, costs, territoryEffects, data, allowMultipleHitsPerUnit, true);
    final CasualtyList defaultCasualties = defaultCasualtiesAndSortedTargets.getFirst();
    final List<Unit> sortedTargetsToPickFrom = defaultCasualtiesAndSortedTargets.getSecond();
    if (sortedTargetsToPickFrom.size() != targetsToPickFrom.size() || !targetsToPickFrom.containsAll(sortedTargetsToPickFrom) || !sortedTargetsToPickFrom.containsAll(targetsToPickFrom)) {
        throw new IllegalStateException("sortedTargetsToPickFrom must contain the same units as targetsToPickFrom list");
    }
    final int totalHitpoints = (allowMultipleHitsPerUnit ? getTotalHitpointsLeft(sortedTargetsToPickFrom) : sortedTargetsToPickFrom.size());
    final CasualtyDetails casualtySelection;
    if (hitsRemaining >= totalHitpoints) {
        casualtySelection = new CasualtyDetails(defaultCasualties, true);
    } else {
        casualtySelection = tripleaPlayer.selectCasualties(sortedTargetsToPickFrom, dependents, hitsRemaining, text, dice, player, friendlyUnits, enemyPlayer, enemyUnits, amphibious, amphibiousLandAttackers, defaultCasualties, battleId, battlesite, allowMultipleHitsPerUnit);
    }
    List<Unit> killed = casualtySelection.getKilled();
    // if partial retreat is possible, kill amphibious units first
    if (isPartialAmphibiousRetreat(data)) {
        killed = killAmphibiousFirst(killed, sortedTargetsToPickFrom);
    }
    final List<Unit> damaged = casualtySelection.getDamaged();
    int numhits = killed.size();
    if (!allowMultipleHitsPerUnit) {
        damaged.clear();
    } else {
        for (final Unit unit : killed) {
            final UnitAttachment ua = UnitAttachment.get(unit.getType());
            final int damageToUnit = Collections.frequency(damaged, unit);
            // allowed damage
            numhits += Math.max(0, Math.min(damageToUnit, (ua.getHitPoints() - (1 + unit.getHits()))));
            // remove from damaged list, since they will die
            damaged.removeIf(unit::equals);
        }
    }
    // check right number
    if (!isEditMode && !(numhits + damaged.size() == (hitsRemaining > totalHitpoints ? totalHitpoints : hitsRemaining))) {
        tripleaPlayer.reportError("Wrong number of casualties selected");
        if (headLess) {
            System.err.println("Possible Infinite Loop: Wrong number of casualties selected: number of hits on units " + (numhits + damaged.size()) + " != number of hits to take " + (hitsRemaining > totalHitpoints ? totalHitpoints : hitsRemaining) + ", for " + casualtySelection.toString());
        }
        return selectCasualties(step, player, sortedTargetsToPickFrom, friendlyUnits, enemyPlayer, enemyUnits, amphibious, amphibiousLandAttackers, battlesite, territoryEffects, bridge, text, dice, defending, battleId, headLess, extraHits, allowMultipleHitsPerUnit);
    }
    // check we have enough of each type
    if (!sortedTargetsToPickFrom.containsAll(killed) || !sortedTargetsToPickFrom.containsAll(damaged)) {
        tripleaPlayer.reportError("Cannot remove enough units of those types");
        if (headLess) {
            System.err.println("Possible Infinite Loop: Cannot remove enough units of those types: targets " + MyFormatter.unitsToTextNoOwner(sortedTargetsToPickFrom) + ", for " + casualtySelection.toString());
        }
        return selectCasualties(step, player, sortedTargetsToPickFrom, friendlyUnits, enemyPlayer, enemyUnits, amphibious, amphibiousLandAttackers, battlesite, territoryEffects, bridge, text, dice, defending, battleId, headLess, extraHits, allowMultipleHitsPerUnit);
    }
    return casualtySelection;
}
Also used : GameData(games.strategy.engine.data.GameData) ArrayList(java.util.ArrayList) Unit(games.strategy.engine.data.Unit) ITripleAPlayer(games.strategy.triplea.player.ITripleAPlayer) UnitAttachment(games.strategy.triplea.attachments.UnitAttachment) WeakAi(games.strategy.triplea.ai.weak.WeakAi) CasualtyList(games.strategy.triplea.delegate.dataObjects.CasualtyList) UnitType(games.strategy.engine.data.UnitType) Collection(java.util.Collection) CasualtyDetails(games.strategy.triplea.delegate.dataObjects.CasualtyDetails) ArrayList(java.util.ArrayList) CasualtyList(games.strategy.triplea.delegate.dataObjects.CasualtyList) List(java.util.List)

Example 5 with Unit

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

the class BattleCalculator method randomAaCasualties.

/**
 * Choose plane casualties randomly.
 */
public static CasualtyDetails randomAaCasualties(final Collection<Unit> planes, final DiceRoll dice, final IDelegateBridge bridge, final boolean allowMultipleHitsPerUnit) {
    {
        final Set<Unit> duplicatesCheckSet1 = new HashSet<>(planes);
        if (planes.size() != duplicatesCheckSet1.size()) {
            throw new IllegalStateException("Duplicate Units Detected: Original List:" + planes + "  HashSet:" + duplicatesCheckSet1);
        }
    }
    final int hitsLeft = dice.getHits();
    if (hitsLeft <= 0) {
        return new CasualtyDetails();
    }
    final CasualtyDetails finalCasualtyDetails = new CasualtyDetails();
    // normal behavior is instant kill, which means planes.size()
    final int planeHitPoints = (allowMultipleHitsPerUnit ? getTotalHitpointsLeft(planes) : planes.size());
    final List<Unit> planesList = new ArrayList<>();
    for (final Unit plane : planes) {
        final int hpLeft = allowMultipleHitsPerUnit ? (UnitAttachment.get(plane.getType()).getHitPoints() - plane.getHits()) : (Math.min(1, UnitAttachment.get(plane.getType()).getHitPoints() - plane.getHits()));
        for (int hp = 0; hp < hpLeft; ++hp) {
            // if allowMultipleHitsPerUnit, then because the number of rolls exactly equals the hitpoints of all units,
            // we roll multiple times for any unit with multiple hitpoints
            planesList.add(plane);
        }
    }
    // We need to choose which planes die randomly
    if (hitsLeft < planeHitPoints) {
        // roll all at once to prevent frequent random calls, important for pbem games
        final int[] hitRandom = bridge.getRandom(planeHitPoints, hitsLeft, null, DiceType.ENGINE, "Deciding which planes should die due to AA fire");
        int pos = 0;
        for (final int element : hitRandom) {
            pos += element;
            final Unit unitHit = planesList.remove(pos % planesList.size());
            if (allowMultipleHitsPerUnit && (Collections.frequency(finalCasualtyDetails.getDamaged(), unitHit) < (getTotalHitpointsLeft(unitHit) - 1))) {
                finalCasualtyDetails.addToDamaged(unitHit);
            } else {
                finalCasualtyDetails.addToKilled(unitHit);
            }
        }
    } else {
        for (final Unit plane : planesList) {
            if (finalCasualtyDetails.getKilled().contains(plane)) {
                finalCasualtyDetails.addToDamaged(plane);
            } else {
                finalCasualtyDetails.addToKilled(plane);
            }
        }
    }
    return finalCasualtyDetails;
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) ArrayList(java.util.ArrayList) CasualtyDetails(games.strategy.triplea.delegate.dataObjects.CasualtyDetails) Unit(games.strategy.engine.data.Unit)

Aggregations

Unit (games.strategy.engine.data.Unit)447 TripleAUnit (games.strategy.triplea.TripleAUnit)301 Territory (games.strategy.engine.data.Territory)255 ArrayList (java.util.ArrayList)204 PlayerID (games.strategy.engine.data.PlayerID)135 GameData (games.strategy.engine.data.GameData)103 HashSet (java.util.HashSet)92 Test (org.junit.jupiter.api.Test)91 Route (games.strategy.engine.data.Route)89 UnitType (games.strategy.engine.data.UnitType)85 CompositeChange (games.strategy.engine.data.CompositeChange)64 HashMap (java.util.HashMap)64 IntegerMap (games.strategy.util.IntegerMap)61 UnitAttachment (games.strategy.triplea.attachments.UnitAttachment)58 Collection (java.util.Collection)58 ITestDelegateBridge (games.strategy.engine.data.ITestDelegateBridge)56 List (java.util.List)48 ScriptedRandomSource (games.strategy.engine.random.ScriptedRandomSource)47 Change (games.strategy.engine.data.Change)44 Set (java.util.Set)43