use of games.strategy.triplea.TripleAUnit in project triplea by triplea-game.
the class RevisedTest method testLoadUndo.
@Test
public void testLoadUndo() {
final Territory sz5 = gameData.getMap().getTerritory("5 Sea Zone");
final Territory eastEurope = gameData.getMap().getTerritory("Eastern Europe");
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);
final String error = moveDelegate.move(infantry, eeToSz5, Collections.singletonList(transport));
assertNull(error, error);
// make sure the transport was loaded
assertTrue(moveDelegate.getMovesMade().get(0).wasTransportLoaded(transport));
// make sure it was laoded
assertTrue(transport.getTransporting().containsAll(infantry));
assertTrue(((TripleAUnit) infantry.get(0)).getWasLoadedThisTurn());
// udo the move
moveDelegate.undoMove(0);
// make sure that loaded is not set
assertTrue(transport.getTransporting().isEmpty());
assertFalse(((TripleAUnit) infantry.get(0)).getWasLoadedThisTurn());
}
use of games.strategy.triplea.TripleAUnit in project triplea by triplea-game.
the class RevisedTest method testLoadUnloadAlliedTransport.
@Test
public void testLoadUnloadAlliedTransport() {
// you cant load and unload an allied transport the same turn
final UnitType infantryType = GameDataTestUtil.infantry(gameData);
final Territory eastEurope = gameData.getMap().getTerritory("Eastern Europe");
// add japanese infantry to eastern europe
final PlayerID japanese = GameDataTestUtil.japanese(gameData);
final Change change = ChangeFactory.addUnits(eastEurope, infantryType.create(1, japanese));
gameData.performChange(change);
final Territory sz5 = gameData.getMap().getTerritory("5 Sea Zone");
final MoveDelegate moveDelegate = (MoveDelegate) gameData.getDelegateList().getDelegate("move");
final ITestDelegateBridge bridge = getDelegateBridge(japanese);
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).and(Matches.unitIsOwnedBy(japanese)));
assertEquals(1, infantry.size());
final TripleAUnit transport = (TripleAUnit) sz5.getUnits().getMatches(Matches.unitIsTransport()).get(0);
String error = moveDelegate.move(infantry, eeToSz5, Collections.singletonList(transport));
assertNull(error, error);
// try to unload
final Route sz5ToEee = new Route();
sz5ToEee.setStart(sz5);
sz5ToEee.add(eastEurope);
error = moveDelegate.move(infantry, sz5ToEee);
assertEquals(MoveValidator.CANNOT_LOAD_AND_UNLOAD_AN_ALLIED_TRANSPORT_IN_THE_SAME_ROUND, error);
}
use of games.strategy.triplea.TripleAUnit in project triplea by triplea-game.
the class LhtrTest method testFightersCanLandOnNewPlacedCarrier.
@Test
public void testFightersCanLandOnNewPlacedCarrier() {
final MoveDelegate delegate = (MoveDelegate) gameData.getDelegateList().getDelegate("move");
delegate.initialize("MoveDelegate", "MoveDelegate");
final PlayerID germans = GameDataTestUtil.germans(gameData);
final ITestDelegateBridge bridge = getDelegateBridge(germans);
bridge.setStepName("germanNonCombatMove");
delegate.setDelegateBridgeAndPlayer(bridge);
delegate.start();
final Territory baltic = gameData.getMap().getTerritory("5 Sea Zone");
final Territory easternEurope = gameData.getMap().getTerritory("Eastern Europe");
final UnitType carrirType = GameDataTestUtil.carrier(gameData);
// move a fighter to the baltic
final Route route = new Route();
route.setStart(easternEurope);
route.add(baltic);
final UnitType fighterType = GameDataTestUtil.fighter(gameData);
delegate.move(easternEurope.getUnits().getMatches(Matches.unitIsOfType(fighterType)), route);
// add a carrier to be produced in germany
final TripleAUnit carrier = new TripleAUnit(carrirType, germans, gameData);
gameData.performChange(ChangeFactory.addUnits(germans, Collections.singleton(carrier)));
// end the move phase
delegate.end();
// make sure the fighter is still there
// in lhtr fighters can hover, and carriers placed beneath them
assertTrue(baltic.getUnits().anyMatch(Matches.unitIsOfType(fighterType)));
}
use of games.strategy.triplea.TripleAUnit in project triplea by triplea-game.
the class RocketsFireHelper method fireRocket.
private static void fireRocket(final PlayerID player, final Territory attackedTerritory, final IDelegateBridge bridge, final Territory attackFrom) {
final GameData data = bridge.getData();
final PlayerID attacked = attackedTerritory.getOwner();
final Resource pus = data.getResourceList().getResource(Constants.PUS);
final boolean damageFromBombingDoneToUnits = isDamageFromBombingDoneToUnitsInsteadOfTerritories(data);
// unit damage vs territory damage
final Collection<Unit> enemyUnits = attackedTerritory.getUnits().getMatches(Matches.enemyUnit(player, data).and(Matches.unitIsBeingTransported().negate()));
final Collection<Unit> enemyTargetsTotal = CollectionUtils.getMatches(enemyUnits, Matches.unitIsAtMaxDamageOrNotCanBeDamaged(attackedTerritory).negate());
final Collection<Unit> rockets;
// attackFrom could be null if WW2V1
if (attackFrom == null) {
rockets = null;
} else {
rockets = new ArrayList<>(CollectionUtils.getMatches(attackFrom.getUnits().getUnits(), rocketMatch(player)));
}
final int numberOfAttacks = (rockets == null ? 1 : Math.min(TechAbilityAttachment.getRocketNumberPerTerritory(player, data), TechAbilityAttachment.getRocketDiceNumber(rockets, data)));
if (numberOfAttacks <= 0) {
return;
}
final Collection<Unit> targets = new ArrayList<>();
if (damageFromBombingDoneToUnits) {
// TODO: rockets needs to be completely redone to allow for multiple rockets to fire at different targets, etc
// etc.
final HashSet<UnitType> legalTargetsForTheseRockets = new HashSet<>();
if (rockets == null) {
legalTargetsForTheseRockets.addAll(data.getUnitTypeList().getAllUnitTypes());
} else {
// a hack for now, we let the rockets fire at anyone who could be targetted by any rocket
for (final Unit r : rockets) {
legalTargetsForTheseRockets.addAll(UnitAttachment.get(r.getType()).getBombingTargets(data));
}
}
final Collection<Unit> enemyTargets = CollectionUtils.getMatches(enemyTargetsTotal, Matches.unitIsOfTypes(legalTargetsForTheseRockets));
if (enemyTargets.isEmpty()) {
// TODO: this sucks
return;
}
Unit target = null;
if (enemyTargets.size() == 1) {
target = enemyTargets.iterator().next();
} else {
while (target == null) {
final ITripleAPlayer iplayer = (ITripleAPlayer) bridge.getRemotePlayer(player);
target = iplayer.whatShouldBomberBomb(attackedTerritory, enemyTargets, rockets);
}
}
if (target == null) {
throw new IllegalStateException("No Targets in " + attackedTerritory.getName());
}
targets.add(target);
}
final boolean doNotUseBombingBonus = !Properties.getUseBombingMaxDiceSidesAndBonus(data) || rockets == null;
int cost = 0;
final String transcript;
if (!Properties.getLowLuckDamageOnly(data)) {
if (doNotUseBombingBonus || rockets == null) {
// no low luck, and no bonus, so just roll based on the map's dice sides
final int[] rolls = bridge.getRandom(data.getDiceSides(), numberOfAttacks, player, DiceType.BOMBING, "Rocket fired by " + player.getName() + " at " + attacked.getName());
for (final int r : rolls) {
// we are zero based
cost += r + 1;
}
transcript = "Rockets " + (attackFrom == null ? "" : "in " + attackFrom.getName()) + " roll: " + MyFormatter.asDice(rolls);
} else {
// we must use bombing bonus
int highestMaxDice = 0;
int highestBonus = 0;
final int diceSides = data.getDiceSides();
for (final Unit u : rockets) {
final UnitAttachment ua = UnitAttachment.get(u.getType());
int maxDice = ua.getBombingMaxDieSides();
final int bonus = ua.getBombingBonus();
// map, and zero for the bonus.
if (maxDice < 0) {
maxDice = diceSides;
}
// we only roll once for rockets, so if there are other rockets here we just roll for the best rocket
if ((bonus + ((maxDice + 1) / 2)) > (highestBonus + ((highestMaxDice + 1) / 2))) {
highestMaxDice = maxDice;
highestBonus = bonus;
}
}
// now we roll, or don't if there is nothing to roll.
if (highestMaxDice > 0) {
final int[] rolls = bridge.getRandom(highestMaxDice, numberOfAttacks, player, DiceType.BOMBING, "Rocket fired by " + player.getName() + " at " + attacked.getName());
for (int i = 0; i < rolls.length; i++) {
final int r = Math.max(-1, rolls[i] + highestBonus);
rolls[i] = r;
// we are zero based
cost += r + 1;
}
transcript = "Rockets " + (attackFrom == null ? "" : "in " + attackFrom.getName()) + " roll: " + MyFormatter.asDice(rolls);
} else {
cost = highestBonus * numberOfAttacks;
transcript = "Rockets " + (attackFrom == null ? "" : "in " + attackFrom.getName()) + " do " + highestBonus + " damage for each rocket";
}
}
} else {
if (doNotUseBombingBonus || rockets == null) {
// no bonus, so just roll based on the map's dice sides, but modify for LL
final int maxDice = (data.getDiceSides() + 1) / 3;
final int bonus = (data.getDiceSides() + 1) / 3;
final int[] rolls = bridge.getRandom(maxDice, numberOfAttacks, player, DiceType.BOMBING, "Rocket fired by " + player.getName() + " at " + attacked.getName());
for (int i = 0; i < rolls.length; i++) {
final int r = rolls[i] + bonus;
rolls[i] = r;
// we are zero based
cost += r + 1;
}
transcript = "Rockets " + (attackFrom == null ? "" : "in " + attackFrom.getName()) + " roll: " + MyFormatter.asDice(rolls);
} else {
int highestMaxDice = 0;
int highestBonus = 0;
final int diceSides = data.getDiceSides();
for (final Unit u : rockets) {
final UnitAttachment ua = UnitAttachment.get(u.getType());
int maxDice = ua.getBombingMaxDieSides();
int bonus = ua.getBombingBonus();
// map, and zero for the bonus.
if (maxDice < 0 || doNotUseBombingBonus) {
maxDice = diceSides;
}
if (doNotUseBombingBonus) {
bonus = 0;
}
// luck by 2/3.
if (maxDice >= 5) {
bonus += (maxDice + 1) / 3;
maxDice = (maxDice + 1) / 3;
}
// we only roll once for rockets, so if there are other rockets here we just roll for the best rocket
if ((bonus + ((maxDice + 1) / 2)) > (highestBonus + ((highestMaxDice + 1) / 2))) {
highestMaxDice = maxDice;
highestBonus = bonus;
}
}
// now we roll, or don't if there is nothing to roll.
if (highestMaxDice > 0) {
final int[] rolls = bridge.getRandom(highestMaxDice, numberOfAttacks, player, DiceType.BOMBING, "Rocket fired by " + player.getName() + " at " + attacked.getName());
for (int i = 0; i < rolls.length; i++) {
final int r = Math.max(-1, rolls[i] + highestBonus);
rolls[i] = r;
// we are zero based
cost += r + 1;
}
transcript = "Rockets " + (attackFrom == null ? "" : "in " + attackFrom.getName()) + " roll: " + MyFormatter.asDice(rolls);
} else {
cost = highestBonus * numberOfAttacks;
transcript = "Rockets " + (attackFrom == null ? "" : "in " + attackFrom.getName()) + " do " + highestBonus + " damage for each rocket";
}
}
}
int territoryProduction = TerritoryAttachment.getProduction(attackedTerritory);
if (damageFromBombingDoneToUnits && !targets.isEmpty()) {
// we are doing damage to 'target', not to the territory
final Unit target = targets.iterator().next();
// UnitAttachment ua = UnitAttachment.get(target.getType());
final TripleAUnit taUnit = (TripleAUnit) target;
final int damageLimit = taUnit.getHowMuchMoreDamageCanThisUnitTake(target, attackedTerritory);
cost = Math.max(0, Math.min(cost, damageLimit));
final int totalDamage = taUnit.getUnitDamage() + cost;
// Record production lost
// DelegateFinder.moveDelegate(data).PUsLost(attackedTerritory, cost);
// apply the hits to the targets
final IntegerMap<Unit> damageMap = new IntegerMap<>();
damageMap.put(target, totalDamage);
bridge.addChange(ChangeFactory.bombingUnitDamage(damageMap));
// attackedTerritory.notifyChanged();
// in WW2V2, limit rocket attack cost to production value of factory.
} else if (isWW2V2(data) || isLimitRocketDamageToProduction(data)) {
// If we are limiting total PUs lost then take that into account
if (isPuCap(data) || isLimitRocketDamagePerTurn(data)) {
final int alreadyLost = DelegateFinder.moveDelegate(data).pusAlreadyLost(attackedTerritory);
territoryProduction -= alreadyLost;
territoryProduction = Math.max(0, territoryProduction);
}
if (cost > territoryProduction) {
cost = territoryProduction;
}
}
// Record the PUs lost
DelegateFinder.moveDelegate(data).pusLost(attackedTerritory, cost);
if (damageFromBombingDoneToUnits && !targets.isEmpty()) {
getRemote(bridge).reportMessage("Rocket attack in " + attackedTerritory.getName() + " does " + cost + " damage to " + targets.iterator().next(), "Rocket attack in " + attackedTerritory.getName() + " does " + cost + " damage to " + targets.iterator().next());
bridge.getHistoryWriter().startEvent("Rocket attack in " + attackedTerritory.getName() + " does " + cost + " damage to " + targets.iterator().next());
} else {
cost *= Properties.getPuMultiplier(data);
getRemote(bridge).reportMessage("Rocket attack in " + attackedTerritory.getName() + " costs:" + cost, "Rocket attack in " + attackedTerritory.getName() + " costs:" + cost);
// Trying to remove more PUs than the victim has is A Bad Thing[tm]
final int availForRemoval = attacked.getResources().getQuantity(pus);
if (cost > availForRemoval) {
cost = availForRemoval;
}
final String transcriptText = attacked.getName() + " lost " + cost + " PUs to rocket attack by " + player.getName();
bridge.getHistoryWriter().startEvent(transcriptText);
final Change rocketCharge = ChangeFactory.changeResourcesChange(attacked, pus, -cost);
bridge.addChange(rocketCharge);
}
bridge.getHistoryWriter().addChildToEvent(transcript, rockets == null ? null : new ArrayList<>(rockets));
// this is null in WW2V1
if (attackFrom != null) {
if (rockets != null && !rockets.isEmpty()) {
// TODO: only a certain number fired...
final Change change = ChangeFactory.markNoMovementChange(Collections.singleton(rockets.iterator().next()));
bridge.addChange(change);
} else {
throw new IllegalStateException("No rockets?" + attackFrom.getUnits().getUnits());
}
}
// kill any units that can die if they have reached max damage (veqryn)
if (targets.stream().anyMatch(Matches.unitCanDieFromReachingMaxDamage())) {
final List<Unit> unitsCanDie = CollectionUtils.getMatches(targets, Matches.unitCanDieFromReachingMaxDamage());
unitsCanDie.retainAll(CollectionUtils.getMatches(unitsCanDie, Matches.unitIsAtMaxDamageOrNotCanBeDamaged(attackedTerritory)));
if (!unitsCanDie.isEmpty()) {
final Change removeDead = ChangeFactory.removeUnits(attackedTerritory, unitsCanDie);
final String transcriptText = MyFormatter.unitsToText(unitsCanDie) + " lost in " + attackedTerritory.getName();
bridge.getHistoryWriter().addChildToEvent(transcriptText, unitsCanDie);
bridge.addChange(removeDead);
}
}
// play a sound
if (cost > 0) {
bridge.getSoundChannelBroadcaster().playSoundForAll(SoundPath.CLIP_BOMBING_ROCKET, player);
}
}
use of games.strategy.triplea.TripleAUnit in project triplea by triplea-game.
the class SpecialMoveDelegate method getNewAssignmentOfNumberLaunchedChange.
private static Change getNewAssignmentOfNumberLaunchedChange(int newNumberLaunched, final Collection<Unit> bases, final PlayerID player, final GameData data) {
final CompositeChange launchedChange = new CompositeChange();
if (newNumberLaunched <= 0) {
return launchedChange;
}
final IntegerMap<UnitType> capacityMap = TechAbilityAttachment.getAirborneCapacity(player, data);
for (final Unit u : bases) {
if (newNumberLaunched <= 0) {
break;
}
final int numberLaunchedAlready = ((TripleAUnit) u).getLaunched();
final int capacity = capacityMap.getInt(u.getType());
final int toAdd = Math.min(newNumberLaunched, capacity - numberLaunchedAlready);
if (toAdd <= 0) {
continue;
}
newNumberLaunched -= toAdd;
launchedChange.add(ChangeFactory.unitPropertyChange(u, (toAdd + numberLaunchedAlready), TripleAUnit.LAUNCHED));
}
return launchedChange;
}
Aggregations