예제 #1
0
        public async Task ScoreShouldIncreaseExponentiallyAfterEatingEachGhost(int numberOfGhosts, int totalScore)
        {
            var ghostStart = _gameSettings.PacMan.Location.Left.Left.Left;
            var ghosts     = GhostBuilder.New().WithLocation(ghostStart).WithChaseStrategyRight()
                             .CreateMany(numberOfGhosts);

            _gameSettings.Ghosts.AddRange(ghosts);

            _gameSettings.PowerPills.Add(_gameSettings.PacMan.Location.FarAway());
            _gameSettings.PowerPills.Add(_gameSettings.PacMan.Location.Left);

            var game = new Game(_gameClock, _gameSettings);

            game.StartGame();

            await game.ChangeDirection(Direction.Left);

            await _gameClock.Tick();

            var scoreBeforeGhost = game.Score;

            WeExpectThat(game.PacMan).IsAt(_gameSettings.PacMan.Location.Left);
            for (int g = 0; g < numberOfGhosts; g++)
            {
                WeExpectThat(game.Ghosts.Values).IsAt(ghostStart.Right);
            }

            await _gameClock.Tick();

            WeExpectThat(game.PacMan).IsAt(_gameSettings.PacMan.Location.Left.Left);

            game.Score.Should().Be(scoreBeforeGhost + totalScore);
        }
예제 #2
0
        public async Task PacManDoesNotCollectCoinAndScoreStaysTheSameWhenCollidesWithGhost()
        {
            var ghostAndCoinLocation = _gameSettings.PacMan.Location + Direction.Right;

            var ghost = GhostBuilder.New()
                        .WithLocation(ghostAndCoinLocation)
                        .WithScatterStrategy(new StandingStillGhostStrategy())
                        .Create();

            _gameSettings.Ghosts.Add(ghost);
            _gameSettings.Coins.Add(ghostAndCoinLocation);

            var gameHarness = new GameHarness(_gameSettings);
            await gameHarness.PlayGame();

            var score = gameHarness.Score;

            await gameHarness.ChangeDirection(Direction.Right);

            await gameHarness.GetEatenByGhost(ghost);

            using var _ = new AssertionScope();
            gameHarness.Game.Coins.Should().ContainEquivalentOf(ghostAndCoinLocation);
            gameHarness.Score.Should().Be(score);
        }
예제 #3
0
        public async Task WeGetAnExtraLifeWhenScoreReachesBonusLifePointAfterEatingAGhost()
        {
            var game = CreateInitialGameSettings(gameSettings =>
            {
                var ghostStart = gameSettings.PacMan.Location.Left.Left.Left;
                var ghosts     = GhostBuilder.New().WithLocation(ghostStart).WithChaseStrategyRight()
                                 .Create();

                gameSettings.Ghosts.Add(ghosts);

                gameSettings.PowerPills.Add(gameSettings.PacMan.Location.FarAway());
                gameSettings.PowerPills.Add(gameSettings.PacMan.Location.Left);
                gameSettings.PointsNeededForBonusLife = 200;
            });

            game.StartGame();

            await game.ChangeDirection(Direction.Left);

            await _gameClock.Tick();

            var previousLives = game.Lives;

            await _gameClock.Tick();


            using var _ = new AssertionScope();

            game.Lives.Should().Be(previousLives + 1);

            _numberOfNotificationsTriggered.Should().Be(1);
        }
예제 #4
0
        public async Task PacManShouldRespawnAfter4Seconds()
        {
            _gameSettings.PacMan = new PacMan((1, 1), Direction.Down);
            _gameSettings.Ghosts.Add(GhostBuilder.New().WithLocation((1, 2)).Create());

            var game = new Game(_gameClock, _gameSettings);

            game.StartGame();
            var now = DateTime.UtcNow;
            await _gameClock.Tick(now);

            await _gameClock.Tick(now.AddSeconds(1));

            await _gameClock.Tick(now.AddSeconds(2));

            await _gameClock.Tick(now.AddSeconds(3));

            if (game.Status != GameStatus.Dying)
            {
                throw new Exception($"Invalid Game State {game.Status:G}");
            }

            await _gameClock.Tick(now.AddSeconds(4));

            game.Status.Should().Be(GameStatus.Respawning);
        }
