Exemplo n.º 1
0
        public static int GetLine(int depth, Board board)
        {
            Debug.Assert(depth < Variables.MAX_DEPTH);

            int move  = PvTable.Probe(board);
            int count = 0;

            while (move != Variables.NO_MOVE && count < depth)
            {
                if (MakeMove.MoveExists(board, move))
                {
                    MakeMove.Make_Move(board, move);
                    board.PvArray[count++] = move;
                }
                else
                {
                    break;
                }

                move = PvTable.Probe(board);
            }

            // Take back the performed moves, so board position stay unchanged.
            while (board.Ply > 0)
            {
                MakeMove.TakeMove(board);
            }

            return(count);
        }
Exemplo n.º 2
0
        public void Perft_Test(int depth, Board board)   // Also prints information regarding the moves
        {
            Debug.Assert(BoardOperations.CheckBoard(board));
            var startTime = Variables.Watch.ElapsedMilliseconds;

            Console.Write("\nStarting Perft Test to Depth {0}", depth);
            BoardOperations.PrintBoard(board);

            LeafNodes = 0;

            MoveList list = new MoveList();

            MoveGen.GenerateAllMoves(board, list, false);


            for (int i = 0; i < list.Count; ++i)
            {
                int move = list.Moves[i].Move;

                if (!MakeMove.Make_Move(board, list.Moves[i].Move))
                {
                    continue;
                }

                long cumulativeNodes = LeafNodes;
                _Perft(depth - 1, board);
                MakeMove.TakeMove(board);
                long oldNodes = LeafNodes - cumulativeNodes;
                Console.Write("\nmove {0} : {1} : {2}", i + 1, Io.MoveToString(move), oldNodes);
            }

            Console.Write("\nTest Complete: {0} nodes visited in {1} miliseconds\n", LeafNodes, Variables.Watch.ElapsedMilliseconds - startTime);
        }
