Esempio n. 1
0
        /// <summary>
        /// Min max searching algorithm with defined cutoff depth.
        /// </summary>
        /// <returns>The column that will be moved played in.</returns>
        private int MinimaxCutoffSearch(BitBoard board)
        {
            int maxDepth = 7;

            var openMoveValue = 0.0m;
            var movedColumn   = -1;

            var alpha = decimal.MinValue;
            var beta  = decimal.MaxValue;

            var nodeCounter = new NodeCounter();
            var stopWatch   = new Stopwatch();

            stopWatch.Start();

            if (AiColor == DiscColor.Red)
            {
                (openMoveValue, movedColumn) = MinValue(board, maxDepth, alpha, beta, nodeCounter, AiColor);
            }
            else
            {
                (openMoveValue, movedColumn) = MaxValue(board, maxDepth, alpha, beta, nodeCounter, AiColor);
            }

            stopWatch.Stop();
            var elapsed = stopWatch.Elapsed;

            var elapsedTime = String.Format("Searched for {0:00}.{1:0000} seconds",
                                            elapsed.Seconds, elapsed.Milliseconds);

            Console.WriteLine(elapsedTime);

            Console.WriteLine($"Column {movedColumn} was chosen.");
            Console.WriteLine($"{nodeCounter.TotalNodes} were explored.");

            return(movedColumn);
        }
Esempio n. 2
0
 public void UpdateBoard(BitBoard board)
 {
     GameBoard = board;
 }
Esempio n. 3
0
        private (decimal BoardScore, int Column) MinValue(
            BitBoard board,
            int depth,
            decimal alpha,
            decimal beta,
            NodeCounter nodeCounter,
            DiscColor movingColor)
        {
            nodeCounter.Increment();

            var openColumns = GetOpenColumns(in board);

            // TODO I think these columns are safe but not certain
            // I didn't see any problems with this during some test games, may require more vetting though
            // Drawn game
            if (openColumns.Count == 0)
            {
                return(0.0m, -1);
            }

            if (depth == 0 ||
                CheckVictory(in board) != DiscColor.None)
            {
                return(EvaluateBoardState(in board, movingColor), -1);
            }

            // Win and return immediately if possible
            var winningMove = FindKillerMove(in board, movingColor);

            if (winningMove.HasWinner &&
                winningMove.Winner == movingColor)
            {
                var winningBoard = BitBoardMove(in board, winningMove.Column, movingColor);
                var winningScore = EvaluateBoardState(in winningBoard, movingColor);

                return(winningScore, winningMove.Column);
            }

            // Stop the opponent from winning if possible
            var oppWinningMove = FindKillerMove(in board, OpponentColor);

            if (oppWinningMove.HasWinner)
            {
                var stopWinningBoard = BitBoardMove(in board, oppWinningMove.Column, AiColor);
                var stopWinningScore = EvaluateBoardState(in stopWinningBoard, movingColor);

                return(stopWinningScore, oppWinningMove.Column);
            }

            decimal minimumMoveValue = decimal.MaxValue;
            int     movedColumn      = -1;

            foreach (int openMove in openColumns)
            {
                var newState = BitBoardMove(in board, openMove, movingColor);

                var childMaxValue = MaxValue(newState, depth - 1, alpha, beta, nodeCounter, ChangeTurnColor(movingColor)).BoardScore;

                if (childMaxValue < minimumMoveValue)
                {
                    minimumMoveValue = childMaxValue;
                    movedColumn      = openMove;
                }

                if (minimumMoveValue <= alpha)
                {
                    return(minimumMoveValue, openMove);
                }

                beta = Math.Min(beta, minimumMoveValue);
            }

            return(minimumMoveValue, movedColumn);
        }