예제 #5
0
        public async Task WhenPacManRespawnsTheGameNotificationShouldFire()
        {
            _gameSettings.PacMan = new PacMan((1, 1), Direction.Down);
            _gameSettings.Ghosts.Add(GhostBuilder.New().WithLocation((1, 2)).Create());

            var numberOfNotificationsTriggered = 0;

            var game = new Game(_gameClock, _gameSettings);

            game.Subscribe(GameNotification.Respawning, () => numberOfNotificationsTriggered++);
            game.StartGame();
            var now = DateTime.UtcNow;
            await _gameClock.Tick(now);

            await _gameClock.Tick(now.AddSeconds(1));

            await _gameClock.Tick(now.AddSeconds(2));

            await _gameClock.Tick(now.AddSeconds(3));

            if (game.Status != GameStatus.Dying)
            {
                throw new Exception($"Invalid Game State {game.Status:G} should be {nameof(GameStatus.Dying)}");
            }

            await _gameClock.Tick(now.AddSeconds(4));

            if (game.Status != GameStatus.Respawning)
            {
                throw new Exception($"Invalid Game State {game.Status:G} should be {nameof(GameStatus.Respawning)}");
            }

            numberOfNotificationsTriggered.Should().Be(1);
        }
예제 #6
0
        public async Task LivesDecreaseWhenCollidesWithGhostWalkingTowardsPacMan()
        {
            // G . . . P
            // . G . P .
            // . . PG . .
            var ghost = GhostBuilder.New()
                        .WithLocation(_gameSettings.PacMan.Location.Left.Left.Left.Left)
                        .WithChaseStrategyRight()
                        .WithScatterStrategyRight()
                        .Create();

            _gameSettings.Ghosts.Add(ghost);

            var gameHarness = new GameHarness(_gameSettings);
            await gameHarness.PlayGame();

            var currentLives = gameHarness.Lives;

            await gameHarness.ChangeDirection(Direction.Left);

            await gameHarness.Move();

            await gameHarness.GetEatenByGhost(ghost);

            gameHarness.Lives.Should().Be(currentLives - 1);
        }
예제 #7
0
        public async Task ShouldNotLoseLifeWhenAlreadyIsDying()
        {
            var ghost = GhostBuilder.New()
                        .WithLocation(_gameSettings.PacMan.Location.Left)
                        .WithScatterStrategyRight()
                        .Create();

            _gameSettings.Ghosts.Add(ghost);

            var ghost2 = GhostBuilder.New()
                         .WithLocation(_gameSettings.PacMan.Location.Left.Left)
                         .WithScatterStrategyRight()
                         .Create();

            _gameSettings.Ghosts.Add(ghost2);

            var gameHarness = new GameHarness(_gameSettings);
            await gameHarness.PlayGame();

            await gameHarness.ChangeDirection(Direction.Left);

            await gameHarness.GetEatenByGhost(ghost);

            gameHarness.WeExpectThatPacMan().HasLives(_gameSettings.InitialLives - 1);

            gameHarness.EnsureGameStatus(GameStatus.Dying);

            await gameHarness.NOP();

            gameHarness.EnsureGameStatus(GameStatus.Dying);

            gameHarness.Lives.Should().Be(_gameSettings.InitialLives - 1);
        }
예제 #8
0
        public async Task TheHighScoreAlwaysIncrementsAfterEatingAGhostDuringTheFirstGame()
        {
            var gameSettings = new TestGameSettings();

            var ghostStart = gameSettings.PacMan.Location.Left.Left.Left;
            var ghost      = GhostBuilder.New()
                             .WithLocation(ghostStart)
                             .WithChaseStrategyRight()
                             .WithScatterStrategyRight()
                             .Create();

            gameSettings.Ghosts.Add(ghost);
            gameSettings.PowerPills.Add(gameSettings.PacMan.Location.FarAway());
            gameSettings.PowerPills.Add(gameSettings.PacMan.Location.Left);

            var gameHarness = new GameHarness(gameSettings);
            await gameHarness.PlayGame();

            gameHarness.WeExpectThatPacMan().IsAt(gameSettings.PacMan.Location);
            gameHarness.WeExpectThatGhost(ghost).IsAt(gameSettings.PacMan.Location.Left.Left.Left);

            await gameHarness.ChangeDirection(Direction.Left);

            await gameHarness.EatPill();

            gameHarness.WeExpectThatPacMan().IsAt(gameSettings.PacMan.Location.Left);
            gameHarness.WeExpectThatGhost(ghost).IsAt(gameSettings.PacMan.Location.Left.Left);

            await gameHarness.EatGhost(ghost);

            gameHarness.Game.HighScore.Should().Be(gameHarness.Score);
        }
예제 #9
0
        public async Task PacManShouldBeAliveAfter4SecondsWhenInRespawning()
        {
            _gameSettings.PacMan = new PacMan((5, 2), Direction.Left);
            _gameSettings.Ghosts.Add(GhostBuilder.New().WithLocation((1, 2)).WithChaseStrategyRight().Create());

            var game = new Game(_gameClock, _gameSettings);

            game.StartGame();
            var now = DateTime.UtcNow;

            await _gameClock.Tick(now);

            await _gameClock.Tick(now);

            await _gameClock.Tick(now.AddSeconds(4));

            if (game.Status != GameStatus.Respawning)
            {
                throw new Exception($"Invalid Game State {game.Status:G}");
            }

            await _gameClock.Tick(now.AddSeconds(8));

            game.Status.Should().Be(GameStatus.Alive);
        }