Exemplo n.º 3
0
        /// <summary>
        ///     Counts the amount of leafNode at the parameter input depth,
        ///     by an inorder recursive tree traversion algorithm.
        ///     It checks all legal moves with the parameter input depth,
        ///     and increments the leafNode counter when the "last" move
        ///     (the leaf) has been located.
        /// </summary>
        /// <param name="depth"> The depth to traverse </param>
        /// <param name="board"> The chess board operate on </param>
        /// <exception cref="Exception"></exception>
        public void _Perft(int depth, Board board)   // For counting the TOTAL available moves
        {
            Debug.Assert(BoardOperations.CheckBoard(board));
            // Increment leafNode and return.
            if (depth == 0)
            {
                LeafNodes++;
                return;
            }

            // Generate moves for rootposition
            MoveList list = new MoveList();

            MoveGen.GenerateAllMoves(board, list, false);

            for (int i = 0; i < list.Count; ++i)
            {
                if (!MakeMove.Make_Move(board, list.Moves[i].Move))
                {
                    continue;
                }

                _Perft(depth - 1, board);
                MakeMove.TakeMove(board);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Search all capture positions, to help avoid the Horizon effect.
        /// </summary>
        private int Quiescence(int alpha, int beta, ref S_SearchInfo info)
        {
            Debug.Assert(BoardOperations.CheckBoard(board));

            if ((info.Nodes & 2047) == 0)
            {
                CheckUp(ref info);
            }

            info.Nodes++;

            // If position is a draw.
            if ((IsRepetition() || board.FiftyMoves >= 100) && board.Ply != 0)
            {
                return(0);
            }

            int score = Evaluate.Position(board); // Stand_pat.

            if (board.Ply > Variables.MAX_DEPTH - 1)
            {
                return(score);
            }

            if (score >= beta)
            {
                return(beta);
            }

            if (score > alpha)
            {
                alpha = score;
            }


            MoveList list = new MoveList();

            MoveGen.GenerateAllMoves(board, list, true); // Only capture moves

            int oldAlpha = alpha;

            score = -infinite;
            int legal    = 0; // Will increment when we find a legal move.
            int bestMove = Variables.NO_MOVE;
            int PvMove   = PvTable.Probe(board);

            for (int i = 0; i < list.Count; ++i)
            {
                PickNextMove(i, list);

                var move = list.Moves[i].Move;

                if (!MakeMove.Make_Move(board, move))
                {
                    continue;
                }

                legal++;
                score = -Quiescence(-beta, -alpha, ref info);
                MakeMove.TakeMove(board); // Take back the made move.

                if (info.Stopped)
                {
                    return(0);
                }

                // We have a new alpha or beta cutoff.
                if (score > alpha)
                {
                    bool isCaptureMove = (move & MoveOperations.MoveFlagCapture) != 0;
                    // beta cutoff?
                    if (score >= beta)
                    {
                        if (legal == 1)
                        {
                            info.Fhf++; // We searched the best move first.
                        }

                        info.Fh++;
                        return(beta);
                    }

                    // Alpha cutoff
                    alpha    = score;
                    bestMove = move;
                }
            }

            if (alpha != oldAlpha)
            {
                PvTable.StoreMove(board, bestMove);
            }

            return(alpha);
        }
Exemplo n.º 5
0
        public int AlphaBeta(int alpha, int beta, int depth, ref S_SearchInfo info, bool DoNull)
        {
            Debug.Assert(BoardOperations.CheckBoard(board));

            if (depth == 0)
            {
                return(Quiescence(alpha, beta, ref info));
            }

            if ((info.Nodes & 2047) == 0)
            {
                CheckUp(ref info);
            }

            info.Nodes++;

            // If position is a draw.
            if ((IsRepetition() || board.FiftyMoves >= 100) && board.Ply != 0)
            {
                return(0);
            }

            if (board.Ply > Variables.MAX_DEPTH - 1)
            {
                return(Evaluate.Position(board));
            }

            bool kingInCheck = Attack.IsSqAttacked(board.KingSq[board.Side], board.Side ^ 1, board);

            // If king is in check, search deeper to get out of check.
            if (kingInCheck)
            {
                depth++;
                // The two following lines are possibly ERROR.
                long timeInc = (info.StopTime - info.StartTime) * (1 / 2);
                info.StopTime += timeInc;
            }

            MoveList list = new MoveList();

            MoveGen.GenerateAllMoves(board, list, false);
            int oldAlpha = alpha;
            int score    = -infinite;
            int legal    = 0; // Will increment when we find a legal move.
            int bestMove = Variables.NO_MOVE;
            int PvMove   = PvTable.Probe(board);

            // Prioritize Principle Variation move if it's found.
            if (PvMove != Variables.NO_MOVE)
            {
                for (int i = 0; i < list.Count; ++i)
                {
                    var move = list.Moves[i].Move;
                    if (move == PvMove)
                    {
                        list.Moves[i].Score = 2000000;
                        break;
                    }
                }
            }

            for (int i = 0; i < list.Count; ++i)
            {
                PickNextMove(i, list);

                var move = list.Moves[i].Move;
                if (!MakeMove.Make_Move(board, move))
                {
                    continue;
                }

                legal++;
                score = -AlphaBeta(-beta, -alpha, depth - 1, ref info, true);
                MakeMove.TakeMove(board); // Take back the made move.

                if (info.Stopped)
                {
                    return(0); // Back up to the root if times up.
                }

                // We have a new alpha or beta cutoff.
                if (score > alpha)
                {
                    bool isCaptureMove = (move & MoveOperations.MoveFlagCapture) != 0;
                    // beta cutoff?
                    if (score >= beta)
                    {
                        if (legal == 1)
                        {
                            info.Fhf++; // We searched the best move first.
                        }

                        info.Fh++;

                        // If beta cutoff, but no capture move.
                        if (!isCaptureMove)
                        {
                            board.SearchKillers[1, board.Ply] = board.SearchKillers[0, board.Ply];
                            board.SearchKillers[0, board.Ply] = move;
                        }
                        return(beta);
                    }

                    // Alpha cutoff
                    alpha    = score;
                    bestMove = move;

                    if (!isCaptureMove)
                    {
                        int from = MoveOperations.FromSq(move);
                        int to   = MoveOperations.ToSq(move);
                        board.SearchHistory[board[from], to] += depth; // Prioritizes move near the root of the tree.
                    }
                }
            }

            // If we haven't had any legal moves.
            if (legal == 0)
            {
                // If in check with no legal moves checkmate.
                if (kingInCheck)
                {
                    return(-mate + board.Ply); // Return the amount of moves it takes to mate.
                    // Returning in this way, allows the method to "prefer" the fastest checkmate combination.
                }
                else
                {
                    return(0); // Stalemate.
                }
            }

            if (alpha != oldAlpha)
            {
                PvTable.StoreMove(board, bestMove);
            }

            return(alpha);
        }