Search in sources :

Example 11 with TripleAUnit

use of games.strategy.triplea.TripleAUnit in project triplea by triplea-game.

the class MustFightBattle method clearTransportedByForAlliedAirOnCarrier.

static CompositeChange clearTransportedByForAlliedAirOnCarrier(final Collection<Unit> attackingUnits, final Territory battleSite, final PlayerID attacker, final GameData data) {
    final CompositeChange change = new CompositeChange();
    // Clear the transported_by for successfully won battles where there was an allied air unit held as cargo by an
    // carrier unit
    final Collection<Unit> carriers = CollectionUtils.getMatches(attackingUnits, Matches.unitIsCarrier());
    if (!carriers.isEmpty() && !Properties.getAlliedAirIndependent(data)) {
        final Predicate<Unit> alliedFighters = Matches.isUnitAllied(attacker, data).and(Matches.unitIsOwnedBy(attacker).negate()).and(Matches.unitIsAir()).and(Matches.unitCanLandOnCarrier());
        final Collection<Unit> alliedAirInTerr = CollectionUtils.getMatches(Sets.union(Sets.newHashSet(attackingUnits), Sets.newHashSet(battleSite.getUnits())), alliedFighters);
        for (final Unit fighter : alliedAirInTerr) {
            final TripleAUnit taUnit = (TripleAUnit) fighter;
            if (taUnit.getTransportedBy() != null) {
                final Unit carrierTransportingThisUnit = taUnit.getTransportedBy();
                if (!Matches.unitHasWhenCombatDamagedEffect(UnitAttachment.UNITSMAYNOTLEAVEALLIEDCARRIER).test(carrierTransportingThisUnit)) {
                    change.add(ChangeFactory.unitPropertyChange(fighter, null, TripleAUnit.TRANSPORTED_BY));
                }
            }
        }
    }
    return change;
}
Also used : CompositeChange(games.strategy.engine.data.CompositeChange) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) TripleAUnit(games.strategy.triplea.TripleAUnit)

Example 12 with TripleAUnit

use of games.strategy.triplea.TripleAUnit in project triplea by triplea-game.

the class WeakAi method purchase.