예제 #10
0
        public async Task GhostIsTeleportedWhenWalkingIntoAPortal()
        {
            var portalEntrance = new CellLocation(10, 1);
            var portalExit     = new CellLocation(1, 5);
            var ghost1         = GhostBuilder.New()
                                 .WithLocation(portalEntrance.Left)
                                 .WithChaseStrategyRight()
                                 .Create();

            _gameSettings.Ghosts.Add(ghost1);
            var game = new Game(_gameClock, _gameSettings);

            game.StartGame();

            _gameSettings.Portals.Add(portalEntrance, portalExit);

            await _gameClock.Tick();

            game.Ghosts.Values.First()
            .Should()
            .BeEquivalentTo(new
            {
                Location = portalExit.Right
            });
        }
예제 #11
0
        public GhostStrategyTests()
        {
            _ghostBuilder = GhostBuilder.New()
                            .WithChaseStrategy(new DirectToStrategy(new DirectToPacManLocation()));

            _gameSettings = new TestGameSettings();
        }
예제 #12
0
        public async Task TheEdibleGhostMovesAtHalfSpeedWhileFrightened()
        {
            var ghostStart1 = _gameSettings.PacMan.Location.Below.Below;
            var ghost1      = GhostBuilder.New()
                              .WithLocation(ghostStart1)
                              .WithChaseStrategyRight()
                              .Create();

            _gameSettings.Ghosts.Add(ghost1);

            _gameSettings.PowerPills.Add(_gameSettings.PacMan.Location.Left);

            var game = new Game(_gameClock, _gameSettings);

            game.StartGame();

            await game.ChangeDirection(Direction.Left);

            await _gameClock.Tick();

            await _gameClock.Tick();

            await _gameClock.Tick();

            await _gameClock.Tick();

            await _gameClock.Tick();

            using var _ = new AssertionScope();
            game.Ghosts[ghost1.Name].Should().BeEquivalentTo(new
            {
                Location = ghostStart1.Right.Right.Right
            });
        }
예제 #13
0
        public async Task AllGhostsShouldRemainInLocationAfterPowerPillIsEaten()
        {
            var ghostStart = _gameSettings.PacMan.Location.Below.Right;
            var ghosts     = GhostBuilder.New()
                             .WithLocation(ghostStart)
                             .CreateMany(3);

            _gameSettings.Ghosts.AddRange(ghosts);

            _gameSettings.PowerPills.Add(_gameSettings.PacMan.Location.Right);

            var game = new Game(_gameClock, _gameSettings);

            game.StartGame();

            await game.ChangeDirection(Direction.Right);

            var now = DateTime.UtcNow;
            await _gameClock.Tick(now);

            if (!game.Ghosts.Values.All(g => g.Edible))
            {
                throw new Exception("All ghosts are meant to be edible.");
            }

            game.Ghosts.Values.Should().AllBeEquivalentTo(new
            {
                Location = ghostStart
            });
        }
예제 #14
0
        public async Task GhostShouldNotMoveWhenPacManIsDying()
        {
            var x = 1;
            var y = 1;

            _gameSettings.InitialGameStatus = GameStatus.Dying;
            var ghost = GhostBuilder.New()
                        .WithLocation((x, y))
                        .WithChaseStrategy(new DirectToStrategy(new DirectToPacManLocation()))
                        .Create();

            _gameSettings.Ghosts.Add(ghost);
            _gameSettings.PacMan = new PacMan((3, 3), Direction.Down);

            var game = new Game(_gameClock, _gameSettings);

            game.StartGame();
            await _gameClock.Tick();

            using var _ = new AssertionScope();
            game.Ghosts.Values.First()
            .Should().BeEquivalentTo(new
            {
                Location = new
                {
                    X = x,
                    Y = y
                }
            });
        }
예제 #15
0
        public async Task EatenGhostNotificationShouldBeFiredAfterEatingAGhost()
        {
            var ghostStart = _gameSettings.PacMan.Location.Left.Left.Left;
            var ghost1     = GhostBuilder.New().WithLocation(ghostStart).WithChaseStrategyRight()
                             .Create();

            _gameSettings.Ghosts.Add(ghost1);

            _gameSettings.PowerPills.Add(_gameSettings.PacMan.Location.Left);

            var game = new Game(_gameClock, _gameSettings);
            var numberOfNotificationsTriggered = 0;

            game.Subscribe(GameNotification.EatGhost, () => numberOfNotificationsTriggered++);
            game.StartGame();

            await game.ChangeDirection(Direction.Left);

            await _gameClock.Tick();

            WeExpectThat(game.PacMan).IsAt(_gameSettings.PacMan.Location.Left);

            WeExpectThat(game.Ghosts.Values).IsAt(ghostStart.Right);

            if (numberOfNotificationsTriggered != 0)
            {
                throw new Exception($"No EatGhost notifications should have been fired but {numberOfNotificationsTriggered} were.");
            }

            await _gameClock.Tick();

            WeExpectThat(game.PacMan).IsAt(_gameSettings.PacMan.Location.Left.Left);

            numberOfNotificationsTriggered.Should().Be(1);
        }
