module TK.SpaceTac { testing("Battle", test => { test.case("places ships on lines, facing the arena center", check => { var fleet1 = new Fleet(); var fleet2 = new Fleet(); var ship1 = new Ship(fleet1, "F1S1"); var ship2 = new Ship(fleet1, "F1S2"); var ship3 = new Ship(fleet1, "F1S3"); var ship4 = new Ship(fleet2, "F2S1"); var ship5 = new Ship(fleet2, "F2S2"); var battle = new Battle(fleet1, fleet2, 1000, 500); battle.placeShips(); check.nears(ship1.arena_x, 250); check.nears(ship1.arena_y, 150); check.nears(ship1.arena_angle, 0); check.nears(ship2.arena_x, 250); check.nears(ship2.arena_y, 250); check.nears(ship2.arena_angle, 0); check.nears(ship3.arena_x, 250); check.nears(ship3.arena_y, 350); check.nears(ship3.arena_angle, 0); check.nears(ship4.arena_x, 750); check.nears(ship4.arena_y, 300); check.nears(ship4.arena_angle, Math.PI); check.nears(ship5.arena_x, 750); check.nears(ship5.arena_y, 200); check.nears(ship5.arena_angle, Math.PI); }); test.case("detects victory condition and logs a final EndBattleDiff", check => { var fleet1 = new Fleet(); var fleet2 = new Fleet(); var ship1 = new Ship(fleet1, "F1S1"); var ship2 = new Ship(fleet1, "F1S2"); let ship3 = new Ship(fleet2, "F2S1"); var battle = new Battle(fleet1, fleet2); battle.ships.list().forEach(ship => TestTools.setShipModel(ship, 10, 0)); battle.start(); check.equals(battle.ended, false); ship1.setDead(); ship2.setDead(); battle.applyTurnPlan({ fleets: [] }); check.equals(battle.ended, true); let diff = battle.log.get(battle.log.count() - 1); if (diff instanceof EndBattleDiff) { check.notequals(diff.outcome.winner, null); check.same(diff.outcome.winner, fleet2.id); } else { check.fail("Not an EndBattleDiff"); } }); test.case("handles a draw in end battle", check => { var fleet1 = new Fleet(); var fleet2 = new Fleet(); var ship1 = new Ship(fleet1, "F1S1"); var ship2 = new Ship(fleet1, "F1S2"); var ship3 = new Ship(fleet2, "F2S1"); var battle = new Battle(fleet1, fleet2); battle.start(); check.equals(battle.ended, false); ship1.setDead(); ship2.setDead(); ship3.setDead(); battle.log.clear(); check.equals(battle.ended, false); battle.performChecks(); check.equals(battle.ended, true); check.equals(battle.log.count(), 1); let diff = battle.log.get(0); if (diff instanceof EndBattleDiff) { check.equals(diff.outcome.winner, null); } else { check.fail("Not an EndBattleDiff"); } }); test.case("collects ships present in a circle", check => { var fleet1 = new Fleet(); var ship1 = new Ship(fleet1, "F1S1"); ship1.setArenaPosition(0, 0); var ship2 = new Ship(fleet1, "F1S2"); ship2.setArenaPosition(5, 8); var ship3 = new Ship(fleet1, "F1S3"); ship3.setArenaPosition(6.5, 9.5); var ship4 = new Ship(fleet1, "F1S4"); ship4.setArenaPosition(12, 12); var battle = new Battle(fleet1); var result = battle.collectShipsInCircle(Target.newFromLocation(5, 8), 3); check.equals(sortedBy(result, ship => ship.name), [ship2, ship3]); }); test.case("adds and remove drones", check => { let battle = new Battle(); let ship = new Ship(); let drone = new Drone(ship); check.equals(battle.drones.count(), 0); battle.addDrone(drone); check.equals(battle.drones.count(), 1); check.same(battle.drones.get(drone.id), drone); battle.addDrone(drone); check.equals(battle.drones.count(), 1); battle.removeDrone(drone); check.equals(battle.drones.count(), 0); battle.removeDrone(drone); check.equals(battle.drones.count(), 0); }); test.case("lists area effects", check => { let battle = new Battle(); let ship = battle.fleets[0].addShip(); let peer = battle.fleets[1].addShip(); peer.setArenaPosition(100, 50); check.equals(battle.getAreaEffects(peer), [], "initial"); let drone1 = new Drone(ship); drone1.x = 120; drone1.y = 60; drone1.radius = 40; drone1.effects = [new DamageEffect(12)]; battle.addDrone(drone1); let drone2 = new Drone(ship); drone2.x = 130; drone2.y = 70; drone2.radius = 20; drone2.effects = [new DamageEffect(14)]; battle.addDrone(drone2); check.equals(battle.getAreaEffects(peer), [[drone1, drone1.effects[0]]], "drone effects"); let eq1 = new ToggleAction("eq1", { power: 0, radius: 500, effects: [new AttributeEffect("initiative", 1)] }); ship.actions.addCustom(eq1); ship.actions.toggle(eq1, true); let eq2 = new ToggleAction("eq2", { power: 0, radius: 500, effects: [new AttributeEffect("initiative", 2)] }); ship.actions.addCustom(eq2); ship.actions.toggle(eq2, false); let eq3 = new ToggleAction("eq3", { power: 0, radius: 100, effects: [new AttributeEffect("initiative", 3)] }); ship.actions.addCustom(eq3); ship.actions.toggle(eq3, true); check.equals(battle.getAreaEffects(peer), [ [drone1, drone1.effects[0]], [ship, eq1.effects[0]], ], "drone and toggle effects"); }); test.case("is serializable", check => { let battle = Battle.newQuickRandom(); let serializer = new Serializer(TK.SpaceTac); let data = serializer.serialize(battle); let loaded = serializer.unserialize(data); check.equals(loaded, battle, "unserialized == initial"); let session = new GameSession(); session.startNewGame(); session.start_location.setupEncounter(); session.start_location.enterLocation(session.player.fleet); let battle1 = nn(session.getBattle()); let data1 = serializer.serialize(battle1); let ratio = data.length / data1.length; check.greaterorequal(ratio, 1.2, `quick battle serialized size (${data.length}) should be larger than campaign's (${data1.length})`); }); test.case("can revert the last turn", check => { let battle = new Battle(); let ship = battle.fleets[0].addShip(); ship.setValue("hull", 13); battle.log.clear(); battle.log.add(new ShipValueDiff(ship, "hull", 4)); battle.log.add(new TurnStartDiff([])); battle.log.add(new ShipValueDiff(ship, "hull", 7)); battle.log.add(new TurnStartDiff([])); battle.log.add(new ShipValueDiff(ship, "hull", 2)); check.in("initial state", check => { check.equals(ship.getValue("hull"), 13, "hull=13"); check.equals(battle.log.count(), 5, "log count=5"); }); battle.revertOneTurn(); check.in("revert 1 turn", check => { check.equals(ship.getValue("hull"), 11, "hull=11"); check.equals(battle.log.count(), 3, "log count=3"); }); battle.revertOneTurn(); check.in("revert 2 turns", check => { check.equals(ship.getValue("hull"), 4, "hull=4"); check.equals(battle.log.count(), 1, "log count=1"); }); battle.revertOneTurn(); check.in("revert 3 turns", check => { check.equals(ship.getValue("hull"), 0, "hull=0"); check.equals(battle.log.count(), 0, "log count=0"); }); }) }); }