@Override
public void purchase(final boolean purchaseForBid, final int pusToSpend, final IPurchaseDelegate purchaseDelegate, final GameData data, final PlayerID player) {
    if (purchaseForBid) {
        // bid will only buy land units, due to weak ai placement for bid not being able to handle sea units
        final Resource pus = data.getResourceList().getResource(Constants.PUS);
        int leftToSpend = pusToSpend;
        final List<ProductionRule> rules = player.getProductionFrontier().getRules();
        final IntegerMap<ProductionRule> purchase = new IntegerMap<>();
        int minCost = Integer.MAX_VALUE;
        int i = 0;
        while ((minCost == Integer.MAX_VALUE || leftToSpend >= minCost) && i < 100000) {
            i++;
            for (final ProductionRule rule : rules) {
                final NamedAttachable resourceOrUnit = rule.getResults().keySet().iterator().next();
                if (!(resourceOrUnit instanceof UnitType)) {
                    continue;
                }
                final UnitType results = (UnitType) resourceOrUnit;
                if (Matches.unitTypeIsSea().test(results) || Matches.unitTypeIsAir().test(results) || Matches.unitTypeIsInfrastructure().test(results) || Matches.unitTypeIsAaForAnything().test(results) || Matches.unitTypeHasMaxBuildRestrictions().test(results) || Matches.unitTypeConsumesUnitsOnCreation().test(results) || Matches.unitTypeIsStatic(player).test(results)) {
                    continue;
                }
                final int cost = rule.getCosts().getInt(pus);
                if (cost < 1) {
                    continue;
                }
                if (minCost == Integer.MAX_VALUE) {
                    minCost = cost;
                }
                if (minCost > cost) {
                    minCost = cost;
                }
                // give a preference to cheap units
                if (Math.random() * cost < 2) {
                    if (cost <= leftToSpend) {
                        leftToSpend -= cost;
                        purchase.add(rule, 1);
                    }
                }
            }
        }
        purchaseDelegate.purchase(purchase);
        pause();
        return;
    }
    final boolean isAmphib = isAmphibAttack(player, data);
    final Route amphibRoute = getAmphibRoute(player, data);
    final int transportCount = countTransports(data, player);
    final int landUnitCount = countLandUnits(data, player);
    int defUnitsAtAmpibRoute = 0;
    if (isAmphib && amphibRoute != null) {
        defUnitsAtAmpibRoute = amphibRoute.getEnd().getUnits().getUnitCount();
    }
    final Resource pus = data.getResourceList().getResource(Constants.PUS);
    final int totalPu = player.getResources().getQuantity(pus);
    int leftToSpend = totalPu;
    final Territory capitol = TerritoryAttachment.getFirstOwnedCapitalOrFirstUnownedCapital(player, data);
    final List<ProductionRule> rules = player.getProductionFrontier().getRules();
    final IntegerMap<ProductionRule> purchase = new IntegerMap<>();
    final List<RepairRule> repairRules;
    final Predicate<Unit> ourFactories = Matches.unitIsOwnedBy(player).and(Matches.unitCanProduceUnits());
    final List<Territory> repairFactories = CollectionUtils.getMatches(Utils.findUnitTerr(data, ourFactories), Matches.isTerritoryOwnedBy(player));
    // figure out if anything needs to be repaired
    if (player.getRepairFrontier() != null && Properties.getDamageFromBombingDoneToUnitsInsteadOfTerritories(data)) {
        repairRules = player.getRepairFrontier().getRules();
        final IntegerMap<RepairRule> repairMap = new IntegerMap<>();
        final HashMap<Unit, IntegerMap<RepairRule>> repair = new HashMap<>();
        final Map<Unit, Territory> unitsThatCanProduceNeedingRepair = new HashMap<>();
        final int minimumUnitPrice = 3;
        int diff;
        int capProduction = 0;
        Unit capUnit = null;
        Territory capUnitTerritory = null;
        int currentProduction = 0;
        // we should sort this
        Collections.shuffle(repairFactories);
        for (final Territory fixTerr : repairFactories) {
            if (!Matches.territoryIsOwnedAndHasOwnedUnitMatching(player, Matches.unitCanProduceUnitsAndCanBeDamaged()).test(fixTerr)) {
                continue;
            }
            final Unit possibleFactoryNeedingRepair = TripleAUnit.getBiggestProducer(CollectionUtils.getMatches(fixTerr.getUnits().getUnits(), ourFactories), fixTerr, player, data, false);
            if (Matches.unitHasTakenSomeBombingUnitDamage().test(possibleFactoryNeedingRepair)) {
                unitsThatCanProduceNeedingRepair.put(possibleFactoryNeedingRepair, fixTerr);
            }
            if (fixTerr == capitol) {
                capProduction = TripleAUnit.getHowMuchCanUnitProduce(possibleFactoryNeedingRepair, fixTerr, player, data, true, true);
                capUnit = possibleFactoryNeedingRepair;
                capUnitTerritory = fixTerr;
            }
            currentProduction += TripleAUnit.getHowMuchCanUnitProduce(possibleFactoryNeedingRepair, fixTerr, player, data, true, true);
        }
        repairFactories.remove(capitol);
        unitsThatCanProduceNeedingRepair.remove(capUnit);
        // assume minimum unit price is 3, and that we are buying only that... if we over repair, oh well, that is better
        // than under-repairing
        // goal is to be able to produce all our units, and at least half of that production in the capitol
        // 
        // if capitol is super safe, we don't have to do this. and if capitol is under siege, we should repair enough to
        // place all our units here
        int maxUnits = (totalPu - 1) / minimumUnitPrice;
        if ((capProduction <= maxUnits / 2 || repairFactories.isEmpty()) && capUnit != null) {
            for (final RepairRule rrule : repairRules) {
                if (!capUnit.getType().equals(rrule.getResults().keySet().iterator().next())) {
                    continue;
                }
                if (!Matches.territoryIsOwnedAndHasOwnedUnitMatching(player, Matches.unitCanProduceUnitsAndCanBeDamaged()).test(capitol)) {
                    continue;
                }
                final TripleAUnit taUnit = (TripleAUnit) capUnit;
                diff = taUnit.getUnitDamage();
                final int unitProductionAllowNegative = TripleAUnit.getHowMuchCanUnitProduce(capUnit, capUnitTerritory, player, data, false, true) - diff;
                if (!repairFactories.isEmpty()) {
                    diff = Math.min(diff, (maxUnits / 2 - unitProductionAllowNegative) + 1);
                } else {
                    diff = Math.min(diff, (maxUnits - unitProductionAllowNegative));
                }
                diff = Math.min(diff, leftToSpend - minimumUnitPrice);
                if (diff > 0) {
                    if (unitProductionAllowNegative >= 0) {
                        currentProduction += diff;
                    } else {
                        currentProduction += diff + unitProductionAllowNegative;
                    }
                    repairMap.add(rrule, diff);
                    repair.put(capUnit, repairMap);
                    leftToSpend -= diff;
                    purchaseDelegate.purchaseRepair(repair);
                    repair.clear();
                    repairMap.clear();
                    // ideally we would adjust this after each single PU spent, then re-evaluate
                    // everything.
                    maxUnits = (leftToSpend - 1) / minimumUnitPrice;
                }
            }
        }
        int i = 0;
        while (currentProduction < maxUnits && i < 2) {
            for (final RepairRule rrule : repairRules) {
                for (final Unit fixUnit : unitsThatCanProduceNeedingRepair.keySet()) {
                    if (fixUnit == null || !fixUnit.getType().equals(rrule.getResults().keySet().iterator().next())) {
                        continue;
                    }
                    if (!Matches.territoryIsOwnedAndHasOwnedUnitMatching(player, Matches.unitCanProduceUnitsAndCanBeDamaged()).test(unitsThatCanProduceNeedingRepair.get(fixUnit))) {
                        continue;
                    }
                    // territories
                    if (currentProduction >= maxUnits) {
                        continue;
                    }
                    final TripleAUnit taUnit = (TripleAUnit) fixUnit;
                    diff = taUnit.getUnitDamage();
                    final int unitProductionAllowNegative = TripleAUnit.getHowMuchCanUnitProduce(fixUnit, unitsThatCanProduceNeedingRepair.get(fixUnit), player, data, false, true) - diff;
                    if (i == 0) {
                        if (unitProductionAllowNegative < 0) {
                            diff = Math.min(diff, (maxUnits - currentProduction) - unitProductionAllowNegative);
                        } else {
                            diff = Math.min(diff, (maxUnits - currentProduction));
                        }
                    }
                    diff = Math.min(diff, leftToSpend - minimumUnitPrice);
                    if (diff > 0) {
                        if (unitProductionAllowNegative >= 0) {
                            currentProduction += diff;
                        } else {
                            currentProduction += diff + unitProductionAllowNegative;
                        }
                        repairMap.add(rrule, diff);
                        repair.put(fixUnit, repairMap);
                        leftToSpend -= diff;
                        purchaseDelegate.purchaseRepair(repair);
                        repair.clear();
                        repairMap.clear();
                        // ideally we would adjust this after each single PU spent, then re-evaluate
                        // everything.
                        maxUnits = (leftToSpend - 1) / minimumUnitPrice;
                    }
                }
            }
            repairFactories.add(capitol);
            if (capUnit != null) {
                unitsThatCanProduceNeedingRepair.put(capUnit, capUnitTerritory);
            }
            i++;
        }
    }
    int minCost = Integer.MAX_VALUE;
    int i = 0;
    while ((minCost == Integer.MAX_VALUE || leftToSpend >= minCost) && i < 100000) {
        i++;
        for (final ProductionRule rule : rules) {
            final NamedAttachable resourceOrUnit = rule.getResults().keySet().iterator().next();
            if (!(resourceOrUnit instanceof UnitType)) {
                continue;
            }
            final UnitType results = (UnitType) resourceOrUnit;
            if (Matches.unitTypeIsAir().test(results) || Matches.unitTypeIsInfrastructure().test(results) || Matches.unitTypeIsAaForAnything().test(results) || Matches.unitTypeHasMaxBuildRestrictions().test(results) || Matches.unitTypeConsumesUnitsOnCreation().test(results) || Matches.unitTypeIsStatic(player).test(results)) {
                continue;
            }
            final int transportCapacity = UnitAttachment.get(results).getTransportCapacity();
            // buy transports if we can be amphibious
            if (Matches.unitTypeIsSea().test(results)) {
                if (!isAmphib || transportCapacity <= 0) {
                    continue;
                }
            }
            final int cost = rule.getCosts().getInt(pus);
            if (cost < 1) {
                continue;
            }
            if (minCost == Integer.MAX_VALUE) {
                minCost = cost;
            }
            if (minCost > cost) {
                minCost = cost;
            }
            // give a preferene to cheap units, and to transports
            // but dont go overboard with buying transports
            int goodNumberOfTransports = 0;
            final boolean isTransport = transportCapacity > 0;
            if (amphibRoute != null) {
                // 25% transports - can be more if frontier is far away
                goodNumberOfTransports = (landUnitCount / 4);
                // boost for transport production
                if (isTransport && defUnitsAtAmpibRoute > goodNumberOfTransports && landUnitCount > defUnitsAtAmpibRoute && defUnitsAtAmpibRoute > transportCount) {
                    final int transports = (leftToSpend / cost);
                    leftToSpend -= cost * transports;
                    purchase.add(rule, transports);
                    continue;
                }
            }
            final boolean buyBecauseTransport = (Math.random() < 0.7 && transportCount < goodNumberOfTransports) || Math.random() < 0.10;
            final boolean dontBuyBecauseTooManyTransports = transportCount > 2 * goodNumberOfTransports;
            if ((!isTransport && Math.random() * cost < 2) || (isTransport && buyBecauseTransport && !dontBuyBecauseTooManyTransports)) {
                if (cost <= leftToSpend) {
                    leftToSpend -= cost;
                    purchase.add(rule, 1);
                }
            }
        }
    }
    purchaseDelegate.purchase(purchase);
    pause();
}
Also used : IntegerMap(games.strategy.util.IntegerMap) Territory(games.strategy.engine.data.Territory) NamedAttachable(games.strategy.engine.data.NamedAttachable) HashMap(java.util.HashMap) Resource(games.strategy.engine.data.Resource) RepairRule(games.strategy.engine.data.RepairRule) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) TripleAUnit(games.strategy.triplea.TripleAUnit) ProductionRule(games.strategy.engine.data.ProductionRule) UnitType(games.strategy.engine.data.UnitType) Route(games.strategy.engine.data.Route)

