public static Missile CopyAndFlip(Missile missile, CoordinateFlipper flipper,
            Dictionary<int, Entity> flippedEntities)
        {
            if (flippedEntities.ContainsKey(missile.Id)) return (Missile) flippedEntities[missile.Id];

            var copy = new Missile(missile)
            {
                PlayerNumber = missile.PlayerNumber == 1 ? 2 : 1,
                X = flipper.CalculateFlippedX(missile.X),
                Y = flipper.CalculateFlippedY(missile.Y)
            };

            flippedEntities.Add(copy.Id, copy);
            return copy;
        }
 public Missile(Missile missile) : base(missile)
 {
     OnDestroyedEvent += OnDestroy;
 }
        public void TestAlienSpawnOnMissileRegistersKill()
        {
            // Given
            var game = Match.GetInstance();
            game.StartNewGame(true);
            var map = game.Map;

            // When
            var missile = new Missile(1) {X = map.Width - 2, Y = map.Height/2 + 2};
            map.AddEntity(missile);
            game.Update();

            AlienFactory.Build(2, 3, map.Width - 2, -1);

            // Then
            Assert.IsFalse(missile.Alive, "Missile was not destroyed as expected - must've mis-timed the spawn.");
            Assert.AreEqual(1, game.GetPlayer(1).Kills,
                "Player 1 did not score a kill for an alien spawning on their missile.");
        }
 public Missile(Missile missile)
     : base(missile)
 {
     OnDestroyedEvent += OnDestroy;
 }
        public void TestShipMovingLeftIntoMissileDies()
        {
            // Given
            var game = Match.GetInstance();
            game.StartNewGame();
            var map = game.Map;

            var player = game.GetPlayer(1);
            var ship = player.Ship;
            var aliens = game.GetPlayer(2).AlienManager;
            var player2 = game.GetPlayer(2);
            var killsBefore = player2.Kills;

            // When
            var missile = new Missile(2) { X = ship.X - 1, Y = ship.Y - 1 };
            map.AddEntity(missile);

            ship.Command = ShipCommand.MoveLeft;
            game.Update();

            // Then
            var killsAfter = player2.Kills;
            Assert.IsFalse(missile.Alive, "Missile was not destroyed, must've mis-timed the collision.");
            Assert.IsNull(player.Ship, "Ship was not destroyed.");
            Assert.IsTrue(killsAfter == killsBefore + 1, "Player 2 did not get the kill.");
        }
        public void Shoot()
        {
            var player = GetPlayer();

            if (player.Missiles.Count >= player.MissileLimit)
            {
                CommandFeedback = "Shot failed - too many missiles in flight.";
                return;
            }

            var missileX = X + 1; // center of the ship
            var missileY = (PlayerNumber == 1) ? Y - 1 : Y + 1;

            var missile = new Missile(PlayerNumber)
            {
                X = missileX,
                Y = missileY
            };

            try
            {
                GetMap().AddEntity(missile);
                player.Missiles.Add(missile);
                missile.OnDestroyedEvent += OnMissileDestroyed;
            }
            catch (CollisionException ex)
            {
                missile.ScoreKill(ex.Entity);
                ex.Entity.Destroy();
            }
        }
        public void TestMissilesOneDoesNotKillTwo()
        {
            // Given
            var renderer = new SpaceInvadersRenderer();
            var game = Match.GetInstance();
            game.StartNewGame();
            var map = game.Map;

            var player = game.GetPlayer(1);
            var ship = player.Ship;
            var aliens = game.GetPlayer(2).AlienManager;
            var player2 = game.GetPlayer(2);
            var killsBefore = player2.Kills;

            // When
            //add them in the order the harness would add them
            var missile1 = new Missile(1) { X = ship.X, Y = ship.Y - 3 };
            map.AddEntity(missile1);

            var missile3 = new Missile(2) { X = ship.X, Y = ship.Y - 4 };
            map.AddEntity(missile3);
            var missile4 = new Missile(2) { X = ship.X, Y = ship.Y - 5 };
            map.AddEntity(missile4);

            // Then
            Console.WriteLine(renderer.Render(game).Map);

            game.Update();
            Console.WriteLine(renderer.Render(game).Map);

            Assert.IsFalse(missile1.Alive, "Missile 1 wasn't destroyed.");
            Assert.IsFalse(missile3.Alive, "Missile 3 wasn't destroyed.");
            Assert.IsTrue(missile4.Alive, "Missile 4 was destroyed.");
        }
        public void TestSamePlayerMissilesDontDestroyEachother4()
        {
            // Given
            var game = Match.GetInstance();
            game.StartNewGame();
            var map = game.Map;

            var player = game.GetPlayer(1);
            var ship = player.Ship;
            var aliens = game.GetPlayer(2).AlienManager;
            var player2 = game.GetPlayer(2);
            var killsBefore = player2.Kills;

            // When
            //add them in the order the harness would add them
            var missile1 = new Missile(1) { X = ship.X, Y = ship.Y - 2 };
            map.AddEntity(missile1);

            var missile3 = new Missile(2) { X = ship.X, Y = ship.Y - 4 };
            map.AddEntity(missile3);
            var missile4 = new Missile(2) { X = ship.X, Y = ship.Y - 5 };
            map.AddEntity(missile4);

            game.Update();

            // Then
            Assert.IsFalse(missile1.Alive, "Missile 1 wasn't destroyed.");
            Assert.IsFalse(missile3.Alive, "Missile 3 wasn't destroyed.");
            Assert.IsTrue(missile4.Alive, "Missile 4 was destroyed.");
            game.Update();
            Assert.IsTrue(missile4.Alive, "Missile 4 was destroyed.");
        }
        public void TestBuildShieldDestroysMissilesAndBullets()
        {
            // Given
            var game = Match.GetInstance();
            game.StartNewGame();
            var map = game.Map;
            var player = game.GetPlayer(1);
            var ship = player.Ship;

            // When
            var missile = new Missile(2) {X = ship.X, Y = ship.Y - 3};
            var bullet = new Bullet(2) {X = ship.X + 2, Y = ship.Y - 3};
            map.AddEntity(missile);
            map.AddEntity(bullet);
            ship.Command = ShipCommand.BuildShield;
            game.Update();

            // Then
            Assert.IsFalse(missile.Alive, "Missile was not destroyed");
            Assert.IsFalse(bullet.Alive, "Bullet was not destroyed");

            Assert.IsNotNull(map.GetEntity(ship.X, ship.Y - 1),
                "Left rear shield tile is missing");
            Assert.IsNotNull(map.GetEntity(ship.X + 1, ship.Y - 1),
                "Center rear shield tile is missing");
            Assert.IsNotNull(map.GetEntity(ship.X + 2, ship.Y - 1),
                "Right rear shield tile is missing");

            // Missiles and bullets fly for one turn before the shields spawn, hence here instead of in front
            Assert.IsNull(map.GetEntity(ship.X, ship.Y - 2),
                "Left middle shield was not destroyed");
            Assert.IsNotNull(map.GetEntity(ship.X + 1, ship.Y - 2),
                "Center middle shield tile is missing");
            Assert.IsNull(map.GetEntity(ship.X + 2, ship.Y - 2),
                "Right middle shield tile was not destroyed");

            Assert.IsNotNull(map.GetEntity(ship.X, ship.Y - 3),
                "Left front shield tile is missing");
            Assert.IsNotNull(map.GetEntity(ship.X + 1, ship.Y - 3),
                "Center front shield tile is missing");
            Assert.IsNotNull(map.GetEntity(ship.X + 2, ship.Y - 3),
                "Right front shield tile is missing");
        }
        public void TestTwoMissileShieldCollission()
        {
            // Given
            var game = Match.GetInstance();
            game.StartNewGame(true);
            var map = game.Map;
            var player = game.GetPlayer(1);
            var ship = player.Ship;

            ship.Command = ShipCommand.BuildShield;
            game.Update();

            // When
            //destroy closest shield
            ship.Command = ShipCommand.Shoot;
            game.Update();

            //destroy second closest shield
            ship.Command = ShipCommand.Shoot;
            game.Update();
            game.Update();

            var missile2 = new Missile(2) { X = ship.X+1, Y = ship.Y - 5}; //place missile so that player 1's missile and player 2's missile collide on a shield
            var missile1 = new Missile(1) { X = ship.X + 1, Y = ship.Y - 1 };
            map.AddEntity(missile1);
            map.AddEntity(missile2);
            //fire at 3rd closest shield
            game.Update();
            game.Update();

            // Then
            Assert.IsNull(map.GetEntity(ship.X + 1, ship.Y - 1),
                "Center shield tile was not destroyed");
            Assert.IsNull(map.GetEntity(ship.X + 1, ship.Y - 2),
                "Second centre shield tile was not destroyed");
            Assert.IsNull(map.GetEntity(ship.X + 1, ship.Y - 3),
                "Third centre shield tile was not destroyed");
            Assert.IsFalse(missile1.Alive, "Missile was not destroyed, must've mis-timed the collision.");
            Assert.IsFalse(missile2.Alive, "Missile was not destroyed, must've mis-timed the collision.");
        }
        public void TestTwoMissilePlayerTwoAlienCollission()
        {
            // Given
            var game = Match.GetInstance();
            game.StartNewGame(true);
            var map = game.Map;
            var player = game.GetPlayer(1);
            var ship = player.Ship;
            var aliens = game.GetPlayer(2).AlienManager;
            var player1 = game.GetPlayer(1);
            var player2 = game.GetPlayer(2);
            var initialScoreP1 = player1.Kills;
            var initialScoreP2 = player2.Kills;

            // When
            var missile2 = new Missile(2) { X = ship.X + 1, Y = ship.Y - 4 };
            var missile1 = new Missile(1) { X = ship.X + 1, Y = ship.Y - 2 };
            map.AddEntity(missile1);
            map.AddEntity(missile2);
            var alien = aliens.TestAddAlien(ship.X + 1, ship.Y - 3);

            game.Update();

            var finalScoreP1 = player1.Kills;
            var finalScoreP2 = player2.Kills;

            // Then
            Assert.IsFalse(alien.Alive, "Alien was not destroyed, must've mis-timed the collision.");
            Assert.IsTrue(finalScoreP1 == initialScoreP1 + 1, "Player 1 score did not increase.");
            Assert.IsTrue(finalScoreP2 == initialScoreP2, "Player 2 score increased.");

            // Then
            Assert.IsFalse(missile1.Alive, "Player 1's missile was not destroyed, must've mis-timed the collision.");
            Assert.IsFalse(missile2.Alive, "Player 2's missile was not destroyed, must've mis-timed the collision.");
        }
        public void TestShipSpawningOnMultipleEntitiesDie()
        {
            // Given
            var game = Match.GetInstance();
            game.StartNewGame();

            var player = game.GetPlayer(1);
            var ship = player.Ship;
            var aliens = game.GetPlayer(2).AlienManager;
            var map = game.Map;
            var player2 = game.GetPlayer(2);
            var initialScore = player2.Kills;

            // When
            var alien = aliens.TestAddAlien(ship.X, ship.Y - 3); //left side of ship
            aliens.TestMakeAllAliensMoveForward();
            ship.Destroy();
            var missile = new Missile(2) { X = ship.X + 1, Y = ship.Y - 3 }; //centre of ship
            map.AddEntity(missile);

            var bullet = new Bullet(2) { X = ship.X + 2, Y = ship.Y - 3 }; //right side of ship
            map.AddEntity(bullet);

            for (var i = 0; i < respawnDelay; i++)
            {
                game.Update();
            }
            var finalScore = player2.Kills;

            // Then
            Assert.IsFalse(alien.Alive, "Alien was not destroyed, must've mis-timed the collision.");
            Assert.IsNull(player.Ship, "Ship was not destroyed.");
            Assert.IsFalse(missile.Alive, "Missile was not destroyed, must've mis-timed the collision.");
            Assert.IsFalse(bullet.Alive, "Bullet was not destroyed, must've mis-timed the collision.");
            Assert.IsTrue(finalScore > initialScore, "Player 2 score did not increase.");
        }
        public void TestShipSpawningOnMissileRegistersKill()
        {
            // Given
            var game = Match.GetInstance();
            game.StartNewGame();

            var map = game.Map;
            var player1 = game.GetPlayer(1);
            var ship = player1.Ship;
            var player2 = game.GetPlayer(2);
            var initialScore = player2.Kills;

            // When
            var missile = new Missile(2) {X = ship.X, Y = ship.Y - 3};
            map.AddEntity(missile);
            ship.Destroy();

            for (var i = 0; i < respawnDelay; i++) {
                game.Update();
            }
            var finalScore = player2.Kills;

            // Then
            Assert.IsFalse(missile.Alive, "Missile was not destroyed, must've mis-timed the collision.");
            Assert.IsNull(player1.Ship, "Player 1 ship was not destroyed.");
            Assert.IsTrue(finalScore > initialScore, "Player 2 score did not increase.");
        }