use of games.strategy.triplea.attachments.UnitAttachment in project triplea by triplea-game.
the class DiceRoll method airBattle.
static DiceRoll airBattle(final List<Unit> unitsList, final boolean defending, final PlayerID player, final IDelegateBridge bridge, final String annotation) {
{
final Set<Unit> duplicatesCheckSet1 = new HashSet<>(unitsList);
if (unitsList.size() != duplicatesCheckSet1.size()) {
throw new IllegalStateException("Duplicate Units Detected: Original List:" + unitsList + " HashSet:" + duplicatesCheckSet1);
}
}
final GameData data = bridge.getData();
final boolean lhtrBombers = Properties.getLhtrHeavyBombers(data);
final List<Unit> units = new ArrayList<>(unitsList);
final int rollCount = AirBattle.getAirBattleRolls(unitsList, defending);
if (rollCount == 0) {
return new DiceRoll(new ArrayList<>(), 0, 0);
}
int[] random;
final List<Die> dice = new ArrayList<>();
int hitCount = 0;
// bonus is normally 1 for most games
final int extraRollBonus = Math.max(1, data.getDiceSides() / 6);
int totalPower = 0;
// We iterate through the units to find the total strength of the units
for (final Unit current : units) {
final UnitAttachment ua = UnitAttachment.get(current.getType());
final int rolls = AirBattle.getAirBattleRolls(current, defending);
int totalStrength = 0;
final int strength = Math.min(data.getDiceSides(), Math.max(0, (defending ? ua.getAirDefense(current.getOwner()) : ua.getAirAttack(current.getOwner()))));
for (int i = 0; i < rolls; i++) {
// simulate the gains of having the best die picked.
if (i > 1 && (lhtrBombers || ua.getChooseBestRoll())) {
totalStrength += extraRollBonus;
continue;
}
totalStrength += strength;
}
totalPower += Math.min(Math.max(totalStrength, 0), data.getDiceSides());
}
if (Properties.getLowLuck(data)) {
// Get number of hits
hitCount = totalPower / data.getDiceSides();
random = new int[0];
// We need to roll dice for the fractional part of the dice.
final int power = totalPower % data.getDiceSides();
if (power != 0) {
random = bridge.getRandom(data.getDiceSides(), 1, player, DiceType.COMBAT, annotation);
final boolean hit = power > random[0];
if (hit) {
hitCount++;
}
dice.add(new Die(random[0], power, hit ? DieType.HIT : DieType.MISS));
}
} else {
random = bridge.getRandom(data.getDiceSides(), rollCount, player, DiceType.COMBAT, annotation);
int diceIndex = 0;
for (final Unit current : units) {
final UnitAttachment ua = UnitAttachment.get(current.getType());
final int strength = Math.min(data.getDiceSides(), Math.max(0, (defending ? ua.getAirDefense(current.getOwner()) : ua.getAirAttack(current.getOwner()))));
final int rolls = AirBattle.getAirBattleRolls(current, defending);
// lhtr heavy bombers take best of n dice for both attack and defense
if (rolls > 1 && (lhtrBombers || ua.getChooseBestRoll())) {
int minIndex = 0;
int min = data.getDiceSides();
for (int i = 0; i < rolls; i++) {
if (random[diceIndex + i] < min) {
min = random[diceIndex + i];
minIndex = i;
}
}
final boolean hit = strength > random[diceIndex + minIndex];
dice.add(new Die(random[diceIndex + minIndex], strength, hit ? DieType.HIT : DieType.MISS));
for (int i = 0; i < rolls; i++) {
if (i != minIndex) {
dice.add(new Die(random[diceIndex + i], strength, DieType.IGNORED));
}
}
if (hit) {
hitCount++;
}
diceIndex += rolls;
} else {
for (int i = 0; i < rolls; i++) {
final boolean hit = strength > random[diceIndex];
dice.add(new Die(random[diceIndex], strength, hit ? DieType.HIT : DieType.MISS));
if (hit) {
hitCount++;
}
diceIndex++;
}
}
}
}
final double expectedHits = ((double) totalPower) / data.getDiceSides();
final DiceRoll diceRoll = new DiceRoll(dice, hitCount, expectedHits);
bridge.getHistoryWriter().addChildToEvent(annotation + " : " + MyFormatter.asDice(random), diceRoll);
return diceRoll;
}
use of games.strategy.triplea.attachments.UnitAttachment in project triplea by triplea-game.
the class DiceRoll method getTotalPowerAndRolls.
private static Tuple<Integer, Integer> getTotalPowerAndRolls(final Map<Unit, Tuple<Integer, Integer>> unitPowerAndRollsMap, final GameData data) {
final int diceSides = data.getDiceSides();
final boolean lhtrBombers = Properties.getLhtrHeavyBombers(data);
// bonus is normally 1 for most games
final int extraRollBonus = Math.max(1, data.getDiceSides() / 6);
int totalPower = 0;
int totalRolls = 0;
for (final Entry<Unit, Tuple<Integer, Integer>> entry : unitPowerAndRollsMap.entrySet()) {
int unitStrength = Math.min(Math.max(0, entry.getValue().getFirst()), diceSides);
final int unitRolls = entry.getValue().getSecond();
if (unitStrength <= 0 || unitRolls <= 0) {
continue;
}
if (unitRolls == 1) {
totalPower += unitStrength;
totalRolls += unitRolls;
} else {
final UnitAttachment ua = UnitAttachment.get(entry.getKey().getType());
if (lhtrBombers || ua.getChooseBestRoll()) {
// LHTR means pick the best dice roll, which doesn't really make sense in LL. So instead, we will just add
// +1 onto the power to
// simulate the gains of having the best die picked.
unitStrength += extraRollBonus * (unitRolls - 1);
totalPower += Math.min(unitStrength, diceSides);
totalRolls += unitRolls;
} else {
totalPower += unitRolls * unitStrength;
totalRolls += unitRolls;
}
}
}
return Tuple.of(totalPower, totalRolls);
}
use of games.strategy.triplea.attachments.UnitAttachment in project triplea by triplea-game.
the class AbstractPlaceDelegate method canWeConsumeUnits.
protected boolean canWeConsumeUnits(final Collection<Unit> units, final Territory to, final boolean actuallyDoIt, final CompositeChange change) {
boolean weCanConsume = true;
final Collection<Unit> unitsAtStartOfTurnInTo = unitsAtStartOfStepInTerritory(to);
final Collection<Unit> removedUnits = new ArrayList<>();
final Collection<Unit> unitsWhichConsume = CollectionUtils.getMatches(units, Matches.unitConsumesUnitsOnCreation());
for (final Unit unit : unitsWhichConsume) {
if (Matches.unitWhichConsumesUnitsHasRequiredUnits(unitsAtStartOfTurnInTo).negate().test(unit)) {
weCanConsume = false;
}
if (!weCanConsume) {
break;
}
// remove units which are now consumed, then test the rest of the consuming units on the diminishing pile of units
// which were in the
// territory at start of turn
final UnitAttachment ua = UnitAttachment.get(unit.getType());
final IntegerMap<UnitType> requiredUnitsMap = ua.getConsumesUnits();
final Collection<UnitType> requiredUnits = requiredUnitsMap.keySet();
for (final UnitType ut : requiredUnits) {
final int requiredNumber = requiredUnitsMap.getInt(ut);
final Predicate<Unit> unitIsOwnedByAndOfTypeAndNotDamaged = Matches.unitIsOwnedBy(unit.getOwner()).and(Matches.unitIsOfType(ut)).and(Matches.unitHasNotTakenAnyBombingUnitDamage()).and(Matches.unitHasNotTakenAnyDamage()).and(Matches.unitIsNotDisabled());
final Collection<Unit> unitsBeingRemoved = CollectionUtils.getNMatches(unitsAtStartOfTurnInTo, requiredNumber, unitIsOwnedByAndOfTypeAndNotDamaged);
unitsAtStartOfTurnInTo.removeAll(unitsBeingRemoved);
// if we should actually do it, not just test, then add to bridge
if (actuallyDoIt && change != null) {
final Change remove = ChangeFactory.removeUnits(to, unitsBeingRemoved);
change.add(remove);
removedUnits.addAll(unitsBeingRemoved);
}
}
}
if (weCanConsume && actuallyDoIt && change != null && !change.isEmpty()) {
bridge.getHistoryWriter().startEvent("Units in " + to.getName() + " being upgraded or consumed: " + MyFormatter.unitsToTextNoOwner(removedUnits), removedUnits);
}
return weCanConsume;
}
use of games.strategy.triplea.attachments.UnitAttachment in project triplea by triplea-game.
the class AirBattle method territoryCouldPossiblyHaveAirBattleDefenders.
static boolean territoryCouldPossiblyHaveAirBattleDefenders(final Territory territory, final PlayerID attacker, final GameData data, final boolean bombing) {
final boolean canScrambleToAirBattle = Properties.getCanScrambleIntoAirBattles(data);
final Predicate<Unit> defendingAirMatch = bombing ? defendingBombingRaidInterceptors(attacker, data) : defendingGroundSeaBattleInterceptors(attacker, data);
int maxScrambleDistance = 0;
if (canScrambleToAirBattle) {
for (final UnitType unitType : data.getUnitTypeList()) {
final UnitAttachment ua = UnitAttachment.get(unitType);
if (ua.getCanScramble() && maxScrambleDistance < ua.getMaxScrambleDistance()) {
maxScrambleDistance = ua.getMaxScrambleDistance();
}
}
} else {
return territory.getUnits().anyMatch(defendingAirMatch);
}
// should we check if the territory also has an air base?
return territory.getUnits().anyMatch(defendingAirMatch) || data.getMap().getNeighbors(territory, maxScrambleDistance).stream().anyMatch(Matches.territoryHasUnitsThatMatch(defendingAirMatch));
}
use of games.strategy.triplea.attachments.UnitAttachment in project triplea by triplea-game.
the class AirMovementValidator method carrierCapacity.
/**
* Does not, and is not supposed to, account for any units already on this carrier (like allied/cargo fighters).
* Instead this method only adds up the total capacity of each unit, and accounts for damaged carriers with special
* properties and restrictions.
*/
public static int carrierCapacity(final Unit unit, final Territory territoryUnitsAreCurrentlyIn) {
if (Matches.unitIsCarrier().test(unit)) {
// here we check to see if the unit can no longer carry units
if (Matches.unitHasWhenCombatDamagedEffect(UnitAttachment.UNITSMAYNOTLANDONCARRIER).test(unit)) {
// and we must check to make sure we let any allied air that are cargo stay here
if (Matches.unitHasWhenCombatDamagedEffect(UnitAttachment.UNITSMAYNOTLEAVEALLIEDCARRIER).test(unit)) {
int cargo = 0;
final Collection<Unit> airCargo = territoryUnitsAreCurrentlyIn.getUnits().getMatches(Matches.unitIsAir().and(Matches.unitCanLandOnCarrier()));
for (final Unit airUnit : airCargo) {
final TripleAUnit taUnit = (TripleAUnit) airUnit;
if (taUnit.getTransportedBy() != null && taUnit.getTransportedBy().equals(unit)) {
// capacity = are cargo only
cargo += UnitAttachment.get(taUnit.getType()).getCarrierCost();
}
}
return cargo;
}
// capacity = zero 0
return 0;
}
final UnitAttachment ua = UnitAttachment.get(unit.getType());
return ua.getCarrierCapacity();
}
return 0;
}
Aggregations