예제 #16
0
        public async Task WeGetAnExtraLifeWhenScoreReachesBonusLifePointAfterEatingAGhost()
        {
            var gameSettings = new TestGameSettings();

            var ghostStart = gameSettings.PacMan.Location.Left.Left.Left;
            var ghost      = GhostBuilder.New()
                             .WithLocation(ghostStart)
                             .WithChaseStrategyRight()
                             .WithScatterStrategyRight()
                             .Create();

            gameSettings.Ghosts.Add(ghost);
            gameSettings.PowerPills.Add(gameSettings.PacMan.Location.FarAway());
            gameSettings.PowerPills.Add(gameSettings.PacMan.Location.Left);
            gameSettings.PointsNeededForBonusLife = PointsFor.EatingFirstGhost;

            var gameHarness = new GameHarness(gameSettings);
            await gameHarness.PlayGame();

            await gameHarness.ChangeDirection(Direction.Left);

            await gameHarness.EatPill();

            var previousLives = gameHarness.Lives;

            using var _ = new AssertionScope();
            await gameHarness.AssertSingleNotificationFires(GameNotification.ExtraPac, async() =>
            {
                await gameHarness.EatGhost(ghost);
            });

            gameHarness.Game.Lives.Should().Be(previousLives + 1);
        }
예제 #17
0
        public async Task PacManShouldBeAliveAfter4SecondsWhenInRespawning()
        {
            var initialPosition = _gameSettings.PacMan.Location;

            var ghost = GhostBuilder.New()
                        .WithLocation(initialPosition.Left.Left.Left.Left)
                        .WithScatterStrategyRight()
                        .WithChaseStrategyRight()
                        .Create();

            _gameSettings.Ghosts.Add(ghost);

            var gameHarness = new GameHarness(_gameSettings);
            await gameHarness.PlayGame();

            await gameHarness.ChangeDirection(Direction.Left);

            await gameHarness.Move();

            await gameHarness.GetEatenByGhost(ghost);

            await gameHarness.WaitToFinishDying();

            gameHarness.EnsureGameStatus(GameStatus.Respawning);

            await gameHarness.WaitToRespawn();

            gameHarness.Game.Status.Should().Be(GameStatus.Alive);
        }
예제 #18
0
        public async Task PacManDoesNotEatPowerPillAndScoreStaysTheSameWhenCollidesWithGhost()
        {
            var pillAndGhostLocation = _gameSettings.PacMan.Location + Direction.Right;

            var ghost = GhostBuilder.New()
                        .WithLocation(pillAndGhostLocation)
                        .Create();

            _gameSettings.Ghosts.Add(ghost);
            _gameSettings.PowerPills.Add(pillAndGhostLocation);

            var gameHarness = new GameHarness(_gameSettings);

            gameHarness.StartGame();

            var score = gameHarness.Score;

            await gameHarness.ChangeDirection(Direction.Right);

            await gameHarness.GetEatenByGhost(ghost);

            using var _ = new AssertionScope();
            gameHarness.Game.PowerPills.Should().ContainEquivalentOf(pillAndGhostLocation);
            gameHarness.Score.Should().Be(score);
        }
예제 #19
0
        public async Task GhostsShouldStandStillInGhostHouse()
        {
            var ghostStart1 = _gameSettings.PacMan.Location.FarAway();

            _gameSettings.GhostHouse.Add(ghostStart1);
            var ghosts = GhostBuilder.New()
                         .WithLocation(ghostStart1)
                         .WithNumberOfCoinsRequiredToExitHouse(int.MaxValue)
                         .CreateMany(2);

            _gameSettings.Ghosts.AddRange(ghosts);

            var game = new Game(_gameClock, _gameSettings);

            game.StartGame();

            await _gameClock.Tick();

            await _gameClock.Tick();

            game.Ghosts.Values.Should().AllBeEquivalentTo(new
            {
                Location = ghostStart1
            });
        }