Example 13 with TripleAUnit

use of games.strategy.triplea.TripleAUnit in project triplea by triplea-game.

the class WW2V3Year41Test method testParatroopersFlyOverBlitzedTerritory.

@Test
public void testParatroopersFlyOverBlitzedTerritory() {
    // We should be able to blitz a territory, then fly over it with paratroops to battle.
    final PlayerID germans = germans(gameData);
    final Territory germany = territory("Germany", gameData);
    final Territory poland = territory("Poland", gameData);
    final Territory eastPoland = territory("East Poland", gameData);
    final Territory beloRussia = territory("Belorussia", gameData);
    // Clear East Poland
    removeFrom(eastPoland, eastPoland.getUnits().getUnits());
    // Set up test
    final ITestDelegateBridge bridge = getDelegateBridge(germans);
    bridge.setStepName("CombatMove");
    moveDelegate(gameData).setDelegateBridgeAndPlayer(bridge);
    moveDelegate(gameData).start();
    TechAttachment.get(germans).setParatroopers("true");
    List<Unit> paratrooper = germany.getUnits().getMatches(Matches.unitIsAirTransportable());
    paratrooper = paratrooper.subList(0, 1);
    final List<Unit> bomberAndParatroop = new ArrayList<>(paratrooper);
    bomberAndParatroop.addAll(germany.getUnits().getMatches(Matches.unitIsAirTransport()));
    final List<Unit> tanks = poland.getUnits().getMatches(Matches.unitCanBlitz());
    move(tanks, new Route(poland, eastPoland, beloRussia));
    final List<Unit> airTransports = CollectionUtils.getMatches(bomberAndParatroop, Matches.unitIsAirTransport());
    for (final Unit airTransport : airTransports) {
        for (final Unit unit : paratrooper) {
            final Change change = TransportTracker.loadTransportChange((TripleAUnit) airTransport, unit);
            bridge.addChange(change);
        }
    }
    // Verify paratroops can overfly blitzed territory
    final String error = moveDelegate(gameData).move(bomberAndParatroop, new Route(germany, poland, eastPoland, beloRussia));
    assertValid(error);
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) Territory(games.strategy.engine.data.Territory) ArrayList(java.util.ArrayList) ITestDelegateBridge(games.strategy.engine.data.ITestDelegateBridge) Change(games.strategy.engine.data.Change) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) Route(games.strategy.engine.data.Route) Test(org.junit.jupiter.api.Test)

