Esempio n. 1
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);
        }
Esempio n. 2
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);
        }
Esempio n. 3
0
        /// <summary>
        ///     Evaluates the input board position.
        /// </summary>
        /// <param name="board"> The board to evaluate </param>
        /// <returns> The integer score for the current position </returns>
        /// <remarks> White scores positive, and black negative. </remarks>
        public static int Position(Board.Board board)
        {
            if (Evaluate.MaterialDraw(board))
            {
                return(0);
            }

            var score = board.Material[(int)Colour.WHITE] - board.Material[(int)Colour.BLACK];

            Evaluate.AddPawnScores(board, (int)Colour.WHITE, ref score);
            Evaluate.AddPawnScores(board, (int)Colour.BLACK, ref score);
            Evaluate.AddKnBishopKingScores(board, (int)Piece.wN, Evaluate.knightTable, ref score);
            Evaluate.AddKnBishopKingScores(board, (int)Piece.bN, Evaluate.knightTable, ref score);
            Evaluate.AddKnBishopKingScores(board, (int)Piece.wB, Evaluate.bishopTable, ref score);
            Evaluate.AddKnBishopKingScores(board, (int)Piece.bB, Evaluate.bishopTable, ref score);
            Evaluate.AddRookOrQueenScores(board, (int)Piece.wR, ref score);
            Evaluate.AddRookOrQueenScores(board, (int)Piece.bR, ref score);

            if (board.Material[(int)Colour.BLACK] <= Evaluate.END_GAME_LIMIT)
            {
                Evaluate.AddKnBishopKingScores(board, (int)Piece.wK, Evaluate.kingEndTable, ref score);
            }
            else
            {
                Evaluate.AddKnBishopKingScores(board, (int)Piece.wK, Evaluate.kingOpeningTable,
                                               ref score);
            }

            // If black king on a castling square
            if ((board.KingSq[(int)Colour.BLACK] == (int)Square.G8) ||
                (board.KingSq[(int)Colour.BLACK] == (int)Square.C8))
            {
                if (KingSafety.CountBitsSetInArea(board.Pawns[(int)Colour.BLACK], board.KingSq[(int)Colour.BLACK]) >= 3)
                {
                    score -= Evaluate.PAWNS_PROTECTING_KING_VAL;
                }
            }


            if (board.Material[(int)Colour.WHITE] <= Evaluate.END_GAME_LIMIT)
            {
                Evaluate.AddKnBishopKingScores(board, (int)Piece.bK, Evaluate.kingEndTable, ref score);
            }
            else
            {
                Evaluate.AddKnBishopKingScores(board, (int)Piece.bK, Evaluate.kingOpeningTable, ref score);
            }

            // If white king on a castling square
            if ((board.KingSq[(int)Colour.WHITE] == (int)Square.G1) ||
                (board.KingSq[(int)Colour.WHITE] == (int)Square.C1))
            {
                if (KingSafety.CountBitsSetInArea(board.Pawns[(int)Colour.WHITE], board.KingSq[(int)Colour.WHITE]) >= 3)
                {
                    score += Evaluate.PAWNS_PROTECTING_KING_VAL;
                }
            }

            // Bishop pair bonus
            if (board.PceNum[(int)Piece.wB] == 2)
            {
                score += Evaluate.BISHOP_PAIR_VAL;
            }

            if (board.PceNum[(int)Piece.bB] == 2)
            {
                score -= Evaluate.BISHOP_PAIR_VAL;
            }

            if (board.Side == (int)Colour.WHITE)
            {
                return(score);
            }
            else
            {
                return(-score); // BLACK to move
            }
        }