use of games.strategy.triplea.attachments.UnitSupportAttachment in project triplea by triplea-game.
the class BattleCalculator method getRolls.
private static int getRolls(final Unit unit, final PlayerID id, final boolean defend, final boolean bombing, final Set<List<UnitSupportAttachment>> supportRulesFriendly, final IntegerMap<UnitSupportAttachment> supportLeftFriendlyCopy, final Set<List<UnitSupportAttachment>> supportRulesEnemy, final IntegerMap<UnitSupportAttachment> supportLeftEnemyCopy, final Collection<TerritoryEffect> territoryEffects) {
final UnitAttachment unitAttachment = UnitAttachment.get(unit.getType());
int rolls;
if (defend) {
rolls = unitAttachment.getDefenseRolls(id);
} else {
rolls = unitAttachment.getAttackRolls(id);
}
final Map<UnitSupportAttachment, LinkedIntegerMap<Unit>> dummyEmptyMap = new HashMap<>();
rolls += DiceRoll.getSupport(unit, supportRulesFriendly, supportLeftFriendlyCopy, dummyEmptyMap, null, false, true);
rolls += DiceRoll.getSupport(unit, supportRulesEnemy, supportLeftEnemyCopy, dummyEmptyMap, null, false, true);
rolls = Math.max(0, rolls);
// if we are strategic bombing, we do not care what the strength of the unit is...
if (bombing) {
return rolls;
}
int strength;
if (defend) {
strength = unitAttachment.getDefense(unit.getOwner());
} else {
strength = unitAttachment.getAttack(unit.getOwner());
}
// TODO: we should add in isMarine bonus too...
strength += DiceRoll.getSupport(unit, supportRulesFriendly, supportLeftFriendlyCopy, dummyEmptyMap, null, true, false);
strength += DiceRoll.getSupport(unit, supportRulesEnemy, supportLeftEnemyCopy, dummyEmptyMap, null, true, false);
strength += TerritoryEffectHelper.getTerritoryCombatBonus(unit.getType(), territoryEffects, defend);
if (strength <= 0) {
rolls = 0;
}
return rolls;
}
use of games.strategy.triplea.attachments.UnitSupportAttachment in project triplea by triplea-game.
the class DiceRoll method getSupport.
/**
* Fills a set and map with the support possibly given by these units.
*
* @param supportsAvailable
* an empty set that will be filled with all support rules grouped into lists of non-stacking rules
* @param supportLeft
* an empty map that will be filled with all the support that can be given in the form of counters
* @param supportUnitsLeft
* an empty map that will be filled with all the support that can be given in the form of counters
* @param defence
* are the receiving units defending?
* @param allies
* are the receiving units allied to the giving units?
*/
public static void getSupport(final List<Unit> unitsGivingTheSupport, final Set<List<UnitSupportAttachment>> supportsAvailable, final IntegerMap<UnitSupportAttachment> supportLeft, final Map<UnitSupportAttachment, LinkedIntegerMap<Unit>> supportUnitsLeft, final GameData data, final boolean defence, final boolean allies) {
if (unitsGivingTheSupport == null || unitsGivingTheSupport.isEmpty()) {
return;
}
for (final UnitSupportAttachment rule : UnitSupportAttachment.get(data)) {
if (rule.getPlayers().isEmpty()) {
continue;
}
if (!((defence && rule.getDefence()) || (!defence && rule.getOffence()))) {
continue;
}
if (!((allies && rule.getAllied()) || (!allies && rule.getEnemy()))) {
continue;
}
final Predicate<Unit> canSupport = Matches.unitIsOfType((UnitType) rule.getAttachedTo()).and(Matches.unitOwnedBy(rule.getPlayers()));
final List<Unit> supporters = CollectionUtils.getMatches(unitsGivingTheSupport, canSupport);
int numSupport = supporters.size();
if (numSupport <= 0) {
continue;
}
final List<Unit> impArtTechUnits = new ArrayList<>();
if (rule.getImpArtTech()) {
impArtTechUnits.addAll(CollectionUtils.getMatches(supporters, Matches.unitOwnerHasImprovedArtillerySupportTech()));
}
numSupport += impArtTechUnits.size();
supportLeft.put(rule, numSupport * rule.getNumber());
supportUnitsLeft.put(rule, new LinkedIntegerMap<>(supporters, rule.getNumber()));
supportUnitsLeft.get(rule).addAll(impArtTechUnits, rule.getNumber());
final Iterator<List<UnitSupportAttachment>> iter2 = supportsAvailable.iterator();
List<UnitSupportAttachment> ruleType = null;
boolean found = false;
final String bonusType = rule.getBonusType();
while (iter2.hasNext()) {
ruleType = iter2.next();
if (ruleType.get(0).getBonusType().equals(bonusType)) {
found = true;
break;
}
}
if (!found) {
ruleType = new ArrayList<>();
supportsAvailable.add(ruleType);
}
if (ruleType != null) {
ruleType.add(rule);
}
}
sortSupportRules(supportsAvailable, defence, allies);
}
use of games.strategy.triplea.attachments.UnitSupportAttachment in project triplea by triplea-game.
the class ProTransportUtils method getUnitsToTransportFromTerritories.
// TODO: this needs fixed to consider whether a valid route exists to load all units
public static List<Unit> getUnitsToTransportFromTerritories(final PlayerID player, final Unit transport, final Set<Territory> territoriesToLoadFrom, final List<Unit> unitsToIgnore, final Predicate<Unit> validUnitMatch) {
final List<Unit> selectedUnits = new ArrayList<>();
// Get units if transport already loaded
if (TransportTracker.isTransporting(transport)) {
selectedUnits.addAll(TransportTracker.transporting(transport));
} else {
// Get all units that can be transported
final List<Unit> units = new ArrayList<>();
for (final Territory loadFrom : territoriesToLoadFrom) {
units.addAll(loadFrom.getUnits().getMatches(validUnitMatch));
}
units.removeAll(unitsToIgnore);
// Sort units by attack
units.sort((o1, o2) -> {
// Very rough way to add support power
final Set<UnitSupportAttachment> supportAttachments1 = UnitSupportAttachment.get(o1.getType());
int maxSupport1 = 0;
for (final UnitSupportAttachment usa : supportAttachments1) {
if (usa.getAllied() && usa.getOffence() && usa.getBonus() > maxSupport1) {
maxSupport1 = usa.getBonus();
}
}
final int attack1 = UnitAttachment.get(o1.getType()).getAttack(player) + maxSupport1;
final Set<UnitSupportAttachment> supportAttachments2 = UnitSupportAttachment.get(o2.getType());
int maxSupport2 = 0;
for (final UnitSupportAttachment usa : supportAttachments2) {
if (usa.getAllied() && usa.getOffence() && usa.getBonus() > maxSupport2) {
maxSupport2 = usa.getBonus();
}
}
final int attack2 = UnitAttachment.get(o2.getType()).getAttack(player) + maxSupport2;
return attack2 - attack1;
});
// Get best units that can be loaded
selectedUnits.addAll(selectUnitsToTransportFromList(transport, units));
}
return selectedUnits;
}
use of games.strategy.triplea.attachments.UnitSupportAttachment in project triplea by triplea-game.
the class ProPurchaseOption method calculateSupportFactor.
// TODO: doesn't consider enemy support
private double calculateSupportFactor(final List<Unit> ownedLocalUnits, final List<Unit> unitsToPlace, final GameData data, final boolean defense) {
if ((!isAttackSupport && !defense) || (!isDefenseSupport && defense)) {
return 0;
}
final List<Unit> units = new ArrayList<>(ownedLocalUnits);
units.addAll(unitsToPlace);
units.addAll(unitType.create(1, player, true));
final Set<List<UnitSupportAttachment>> supportsAvailable = new HashSet<>();
final IntegerMap<UnitSupportAttachment> supportLeft = new IntegerMap<>();
DiceRoll.getSupport(units, supportsAvailable, supportLeft, new HashMap<>(), data, defense, true);
double totalSupportFactor = 0;
for (final UnitSupportAttachment usa : unitSupportAttachments) {
for (final List<UnitSupportAttachment> bonusType : supportsAvailable) {
if (!bonusType.contains(usa)) {
continue;
}
// Find number of support provided and supportable units
int numAddedSupport = usa.getNumber();
if (usa.getImpArtTech() && TechTracker.hasImprovedArtillerySupport(player)) {
numAddedSupport *= 2;
}
int numSupportProvided = -numAddedSupport;
final Set<Unit> supportableUnits = new HashSet<>();
for (final UnitSupportAttachment usa2 : bonusType) {
numSupportProvided += supportLeft.getInt(usa2);
supportableUnits.addAll(CollectionUtils.getMatches(units, Matches.unitIsOfTypes(usa2.getUnitType())));
}
final int numSupportableUnits = supportableUnits.size();
// Find ratio of supportable to support units (optimal 2 to 1)
final int numExtraSupportableUnits = Math.max(0, numSupportableUnits - numSupportProvided);
// Ranges from 0 to 1
final double ratio = Math.min(1, 2.0 * numExtraSupportableUnits / (numSupportableUnits + numAddedSupport));
// Find approximate strength bonus provided
double bonus = 0;
if (usa.getStrength()) {
bonus += usa.getBonus();
}
if (usa.getRoll()) {
bonus += (usa.getBonus() * data.getDiceSides() * 0.75);
}
// Find support factor value
final double supportFactor = Math.pow(numAddedSupport * 0.9, 0.9) * bonus * ratio;
totalSupportFactor += supportFactor;
ProLogger.trace(unitType.getName() + ", bonusType=" + usa.getBonusType() + ", supportFactor=" + supportFactor + ", numSupportProvided=" + numSupportProvided + ", numSupportableUnits=" + numSupportableUnits + ", numAddedSupport=" + numAddedSupport + ", ratio=" + ratio + ", bonus=" + bonus);
}
}
ProLogger.debug(unitType.getName() + ", defense=" + defense + ", totalSupportFactor=" + totalSupportFactor);
return totalSupportFactor;
}
use of games.strategy.triplea.attachments.UnitSupportAttachment in project triplea by triplea-game.
the class DiceRoll method getSupport.
/**
* Returns the support for this unit type, and decrements the supportLeft counters.
*
* @return the bonus given to the unit
*/
public static int getSupport(final Unit unit, final Set<List<UnitSupportAttachment>> supportsAvailable, final IntegerMap<UnitSupportAttachment> supportLeft, final Map<UnitSupportAttachment, LinkedIntegerMap<Unit>> supportUnitsLeft, final Map<Unit, IntegerMap<Unit>> unitSupportMap, final boolean strength, final boolean rolls) {
int givenSupport = 0;
for (final List<UnitSupportAttachment> bonusType : supportsAvailable) {
for (final UnitSupportAttachment rule : bonusType) {
if (!((strength && rule.getStrength()) || (rolls && rule.getRoll()))) {
continue;
}
final Set<UnitType> types = rule.getUnitType();
if (types != null && types.contains(unit.getType()) && supportLeft.getInt(rule) > 0) {
givenSupport += rule.getBonus();
supportLeft.add(rule, -1);
final LinkedIntegerMap<Unit> supportersLeft = supportUnitsLeft.get(rule);
if (supportersLeft != null) {
final Set<Unit> supporters = supportersLeft.keySet();
if (!supporters.isEmpty()) {
final Unit u = supporters.iterator().next();
supportUnitsLeft.get(rule).add(u, -1);
if (supportUnitsLeft.get(rule).getInt(u) <= 0) {
supportUnitsLeft.get(rule).removeKey(u);
}
if (unitSupportMap.containsKey(u)) {
unitSupportMap.get(u).add(unit, rule.getBonus());
} else {
unitSupportMap.put(u, new IntegerMap<>(unit, rule.getBonus()));
}
}
}
break;
}
}
}
return givenSupport;
}
Aggregations