Example 14 with TripleAUnit

use of games.strategy.triplea.TripleAUnit in project triplea by triplea-game.

the class WW2V3Year41Test method testParatroopersMoveTwice.

@Test
public void testParatroopersMoveTwice() {
    // After a battle move to put a bomber + infantry (paratroop) in a first enemy
    // territory, you can make a new move (in the same battle move round) to put
    // bomber+ infantry in a more internal enemy territory.
    final PlayerID germans = germans(gameData);
    final Territory germany = territory("Germany", gameData);
    final Territory poland = territory("Poland", gameData);
    final Territory eastPoland = territory("East Poland", gameData);
    final Territory beloRussia = territory("Belorussia", gameData);
    final ITestDelegateBridge bridge = getDelegateBridge(germans);
    bridge.setStepName("CombatMove");
    moveDelegate(gameData).setDelegateBridgeAndPlayer(bridge);
    moveDelegate(gameData).start();
    TechAttachment.get(germans).setParatroopers("true");
    List<Unit> paratroopers = germany.getUnits().getMatches(Matches.unitIsAirTransportable());
    paratroopers = paratroopers.subList(0, 1);
    final List<Unit> bomberAndParatroop = new ArrayList<>(paratroopers);
    bomberAndParatroop.addAll(germany.getUnits().getMatches(Matches.unitIsAirTransport()));
    final Route route = new Route(germany, poland, eastPoland);
    final List<Unit> airTransports = germany.getUnits().getMatches(Matches.unitIsAirTransport());
    for (final Unit airTransport : airTransports) {
        for (final Unit unit : paratroopers) {
            final Change change = TransportTracker.loadTransportChange((TripleAUnit) airTransport, unit);
            bridge.addChange(change);
        }
    }
    // move the units to east poland
    // airTransports
    String error = moveDelegate(gameData).move(bomberAndParatroop, route);
    assertValid(error);
    // try to move them further, this should fail
    error = moveDelegate(gameData).move(bomberAndParatroop, new Route(eastPoland, beloRussia));
    assertError(error);
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) Territory(games.strategy.engine.data.Territory) ArrayList(java.util.ArrayList) ITestDelegateBridge(games.strategy.engine.data.ITestDelegateBridge) Change(games.strategy.engine.data.Change) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) Route(games.strategy.engine.data.Route) Test(org.junit.jupiter.api.Test)

