public void FiveStepsAwayFromMaxWinning_IterativeSearch_ReuseCache_MaxWin(int degreeOfParallelism, ParallelismMode parallelismMode)
        {
            var startState = Connect4TestUtils.GetMaxFiveMovesAwayFromWinningState();
            var engine     = Connect4TestUtils.GetSearchEngine(degreeOfParallelism, parallelismMode, 1, CacheMode.ReuseCache);

            var evaluation = new IterativeSearchWrapper(engine).IterativeSearch(startState, 1, 8, CancellationToken.None);

            Assert.AreEqual(BoardEvaluator.MaxEvaluation, evaluation.Evaluation);
        }
        public void BenchmarkConnect4()
        {
            var searchDepth = 11;
            var board       = Connect4TestUtils.GetEmptyBoard();

            Benchmark(board, searchDepth, ParallelismMode.NonParallelism);
            Benchmark(board, searchDepth, ParallelismMode.FirstLevelOnly);
            Benchmark(board, searchDepth, ParallelismMode.ParallelismByLevel, levelOfParallelism: 2);
            Benchmark(board, searchDepth, ParallelismMode.TotalParallelism, 4);
        }
        public void FiveStepsAwayFromMaxWinning_MaxTurn_MaxWin(int degreeOfParallelism, ParallelismMode parallelismMode, CacheMode cacheMode)
        {
            var startState = Connect4TestUtils.GetMaxFiveMovesAwayFromWinningState();

            var engine     = Connect4TestUtils.GetSearchEngine(degreeOfParallelism, parallelismMode, 1, CacheMode.ReuseCache);
            var evaluation = engine.Search(startState, 5);

            Assert.AreEqual(BoardEvaluator.MaxEvaluation, evaluation.Evaluation);
            Assert.IsTrue(BoardEvaluator.IsWin(((Connect4State)evaluation.StateSequence.Last()).Board, Player.Max), "Should have found a wining state");
            Assert.IsTrue(evaluation.AllChildrenAreDeadEnds, "All children should be dead ends");
        }
        public void FiveStepsAwayFromMaxWinning_ReuseCache_DontDieEarly_MaxWin(int degreeOfParallelism, ParallelismMode parallelismMode)
        {
            var startState = Connect4TestUtils.GetMaxFiveMovesAwayFromWinningState();

            var engine = Connect4TestUtils.GetSearchEngine(degreeOfParallelism, parallelismMode, 1, CacheMode.ReuseCache);

            engine.DieEarly = false;
            engine.Search(startState, 5);
            Assert.IsTrue(((StateCacheManager)engine.CacheManager).Count > 0, "The cache doesn't contain any states");

            var evaluation = engine.Search(startState, 5);

            Assert.AreEqual(BoardEvaluator.MaxEvaluation, evaluation.Evaluation);
        }
        private void Benchmark(Player[,] startBoard, int searchDepth,
                               ParallelismMode parallelismMode = ParallelismMode.FirstLevelOnly, int degreeOfParallelism = 1,
                               int levelOfParallelism          = 1)
        {
            Console.WriteLine(GetTestMessage(parallelismMode, degreeOfParallelism, levelOfParallelism));
            var engine     = Connect4TestUtils.GetSearchEngine(degreeOfParallelism, parallelismMode, levelOfParallelism);
            var startState = new Connect4State(startBoard, Player.Max);

            var results = engine.Search(startState, searchDepth);

            Console.WriteLine("Time: " + results.SearchTime);
            Console.WriteLine("Leaves: " + results.Leaves);
            Console.WriteLine("InternalNodes: " + results.InternalNodes);
        }
        public void NewGame_CheckCancellationToken(int degreeOfParallelism, ParallelismMode parallelismMode)
        {
            var startState = new Connect4State(Connect4TestUtils.GetEmptyBoard(), Player.Max);

            var engine             = Connect4TestUtils.GetSearchEngine(degreeOfParallelism, parallelismMode);
            var cancellationSource = new CancellationTokenSource();
            var searchTask         = engine.SearchAsync(startState, 20, cancellationSource.Token);

            Thread.Sleep(500);
            cancellationSource.Cancel();
            Thread.Sleep(500);

            Assert.IsTrue(searchTask.IsCompleted, "Search should have complated by now");
            var t = searchTask.Result; // Check that we can get a result even if the search was terminated
        }
        public void FiveStepsAwayFromMaxWinning_FillCache_MaxWin(int degreeOfParallelism, ParallelismMode parallelismMode)
        {
            var startState = Connect4TestUtils.GetMaxFiveMovesAwayFromWinningState();

            var engine = Connect4TestUtils.GetSearchEngine(degreeOfParallelism, parallelismMode, 1, CacheMode.ReuseCache);

            engine.DieEarly = true;
            engine.FillCache(startState, CancellationToken.None);
            Assert.IsTrue(((StateCacheManager)engine.CacheManager).Count > 0, "The cache doesn't contain any states");
            Assert.IsNotNull(engine.CacheManager.GetStateEvaluation(startState, 0, null), "The cache doesn't contain the start state");

            var evaluation = engine.Search(startState, 5);

            Assert.AreEqual(BoardEvaluator.MaxEvaluation, evaluation.Evaluation);
        }
        public void ThreeStepsAwayFromMaxWinning_MaxTurn_MaxWin(int degreeOfParallelism, ParallelismMode parallelismMode)
        {
            var startState = new Connect4State(new[, ]
            {
                { Player.Empty, Player.Empty, Player.Empty, Player.Max, Player.Max, Player.Empty },
                { Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty },
                { Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty },
                { Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty },
                { Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty },
                { Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty },
            }, Player.Max);

            var engine     = Connect4TestUtils.GetSearchEngine(degreeOfParallelism, parallelismMode);
            var evaluation = engine.Search(startState, 3);

            Assert.IsTrue(BoardEvaluator.IsWin(((Connect4State)evaluation.StateSequence.Last()).Board, Player.Max), "Should have found a wining state");
        }
        public void TwoStepsAwayFromMaxWinning__MinsTurn_DontLetMinMax(int degreeOfParallelism, ParallelismMode parallelismMode)
        {
            var startState = new Connect4State(new[, ]
            {
                { Player.Empty, Player.Max, Player.Empty, Player.Empty, Player.Empty, Player.Empty },
                { Player.Empty, Player.Max, Player.Empty, Player.Empty, Player.Empty, Player.Empty },
                { Player.Empty, Player.Max, Player.Empty, Player.Empty, Player.Empty, Player.Empty },
                { Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty },
                { Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty },
                { Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty },
            }, Player.Min);

            var engine   = Connect4TestUtils.GetSearchEngine(degreeOfParallelism, parallelismMode);
            var newState = (Connect4State)engine.Search(startState, 2).NextMove;

            Assert.AreEqual(Player.Min, newState.Board[3, 1], "Min didn't block Max's win");
        }
        public void OneStepAwayFromMaxWinning_MaxTurn_MaxWin(int degreeOfParallelism, ParallelismMode parallelismMode)
        {
            var startState = new Connect4State(new[, ]
            {
                { Player.Empty, Player.Max, Player.Empty, Player.Empty, Player.Empty, Player.Empty },
                { Player.Empty, Player.Max, Player.Empty, Player.Empty, Player.Empty, Player.Empty },
                { Player.Empty, Player.Max, Player.Empty, Player.Empty, Player.Empty, Player.Empty },
                { Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty },
                { Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty },
                { Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty, Player.Empty },
            }, Player.Max);

            var engine     = Connect4TestUtils.GetSearchEngine(degreeOfParallelism, parallelismMode);
            var evaluation = engine.Search(startState, 2);

            Assert.IsTrue(BoardEvaluator.IsWin(((Connect4State)evaluation.NextMove).Board, Player.Max),
                          "Should have found a wining state");
            Assert.AreEqual(1, evaluation.StateSequence.Count, "StateSequence should only have one state in it");
        }
        public void NewGame_NoOneCanWin(int degreeOfParallelism, ParallelismMode parallelismMode)
        {
            var startState = new Connect4State(Connect4TestUtils.GetEmptyBoard(), Player.Max);

            var engine     = Connect4TestUtils.GetSearchEngine(degreeOfParallelism, parallelismMode);
            var evaluation = engine.Search(startState, 7);

            Assert.IsFalse(BoardEvaluator.IsWin(((Connect4State)evaluation.StateSequence.Last()).Board, Player.Max));
            Assert.IsFalse(evaluation.FullTreeSearchedOrPruned);
            Assert.IsFalse(evaluation.AllChildrenAreDeadEnds);

            if (degreeOfParallelism == 1)
            {
                //Check that the our optimizations are working
                Assert.IsTrue(evaluation.Leaves < 26000, "Too many leaves in search. Leaves = " + evaluation.Leaves);
                Assert.IsTrue(evaluation.InternalNodes < 10000,
                              "Too many intarnal nodes in search. Nodes = " + evaluation.InternalNodes);
            }
            // Too few leaves or internal nodes means that something went wrong
            Assert.IsTrue(evaluation.Leaves > 1000, "Too few leaves in search. Leaves = " + evaluation.Leaves);
            Assert.IsTrue(evaluation.InternalNodes > 1000, "Too few intarnal nodes in search. Nodes = " + evaluation.InternalNodes);
        }
 public void BenchmarkConnect4_HalfFullBoard() =>
 Benchmark(Connect4TestUtils.GetHalfFullBoard(), 20);