예제 #20
0
        public async Task GhostShouldScatterToStartWith()
        {
            _gameSettings.InitialGameStatus = GameStatus.Initial;
            _gameSettings.PacMan            = new PacMan((10, 10), Direction.Left);
            var startingLocation = new CellLocation(3, 1);
            var scatterLocation  = new CellLocation(1, 1);

            var ghost = GhostBuilder.New()
                        .WithLocation(startingLocation)
                        .WithScatterTarget(scatterLocation)
                        .WithDirection(Direction.Right)
                        .WithChaseStrategyRight()
                        .Create();

            _gameSettings.Ghosts.Add(ghost);

            var game = new Game(_gameClock, _gameSettings);

            game.StartGame();
            await _gameClock.Tick();

            await _gameClock.Tick();

            await _gameClock.Tick();

            game.Ghosts.Values.First()
            .Should().BeEquivalentTo(new
            {
                Location = new
                {
                    X = scatterLocation.X,
                    Y = scatterLocation.Y
                }
            });
        }
예제 #21
0
        public async Task GhostsShouldBeInScatterModeAfterPacManComesBackToLife()
        {
            //   G
            // > .
            var ghost = GhostBuilder.New()
                        .WithLocation(_gameSettings.PacMan.Location.Right.Above)
                        .WithScatterTarget(_gameSettings.PacMan.Location.Right.Above.Above)
                        .Create();

            var directionPicker = new TestDirectionPicker()
            {
                DefaultDirection = Direction.Down
            };

            _gameSettings.DirectionPicker = directionPicker;
            _gameSettings.Ghosts.Add(ghost);

            var now  = DateTime.UtcNow;
            var game = new Game(_gameClock, _gameSettings);

            game.StartGame();

            await game.ChangeDirection(Direction.Right);

            await _gameClock.Tick(now);

            await game.ChangeDirection(Direction.Up);

            await _gameClock.Tick(now);   //Now dead

            if (game.Status != GameStatus.Dying)
            {
                throw new Exception($"Invalid Game State {game.Status:G} Should be Dying");
            }

            await _gameClock.Tick(now.AddSeconds(4));

            if (game.Status != GameStatus.Respawning)
            {
                throw new Exception($"Invalid Game State {game.Status:G} Should be Respawning");
            }

            await _gameClock.Tick(now.AddSeconds(8));

            if (game.Status != GameStatus.Alive)
            {
                throw new Exception($"Invalid Game State {game.Status:G} Should be Alive");
            }

            await _gameClock.Tick(now.AddSeconds(9));

            game.Ghosts.Values.Should().AllBeEquivalentTo(new
            {
                Edible   = false,
                Location = _gameSettings.PacMan.Location.Right.Above.Above
            });
        }
예제 #22
0
        public async Task GhostShouldScatter7SecondsAfterChase()
        {
            _gameSettings.InitialGameStatus = GameStatus.AttractMode;
            _gameSettings.PacMan            = new PacMan((29, 10), Direction.Left);
            var startingLocation = new CellLocation(30, 1);
            var scatterLocation  = new CellLocation(1, 1);

            var ghost = GhostBuilder.New()
                        .WithLocation(startingLocation)
                        .WithScatterTarget(scatterLocation)
                        .WithDirection(Direction.Right)
                        .WithChaseStrategyRight()
                        .Create();

            _gameSettings.Ghosts.Add(ghost);

            var game = new Game(_gameClock, _gameSettings);

            game.StartGame();
            var now = DateTime.UtcNow;
            await _gameClock.Tick(now);

            await game.PressStart();

            WeExpectThat(ourGhost()).IsAt(startingLocation);
            await _gameClock.Tick(now);

            WeExpectThat(ourGhost()).IsAt(startingLocation.Left);

            await _gameClock.Tick(now.AddSeconds(_gameSettings.InitialScatterTimeInSeconds + 1));

            WeExpectThat(ourGhost()).IsAt(startingLocation.Left.Right);

            await _gameClock.Tick(now.AddSeconds(_gameSettings.InitialScatterTimeInSeconds + 2));

            WeExpectThat(ourGhost()).IsAt(startingLocation.Left.Right.Right);

            now = now.AddSeconds(_gameSettings.InitialScatterTimeInSeconds);
            await _gameClock.Tick(now.AddSeconds(_gameSettings.ChaseTimeInSeconds + 1));

            WeExpectThat(ourGhost()).IsAt(startingLocation.Left.Right.Right.Left);

            await _gameClock.Tick(now.AddSeconds(_gameSettings.ChaseTimeInSeconds + 2));

            ourGhost()
            .Should().BeEquivalentTo(new
            {
                Location = new
                {
                    X = 29,
                    Y = 1
                }
            });


            Ghost ourGhost() => game.Ghosts.Values.First();
        }