Example 15 with TripleAUnit

use of games.strategy.triplea.TripleAUnit in project triplea by triplea-game.

the class RevisedTest method testLoadDependencies.

@Test
public void testLoadDependencies() {
    final Territory sz5 = gameData.getMap().getTerritory("5 Sea Zone");
    final Territory eastEurope = gameData.getMap().getTerritory("Eastern Europe");
    final Territory norway = gameData.getMap().getTerritory("Norway");
    final UnitType infantryType = GameDataTestUtil.infantry(gameData);
    final PlayerID germans = GameDataTestUtil.germans(gameData);
    final MoveDelegate moveDelegate = (MoveDelegate) gameData.getDelegateList().getDelegate("move");
    final ITestDelegateBridge bridge = getDelegateBridge(germans);
    bridge.setStepName("CombatMove");
    moveDelegate.setDelegateBridgeAndPlayer(bridge);
    moveDelegate.start();
    final Route eeToSz5 = new Route();
    eeToSz5.setStart(eastEurope);
    eeToSz5.add(sz5);
    // load the transport in the baltic
    final List<Unit> infantry = eastEurope.getUnits().getMatches(Matches.unitIsOfType(infantryType));
    assertEquals(2, infantry.size());
    final TripleAUnit transport = (TripleAUnit) sz5.getUnits().getMatches(Matches.unitIsTransport()).get(0);
    // load the transport
    String error = moveDelegate.move(infantry, eeToSz5, Collections.singletonList(transport));
    assertNull(error, error);
    final Route sz5ToNorway = new Route();
    sz5ToNorway.setStart(sz5);
    sz5ToNorway.add(norway);
    // move the infantry in two steps
    error = moveDelegate.move(infantry.subList(0, 1), sz5ToNorway);
    assertNull(error);
    error = moveDelegate.move(infantry.subList(1, 2), sz5ToNorway);
    assertNull(error);
    assertEquals(3, moveDelegate.getMovesMade().size());
    // the load
    final UndoableMove move1 = moveDelegate.getMovesMade().get(0);
    // the first unload
    // AbstractUndoableMove move2 = moveDelegate.getMovesMade().get(0);
    // the second unload must be done first
    assertFalse(move1.getcanUndo());
    error = moveDelegate.undoMove(2);
    assertNull(error);
    // the second unload must be done first
    assertFalse(move1.getcanUndo());
    error = moveDelegate.undoMove(1);
    assertNull(error);
    // we can now be undone
    assertTrue(move1.getcanUndo());
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) Territory(games.strategy.engine.data.Territory) UnitType(games.strategy.engine.data.UnitType) ITestDelegateBridge(games.strategy.engine.data.ITestDelegateBridge) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) TripleAUnit(games.strategy.triplea.TripleAUnit) Route(games.strategy.engine.data.Route) Test(org.junit.jupiter.api.Test)

Aggregations

TripleAUnit (games.strategy.triplea.TripleAUnit)47 Unit (games.strategy.engine.data.Unit)42 Territory (games.strategy.engine.data.Territory)25 PlayerID (games.strategy.engine.data.PlayerID)19 UnitType (games.strategy.engine.data.UnitType)16 CompositeChange (games.strategy.engine.data.CompositeChange)15 Test (org.junit.jupiter.api.Test)14 Route (games.strategy.engine.data.Route)13 ITestDelegateBridge (games.strategy.engine.data.ITestDelegateBridge)12 ArrayList (java.util.ArrayList)11 GameData (games.strategy.engine.data.GameData)10 UnitAttachment (games.strategy.triplea.attachments.UnitAttachment)8 IntegerMap (games.strategy.util.IntegerMap)8 Change (games.strategy.engine.data.Change)7 RepairRule (games.strategy.engine.data.RepairRule)5 HashSet (java.util.HashSet)4 Resource (games.strategy.engine.data.Resource)3 Collection (java.util.Collection)3 HashMap (java.util.HashMap)3 ResourceCollection (games.strategy.engine.data.ResourceCollection)2