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;
}
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();
}
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);
}
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);
}
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());
}
Aggregations