package games.strategy.triplea.delegate;
import static games.strategy.triplea.delegate.BattleStepStrings.ATTACKER_WITHDRAW;
import static games.strategy.triplea.delegate.BattleStepStrings.FIRE;
import static games.strategy.triplea.delegate.BattleStepStrings.REMOVE_CASUALTIES;
import static games.strategy.triplea.delegate.BattleStepStrings.REMOVE_SNEAK_ATTACK_CASUALTIES;
import static games.strategy.triplea.delegate.BattleStepStrings.SELECT_CASUALTIES;
import static games.strategy.triplea.delegate.BattleStepStrings.SELECT_SUB_CASUALTIES;
import static games.strategy.triplea.delegate.BattleStepStrings.SUBS_FIRE;
import static games.strategy.triplea.delegate.BattleStepStrings.SUBS_SUBMERGE;
import static games.strategy.triplea.delegate.GameDataTestUtil.aaGun;
import static games.strategy.triplea.delegate.GameDataTestUtil.addTo;
import static games.strategy.triplea.delegate.GameDataTestUtil.americans;
import static games.strategy.triplea.delegate.GameDataTestUtil.armour;
import static games.strategy.triplea.delegate.GameDataTestUtil.assertError;
import static games.strategy.triplea.delegate.GameDataTestUtil.assertMoveError;
import static games.strategy.triplea.delegate.GameDataTestUtil.assertValid;
import static games.strategy.triplea.delegate.GameDataTestUtil.battleship;
import static games.strategy.triplea.delegate.GameDataTestUtil.bidPlaceDelegate;
import static games.strategy.triplea.delegate.GameDataTestUtil.bomber;
import static games.strategy.triplea.delegate.GameDataTestUtil.british;
import static games.strategy.triplea.delegate.GameDataTestUtil.destroyer;
import static games.strategy.triplea.delegate.GameDataTestUtil.germans;
import static games.strategy.triplea.delegate.GameDataTestUtil.getIndex;
import static games.strategy.triplea.delegate.GameDataTestUtil.infantry;
import static games.strategy.triplea.delegate.GameDataTestUtil.japanese;
import static games.strategy.triplea.delegate.GameDataTestUtil.load;
import static games.strategy.triplea.delegate.GameDataTestUtil.makeGameLowLuck;
import static games.strategy.triplea.delegate.GameDataTestUtil.move;
import static games.strategy.triplea.delegate.GameDataTestUtil.moveDelegate;
import static games.strategy.triplea.delegate.GameDataTestUtil.placeDelegate;
import static games.strategy.triplea.delegate.GameDataTestUtil.removeFrom;
import static games.strategy.triplea.delegate.GameDataTestUtil.submarine;
import static games.strategy.triplea.delegate.GameDataTestUtil.techDelegate;
import static games.strategy.triplea.delegate.GameDataTestUtil.territory;
import static games.strategy.triplea.delegate.GameDataTestUtil.transport;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import games.strategy.engine.data.Change;
import games.strategy.engine.data.GameData;
import games.strategy.engine.data.ITestDelegateBridge;
import games.strategy.engine.data.PlayerID;
import games.strategy.engine.data.Route;
import games.strategy.engine.data.TechnologyFrontier;
import games.strategy.engine.data.Territory;
import games.strategy.engine.data.Unit;
import games.strategy.engine.data.UnitType;
import games.strategy.engine.data.changefactory.ChangeFactory;
import games.strategy.engine.random.ScriptedRandomSource;
import games.strategy.test.TestUtil;
import games.strategy.triplea.Constants;
import games.strategy.triplea.TripleAUnit;
import games.strategy.triplea.attachments.TechAttachment;
import games.strategy.triplea.attachments.UnitAttachment;
import games.strategy.triplea.delegate.IBattle.BattleType;
import games.strategy.triplea.delegate.dataObjects.CasualtyDetails;
import games.strategy.triplea.delegate.dataObjects.CasualtyList;
import games.strategy.triplea.delegate.dataObjects.PlaceableUnits;
import games.strategy.triplea.delegate.dataObjects.TechResults;
import games.strategy.triplea.player.ITripleAPlayer;
import games.strategy.triplea.xml.TestMapGameData;
import games.strategy.util.CompositeMatchAnd;
import games.strategy.util.CompositeMatchOr;
import games.strategy.util.Match;
public class RevisedTest {
private GameData gameData;
private final ITripleAPlayer dummyPlayer = mock(ITripleAPlayer.class);
@Before
public void setUp() throws Exception {
when(dummyPlayer.selectCasualties(any(), any(), anyInt(), any(), any(), any(), any(), any(), any(),
anyBoolean(), any(), any(), any(), any(), anyBoolean())).thenAnswer(new Answer<CasualtyDetails>() {
@Override
public CasualtyDetails answer(final InvocationOnMock invocation) throws Throwable {
final CasualtyList defaultCasualties = invocation.getArgument(11);
if (defaultCasualties != null) {
return new CasualtyDetails(defaultCasualties.getKilled(), defaultCasualties.getDamaged(), true);
}
return null;
}
});
gameData = TestMapGameData.REVISED.getGameData();
}
private ITestDelegateBridge getDelegateBridge(final PlayerID player) {
return GameDataTestUtil.getDelegateBridge(player, gameData);
}
public static String fight(final BattleDelegate battle, final Territory territory, final boolean bombing) {
for (final Entry<BattleType, Collection<Territory>> entry : battle.getBattles().getBattles().entrySet()) {
if (entry.getKey().isBombingRun() == bombing) {
if (entry.getValue().contains(territory)) {
return battle.fightBattle(territory, bombing, entry.getKey());
}
}
}
throw new IllegalStateException(
"Could not find " + (bombing ? "bombing" : "normal") + " battle in: " + territory.getName());
}
@Test
public void testMoveBadRoute() {
final PlayerID british = GameDataTestUtil.british(gameData);
final Territory sz1 = gameData.getMap().getTerritory("1 Sea Zone");
final Territory sz11 = gameData.getMap().getTerritory("11 Sea Zone");
final Territory sz9 = gameData.getMap().getTerritory("9 Sea Zone");
final ITestDelegateBridge bridge = getDelegateBridge(british);
bridge.setStepName("NonCombatMove");
moveDelegate(gameData).setDelegateBridgeAndPlayer(bridge);
moveDelegate(gameData).start();
final String error = moveDelegate(gameData).move(sz1.getUnits().getUnits(), new Route(sz1, sz11, sz9));
assertTrue(error != null);
}
@Test
public void testAlliedNeighbors() {
final PlayerID americans = americans(gameData);
final Territory centralUs = territory("Central United States", gameData);
final Set<Territory> enemyNeighbors =
gameData.getMap().getNeighbors(centralUs, Matches.isTerritoryEnemy(americans, gameData));
assertTrue(enemyNeighbors.isEmpty());
}
@Test
public void testSubAdvance() {
final UnitType sub = GameDataTestUtil.submarine(gameData);
final UnitAttachment attachment = UnitAttachment.get(sub);
final PlayerID japanese = GameDataTestUtil.japanese(gameData);
// before the advance, subs defend and attack at 2
assertEquals(2, attachment.getDefense(japanese));
assertEquals(2, attachment.getAttack(japanese));
final ITestDelegateBridge bridge = getDelegateBridge(japanese);
TechTracker.addAdvance(japanese, bridge,
TechAdvance.findAdvance(TechAdvance.TECH_PROPERTY_SUPER_SUBS, gameData, japanese));
// after tech advance, this is now 3
assertEquals(2, attachment.getDefense(japanese));
assertEquals(3, attachment.getAttack(japanese));
}
@Test
public void testMoveThroughSubmergedSubs() {
final PlayerID british = GameDataTestUtil.british(gameData);
final Territory sz1 = gameData.getMap().getTerritory("1 Sea Zone");
final Territory sz7 = gameData.getMap().getTerritory("7 Sea Zone");
final Territory sz8 = gameData.getMap().getTerritory("8 Sea Zone");
final TripleAUnit sub = (TripleAUnit) sz8.getUnits().iterator().next();
sub.setSubmerged(true);
// now move to attack it
final MoveDelegate moveDelegate = (MoveDelegate) gameData.getDelegateList().getDelegate("move");
final ITestDelegateBridge bridge = getDelegateBridge(british);
bridge.setStepName("NonCombatMove");
moveDelegate.setDelegateBridgeAndPlayer(bridge);
moveDelegate.start();
// the transport can enter sz 8
// since the sub is submerged
final Route m1 = new Route(sz1, sz8);
assertNull(moveDelegate.move(sz1.getUnits().getUnits(), m1));
// the transport can now leave sz8
final Route m2 = new Route(sz8, sz7);
final String error = moveDelegate.move(sz8.getUnits().getMatches(Matches.unitIsOwnedBy(british)), m2);
assertNull(error, error);
}
@Test
public void testRetreatBug() {
final PlayerID russians = GameDataTestUtil.russians(gameData);
final PlayerID americans = GameDataTestUtil.americans(gameData);
final ITestDelegateBridge bridge = getDelegateBridge(russians);
// we need to initialize the original owner
final InitializationDelegate initDel =
(InitializationDelegate) gameData.getDelegateList().getDelegate("initDelegate");
initDel.setDelegateBridgeAndPlayer(bridge);
initDel.start();
initDel.end();
// make sinkian japanese owned, put one infantry in it
final Territory sinkiang = gameData.getMap().getTerritory("Sinkiang");
gameData.performChange(ChangeFactory.removeUnits(sinkiang, sinkiang.getUnits().getUnits()));
final PlayerID japanese = GameDataTestUtil.japanese(gameData);
sinkiang.setOwner(japanese);
final UnitType infantryType = GameDataTestUtil.infantry(gameData);
gameData.performChange(ChangeFactory.addUnits(sinkiang, infantryType.create(1, japanese)));
// now move to attack it
final MoveDelegate moveDelegate = (MoveDelegate) gameData.getDelegateList().getDelegate("move");
bridge.setStepName("CombatMove");
moveDelegate.setDelegateBridgeAndPlayer(bridge);
moveDelegate.start();
final Territory novo = gameData.getMap().getTerritory("Novosibirsk");
moveDelegate.move(novo.getUnits().getUnits(), gameData.getMap().getRoute(novo, sinkiang));
moveDelegate.end();
final BattleDelegate battle = (BattleDelegate) gameData.getDelegateList().getDelegate("battle");
battle.setDelegateBridgeAndPlayer(bridge);
bridge.setRandomSource(new ScriptedRandomSource(new int[] {0, 0, 0}));
bridge.setRemote(dummyPlayer);
battle.start(); // fights battle
battle.end();
assertEquals(sinkiang.getOwner(), americans);
assertTrue(battle.getBattleTracker().wasConquered(sinkiang));
bridge.setStepName("NonCombatMove");
moveDelegate.setDelegateBridgeAndPlayer(bridge);
moveDelegate.start();
final Territory russia = gameData.getMap().getTerritory("Russia");
// move two tanks from russia, then undo
final Route r = new Route();
r.setStart(russia);
r.add(novo);
r.add(sinkiang);
assertNull(moveDelegate.move(russia.getUnits().getMatches(Matches.UnitCanBlitz), r));
moveDelegate.undoMove(0);
assertTrue(battle.getBattleTracker().wasConquered(sinkiang));
// now move the planes into the territory
assertNull(moveDelegate.move(russia.getUnits().getMatches(Matches.UnitIsAir), r));
// make sure they can't land, they can't because the territory was conquered
assertEquals(1, moveDelegate.getTerritoriesWhereAirCantLand().size());
}
@Test
public void testContinuedBattles() {
final PlayerID russians = GameDataTestUtil.russians(gameData);
final PlayerID germans = GameDataTestUtil.germans(gameData);
final ITestDelegateBridge bridge = getDelegateBridge(germans);
final MoveDelegate moveDelegate = (MoveDelegate) gameData.getDelegateList().getDelegate("move");
bridge.setStepName("CombatMove");
moveDelegate.setDelegateBridgeAndPlayer(bridge);
moveDelegate.start();
// set up battle
final Territory germany = gameData.getMap().getTerritory("Germany");
final Territory karelia = gameData.getMap().getTerritory("Karelia S.S.R.");
final Territory sz5 = gameData.getMap().getTerritory("5 Sea Zone");
gameData.performChange(ChangeFactory.removeUnits(sz5, sz5.getUnits().getUnits()));
final UnitType infantryType = GameDataTestUtil.infantry(gameData);
final UnitType subType = GameDataTestUtil.submarine(gameData);
final UnitType trnType = GameDataTestUtil.transport(gameData);
gameData.performChange(ChangeFactory.addUnits(sz5, subType.create(1, germans)));
gameData.performChange(ChangeFactory.addUnits(sz5, trnType.create(1, germans)));
gameData.performChange(ChangeFactory.addUnits(sz5, subType.create(1, russians)));
// submerge the russian sub
final TripleAUnit sub =
(TripleAUnit) Match.getMatches(sz5.getUnits().getUnits(), Matches.unitIsOwnedBy(russians)).iterator().next();
sub.setSubmerged(true);
// now move an infantry through the sz
String results =
moveDelegate.move(Match.getNMatches(germany.getUnits().getUnits(), 1, Matches.unitIsOfType(infantryType)),
gameData.getMap().getRoute(germany, sz5),
Match.getMatches(sz5.getUnits().getUnits(), Matches.unitIsOfType(trnType)));
assertNull(results);
results = moveDelegate.move(Match.getNMatches(sz5.getUnits().getUnits(), 1, Matches.unitIsOfType(infantryType)),
gameData.getMap().getRoute(sz5, karelia));
assertNull(results);
moveDelegate.end();
final BattleDelegate battle = (BattleDelegate) gameData.getDelegateList().getDelegate("battle");
battle.setDelegateBridgeAndPlayer(bridge);
battle.start();
final BattleTracker tracker = AbstractMoveDelegate.getBattleTracker(gameData);
// The battle should NOT be empty
assertTrue(tracker.hasPendingBattle(sz5, false));
assertFalse(tracker.getPendingBattle(sz5, false, null).isEmpty());
battle.end();
}
@Test
public void testLoadAlliedTransports() {
final PlayerID british = british(gameData);
final PlayerID americans = americans(gameData);
final Territory uk = territory("United Kingdom", gameData);
final ITestDelegateBridge bridge = getDelegateBridge(british);
bridge.setStepName("CombatMove");
moveDelegate(gameData).setDelegateBridgeAndPlayer(bridge);
moveDelegate(gameData).start();
// create 2 us infantry
addTo(uk, infantry(gameData).create(2, americans));
// try to load them on the british players turn
final Territory sz2 = territory("2 Sea Zone", gameData);
final String error = moveDelegate(gameData).move(uk.getUnits().getMatches(Matches.unitIsOwnedBy(americans)),
new Route(uk, sz2), sz2.getUnits().getMatches(Matches.UnitIsTransport));
// should not be able to load on british turn, only on american turn
assertFalse(error == null);
}
@Test
public void testBidPlace() {
final ITestDelegateBridge bridge = getDelegateBridge(british(gameData));
bridge.setStepName("BidPlace");
bidPlaceDelegate(gameData).setDelegateBridgeAndPlayer(bridge);
bidPlaceDelegate(gameData).start();
// create 20 british infantry
addTo(british(gameData), infantry(gameData).create(20, british(gameData)), gameData);
final Territory uk = territory("United Kingdom", gameData);
final Collection<Unit> units = british(gameData).getUnits().getUnits();
final PlaceableUnits placeable = bidPlaceDelegate(gameData).getPlaceableUnits(units, uk);
assertEquals(20, placeable.getMaxUnits());
assertNull(placeable.getErrorMessage());
final String error = bidPlaceDelegate(gameData).placeUnits(units, uk);
assertNull(error);
}
@Test
public void testOverFlyBombersDies() {
final PlayerID british = british(gameData);
final MoveDelegate moveDelegate = (MoveDelegate) gameData.getDelegateList().getDelegate("move");
final ITestDelegateBridge bridge = getDelegateBridge(british);
bridge.setStepName("CombatMove");
moveDelegate.setDelegateBridgeAndPlayer(bridge);
moveDelegate.start();
when(dummyPlayer.confirmMoveInFaceOfAA(any())).thenReturn(true);
bridge.setRemote(dummyPlayer);
bridge.setRandomSource(new ScriptedRandomSource(0));
final Territory uk = territory("United Kingdom", gameData);
final Territory we = territory("Western Europe", gameData);
final Territory se = territory("Southern Europe", gameData);
final Route route = new Route(uk, territory("7 Sea Zone", gameData), we, se);
move(uk.getUnits().getMatches(Matches.UnitIsStrategicBomber), route);
// the aa gun should have fired. the bomber no longer exists
assertTrue(se.getUnits().getMatches(Matches.UnitIsStrategicBomber).isEmpty());
assertTrue(we.getUnits().getMatches(Matches.UnitIsStrategicBomber).isEmpty());
assertTrue(uk.getUnits().getMatches(Matches.UnitIsStrategicBomber).isEmpty());
}
@Test
public void testMultipleOverFlyBombersDies() {
final PlayerID british = british(gameData);
final MoveDelegate moveDelegate = (MoveDelegate) gameData.getDelegateList().getDelegate("move");
final ITestDelegateBridge bridge = getDelegateBridge(british);
bridge.setStepName("CombatMove");
moveDelegate.setDelegateBridgeAndPlayer(bridge);
moveDelegate.start();
when(dummyPlayer.confirmMoveInFaceOfAA(any())).thenReturn(true);
bridge.setRemote(dummyPlayer);
bridge.setRandomSource(new ScriptedRandomSource(0, 4));
final Territory uk = territory("United Kingdom", gameData);
final Territory sz7 = territory("7 Sea Zone", gameData);
final Territory we = territory("Western Europe", gameData);
final Territory se = territory("Southern Europe", gameData);
final Territory balk = territory("Balkans", gameData);
addTo(uk, bomber(gameData).create(1, british));
final Route route = new Route(uk, sz7, we, se, balk);
move(uk.getUnits().getMatches(Matches.UnitIsStrategicBomber), route);
// the aa gun should have fired (one hit, one miss in each territory overflown). the bombers no longer exists
assertTrue(uk.getUnits().getMatches(Matches.UnitIsStrategicBomber).isEmpty());
assertTrue(we.getUnits().getMatches(Matches.UnitIsStrategicBomber).isEmpty());
assertTrue(se.getUnits().getMatches(Matches.UnitIsStrategicBomber).isEmpty());
assertTrue(balk.getUnits().getMatches(Matches.UnitIsStrategicBomber).isEmpty());
}
@Test
public void testOverFlyBombersJoiningBattleDie() {
// a bomber flies over aa to join a battle, gets hit,
// it should not appear in the battle
final PlayerID british = british(gameData);
final MoveDelegate moveDelegate = (MoveDelegate) gameData.getDelegateList().getDelegate("move");
final ITestDelegateBridge bridge = getDelegateBridge(british);
bridge.setStepName("CombatMove");
moveDelegate.setDelegateBridgeAndPlayer(bridge);
moveDelegate.start();
when(dummyPlayer.confirmMoveInFaceOfAA(any())).thenReturn(true);
bridge.setRemote(dummyPlayer);
bridge.setRandomSource(new ScriptedRandomSource(0));
final Territory uk = territory("United Kingdom", gameData);
final Territory we = territory("Western Europe", gameData);
final Territory se = territory("Southern Europe", gameData);
final Territory sz14 = territory("14 Sea Zone", gameData);
final Territory sz15 = territory("15 Sea Zone", gameData);
final Territory egypt = territory("Anglo Egypt", gameData);
// start a battle in se
removeFrom(sz14, sz14.getUnits().getUnits());
addTo(sz15, transport(gameData).create(1, british));
load(egypt.getUnits().getMatches(Matches.UnitIsInfantry), new Route(egypt, sz15));
move(sz15.getUnits().getUnits(), new Route(sz15, sz14));
move(sz14.getUnits().getMatches(Matches.UnitIsInfantry), new Route(sz14, se));
final Route route = new Route(uk, territory("7 Sea Zone", gameData), we, se);
move(uk.getUnits().getMatches(Matches.UnitIsStrategicBomber), route);
// the aa gun should have fired and hit
assertTrue(se.getUnits().getMatches(Matches.UnitIsStrategicBomber).isEmpty());
assertTrue(we.getUnits().getMatches(Matches.UnitIsStrategicBomber).isEmpty());
assertTrue(uk.getUnits().getMatches(Matches.UnitIsStrategicBomber).isEmpty());
}
@Test
public void testTransportAttack() {
final Territory sz14 = gameData.getMap().getTerritory("14 Sea Zone");
final Territory sz13 = gameData.getMap().getTerritory("13 Sea Zone");
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 sz14To13 = new Route();
sz14To13.setStart(sz14);
sz14To13.add(sz13);
final List<Unit> transports = sz14.getUnits().getMatches(Matches.UnitIsTransport);
assertEquals(1, transports.size());
final String error = moveDelegate.move(transports, sz14To13);
assertNull(error, error);
}
@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.<Unit>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());
}
@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.<Unit>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());
}
@Test
public void testLoadUndoInWrongOrder() {
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);
// load the transports
// in two moves
String error = moveDelegate.move(infantry.subList(0, 1), eeToSz5, Collections.<Unit>singletonList(transport));
assertNull(error, error);
error = moveDelegate.move(infantry.subList(1, 2), eeToSz5, Collections.<Unit>singletonList(transport));
assertNull(error, error);
// make sure the transport was loaded
assertTrue(moveDelegate.getMovesMade().get(0).wasTransportLoaded(transport));
assertTrue(moveDelegate.getMovesMade().get(1).wasTransportLoaded(transport));
// udo the moves in reverse order
moveDelegate.undoMove(0);
moveDelegate.undoMove(0);
// make sure that loaded is not set
assertTrue(transport.getTransporting().isEmpty());
assertFalse(((TripleAUnit) infantry.get(0)).getWasLoadedThisTurn());
}
@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(new CompositeMatchAnd<>(Matches.unitIsOfType(infantryType), 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.<Unit>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);
}
@Test
public void testUnloadMultipleTerritories() {
// in revised a transport may only unload to 1 territory.
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);
String error = moveDelegate.move(infantry, eeToSz5, Collections.<Unit>singletonList(transport));
assertNull(error, error);
// unload one infantry to Norway
final Territory norway = gameData.getMap().getTerritory("Norway");
final Route sz5ToNorway = new Route();
sz5ToNorway.setStart(sz5);
sz5ToNorway.add(norway);
error = moveDelegate.move(infantry.subList(0, 1), sz5ToNorway);
assertNull(error, error);
// make sure the transport was unloaded
assertTrue(moveDelegate.getMovesMade().get(1).wasTransportUnloaded(transport));
// try to unload the other infantry somewhere else, an error occurs
final Route sz5ToEE = new Route();
sz5ToEE.setStart(sz5);
sz5ToEE.add(eastEurope);
error = moveDelegate.move(infantry.subList(1, 2), sz5ToEE);
assertNotNull(error, error);
assertTrue(error.startsWith(MoveValidator.TRANSPORT_HAS_ALREADY_UNLOADED_UNITS_TO));
// end the round
moveDelegate.end();
bridge.setStepName("NonCombatMove");
moveDelegate.setDelegateBridgeAndPlayer(bridge);
moveDelegate.start();
moveDelegate.end();
bridge.setStepName("CombatMove");
moveDelegate.setDelegateBridgeAndPlayer(bridge);
moveDelegate.start();
// a new round, the move should work
moveDelegate.setDelegateBridgeAndPlayer(bridge);
moveDelegate.start();
error = moveDelegate.move(infantry.subList(1, 2), sz5ToEE);
assertNull(error);
}
@Test
public void testUnloadInPreviousPhase() {
// a transport may not unload in both combat and non combat
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);
String error = moveDelegate.move(infantry, eeToSz5, Collections.<Unit>singletonList(transport));
assertNull(error, error);
// unload one infantry to Norway
final Territory norway = gameData.getMap().getTerritory("Norway");
final Route sz5ToNorway = new Route();
sz5ToNorway.setStart(sz5);
sz5ToNorway.add(norway);
error = moveDelegate.move(infantry.subList(0, 1), sz5ToNorway);
assertNull(error, error);
assertTrue(((TripleAUnit) infantry.get(0)).getWasUnloadedInCombatPhase());
// start non combat
moveDelegate.end();
bridge.setStepName("germanNonCombatMove");
// the transport tracker relies on the step name
while (!gameData.getSequence().getStep().getName().equals("germanNonCombatMove")) {
gameData.getSequence().next();
}
moveDelegate.setDelegateBridgeAndPlayer(bridge);
moveDelegate.start();
// try to unload the other infantry somewhere else, an error occurs
error = moveDelegate.move(infantry.subList(1, 2), sz5ToNorway);
assertNotNull(error, error);
assertTrue(error.startsWith(MoveValidator.TRANSPORT_HAS_ALREADY_UNLOADED_UNITS_IN_A_PREVIOUS_PHASE));
}
@Test
public void testSubAttackTransportNonCombat() {
final Territory sz1 = territory("1 Sea Zone", gameData);
final Territory sz8 = territory("8 Sea Zone", gameData);
final PlayerID germans = germans(gameData);
// german sub tries to attack a transport in non combat
// should be an error
final MoveDelegate moveDelegate = (MoveDelegate) gameData.getDelegateList().getDelegate("move");
final ITestDelegateBridge bridge = getDelegateBridge(germans);
bridge.setStepName("NonCombatMove");
moveDelegate.setDelegateBridgeAndPlayer(bridge);
moveDelegate.start();
final String error = moveDelegate(gameData).move(sz8.getUnits().getUnits(), new Route(sz8, sz1));
assertError(error);
}
@Test
public void testSubAttackNonCombat() {
final Territory sz2 = territory("2 Sea Zone", gameData);
final Territory sz8 = territory("8 Sea Zone", gameData);
final PlayerID germans = germans(gameData);
// german sub tries to attack a transport in non combat
// should be an error
final MoveDelegate moveDelegate = (MoveDelegate) gameData.getDelegateList().getDelegate("move");
final ITestDelegateBridge bridge = getDelegateBridge(germans);
bridge.setStepName("NonCombatMove");
moveDelegate.setDelegateBridgeAndPlayer(bridge);
moveDelegate.start();
final String error = moveDelegate(gameData).move(sz8.getUnits().getUnits(), new Route(sz8, sz2));
assertError(error);
}
@Test
public void testTransportAttackSubNonCombat() {
final Territory sz1 = territory("1 Sea Zone", gameData);
final Territory sz8 = territory("8 Sea Zone", gameData);
final PlayerID british = british(gameData);
// german sub tries to attack a transport in non combat
// should be an error
final MoveDelegate moveDelegate = (MoveDelegate) gameData.getDelegateList().getDelegate("move");
final ITestDelegateBridge bridge = getDelegateBridge(british);
bridge.setStepName("NonCombatMove");
moveDelegate.setDelegateBridgeAndPlayer(bridge);
moveDelegate.start();
final String error = moveDelegate(gameData).move(sz8.getUnits().getUnits(), new Route(sz1, sz8));
assertError(error);
}
@Test
public void testMoveSubAwayFromSubmergedSubsInBattleZone() {
final Territory sz45 = gameData.getMap().getTerritory("45 Sea Zone");
final Territory sz50 = gameData.getMap().getTerritory("50 Sea Zone");
final PlayerID british = GameDataTestUtil.british(gameData);
final PlayerID japanese = GameDataTestUtil.japanese(gameData);
// put 1 british sub in sz 45, this simulates a submerged enemy sub
final UnitType sub = GameDataTestUtil.submarine(gameData);
final Change c = ChangeFactory.addUnits(sz45, sub.create(1, british));
gameData.performChange(c);
// new move delegate
final MoveDelegate moveDelegate = (MoveDelegate) gameData.getDelegateList().getDelegate("move");
final ITestDelegateBridge bridge = getDelegateBridge(japanese);
bridge.setStepName("CombatMove");
moveDelegate.setDelegateBridgeAndPlayer(bridge);
moveDelegate.start();
// move a fighter into the sea zone, this will cause a battle
final Route sz50To45 = new Route();
sz50To45.setStart(sz50);
sz50To45.add(sz45);
String error = moveDelegate.move(sz50.getUnits().getMatches(Matches.UnitIsAir), sz50To45);
assertNull(error);
assertEquals(1, AbstractMoveDelegate.getBattleTracker(gameData).getPendingBattleSites(false).size());
// we should be able to move the sub out of the sz
final Route sz45To50 = new Route();
sz45To50.setStart(sz45);
sz45To50.add(sz50);
final List<Unit> japSub =
sz45.getUnits().getMatches(new CompositeMatchAnd<>(Matches.UnitIsSub, Matches.unitIsOwnedBy(japanese)));
error = moveDelegate.move(japSub, sz45To50);
// make sure no error
assertNull(error);
// make sure the battle is still there
assertEquals(1, AbstractMoveDelegate.getBattleTracker(gameData).getPendingBattleSites(false).size());
// we should be able to undo the move of the sub
error = moveDelegate.undoMove(1);
assertNull(error);
// undo the move of the fighter, should be no battles now
error = moveDelegate.undoMove(0);
assertNull(error);
assertEquals(0, AbstractMoveDelegate.getBattleTracker(gameData).getPendingBattleSites(false).size());
}
@Test
public void testAAOwnership() {
// Set up players
// PlayerID british = GameDataTestUtil.british(gameData);
final PlayerID japanese = GameDataTestUtil.japanese(gameData);
// PlayerID americans = GameDataTestUtil.americans(gameData);
// Set up the territories
final Territory india = territory("India", gameData);
final Territory fic = territory("French Indochina", gameData);
final Territory china = territory("China", gameData);
final Territory kwang = territory("Kwantung", gameData);
// Preset units in FIC
final UnitType infType = GameDataTestUtil.infantry(gameData);
// UnitType aaType = GameDataTestUtil.aaGun(gameData);
removeFrom(fic, fic.getUnits().getUnits());
addTo(fic, aaGun(gameData).create(1, japanese));
addTo(fic, infantry(gameData).create(1, japanese));
assertEquals(2, fic.getUnits().getUnitCount());
// Get attacking units
final Collection<Unit> britishUnits = india.getUnits().getUnits(infType, 1);
final Collection<Unit> japaneseUnits = kwang.getUnits().getUnits(infType, 1);
final Collection<Unit> americanUnits = china.getUnits().getUnits(infType, 1);
// Get Owner prior to battle
assertTrue(fic.getUnits().allMatch(Matches.unitIsOwnedBy(japanese(gameData))));
final String preOwner = fic.getOwner().getName();
assertEquals(preOwner, Constants.PLAYER_NAME_JAPANESE);
// Set up the move delegate
ITestDelegateBridge delegateBridge = getDelegateBridge(british(gameData));
final MoveDelegate moveDelegate = moveDelegate(gameData);
delegateBridge.setStepName("CombatMove");
moveDelegate.setDelegateBridgeAndPlayer(delegateBridge);
moveDelegate.start();
/*
* add a VALID BRITISH attack
*/
String validResults = moveDelegate.move(britishUnits, new Route(india, fic));
assertValid(validResults);
moveDelegate(gameData).end();
// Set up battle
MustFightBattle battle =
(MustFightBattle) AbstractMoveDelegate.getBattleTracker(gameData).getPendingBattle(fic, false, null);
delegateBridge.setRemote(dummyPlayer);
// fight
ScriptedRandomSource randomSource = new ScriptedRandomSource(0, 5);
delegateBridge.setRandomSource(randomSource);
battle.fight(delegateBridge);
// Get Owner after to battle
assertTrue(fic.getUnits().allMatch(Matches.unitIsOwnedBy(british(gameData))));
final String postOwner = fic.getOwner().getName();
assertEquals(postOwner, Constants.PLAYER_NAME_BRITISH);
/*
* add a VALID JAPANESE attack
*/
// Set up battle
delegateBridge = getDelegateBridge(japanese(gameData));
delegateBridge.setStepName("CombatMove");
moveDelegate.setDelegateBridgeAndPlayer(delegateBridge);
moveDelegate.start();
// Move to battle
validResults = moveDelegate.move(japaneseUnits, new Route(kwang, fic));
assertValid(validResults);
moveDelegate(gameData).end();
battle = (MustFightBattle) AbstractMoveDelegate.getBattleTracker(gameData).getPendingBattle(fic, false, null);
delegateBridge.setRemote(dummyPlayer);
// fight
randomSource = new ScriptedRandomSource(0, 5);
delegateBridge.setRandomSource(randomSource);
battle.fight(delegateBridge);
// Get Owner after to battle
assertTrue(fic.getUnits().allMatch(Matches.unitIsOwnedBy(japanese(gameData))));
final String midOwner = fic.getOwner().getName();
assertEquals(midOwner, Constants.PLAYER_NAME_JAPANESE);
/*
* add a VALID AMERICAN attack
*/
// Set up battle
delegateBridge = getDelegateBridge(americans(gameData));
delegateBridge.setStepName("CombatMove");
moveDelegate.setDelegateBridgeAndPlayer(delegateBridge);
moveDelegate.start();
// Move to battle
validResults = moveDelegate.move(americanUnits, new Route(china, fic));
assertValid(validResults);
moveDelegate(gameData).end();
battle = (MustFightBattle) AbstractMoveDelegate.getBattleTracker(gameData).getPendingBattle(fic, false, null);
delegateBridge.setRemote(dummyPlayer);
// fight
randomSource = new ScriptedRandomSource(0, 5);
delegateBridge.setRandomSource(randomSource);
battle.fight(delegateBridge);
// Get Owner after to battle
assertTrue(fic.getUnits().allMatch(Matches.unitIsOwnedBy(americans(gameData))));
final String endOwner = fic.getOwner().getName();
assertEquals(endOwner, Constants.PLAYER_NAME_AMERICANS);
}
@Test
public void testStratBombCasualties() {
final Territory germany = gameData.getMap().getTerritory("Germany");
final Territory uk = gameData.getMap().getTerritory("United Kingdom");
final PlayerID germans = GameDataTestUtil.germans(gameData);
final PlayerID british = GameDataTestUtil.british(gameData);
final BattleTracker tracker = new BattleTracker();
final StrategicBombingRaidBattle battle = new StrategicBombingRaidBattle(germany, gameData, british, tracker);
final List<Unit> bombers = uk.getUnits().getMatches(Matches.UnitIsStrategicBomber);
addTo(germany, bombers);
battle.addAttackChange(gameData.getMap().getRoute(uk, germany), bombers, null);
tracker.getBattleRecords().addBattle(british, battle.getBattleID(), germany, battle.getBattleType());
final ITestDelegateBridge bridge = getDelegateBridge(british);
bridge.setRemote(dummyPlayer);
// aa guns rolls 0 and hits
bridge.setRandomSource(new ScriptedRandomSource(new int[] {0, ScriptedRandomSource.ERROR}));
// int PUsBeforeRaid = germans.getResources().getQuantity(gameData.getResourceList().getResource(Constants.PUS));
final int pusBeforeRaid = germans.getResources().getQuantity(gameData.getResourceList().getResource(Constants.PUS));
battle.fight(bridge);
// int PUsAfterRaid = germans.getResources().getQuantity(gameData.getResourceList().getResource(Constants.PUS));
final int pusAfterRaid = germans.getResources().getQuantity(gameData.getResourceList().getResource(Constants.PUS));
assertEquals(pusBeforeRaid, pusAfterRaid);
assertEquals(0, germany.getUnits().getMatches(Matches.unitIsOwnedBy(british)).size());
}
@Test
public void testStratBombCasualtiesLowLuck() {
makeGameLowLuck(gameData);
final Territory germany = gameData.getMap().getTerritory("Germany");
final Territory uk = gameData.getMap().getTerritory("United Kingdom");
final PlayerID germans = GameDataTestUtil.germans(gameData);
final PlayerID british = GameDataTestUtil.british(gameData);
final BattleTracker tracker = new BattleTracker();
final StrategicBombingRaidBattle battle = new StrategicBombingRaidBattle(germany, gameData, british, tracker);
final List<Unit> bombers = bomber(gameData).create(2, british);
addTo(germany, bombers);
battle.addAttackChange(gameData.getMap().getRoute(uk, germany), bombers, null);
tracker.getBattleRecords().addBattle(british, battle.getBattleID(), germany, battle.getBattleType());
final ITestDelegateBridge bridge = getDelegateBridge(british);
bridge.setRemote(dummyPlayer);
// should be exactly 3 rolls total. would be exactly 2 rolls if the number of units being shot at = max dice side of
// the AA gun, because
// the casualty selection roll would not happen in LL
// first 0 is the AA gun rolling 1@2 and getting a 1, which is a hit
// second 0 is the LL AA casualty selection randomly picking the first unit to die
// third 0 is the single remaining bomber dealing 1 damage to the enemy's PUs
bridge.setRandomSource(new ScriptedRandomSource(new int[] {0, 0, 0, ScriptedRandomSource.ERROR}));
final int pusBeforeRaid = germans.getResources().getQuantity(gameData.getResourceList().getResource(Constants.PUS));
battle.fight(bridge);
final int pusAfterRaid = germans.getResources().getQuantity(gameData.getResourceList().getResource(Constants.PUS));
assertEquals(pusBeforeRaid - 1, pusAfterRaid);
assertEquals(1, germany.getUnits().getMatches(Matches.unitIsOwnedBy(british)).size());
}
@Test
public void testStratBombCasualtiesLowLuckManyBombers() {
makeGameLowLuck(gameData);
final Territory germany = gameData.getMap().getTerritory("Germany");
final Territory uk = gameData.getMap().getTerritory("United Kingdom");
final PlayerID germans = GameDataTestUtil.germans(gameData);
final PlayerID british = GameDataTestUtil.british(gameData);
final BattleTracker tracker = new BattleTracker();
final StrategicBombingRaidBattle battle = new StrategicBombingRaidBattle(germany, gameData, british, tracker);
final List<Unit> bombers = bomber(gameData).create(7, british);
addTo(germany, bombers);
battle.addAttackChange(gameData.getMap().getRoute(uk, germany), bombers, null);
tracker.getBattleRecords().addBattle(british, battle.getBattleID(), germany, battle.getBattleType());
final ITestDelegateBridge bridge = getDelegateBridge(british);
bridge.setRemote(dummyPlayer);
// aa guns rolls 0 and hits, next 5 dice are for the bombing raid cost for the
// surviving bombers
bridge.setRandomSource(new ScriptedRandomSource(new int[] {0, 0, 0, 0, 0, 0, ScriptedRandomSource.ERROR}));
final int pusBeforeRaid = germans.getResources().getQuantity(gameData.getResourceList().getResource(Constants.PUS));
battle.fight(bridge);
final int pusAfterRaid = germans.getResources().getQuantity(gameData.getResourceList().getResource(Constants.PUS));
assertEquals(pusBeforeRaid - 5, pusAfterRaid);
// 2 bombers get hit
assertEquals(5, germany.getUnits().getMatches(Matches.unitIsOwnedBy(british)).size());
}
@Test
public void testStratBombRaidWithHeavyBombers() {
final Territory germany = gameData.getMap().getTerritory("Germany");
final Territory uk = gameData.getMap().getTerritory("United Kingdom");
final PlayerID germans = GameDataTestUtil.germans(gameData);
final PlayerID british = GameDataTestUtil.british(gameData);
final BattleTracker tracker = new BattleTracker();
final StrategicBombingRaidBattle battle = new StrategicBombingRaidBattle(germany, gameData, british, tracker);
battle.addAttackChange(gameData.getMap().getRoute(uk, germany),
uk.getUnits().getMatches(Matches.UnitIsStrategicBomber), null);
addTo(germany, uk.getUnits().getMatches(Matches.UnitIsStrategicBomber));
tracker.getBattleRecords().addBattle(british, battle.getBattleID(), germany, battle.getBattleType());
final ITestDelegateBridge bridge = getDelegateBridge(british);
TechTracker.addAdvance(british, bridge,
TechAdvance.findAdvance(TechAdvance.TECH_PROPERTY_HEAVY_BOMBER, gameData, british));
// aa guns rolls 3, misses, bomber rolls 2 dice at 3
bridge.setRandomSource(new ScriptedRandomSource(new int[] {3, 2, 2}));
// if we try to move aa, then the game will ask us if we want to move
// fail if we are called
final InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
return null;
}
};
final ITripleAPlayer player = (ITripleAPlayer) Proxy
.newProxyInstance(Thread.currentThread().getContextClassLoader(),
TestUtil.getClassArrayFrom(ITripleAPlayer.class), handler);
bridge.setRemote(player);
// int PUsBeforeRaid = germans.getResources().getQuantity(gameData.getResourceList().getResource(Constants.PUS));
final int pusBeforeRaid = germans.getResources().getQuantity(gameData.getResourceList().getResource(Constants.PUS));
battle.fight(bridge);
// int PUsAfterRaid = germans.getResources().getQuantity(gameData.getResourceList().getResource(Constants.PUS));
final int pusAfterRaid = germans.getResources().getQuantity(gameData.getResourceList().getResource(Constants.PUS));
assertEquals(pusBeforeRaid - 6, pusAfterRaid);
}
@Test
public void testLandBattleNoSneakAttack() {
final String defender = "Germans";
final String attacker = "British";
final Territory attacked = territory("Libya", gameData);
final Territory from = territory("Anglo Egypt", gameData);
final ITestDelegateBridge bridge = getDelegateBridge(british(gameData));
bridge.setStepName("CombatMove");
moveDelegate(gameData).setDelegateBridgeAndPlayer(bridge);
moveDelegate(gameData).start();
move(from.getUnits().getUnits(), new Route(from, attacked));
moveDelegate(gameData).end();
final MustFightBattle battle =
(MustFightBattle) AbstractMoveDelegate.getBattleTracker(gameData).getPendingBattle(attacked, false, null);
final List<String> steps = battle.determineStepStrings(true, bridge);
assertEquals(Arrays.asList(attacker + FIRE, defender + SELECT_CASUALTIES, defender + FIRE,
attacker + SELECT_CASUALTIES, REMOVE_CASUALTIES, attacker + ATTACKER_WITHDRAW).toString(), steps.toString());
}
@Test
public void testSeaBattleNoSneakAttack() {
final String defender = "Germans";
final String attacker = "British";
final Territory attacked = territory("31 Sea Zone", gameData);
final Territory from = territory("32 Sea Zone", gameData);
// 1 destroyer attacks 1 destroyer
addTo(from, destroyer(gameData).create(1, british(gameData)));
addTo(attacked, destroyer(gameData).create(1, germans(gameData)));
final ITestDelegateBridge bridge = getDelegateBridge(british(gameData));
bridge.setStepName("CombatMove");
moveDelegate(gameData).setDelegateBridgeAndPlayer(bridge);
moveDelegate(gameData).start();
move(from.getUnits().getUnits(), new Route(from, attacked));
moveDelegate(gameData).end();
final MustFightBattle battle =
(MustFightBattle) AbstractMoveDelegate.getBattleTracker(gameData).getPendingBattle(attacked, false, null);
final List<String> steps = battle.determineStepStrings(true, bridge);
assertEquals(Arrays.asList(attacker + FIRE, defender + SELECT_CASUALTIES, defender + FIRE,
attacker + SELECT_CASUALTIES, REMOVE_CASUALTIES, attacker + ATTACKER_WITHDRAW).toString(), steps.toString());
}
@Test
public void testAttackSubsOnSubs() {
final String defender = "Germans";
final String attacker = "British";
final Territory attacked = territory("31 Sea Zone", gameData);
final Territory from = territory("32 Sea Zone", gameData);
// 1 sub attacks 1 sub
addTo(from, submarine(gameData).create(1, british(gameData)));
addTo(attacked, submarine(gameData).create(1, germans(gameData)));
final ITestDelegateBridge bridge = getDelegateBridge(british(gameData));
bridge.setStepName("CombatMove");
moveDelegate(gameData).setDelegateBridgeAndPlayer(bridge);
moveDelegate(gameData).start();
move(from.getUnits().getUnits(), new Route(from, attacked));
moveDelegate(gameData).end();
final MustFightBattle battle =
(MustFightBattle) AbstractMoveDelegate.getBattleTracker(gameData).getPendingBattle(attacked, false, null);
final List<String> steps = battle.determineStepStrings(true, bridge);
assertEquals(
Arrays.asList(attacker + SUBS_FIRE, defender + SELECT_SUB_CASUALTIES, defender + SUBS_FIRE,
attacker + SELECT_SUB_CASUALTIES, REMOVE_SNEAK_ATTACK_CASUALTIES, REMOVE_CASUALTIES,
attacker + SUBS_SUBMERGE, defender + SUBS_SUBMERGE, attacker + ATTACKER_WITHDRAW).toString(),
steps.toString());
final List<IExecutable> execs = battle.getBattleExecutables(false);
final int attackSubs = getIndex(execs, MustFightBattle.AttackSubs.class);
final int defendSubs = getIndex(execs, MustFightBattle.DefendSubs.class);
assertTrue(attackSubs < defendSubs);
bridge.setRemote(dummyPlayer);
// fight, each sub should fire
// and hit
final ScriptedRandomSource randomSource = new ScriptedRandomSource(0, 0, ScriptedRandomSource.ERROR);
bridge.setRandomSource(randomSource);
battle.fight(bridge);
assertEquals(2, randomSource.getTotalRolled());
assertTrue(attacked.getUnits().isEmpty());
}
@Test
public void testAttackSubsOnDestroyer() {
final String defender = "Germans";
final String attacker = "British";
final Territory attacked = territory("31 Sea Zone", gameData);
final Territory from = territory("32 Sea Zone", gameData);
// 2 sub attacks 1 sub and 1 destroyer
addTo(from, submarine(gameData).create(2, british(gameData)));
addTo(attacked, submarine(gameData).create(1, germans(gameData)));
addTo(attacked, destroyer(gameData).create(1, germans(gameData)));
final ITestDelegateBridge bridge = getDelegateBridge(british(gameData));
bridge.setStepName("CombatMove");
moveDelegate(gameData).setDelegateBridgeAndPlayer(bridge);
moveDelegate(gameData).start();
move(from.getUnits().getUnits(), new Route(from, attacked));
moveDelegate(gameData).end();
final MustFightBattle battle =
(MustFightBattle) AbstractMoveDelegate.getBattleTracker(gameData).getPendingBattle(attacked, false, null);
final List<String> steps = battle.determineStepStrings(true, bridge);
/*
* Here are the exact errata clarifications on how REVISED rules subs work:
* Every sub, regardless of whether it is on the attacking or defending side, fires in the Opening Fire step of
* combat. That is the only
* time a sub ever fires.
* Losses caused by attacking or defending subs are removed at the end of the Opening Fire step, before normal
* attack and defense rolls,
* unless the enemy has a destroyer present.
* If the enemy (attacker or defender) has a destroyer, then hits caused by your subs are not removed until the
* Remove Casualties step
* (step 6) of combat.
* In other words, subs work exactly the same for the attacker and the defender. Nothing, not even a destroyer, ever
* stops a sub from
* rolling its die (attack or defense) in the Opening Fire step.
* What a destroyer does do is let you keep your units that were sunk by enemy subs on the battle board until step
* 6, allowing them to
* fire back before going to the scrap heap.
*/
assertEquals(Arrays.asList(attacker + SUBS_FIRE, defender + SELECT_SUB_CASUALTIES, defender + SUBS_FIRE,
attacker + SELECT_SUB_CASUALTIES, REMOVE_SNEAK_ATTACK_CASUALTIES, defender + FIRE, attacker + SELECT_CASUALTIES,
REMOVE_CASUALTIES, attacker + SUBS_SUBMERGE, defender + SUBS_SUBMERGE, attacker + ATTACKER_WITHDRAW).toString(),
steps.toString());
final List<IExecutable> execs = battle.getBattleExecutables(false);
final int attackSubs = getIndex(execs, MustFightBattle.AttackSubs.class);
final int defendSubs = getIndex(execs, MustFightBattle.DefendSubs.class);
assertTrue(attackSubs < defendSubs);
bridge.setRemote(dummyPlayer);
// attacking subs fires, defending destroyer and sub still gets to fire
// attacking subs still gets to fire even if defending sub hits
final ScriptedRandomSource randomSource = new ScriptedRandomSource(0, 2, 0, 0, ScriptedRandomSource.ERROR);
bridge.setRandomSource(randomSource);
battle.fight(bridge);
assertEquals(4, randomSource.getTotalRolled());
assertTrue(attacked.getUnits().getMatches(Matches.unitIsOwnedBy(british(gameData))).isEmpty());
assertEquals(1, attacked.getUnits().size());
}
@Test
public void testAttackSubsAndBBOnDestroyerAndSubs() {
final String defender = "Germans";
final String attacker = "British";
final Territory attacked = territory("31 Sea Zone", gameData);
final Territory from = territory("32 Sea Zone", gameData);
// 1 sub and 1 BB (two hp) attacks 3 subs and 1 destroyer
addTo(from, submarine(gameData).create(1, british(gameData)));
addTo(from, battleship(gameData).create(1, british(gameData)));
addTo(attacked, submarine(gameData).create(3, germans(gameData)));
addTo(attacked, destroyer(gameData).create(1, germans(gameData)));
final ITestDelegateBridge bridge = getDelegateBridge(british(gameData));
bridge.setStepName("CombatMove");
moveDelegate(gameData).setDelegateBridgeAndPlayer(bridge);
moveDelegate(gameData).start();
move(from.getUnits().getUnits(), new Route(from, attacked));
moveDelegate(gameData).end();
final MustFightBattle battle =
(MustFightBattle) AbstractMoveDelegate.getBattleTracker(gameData).getPendingBattle(attacked, false, null);
final List<String> steps = battle.determineStepStrings(true, bridge);
/*
* Here are the exact errata clarifications on how REVISED rules subs work:
* Every sub, regardless of whether it is on the attacking or defending side, fires in the Opening Fire step of
* combat. That is the only
* time a sub ever fires.
* Losses caused by attacking or defending subs are removed at the end of the Opening Fire step, before normal
* attack and defense rolls,
* unless the enemy has a destroyer present.
* If the enemy (attacker or defender) has a destroyer, then hits caused by your subs are not removed until the
* Remove Casualties step
* (step 6) of combat.
* In other words, subs work exactly the same for the attacker and the defender. Nothing, not even a destroyer, ever
* stops a sub from
* rolling its die (attack or defense) in the Opening Fire step.
* What a destroyer does do is let you keep your units that were sunk by enemy subs on the battle board until step
* 6, allowing them to
* fire back before going to the scrap heap.
*/
assertEquals(
Arrays.asList(attacker + SUBS_FIRE, defender + SELECT_SUB_CASUALTIES, defender + SUBS_FIRE,
attacker + SELECT_SUB_CASUALTIES, REMOVE_SNEAK_ATTACK_CASUALTIES, attacker + FIRE,
defender + SELECT_CASUALTIES, defender + FIRE, attacker + SELECT_CASUALTIES, REMOVE_CASUALTIES,
attacker + SUBS_SUBMERGE, defender + SUBS_SUBMERGE, attacker + ATTACKER_WITHDRAW).toString(),
steps.toString());
final List<IExecutable> execs = battle.getBattleExecutables(false);
final int attackSubs = getIndex(execs, MustFightBattle.AttackSubs.class);
final int defendSubs = getIndex(execs, MustFightBattle.DefendSubs.class);
assertTrue(attackSubs < defendSubs);
bridge.setRemote(dummyPlayer);
// attacking subs fires, defending destroyer and sub still gets to fire
// attacking subs still gets to fire even if defending sub hits
// battleship will not get to fire since it is killed by defending sub's sneak attack
final ScriptedRandomSource randomSource = new ScriptedRandomSource(0, 0, 0, 0, ScriptedRandomSource.ERROR);
bridge.setRandomSource(randomSource);
battle.fight(bridge);
assertEquals(4, randomSource.getTotalRolled());
assertTrue(attacked.getUnits().getMatches(Matches.unitIsOwnedBy(british(gameData))).isEmpty());
assertEquals(3, attacked.getUnits().size());
}
@Test
public void testAttackDestroyerAndSubsAgainstSub() {
final String defender = "Germans";
final String attacker = "British";
final Territory attacked = territory("31 Sea Zone", gameData);
final Territory from = territory("32 Sea Zone", gameData);
// 1 sub and 1 destroyer attack 1 sub
// defender sneak attacks, not attacker
addTo(from, submarine(gameData).create(1, british(gameData)));
addTo(from, destroyer(gameData).create(1, british(gameData)));
addTo(attacked, submarine(gameData).create(1, germans(gameData)));
final ITestDelegateBridge bridge = getDelegateBridge(british(gameData));
bridge.setStepName("CombatMove");
moveDelegate(gameData).setDelegateBridgeAndPlayer(bridge);
moveDelegate(gameData).start();
move(from.getUnits().getUnits(), new Route(from, attacked));
moveDelegate(gameData).end();
final MustFightBattle battle =
(MustFightBattle) AbstractMoveDelegate.getBattleTracker(gameData).getPendingBattle(attacked, false, null);
final List<String> steps = battle.determineStepStrings(true, bridge);
assertEquals(Arrays.asList(attacker + SUBS_FIRE, defender + SELECT_SUB_CASUALTIES, defender + SUBS_FIRE,
attacker + SELECT_SUB_CASUALTIES, REMOVE_SNEAK_ATTACK_CASUALTIES, attacker + FIRE, defender + SELECT_CASUALTIES,
REMOVE_CASUALTIES, attacker + SUBS_SUBMERGE, defender + SUBS_SUBMERGE, attacker + ATTACKER_WITHDRAW).toString(),
steps.toString());
final List<IExecutable> execs = battle.getBattleExecutables(false);
final int attackSubs = getIndex(execs, MustFightBattle.AttackSubs.class);
final int defendSubs = getIndex(execs, MustFightBattle.DefendSubs.class);
assertTrue(attackSubs < defendSubs);
bridge.setRemote(dummyPlayer);
// attacking sub hits with sneak attack, but defending sub gets to return fire because it is a sub and this is
// revised rules
final ScriptedRandomSource randomSource = new ScriptedRandomSource(0, 0, ScriptedRandomSource.ERROR);
bridge.setRandomSource(randomSource);
battle.fight(bridge);
assertEquals(2, randomSource.getTotalRolled());
assertTrue(attacked.getUnits().getMatches(Matches.unitIsOwnedBy(germans(gameData))).isEmpty());
assertEquals(1, attacked.getUnits().size());
}
@Test
public void testAttackSubsAndDestroyerOnBBAndSubs() {
final String defender = "Germans";
final String attacker = "British";
final Territory attacked = territory("31 Sea Zone", gameData);
final Territory from = territory("32 Sea Zone", gameData);
// 1 sub and 1 BB (two hp) attacks 3 subs and 1 destroyer
addTo(from, submarine(gameData).create(3, british(gameData)));
addTo(from, destroyer(gameData).create(1, british(gameData)));
addTo(attacked, submarine(gameData).create(1, germans(gameData)));
addTo(attacked, battleship(gameData).create(1, germans(gameData)));
final ITestDelegateBridge bridge = getDelegateBridge(british(gameData));
bridge.setStepName("CombatMove");
moveDelegate(gameData).setDelegateBridgeAndPlayer(bridge);
moveDelegate(gameData).start();
move(from.getUnits().getUnits(), new Route(from, attacked));
moveDelegate(gameData).end();
final MustFightBattle battle =
(MustFightBattle) AbstractMoveDelegate.getBattleTracker(gameData).getPendingBattle(attacked, false, null);
final List<String> steps = battle.determineStepStrings(true, bridge);
/*
* Here are the exact errata clarifications on how REVISED rules subs work:
* Every sub, regardless of whether it is on the attacking or defending side, fires in the Opening Fire step of
* combat. That is the only
* time a sub ever fires.
* Losses caused by attacking or defending subs are removed at the end of the Opening Fire step, before normal
* attack and defense rolls,
* unless the enemy has a destroyer present.
* If the enemy (attacker or defender) has a destroyer, then hits caused by your subs are not removed until the
* Remove Casualties step
* (step 6) of combat.
* In other words, subs work exactly the same for the attacker and the defender. Nothing, not even a destroyer, ever
* stops a sub from
* rolling its die (attack or defense) in the Opening Fire step.
* What a destroyer does do is let you keep your units that were sunk by enemy subs on the battle board until step
* 6, allowing them to
* fire back before going to the scrap heap.
*/
assertEquals(
Arrays.asList(attacker + SUBS_FIRE, defender + SELECT_SUB_CASUALTIES, defender + SUBS_FIRE,
attacker + SELECT_SUB_CASUALTIES, REMOVE_SNEAK_ATTACK_CASUALTIES, attacker + FIRE,
defender + SELECT_CASUALTIES, defender + FIRE, attacker + SELECT_CASUALTIES, REMOVE_CASUALTIES,
attacker + SUBS_SUBMERGE, defender + SUBS_SUBMERGE, attacker + ATTACKER_WITHDRAW).toString(),
steps.toString());
final List<IExecutable> execs = battle.getBattleExecutables(false);
final int attackSubs = getIndex(execs, MustFightBattle.AttackSubs.class);
final int defendSubs = getIndex(execs, MustFightBattle.DefendSubs.class);
assertTrue(attackSubs < defendSubs);
bridge.setRemote(dummyPlayer);
// attacking subs fires, defending destroyer and sub still gets to fire
// attacking subs still gets to fire even if defending sub hits
// battleship will not get to fire since it is killed by defending sub's sneak attack
final ScriptedRandomSource randomSource = new ScriptedRandomSource(0, 0, 0, 0, ScriptedRandomSource.ERROR);
bridge.setRandomSource(randomSource);
battle.fight(bridge);
assertEquals(4, randomSource.getTotalRolled());
assertTrue(attacked.getUnits().getMatches(Matches.unitIsOwnedBy(germans(gameData))).isEmpty());
assertEquals(3, attacked.getUnits().size());
}
@Test
public void testAttackDestroyerAndSubsAgainstSubAndDestroyer() {
final String defender = "Germans";
final String attacker = "British";
final Territory attacked = territory("31 Sea Zone", gameData);
final Territory from = territory("32 Sea Zone", gameData);
// 1 sub and 1 destroyer attack 1 sub and 1 destroyer
// defender sneak attacks, not attacker
addTo(from, submarine(gameData).create(1, british(gameData)));
addTo(from, destroyer(gameData).create(1, british(gameData)));
addTo(attacked, submarine(gameData).create(1, germans(gameData)));
addTo(attacked, destroyer(gameData).create(1, germans(gameData)));
final ITestDelegateBridge bridge = getDelegateBridge(british(gameData));
bridge.setStepName("CombatMove");
moveDelegate(gameData).setDelegateBridgeAndPlayer(bridge);
moveDelegate(gameData).start();
move(from.getUnits().getUnits(), new Route(from, attacked));
moveDelegate(gameData).end();
final MustFightBattle battle =
(MustFightBattle) AbstractMoveDelegate.getBattleTracker(gameData).getPendingBattle(attacked, false, null);
final List<String> steps = battle.determineStepStrings(true, bridge);
assertEquals(Arrays.asList(attacker + SUBS_FIRE, defender + SELECT_SUB_CASUALTIES, defender + SUBS_FIRE,
attacker + SELECT_SUB_CASUALTIES, attacker + FIRE, defender + SELECT_CASUALTIES, defender + FIRE,
attacker + SELECT_CASUALTIES, REMOVE_CASUALTIES, attacker + SUBS_SUBMERGE, defender + SUBS_SUBMERGE,
attacker + ATTACKER_WITHDRAW).toString(), steps.toString());
final List<IExecutable> execs = battle.getBattleExecutables(false);
final int attackSubs = getIndex(execs, MustFightBattle.AttackSubs.class);
final int defendSubs = getIndex(execs, MustFightBattle.DefendSubs.class);
assertTrue(attackSubs < defendSubs);
when(dummyPlayer.selectCasualties(any(), any(), anyInt(), any(),
any(), any(), any(), any(), any(),
anyBoolean(), any(),
any(), any(), any(), anyBoolean()))
.thenAnswer(new Answer<CasualtyDetails>() {
@Override
public CasualtyDetails answer(final InvocationOnMock invocation) throws Throwable {
final Collection<Unit> selectFrom = invocation.getArgument(0);
return new CasualtyDetails(Arrays.asList(selectFrom.iterator().next()), new ArrayList<>(), false);
}
});
bridge.setRemote(dummyPlayer);
final ScriptedRandomSource randomSource = new ScriptedRandomSource(0, 0, 0, 0, ScriptedRandomSource.ERROR);
bridge.setRandomSource(randomSource);
battle.fight(bridge);
assertEquals(4, randomSource.getTotalRolled());
assertEquals(0, attacked.getUnits().size());
}
@Test
public void testUnplacedDie() {
final PlaceDelegate del = placeDelegate(gameData);
del.setDelegateBridgeAndPlayer(getDelegateBridge(british(gameData)));
del.start();
addTo(british(gameData), transport(gameData).create(1, british(gameData)), gameData);
del.end();
// unplaced units die
assertTrue(british(gameData).getUnits().isEmpty());
}
@Test
public void testRocketsDontFireInConquered() {
final MoveDelegate move = moveDelegate(gameData);
final ITestDelegateBridge bridge = getDelegateBridge(germans(gameData));
bridge.setStepName("CombatMove");
bridge.setRemote(dummyPlayer);
move.setDelegateBridgeAndPlayer(bridge);
move.start();
// remove the russians units in caucasus so we can blitz
final Territory cauc = territory("Caucasus", gameData);
removeFrom(cauc, cauc.getUnits().getMatches(Matches.UnitIsNotAA));
// blitz
final Territory wr = territory("West Russia", gameData);
move(wr.getUnits().getMatches(Matches.UnitCanBlitz), new Route(wr, cauc));
final Set<Territory> fire = new RocketsFireHelper().getTerritoriesWithRockets(gameData, germans(gameData));
// germany, WE, SE, but not caucusus
assertEquals(fire.size(), 3);
}
@Test
public void testTechRolls() {
// Set up the test
final PlayerID germans = GameDataTestUtil.germans(gameData);
final ITestDelegateBridge delegateBridge = getDelegateBridge(germans);
delegateBridge.setStepName("germanTech");
final TechnologyDelegate techDelegate = techDelegate(gameData);
techDelegate.setDelegateBridgeAndPlayer(delegateBridge);
techDelegate.start();
final TechAttachment ta = TechAttachment.get(germans);
// PlayerAttachment pa = PlayerAttachment.get(germans);
final TechnologyFrontier rockets = new TechnologyFrontier("", gameData);
rockets.addAdvance(TechAdvance.findAdvance(TechAdvance.TECH_PROPERTY_ROCKETS, gameData, null));
final TechnologyFrontier jet = new TechnologyFrontier("", gameData);
jet.addAdvance(TechAdvance.findAdvance(TechAdvance.TECH_PROPERTY_JET_POWER, gameData, null));
// Check to make sure it was successful
final int initPUs = germans.getResources().getQuantity("PUs");
// Fail the roll
delegateBridge.setRandomSource(new ScriptedRandomSource(new int[] {3, 4}));
final TechResults roll = techDelegate.rollTech(2, rockets, 0, null);
// Check to make sure it failed
assertEquals(0, roll.getHits());
final int midPUs = germans.getResources().getQuantity("PUs");
assertEquals(initPUs - 10, midPUs);
// Make a Successful roll
delegateBridge.setRandomSource(new ScriptedRandomSource(new int[] {5}));
final TechResults roll2 = techDelegate.rollTech(1, rockets, 0, null);
// Check to make sure it succeeded
assertEquals(1, roll2.getHits());
final int finalPUs = germans.getResources().getQuantity("PUs");
assertEquals(midPUs - 5, finalPUs);
// Test the variable tech cost
// Make a Successful roll
ta.setTechCost("6");
delegateBridge.setRandomSource(new ScriptedRandomSource(new int[] {5}));
final TechResults roll3 = techDelegate.rollTech(1, jet, 0, null);
// Check to make sure it succeeded
assertEquals(1, roll3.getHits());
final int VariablePUs = germans.getResources().getQuantity("PUs");
assertEquals(finalPUs - 6, VariablePUs);
}
@Test
public void testTransportsUnloadingToMultipleTerritoriesDie() {
// two transports enter a battle, but drop off
// their units to two allied territories before
// the begin the battle
// the units they drop off should die with the transports
final PlayerID germans = germans(gameData);
final PlayerID british = british(gameData);
final Territory sz6 = territory("6 Sea Zone", gameData);
final Territory sz5 = territory("5 Sea Zone", gameData);
final Territory germany = territory("Germany", gameData);
final Territory norway = territory("Norway", gameData);
final Territory we = territory("Western Europe", gameData);
final Territory uk = territory("United Kingdom", gameData);
addTo(sz6, destroyer(gameData).create(2, british));
addTo(sz5, transport(gameData).create(3, germans));
addTo(germany, armour(gameData).create(3, germans));
final ITestDelegateBridge bridge = getDelegateBridge(germans(gameData));
bridge.setStepName("CombatMove");
bridge.setRemote(dummyPlayer);
moveDelegate(gameData).setDelegateBridgeAndPlayer(bridge);
moveDelegate(gameData).start();
// load two transports, 1 tank each
load(germany.getUnits().getMatches(Matches.UnitCanBlitz).subList(0, 1), new Route(germany, sz5));
load(germany.getUnits().getMatches(Matches.UnitCanBlitz).subList(0, 1), new Route(germany, sz5));
load(germany.getUnits().getMatches(Matches.UnitCanBlitz).subList(0, 1), new Route(germany, sz5));
// attack sz 6
move(sz5.getUnits().getMatches(new CompositeMatchOr<>(Matches.UnitCanBlitz, Matches.UnitIsTransport)),
new Route(sz5, sz6));
// unload transports, 1 each to a different country
// this move is illegal now
assertMoveError(sz6.getUnits().getMatches(Matches.UnitCanBlitz).subList(0, 1), new Route(sz6, norway));
// this move is illegal now
assertMoveError(sz6.getUnits().getMatches(Matches.UnitCanBlitz).subList(0, 1), new Route(sz6, we));
move(sz6.getUnits().getMatches(Matches.UnitCanBlitz).subList(0, 1), new Route(sz6, uk));
// fight the battle
moveDelegate(gameData).end();
final MustFightBattle battle =
(MustFightBattle) AbstractMoveDelegate.getBattleTracker(gameData).getPendingBattle(sz6, false, null);
// everything hits, this will kill both transports
bridge.setRandomSource(new ScriptedRandomSource(0));
battle.fight(bridge);
// the armour should have died
assertEquals(0, norway.getUnits().countMatches(Matches.UnitCanBlitz));
assertEquals(2, we.getUnits().countMatches(Matches.UnitCanBlitz));
assertEquals(0, uk.getUnits().countMatches(Matches.unitIsOwnedBy(germans)));
}
@Test
public void testCanalMovePass() {
final Territory sz15 = territory("15 Sea Zone", gameData);
final Territory sz34 = territory("34 Sea Zone", gameData);
final ITestDelegateBridge bridge = getDelegateBridge(british(gameData));
bridge.setStepName("CombatMove");
final MoveDelegate moveDelegate = moveDelegate(gameData);
moveDelegate.setDelegateBridgeAndPlayer(bridge);
moveDelegate.start();
final String error = moveDelegate.move(sz15.getUnits().getUnits(), new Route(sz15, sz34));
assertValid(error);
}
@Test
public void testCanalMovementFail() {
final Territory sz14 = territory("14 Sea Zone", gameData);
final Territory sz15 = territory("15 Sea Zone", gameData);
final Territory sz34 = territory("34 Sea Zone", gameData);
// clear the british in sz 15
removeFrom(sz15, sz15.getUnits().getUnits());
final ITestDelegateBridge bridge = getDelegateBridge(germans(gameData));
bridge.setStepName("CombatMove");
final MoveDelegate moveDelegate = moveDelegate(gameData);
moveDelegate.setDelegateBridgeAndPlayer(bridge);
moveDelegate.start();
final String error = moveDelegate.move(sz14.getUnits().getUnits(), new Route(sz14, sz15, sz34));
assertError(error);
}
@Test
public void testTransportIsTransport() {
assertTrue(Matches.UnitIsTransport.match(transport(gameData).create(british(gameData))));
assertFalse(Matches.UnitIsTransport.match(infantry(gameData).create(british(gameData))));
}
}