예제 #23
0
        public async Task TheGamePausesAfterGhostIsEaten()
        {
            var ghostStart1 = _gameSettings.PacMan.Location.Left.Left.Left;
            var ghost1      = GhostBuilder.New()
                              .WithLocation(ghostStart1)
                              .WithChaseStrategyRight()
                              .Create();
            var ghost2 = GhostBuilder.New()
                         .WithLocation(_gameSettings.PacMan.Location.FarAway())
                         .WithChaseStrategyRight()
                         .Create();

            _gameSettings.Ghosts.Add(ghost1);
            _gameSettings.Ghosts.Add(ghost2);

            _gameSettings.PowerPills.Add(_gameSettings.PacMan.Location.Left);

            var game = new Game(_gameClock, _gameSettings);

            game.StartGame();

            await game.ChangeDirection(Direction.Left);

            var now = DateTime.UtcNow;
            await _gameClock.Tick(now);

            WeExpectThat(game.PacMan).IsAt(_gameSettings.PacMan.Location.Left);
            WeExpectThat(game.Ghosts[ghost1.Name]).IsAt(ghostStart1.Right);

            await _gameClock.Tick(now);

            WeExpectThat(game.PacMan).IsAt(_gameSettings.PacMan.Location.Left.Left);

            var pacManLocation = game.PacMan.Location;
            var ghostLocations = game.Ghosts.Values.Select(x => new {
                x.Name,
                x.Location,
                Status = x.Name == ghost1.Name ? GhostStatus.Score : GhostStatus.Edible
            }).ToDictionary(x => x.Name);

            // Should not move
            await _gameClock.Tick(now);

            await _gameClock.Tick(now);

            await _gameClock.Tick(now);

            using var _ = new AssertionScope();
            game.Should().BeEquivalentTo(new
            {
                PacMan = new
                {
                    Location = pacManLocation
                },
                Ghosts = ghostLocations
            });
        }
예제 #24
0
        public async Task TheEdibleGhostReturnsToStrategyAfterBeingEaten()
        {
            var ghostStart1 = _gameSettings.PacMan.Location.Above.Above.Left;
            var ghost1      = GhostBuilder.New()
                              .WithLocation(ghostStart1)
                              .Create();

            _gameSettings.Ghosts.Add(ghost1);

            _gameSettings.PowerPills.Add(_gameSettings.PacMan.Location.Above);

            // . . .
            // . G .
            // . . *
            // . . V

            var game = new Game(_gameClock, _gameSettings);

            game.StartGame();

            await game.ChangeDirection(Direction.Up);

            var now = DateTime.UtcNow;
            await _gameClock.Tick(now);

            // . . .
            // . G .
            // . . V

            WeExpectThat(game.PacMan).IsAt(_gameSettings.PacMan.Location.Above);
            WeExpectThat(game.Ghosts[ghost1.Name]).IsAt(ghostStart1);

            await _gameClock.Tick(now);

            // . . .
            // . . GV

            // Perhaps . G V ????

            WeExpectThat(game.PacMan).IsAt(_gameSettings.PacMan.Location.Above.Above);
            WeExpectThat(game.Ghosts[ghost1.Name]).IsAt(ghostStart1);

            await _gameClock.Tick(now);

            // . . V
            // . G .
            // . . .

            WeExpectThat(game.PacMan).IsAt(_gameSettings.PacMan.Location.Above.Above.Above);

            using var _ = new AssertionScope();
            game.Ghosts[ghost1.Name].Should().BeEquivalentTo(new
            {
                Location = ghostStart1
            });
        }
예제 #25
0
        public async Task TheGameResumesAfterBeingPausedForOneSecondAfterGhostIsEaten()
        {
            //      P
            //   .  *
            // G .  .

            var ghostStart1 = _gameSettings.PacMan.Location.Below.Below.Left.Left;
            var ghost1      = GhostBuilder.New()
                              .WithLocation(ghostStart1)
                              .WithChaseStrategyRight()
                              .Create();
            var ghost2 = GhostBuilder.New()
                         .WithLocation(_gameSettings.PacMan.Location.FarAway())
                         .WithChaseStrategyRight()
                         .Create();

            _gameSettings.Ghosts.Add(ghost1);
            _gameSettings.Ghosts.Add(ghost2);

            _gameSettings.PowerPills.Add(_gameSettings.PacMan.Location.Below);


            var gameHarness = new GameHarness(_gameSettings);

            gameHarness.Game.StartGame();

            await gameHarness.ChangeDirection(Direction.Down);

            await gameHarness.EatPill();

            gameHarness.WeExpectThatPacMan().IsAt(_gameSettings.PacMan.Location.Below);
            gameHarness.WeExpectThatGhost(ghost1).IsAt(ghostStart1.Right);

            await gameHarness.EatGhost(ghost1);

            gameHarness.WeExpectThatPacMan().IsAt(_gameSettings.PacMan.Location.Below.Below);

            var pacManLocation = gameHarness.Game.PacMan.Location;
            var ghostLocations = gameHarness.Game.Ghosts.Values.Select(x => new {
                x.Name,
                x.Location
            }).ToDictionary(x => x.Name);

            await gameHarness.WaitForPauseToComplete();

            await gameHarness.Move();

            using var _ = new AssertionScope();
            gameHarness.Game.PacMan.Should().NotBeEquivalentTo(new
            {
                Location = pacManLocation
            });
            gameHarness.Game.Ghosts.Should().NotBeEmpty();
            gameHarness.Game.Ghosts.Should().NotBeEquivalentTo(ghostLocations);
        }
