Search in sources :

Example 21 with UnitAttachment

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()));
        }
    }
}
Also used : UnitAttachment(games.strategy.triplea.attachments.UnitAttachment) Territory(games.strategy.engine.data.Territory) ArrayList(java.util.ArrayList) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) Route(games.strategy.engine.data.Route)

Example 22 with UnitAttachment

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;
}
Also used : UnitAttachment(games.strategy.triplea.attachments.UnitAttachment) Unit(games.strategy.engine.data.Unit)

Example 23 with UnitAttachment

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;
}
Also used : Territory(games.strategy.engine.data.Territory) ProTerritory(games.strategy.triplea.ai.pro.data.ProTerritory) GameData(games.strategy.engine.data.GameData) Set(java.util.Set) ProTerritory(games.strategy.triplea.ai.pro.data.ProTerritory) ArrayList(java.util.ArrayList) Unit(games.strategy.engine.data.Unit) LinkedHashMap(java.util.LinkedHashMap) UnitBattleComparator(games.strategy.triplea.delegate.UnitBattleComparator) UnitAttachment(games.strategy.triplea.attachments.UnitAttachment) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Example 24 with UnitAttachment

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;
}
Also used : UnitAttachment(games.strategy.triplea.attachments.UnitAttachment) ArrayList(java.util.ArrayList) Unit(games.strategy.engine.data.Unit)

Example 25 with UnitAttachment

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());
}
Also used : UnitAttachment(games.strategy.triplea.attachments.UnitAttachment) PlayerID(games.strategy.engine.data.PlayerID) Territory(games.strategy.engine.data.Territory) ITestDelegateBridge(games.strategy.engine.data.ITestDelegateBridge) ScriptedRandomSource(games.strategy.engine.random.ScriptedRandomSource) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) Route(games.strategy.engine.data.Route) Test(org.junit.jupiter.api.Test)

Aggregations

UnitAttachment (games.strategy.triplea.attachments.UnitAttachment)60 Unit (games.strategy.engine.data.Unit)45 ArrayList (java.util.ArrayList)25 TripleAUnit (games.strategy.triplea.TripleAUnit)23 UnitType (games.strategy.engine.data.UnitType)20 GameData (games.strategy.engine.data.GameData)19 Territory (games.strategy.engine.data.Territory)19 PlayerID (games.strategy.engine.data.PlayerID)12 CompositeChange (games.strategy.engine.data.CompositeChange)8 TerritoryAttachment (games.strategy.triplea.attachments.TerritoryAttachment)7 IntegerMap (games.strategy.util.IntegerMap)6 Collection (java.util.Collection)6 Set (java.util.Set)6 Change (games.strategy.engine.data.Change)5 Resource (games.strategy.engine.data.Resource)5 Tuple (games.strategy.util.Tuple)5 HashSet (java.util.HashSet)5 ITestDelegateBridge (games.strategy.engine.data.ITestDelegateBridge)4 Route (games.strategy.engine.data.Route)4 List (java.util.List)4