use of games.strategy.triplea.attachments.UnitAttachment in project triplea by triplea-game.
the class WeakAi method populateTransportLoad.
private void populateTransportLoad(final GameData data, final List<Collection<Unit>> moveUnits, final List<Route> moveRoutes, final List<Collection<Unit>> transportsToLoad, final PlayerID player) {
if (!isAmphibAttack(player, data)) {
return;
}
final Territory capitol = TerritoryAttachment.getFirstOwnedCapitalOrFirstUnownedCapital(player, data);
if (capitol == null || !capitol.getOwner().equals(player)) {
return;
}
List<Unit> unitsToLoad = capitol.getUnits().getMatches(Matches.unitIsInfrastructure().negate());
unitsToLoad = CollectionUtils.getMatches(unitsToLoad, Matches.unitIsOwnedBy(getPlayerId()));
for (final Territory neighbor : data.getMap().getNeighbors(capitol)) {
if (!neighbor.isWater()) {
continue;
}
final List<Unit> units = new ArrayList<>();
for (final Unit transport : neighbor.getUnits().getMatches(Matches.unitIsOwnedBy(player))) {
int free = TransportTracker.getAvailableCapacity(transport);
if (free <= 0) {
continue;
}
final Iterator<Unit> iter = unitsToLoad.iterator();
while (iter.hasNext() && free > 0) {
final Unit current = iter.next();
final UnitAttachment ua = UnitAttachment.get(current.getType());
if (ua.getIsAir()) {
continue;
}
if (ua.getTransportCost() <= free) {
iter.remove();
free -= ua.getTransportCost();
units.add(current);
}
}
}
if (units.size() > 0) {
final Route route = new Route();
route.setStart(capitol);
route.add(neighbor);
moveUnits.add(units);
moveRoutes.add(route);
transportsToLoad.add(neighbor.getUnits().getMatches(Matches.unitIsTransport()));
}
}
}
use of games.strategy.triplea.attachments.UnitAttachment in project triplea by triplea-game.
the class ProTechAi method strength.
/**
* Get a quick and dirty estimate of the strength of some units in a battle.
*
* @param units - the units to measure
* @param attacking - are the units on attack or defense
* @param sea - calculate the strength of the units in a sea or land battle?
*/
private static float strength(final Collection<Unit> units, final boolean attacking, final boolean sea, final boolean transportsFirst) {
float strength = 0.0F;
if (units.isEmpty()) {
return strength;
}
if (attacking && units.stream().noneMatch(Matches.unitHasAttackValueOfAtLeast(1)) || !attacking && units.stream().noneMatch(Matches.unitHasDefendValueOfAtLeast(1))) {
return strength;
}
for (final Unit u : units) {
final UnitAttachment unitAttachment = UnitAttachment.get(u.getType());
if (unitAttachment.getIsInfrastructure()) {
if (unitAttachment.getIsSea() == sea) {
final int unitAttack = unitAttachment.getAttack(u.getOwner());
// BB = 6.0; AC=2.0/4.0; SUB=3.0; DS=4.0; TR=0.50/2.0; F=4.0/5.0; B=5.0/2.0;
// played with this value a good bit
strength += 1.00F;
if (attacking) {
strength += unitAttack * unitAttachment.getHitPoints();
} else {
strength += unitAttachment.getDefense(u.getOwner()) * unitAttachment.getHitPoints();
}
if (attacking && unitAttack == 0) {
strength -= 0.50F;
}
if (unitAttack == 0 && unitAttachment.getTransportCapacity() > 0 && !transportsFirst) {
// only allow transport to have 0.35 on defense; none on attack
strength -= 0.50F;
}
} else if (unitAttachment.getIsAir() == sea) {
strength += 1.00F;
if (attacking) {
strength += unitAttachment.getAttack(u.getOwner()) * unitAttachment.getAttackRolls(u.getOwner());
} else {
strength += unitAttachment.getDefense(u.getOwner());
}
}
}
}
if (attacking && !sea) {
final int art = CollectionUtils.countMatches(units, Matches.unitIsArtillery());
final int artSupport = CollectionUtils.countMatches(units, Matches.unitIsArtillerySupportable());
strength += Math.min(art, artSupport);
}
return strength;
}
use of games.strategy.triplea.attachments.UnitAttachment in project triplea by triplea-game.
the class ProSortMoveOptionsUtils method sortUnitNeededOptionsThenAttack.
public static Map<Unit, Set<Territory>> sortUnitNeededOptionsThenAttack(final PlayerID player, final Map<Unit, Set<Territory>> unitAttackOptions, final Map<Territory, ProTerritory> attackMap, final Map<Unit, Territory> unitTerritoryMap, final ProOddsCalculator calc) {
final GameData data = ProData.getData();
final List<Map.Entry<Unit, Set<Territory>>> list = new ArrayList<>(unitAttackOptions.entrySet());
list.sort((o1, o2) -> {
// Sort by number of territories that still need units
int numOptions1 = 0;
for (final Territory t : o1.getValue()) {
final ProTerritory patd = attackMap.get(t);
if (patd.getBattleResult() == null) {
patd.setBattleResult(calc.estimateAttackBattleResults(t, patd.getUnits(), patd.getMaxEnemyDefenders(player, data), patd.getBombardTerritoryMap().keySet()));
}
if (!patd.isCurrentlyWins()) {
numOptions1++;
}
}
int numOptions2 = 0;
for (final Territory t : o2.getValue()) {
final ProTerritory patd = attackMap.get(t);
if (patd.getBattleResult() == null) {
patd.setBattleResult(calc.estimateAttackBattleResults(t, patd.getUnits(), patd.getMaxEnemyDefenders(player, data), patd.getBombardTerritoryMap().keySet()));
}
if (!patd.isCurrentlyWins()) {
numOptions2++;
}
}
if (numOptions1 != numOptions2) {
return (numOptions1 - numOptions2);
}
if (numOptions1 == 0) {
return 0;
}
// Sort by attack efficiency
int minPower1 = Integer.MAX_VALUE;
for (final Territory t : o1.getValue()) {
if (!attackMap.get(t).isCurrentlyWins()) {
final List<Unit> defendingUnits = t.getUnits().getMatches(Matches.enemyUnit(player, data));
final List<Unit> sortedUnitsList = new ArrayList<>(attackMap.get(t).getUnits());
sortedUnitsList.sort(new UnitBattleComparator(false, ProData.unitValueMap, TerritoryEffectHelper.getEffects(t), data, false, false));
Collections.reverse(sortedUnitsList);
final int powerWithout = DiceRoll.getTotalPower(DiceRoll.getUnitPowerAndRollsForNormalBattles(sortedUnitsList, defendingUnits, false, false, data, t, TerritoryEffectHelper.getEffects(t), false, null), data);
sortedUnitsList.add(o1.getKey());
sortedUnitsList.sort(new UnitBattleComparator(false, ProData.unitValueMap, TerritoryEffectHelper.getEffects(t), data, false, false));
Collections.reverse(sortedUnitsList);
final int powerWith = DiceRoll.getTotalPower(DiceRoll.getUnitPowerAndRollsForNormalBattles(sortedUnitsList, defendingUnits, false, false, data, t, TerritoryEffectHelper.getEffects(t), false, null), data);
final int power = powerWith - powerWithout;
if (power < minPower1) {
minPower1 = power;
}
}
}
final UnitAttachment ua1 = UnitAttachment.get(o1.getKey().getType());
if (ua1.getIsAir()) {
minPower1 *= 10;
}
final double attackEfficiency1 = (double) minPower1 / ProData.unitValueMap.getInt(o1.getKey().getType());
int minPower2 = Integer.MAX_VALUE;
for (final Territory t : o2.getValue()) {
if (!attackMap.get(t).isCurrentlyWins()) {
final List<Unit> defendingUnits = t.getUnits().getMatches(Matches.enemyUnit(player, data));
final List<Unit> sortedUnitsList = new ArrayList<>(attackMap.get(t).getUnits());
sortedUnitsList.sort(new UnitBattleComparator(false, ProData.unitValueMap, TerritoryEffectHelper.getEffects(t), data, false, false));
Collections.reverse(sortedUnitsList);
final int powerWithout = DiceRoll.getTotalPower(DiceRoll.getUnitPowerAndRollsForNormalBattles(sortedUnitsList, defendingUnits, false, false, data, t, TerritoryEffectHelper.getEffects(t), false, null), data);
sortedUnitsList.add(o2.getKey());
sortedUnitsList.sort(new UnitBattleComparator(false, ProData.unitValueMap, TerritoryEffectHelper.getEffects(t), data, false, false));
Collections.reverse(sortedUnitsList);
final int powerWith = DiceRoll.getTotalPower(DiceRoll.getUnitPowerAndRollsForNormalBattles(sortedUnitsList, defendingUnits, false, false, data, t, TerritoryEffectHelper.getEffects(t), false, null), data);
final int power = powerWith - powerWithout;
if (power < minPower2) {
minPower2 = power;
}
}
}
final UnitAttachment ua2 = UnitAttachment.get(o2.getKey().getType());
if (ua2.getIsAir()) {
minPower2 *= 10;
}
final double attackEfficiency2 = (double) minPower2 / ProData.unitValueMap.getInt(o2.getKey().getType());
if (attackEfficiency1 != attackEfficiency2) {
return (attackEfficiency1 < attackEfficiency2) ? 1 : -1;
}
// Check if unit types are equal and is air then sort by average distance
if (o1.getKey().getType().equals(o2.getKey().getType())) {
final boolean isAirUnit = UnitAttachment.get(o1.getKey().getType()).getIsAir();
if (isAirUnit) {
int distance1 = 0;
for (final Territory t : o1.getValue()) {
if (!attackMap.get(t).isCurrentlyWins()) {
distance1 += data.getMap().getDistance_IgnoreEndForCondition(unitTerritoryMap.get(o1.getKey()), t, ProMatches.territoryCanMoveAirUnitsAndNoAa(player, data, true));
}
}
int distance2 = 0;
for (final Territory t : o2.getValue()) {
if (!attackMap.get(t).isCurrentlyWins()) {
distance2 += data.getMap().getDistance_IgnoreEndForCondition(unitTerritoryMap.get(o2.getKey()), t, ProMatches.territoryCanMoveAirUnitsAndNoAa(player, data, true));
}
}
if (distance1 != distance2) {
return distance1 - distance2;
}
}
}
return o1.getKey().getType().getName().compareTo(o2.getKey().getType().getName());
});
final Map<Unit, Set<Territory>> sortedUnitAttackOptions = new LinkedHashMap<>();
for (final Map.Entry<Unit, Set<Territory>> entry : list) {
sortedUnitAttackOptions.put(entry.getKey(), entry.getValue());
}
return sortedUnitAttackOptions;
}
use of games.strategy.triplea.attachments.UnitAttachment in project triplea by triplea-game.
the class AiUtils method interleaveCarriersAndPlanes.
static List<Unit> interleaveCarriersAndPlanes(final List<Unit> units, final int planesThatDontNeedToLand) {
if (units.stream().noneMatch(Matches.unitIsCarrier()) || units.stream().noneMatch(Matches.unitCanLandOnCarrier())) {
return units;
}
// Clone the current list
final ArrayList<Unit> result = new ArrayList<>(units);
Unit seekedCarrier = null;
int indexToPlaceCarrierAt = -1;
int spaceLeftOnSeekedCarrier = -1;
int processedPlaneCount = 0;
final List<Unit> filledCarriers = new ArrayList<>();
// Loop through all units, starting from the right, and rearrange units
for (int i = result.size() - 1; i >= 0; i--) {
final Unit unit = result.get(i);
final UnitAttachment ua = UnitAttachment.get(unit.getType());
// If this is a plane
if (ua.getCarrierCost() > 0) {
// If we haven't ignored enough trailing planes
if (processedPlaneCount < planesThatDontNeedToLand) {
// Increase number of trailing planes ignored
processedPlaneCount++;
// And skip any processing
continue;
}
// If this is the first carrier seek
if (seekedCarrier == null) {
final int seekedCarrierIndex = getIndexOfLastUnitMatching(result, Matches.unitIsCarrier().and(Matches.isNotInList(filledCarriers)), result.size() - 1);
if (seekedCarrierIndex == -1) {
// No carriers left
break;
}
seekedCarrier = result.get(seekedCarrierIndex);
// Tell the code to insert carrier to the right of this plane
indexToPlaceCarrierAt = i + 1;
spaceLeftOnSeekedCarrier = UnitAttachment.get(seekedCarrier.getType()).getCarrierCapacity();
}
spaceLeftOnSeekedCarrier -= ua.getCarrierCost();
// If the carrier has been filled or overflowed
if (spaceLeftOnSeekedCarrier <= 0) {
if (spaceLeftOnSeekedCarrier < 0) {
// Move current unit index up one, so we re-process this unit (since it can't fit on the current seeked
// carrier)
i++;
}
// If the seeked carrier is earlier in the list
if (result.indexOf(seekedCarrier) < i) {
// Move the carrier up to the planes by: removing carrier, then reinserting it
// (index decreased cause removal of carrier reduced indexes)
result.remove(seekedCarrier);
result.add(indexToPlaceCarrierAt - 1, seekedCarrier);
// We removed carrier in earlier part of list, so decrease index
i--;
filledCarriers.add(seekedCarrier);
// Find the next carrier
seekedCarrier = getLastUnitMatching(result, Matches.unitIsCarrier().and(Matches.isNotInList(filledCarriers)), result.size() - 1);
if (seekedCarrier == null) {
// No carriers left
break;
}
// Place next carrier right before this plane (which just filled the old carrier that was just moved)
indexToPlaceCarrierAt = i;
spaceLeftOnSeekedCarrier = UnitAttachment.get(seekedCarrier.getType()).getCarrierCapacity();
} else {
// If it's later in the list
final int oldIndex = result.indexOf(seekedCarrier);
int carrierPlaceLocation = indexToPlaceCarrierAt;
// Place carrier where it's supposed to go
result.remove(seekedCarrier);
if (oldIndex < indexToPlaceCarrierAt) {
carrierPlaceLocation--;
}
result.add(carrierPlaceLocation, seekedCarrier);
filledCarriers.add(seekedCarrier);
// Move the planes down to the carrier
final List<Unit> planesBetweenHereAndCarrier = new ArrayList<>();
for (int i2 = i; i2 < carrierPlaceLocation; i2++) {
final Unit unit2 = result.get(i2);
final UnitAttachment ua2 = UnitAttachment.get(unit2.getType());
if (ua2.getCarrierCost() > 0) {
planesBetweenHereAndCarrier.add(unit2);
}
}
// Invert list, so they are inserted in the same order
Collections.reverse(planesBetweenHereAndCarrier);
int planeMoveCount = 0;
for (final Unit plane : planesBetweenHereAndCarrier) {
result.remove(plane);
// Insert each plane right before carrier (index decreased cause removal of carrier reduced indexes)
result.add(carrierPlaceLocation - 1, plane);
planeMoveCount++;
}
// Find the next carrier
seekedCarrier = getLastUnitMatching(result, Matches.unitIsCarrier().and(Matches.isNotInList(filledCarriers)), result.size() - 1);
if (seekedCarrier == null) {
// No carriers left
break;
}
// Since we only moved planes up, just reduce next carrier place index by plane move count
indexToPlaceCarrierAt = carrierPlaceLocation - planeMoveCount;
spaceLeftOnSeekedCarrier = UnitAttachment.get(seekedCarrier.getType()).getCarrierCapacity();
}
}
}
}
return result;
}
use of games.strategy.triplea.attachments.UnitAttachment in project triplea by triplea-game.
the class WW2V3Year41Test method testBombardStrengthVariable.
@Test
public void testBombardStrengthVariable() {
final MoveDelegate move = moveDelegate(gameData);
final ITestDelegateBridge bridge = getDelegateBridge(italians(gameData));
when(dummyPlayer.selectShoreBombard(any())).thenReturn(true);
bridge.setRemote(dummyPlayer);
bridge.setStepName("CombatMove");
move.setDelegateBridgeAndPlayer(bridge);
move.start();
final Territory sz14 = territory("14 Sea Zone", gameData);
final Territory sz15 = territory("15 Sea Zone", gameData);
final Territory eg = territory("Egypt", gameData);
final Territory balkans = territory("Balkans", gameData);
// Clear all units
removeFrom(eg, eg.getUnits().getUnits());
removeFrom(sz14, sz14.getUnits().getUnits());
// Add 2 inf to the attacked terr
final PlayerID british = GameDataTestUtil.british(gameData);
addTo(eg, infantry(gameData).create(2, british));
// create/load the destroyers and transports
final PlayerID italians = GameDataTestUtil.italians(gameData);
addTo(sz14, transport(gameData).create(1, italians));
addTo(sz14, destroyer(gameData).create(2, italians));
// load the transports
load(balkans.getUnits().getMatches(Matches.unitIsLandTransportable()), new Route(balkans, sz14));
// move the fleet
move(sz14.getUnits().getUnits(), new Route(sz14, sz15));
// unload the transports
move(sz15.getUnits().getMatches(Matches.unitIsLand()), new Route(sz15, eg));
move.end();
// Set the tech for DDs bombard
// ww2v3 doesn't have this tech, so this does nothing...
// TechAttachment.get(italians).setDestroyerBombard("true");
UnitAttachment.get(destroyer(gameData)).setCanBombard("true");
// Set the bombard strength for the DDs
final Collection<Unit> dds = CollectionUtils.getMatches(sz15.getUnits().getUnits(), Matches.unitIsDestroyer());
final Iterator<Unit> ddIter = dds.iterator();
while (ddIter.hasNext()) {
final Unit unit = ddIter.next();
final UnitAttachment ua = UnitAttachment.get(unit.getType());
ua.setBombard(3);
}
// start the battle phase, this will ask the user to bombard
battleDelegate(gameData).setDelegateBridgeAndPlayer(bridge);
BattleDelegate.doInitialize(battleDelegate(gameData).getBattleTracker(), bridge);
battleDelegate(gameData).addBombardmentSources();
final MustFightBattle mfb = (MustFightBattle) AbstractMoveDelegate.getBattleTracker(gameData).getPendingBattle(eg, false, null);
assertNotNull(mfb);
// Show that bombard casualties can return fire
// destroyer bombard hit/miss on rolls of 4 & 3
// landing inf miss
// defending inf hit
bridge.setRandomSource(new ScriptedRandomSource(3, 2, 6, 6, 1, 1));
battleDelegate(gameData).setDelegateBridgeAndPlayer(bridge);
BattleDelegate.doInitialize(battleDelegate(gameData).getBattleTracker(), bridge);
battleDelegate(gameData).addBombardmentSources();
fight(battleDelegate(gameData), eg);
// 1 defending inf remaining
assertEquals(1, eg.getUnits().size());
}
Aggregations