예제 #26
0
        public async Task GhostsShouldLeaveGhostHouseWhenPillCountHasBeenReached()
        {
            // X
            // -
            // H G

            var ghostStart1 = new CellLocation(1, 2);

            _gameSettings.PacMan = new PacMan(ghostStart1.FarAway(), Direction.Left);
            _gameSettings.GhostHouse.AddRange(new[] { ghostStart1, ghostStart1.Left });
            _gameSettings.Doors.Add(ghostStart1.Left.Above);
            var ghost1 = GhostBuilder.New()
                         .WithLocation(ghostStart1)
                         .WithNumberOfCoinsRequiredToExitHouse(1)
                         .Create();
            var ghost2 = GhostBuilder.New()
                         .WithLocation(ghostStart1)
                         .WithNumberOfCoinsRequiredToExitHouse(10)
                         .Create();

            _gameSettings.Ghosts.Add(ghost1);
            _gameSettings.Ghosts.Add(ghost2);

            _gameSettings.Coins.Add(_gameSettings.PacMan.Location.FarAway());
            _gameSettings.Coins.Add(_gameSettings.PacMan.Location.Left);

            var game = new Game(_gameClock, _gameSettings);

            game.StartGame();
            await game.ChangeDirection(Direction.Left);

            // PacMan Eats Coin
            await _gameClock.Tick();

            // Still in House, under door
            await _gameClock.Tick();

            // On ghost door
            await _gameClock.Tick();

            // Out of house
            await _gameClock.Tick();

            using var _ = new AssertionScope();
            game.Ghosts[ghost1.Name].Should().BeEquivalentTo(new
            {
                Location = ghostStart1.Left.Above.Above
            });
            game.Ghosts[ghost2.Name].Should().BeEquivalentTo(new
            {
                Location = ghostStart1
            });
        }
예제 #27
0
        public async Task AllGhostsShouldChangeDirectionWhenPacManEatsPowerPill()
        {
            var ghost1 = GhostBuilder.New()
                         .WithLocation(_gameSettings.PacMan.Location.FarAway())
                         .WithDirection(Direction.Up)
                         .Create();
            var ghost2 = GhostBuilder.New()
                         .WithLocation(_gameSettings.PacMan.Location.FarAway())
                         .WithDirection(Direction.Down)
                         .Create();
            var ghost3 = GhostBuilder.New()
                         .WithLocation(_gameSettings.PacMan.Location.FarAway())
                         .WithDirection(Direction.Left)
                         .Create();
            var ghost4 = GhostBuilder.New()
                         .WithLocation(_gameSettings.PacMan.Location.FarAway())
                         .WithDirection(Direction.Right)
                         .Create();

            _gameSettings.Ghosts.AddRange(new[] { ghost1, ghost2, ghost3, ghost4 });

            _gameSettings.PowerPills.Add(_gameSettings.PacMan.Location.FarAway());
            _gameSettings.PowerPills.Add(_gameSettings.PacMan.Location.Right);

            var game = new Game(_gameClock, _gameSettings);

            game.StartGame();

            await game.ChangeDirection(Direction.Right);

            await _gameClock.Tick();

            game.Ghosts.Should().BeEquivalentTo(new Dictionary <string, object>
            {
                [ghost1.Name] = new
                {
                    Direction = ghost1.Direction.Opposite()
                },
                [ghost2.Name] = new
                {
                    Direction = ghost2.Direction.Opposite()
                },
                [ghost3.Name] = new
                {
                    Direction = ghost3.Direction.Opposite()
                },
                [ghost4.Name] = new
                {
                    Direction = ghost4.Direction.Opposite()
                },
            });
        }
예제 #28
0
        public async Task AllGhostsShouldChangeDirectionWhenPacManEatsPowerPill()
        {
            var ghost1 = GhostBuilder.New()
                         .WithLocation(_gameSettings.PacMan.Location.FarAway())
                         .WithScatterStrategyUp()
                         .Create();
            var ghost2 = GhostBuilder.New()
                         .WithLocation(_gameSettings.PacMan.Location.FarAway())
                         .WithScatterStrategyDown()
                         .Create();
            var ghost3 = GhostBuilder.New()
                         .WithLocation(_gameSettings.PacMan.Location.FarAway())
                         .WithScatterStrategyLeft()
                         .Create();
            var ghost4 = GhostBuilder.New()
                         .WithLocation(_gameSettings.PacMan.Location.FarAway())
                         .WithScatterStrategyRight()
                         .Create();

            _gameSettings.Ghosts.AddRange(new[] { ghost1, ghost2, ghost3, ghost4 });

            _gameSettings.PowerPills.Add(_gameSettings.PacMan.Location.FarAway());
            _gameSettings.PowerPills.Add(_gameSettings.PacMan.Location.Right);

            var gameHarness = new GameHarness(_gameSettings);
            await gameHarness.PlayGame();

            await gameHarness.ChangeDirection(Direction.Right);

            await gameHarness.EatPill();

            gameHarness.Game.Ghosts.Should().BeEquivalentTo(new Dictionary <string, object>
            {
                [ghost1.Name] = new
                {
                    Direction = Direction.Down
                },
                [ghost2.Name] = new
                {
                    Direction = Direction.Up
                },
                [ghost3.Name] = new
                {
                    Direction = Direction.Right
                },
                [ghost4.Name] = new
                {
                    Direction = Direction.Left
                },
            });
        }
예제 #29
0
        public async Task GhostsGoHomeAfterCollidesWithPacManAfterEatingPowerPill()
        {
            var ghostStart1and3 = _gameSettings.PacMan.Location.Left.Left.Left;
            var ghostStart2     = ghostStart1and3.Below;
            var haunt1          = GhostBuilder.New()
                                  .WithLocation(ghostStart1and3)
                                  .WithChaseStrategyRight()
                                  .CreateMany(2);
            var haunt2 = GhostBuilder.New()
                         .WithLocation(ghostStart2)
                         .WithChaseStrategyRight()
                         .CreateMany(1);

            _gameSettings.Ghosts.AddRange(haunt1.Concat(haunt2));

            _gameSettings.PowerPills.Add(_gameSettings.PacMan.Location.Left);

            var game = new Game(_gameClock, _gameSettings);

            game.StartGame();

            await game.ChangeDirection(Direction.Left);

            var now = DateTime.UtcNow;
            await _gameClock.Tick(now);

            WeExpectThat(game.PacMan).IsAt(_gameSettings.PacMan.Location.Left);
            foreach (var g in haunt1)
            {
                WeExpectThat(game.Ghosts[g.Name]).IsAt(ghostStart1and3.Right);
            }

            await _gameClock.Tick(now);

            WeExpectThat(game.PacMan).IsAt(_gameSettings.PacMan.Location.Left.Left);

            game.Ghosts[haunt1[0].Name].Should().BeEquivalentTo(new
            {
                Location = ghostStart1and3
            });

            game.Ghosts[haunt2.First().Name].Should().NotBeEquivalentTo(new
            {
                Location = ghostStart2
            });

            game.Ghosts[haunt1[1].Name].Should().BeEquivalentTo(new
            {
                Location = ghostStart1and3
            });
        }
예제 #30
0
        public async Task GhostShouldBeRunningHomeAfterThePauseAfterBeingTheEaten()
        {
            //      P
            //   .  *
            // G .  .

            var ghostStart1 = _gameSettings.PacMan.Location.Below.Below.Left.Left;
            var ghost1      = GhostBuilder.New()
                              .WithLocation(ghostStart1)
                              .WithChaseStrategyRight()
                              .Create();
            var ghost2 = GhostBuilder.New()
                         .WithLocation(_gameSettings.PacMan.Location.FarAway())
                         .WithChaseStrategyRight()
                         .Create();

            _gameSettings.Ghosts.Add(ghost1);
            _gameSettings.Ghosts.Add(ghost2);

            _gameSettings.PowerPills.Add(_gameSettings.PacMan.Location.Below);


            var gameHarness = new GameHarness(_gameSettings);

            gameHarness.Game.StartGame();

            await gameHarness.ChangeDirection(Direction.Down);

            await gameHarness.EatPill();

            gameHarness.WeExpectThatPacMan().IsAt(_gameSettings.PacMan.Location.Below);
            gameHarness.WeExpectThatGhost(ghost1).IsAt(ghostStart1.Right);

            await gameHarness.EatGhost(ghost1);

            gameHarness.WeExpectThatPacMan().IsAt(_gameSettings.PacMan.Location.Below.Below);

            var pacManLocation = gameHarness.Game.PacMan.Location;
            var ghostLocations = gameHarness.Game.Ghosts.Values.Select(x => new {
                x.Name,
                x.Location
            }).ToDictionary(x => x.Name);

            await gameHarness.WaitForPauseToComplete();

            await gameHarness.Move();

            using var _ = new AssertionScope();
            gameHarness.Game.Ghosts[ghost1.Name].Status.Should().Be(GhostStatus.RunningHome);
            gameHarness.Game.Ghosts[ghost2.Name].Status.Should().Be(GhostStatus.Edible);
        }