// Returns true if a check mate or stalemate is found
        // Values of type of mate and side mated are stored in the three reference variables
        internal static bool SearchForMate(ChessPieceColor movingSide,
                                           Board examineBoard,
                                           ref bool blackMate,
                                           ref bool whiteMate,
                                           ref bool staleMate)
        {
            var foundNonCheckBlack = false;
            var foundNonCheckWhite = false;

            for (byte x = 0; x < 64; x++)
            {
                var sqr = examineBoard.Squares[x];

                //Make sure there is a piece on the square
                if (sqr.Piece == null)
                {
                    continue;
                }

                //Make sure the color is the same color as the one we are moving.
                if (sqr.Piece.PieceColor != movingSide)
                {
                    continue;
                }

                //For each valid move for this piece
                foreach (var dst in sqr.Piece.ValidMoves)
                {
                    //We make copies of the board and move so that we can move it without effecting the parent board
                    var board = examineBoard.FastCopy();

                    //Make move so we can examine it
                    Board.MovePiece(board, x, dst, ChessPieceType.Queen);

                    //We Generate Valid Moves for Board
                    PieceValidMoves.GenerateValidMoves(board);

                    if (board.BlackCheck == false)
                    {
                        foundNonCheckBlack = true;
                    }
                    else if (movingSide == ChessPieceColor.Black)
                    {
                        continue;
                    }

                    if (board.WhiteCheck == false)
                    {
                        foundNonCheckWhite = true;
                    }
                    else if (movingSide == ChessPieceColor.White)
                    {
                    }
                }
            }

            if (foundNonCheckBlack == false)
            {
                if (examineBoard.BlackCheck)
                {
                    blackMate = true;
                    return(true);
                }

                if (!examineBoard.WhiteMate && movingSide != ChessPieceColor.White)
                {
                    staleMate = true;
                    return(true);
                }
            }

            // ReSharper disable once InvertIf
            if (foundNonCheckWhite == false)
            {
                if (examineBoard.WhiteCheck)
                {
                    whiteMate = true;
                    return(true);
                }

                // ReSharper disable once InvertIf
                if (!examineBoard.BlackMate && movingSide != ChessPieceColor.Black)
                {
                    staleMate = true;
                    return(true);
                }
            }

            return(false);
        }
        public void AiPonderMove()
        {
            Thinking = true;

            ChessBoard.BlackMate = false;
            ChessBoard.WhiteMate = false;

            PieceValidMoves.GenerateValidMoves(ChessBoard);

            NodesSearched = 0;

            var resultBoards = new ResultBoards
            {
                Positions = new List <Board>()
            };

            // First search if human move might have caused a mate
            if (CheckForMate(WhoseMove, ref ChessBoard))
            {
                Thinking = false;
                return;
            }

            var bestMove = new MoveContent();

            //If there is no playbook move search for the best move
            if (FindPlayBookMove(ref bestMove, ChessBoard, OpeningBook) == false ||
                ChessBoard.HalfMoveClock > 90 ||
                ChessBoard.RepeatedMove >= 2)
            {
                if (FindPlayBookMove(ref bestMove, ChessBoard, CurrentGameBook) == false ||
                    ChessBoard.HalfMoveClock > 90 ||
                    ChessBoard.RepeatedMove >= 2)
                {
                    bestMove = Search.IterativeSearch(
                        ChessBoard,
                        PlyDepthSearched,
                        ref NodesSearched,
                        ref NodesQuiessence,
                        ref pvLine,
                        ref PlyDepthReached,
                        ref RootMovesSearched,
                        CurrentGameBook);
                }
            }

            //Make the move
            PreviousChessBoard = new Board(ChessBoard);

            RootMovesSearched = (byte)resultBoards.Positions.Count;

            Board.MovePiece(ChessBoard,
                            bestMove.MovingPiecePrimary.SrcPosition,
                            bestMove.MovingPiecePrimary.DstPosition,
                            ChessPieceType.Queen);

            ChessBoard.LastMove.GeneratePGNString(ChessBoard);

            FileIO.SaveCurrentGameMove(ChessBoard, PreviousChessBoard, CurrentGameBook, bestMove);

            for (byte x = 0; x < 64; x++)
            {
                var sqr = ChessBoard.Squares[x];

                if (sqr.Piece == null)
                {
                    continue;
                }

                sqr.Piece.DefendedValue = 0;
                sqr.Piece.AttackedValue = 0;
            }

            PieceValidMoves.GenerateValidMoves(ChessBoard);
            Evaluation.EvaluateBoardScore(ChessBoard);

            PieceTakenAdd(ChessBoard.LastMove);

            MoveHistory.Push(ChessBoard.LastMove);

            //Second Call if computer move might have caused a mate
            if (CheckForMate(WhoseMove, ref ChessBoard))
            {
                Thinking = false;

                if (ChessBoard.WhiteMate || ChessBoard.BlackMate)
                {
                    LastMove.PgnMove += "#";
                }

                return;
            }

            if (ChessBoard.WhiteCheck || ChessBoard.BlackCheck)
            {
                LastMove.PgnMove += "+";
            }

            Thinking = false;
        }
        //Quiescence Search
        private static int Quiescence(Board examineBoard, int alpha, int beta, ref int nodesSearched)
        {
            nodesSearched++;

            //Evaluate Score
            Evaluation.EvaluateBoardScore(examineBoard);

            //Invert Score to support Negamax
            examineBoard.Score = SideToMoveScore(examineBoard.Score, examineBoard.WhoseMove);

            if (examineBoard.Score >= beta)
            {
                return(beta);
            }

            if (examineBoard.Score > alpha)
            {
                alpha = examineBoard.Score;
            }

            List <Position> positions;

            if (examineBoard.WhiteCheck || examineBoard.BlackCheck)
            {
                positions = EvaluateMoves(examineBoard, 0);
            }
            else
            {
                positions = EvaluateMovesQ(examineBoard);
            }

            if (positions.Count == 0)
            {
                return(examineBoard.Score);
            }

            positions.Sort(Sort);

            foreach (var move in positions)
            {
                if (StaticExchangeEvaluation(examineBoard.Squares[move.DstPosition]) >= 0)
                {
                    continue;
                }

                //Make a copy
                var board = examineBoard.FastCopy();

                //Move Piece
                Board.MovePiece(board, move.SrcPosition, move.DstPosition, ChessPieceType.Queen);

                //We Generate Valid Moves for Board
                PieceValidMoves.GenerateValidMoves(board);

                if (board.BlackCheck)
                {
                    if (examineBoard.WhoseMove == ChessPieceColor.Black)
                    {
                        continue;
                    }
                }

                if (board.WhiteCheck)
                {
                    if (examineBoard.WhoseMove == ChessPieceColor.White)
                    {
                        continue;
                    }
                }

                var value = -Quiescence(board,
                                        -beta,
                                        -alpha,
                                        ref nodesSearched);

                if (value >= beta)
                {
                    KillerMove[2, 0].SrcPosition = move.SrcPosition;
                    KillerMove[2, 0].DstPosition = move.DstPosition;

                    return(beta);
                }

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

            return(alpha);
        }
        // Final version
        // ReSharper disable once IdentifierTypo
        private static int AlphaBeta(Board examineBoard,
                                     byte depth,
                                     int alpha,
                                     int beta,
                                     ref int nodesSearched,
                                     ref int nodesQuiessence,
                                     ref List <Position> pvLine,
                                     bool extended)
        {
            nodesSearched++;

            if (examineBoard.HalfMoveClock >= 100 || examineBoard.RepeatedMove >= 3)
            {
                return(0);
            }

            //End Main Search with Quiescence
            if (depth == 0)
            {
                if (!extended && examineBoard.BlackCheck || examineBoard.WhiteCheck)
                {
                    depth++;
                    extended = true;
                }
                else
                {
                    //Perform a Quiessence Search
                    return(Quiescence(examineBoard,
                                      alpha,
                                      beta,
                                      ref nodesQuiessence));
                }
            }

            var positions = EvaluateMoves(examineBoard, depth);

            if (examineBoard.WhiteCheck || examineBoard.BlackCheck || positions.Count == 0)
            {
                if (SearchForMate(examineBoard.WhoseMove, examineBoard, ref examineBoard.BlackMate,
                                  ref examineBoard.WhiteMate, ref examineBoard.StaleMate))
                {
                    if (examineBoard.BlackMate)
                    {
                        if (examineBoard.WhoseMove == ChessPieceColor.Black)
                        {
                            return(-32767 - depth);
                        }

                        return(32767 + depth);
                    }

                    // ReSharper disable once InvertIf
                    if (examineBoard.WhiteMate)
                    {
                        if (examineBoard.WhoseMove == ChessPieceColor.Black)
                        {
                            return(32767 + depth);
                        }

                        return(-32767 - depth);
                    }

                    //If Not Mate then StaleMate
                    return(0);
                }
            }

            positions.Sort(Sort);

            foreach (var move in positions)
            {
                var pvChild = new List <Position>();

                //Make a copy
                var board = examineBoard.FastCopy();

                //Move Piece
                Board.MovePiece(board, move.SrcPosition, move.DstPosition, ChessPieceType.Queen);

                //We Generate Valid Moves for Board
                PieceValidMoves.GenerateValidMoves(board);

                if (board.BlackCheck)
                {
                    if (examineBoard.WhoseMove == ChessPieceColor.Black)
                    {
                        continue;
                    }
                }

                if (board.WhiteCheck)
                {
                    if (examineBoard.WhoseMove == ChessPieceColor.White)
                    {
                        continue;
                    }
                }

                var value = -AlphaBeta(board,
                                       (byte)(depth - 1),
                                       -beta,
                                       -alpha,
                                       ref nodesSearched,
                                       ref nodesQuiessence,
                                       ref pvChild,
                                       extended);

                if (value >= beta)
                {
                    KillerMove[kIndex, depth].SrcPosition = move.SrcPosition;
                    KillerMove[kIndex, depth].DstPosition = move.DstPosition;

                    kIndex = (kIndex + 1) % 2;

                    return(beta);
                }

                // ReSharper disable once InvertIf
                if (value > alpha)
                {
                    //This nodes is PV-node
                    //That nodes have a score that ends up being inside the window
                    //Between the lower bound Alpha and the upper bound Beta.

                    var pvPos = new Position
                    {
                        SrcPosition = board.LastMove.MovingPiecePrimary.SrcPosition,
                        DstPosition = board.LastMove.MovingPiecePrimary.DstPosition,
                        Move        = board.LastMove.ToString()
                    };

                    //All Siblings of a PV-node are expected Cut-nodes
                    pvChild.Insert(0, pvPos);

                    pvLine = pvChild;

                    alpha = value;
                }
            }

            return(alpha);
        }
        // Not used anymore
        // ReSharper disable once UnusedMember.Local
        private static int AlphaBeta(Board examineBoard, byte depth, int alpha, int beta, ref int nodesSearched)
        {
            nodesSearched++;

            if (examineBoard.HalfMoveClock >= 100 || examineBoard.RepeatedMove >= 3)
            {
                return(0);
            }

            if (depth == 0)
            {
                //Evaluate Score
                Evaluation.EvaluateBoardScore(examineBoard);
                //Invert Score to support Negamax
                return(SideToMoveScore(examineBoard.Score, examineBoard.WhoseMove));
            }

            var positions = EvaluateMoves(examineBoard, depth);

            if (examineBoard.WhiteCheck || examineBoard.BlackCheck || positions.Count == 0)
            {
                if (SearchForMate(examineBoard.WhoseMove, examineBoard, ref examineBoard.BlackMate,
                                  ref examineBoard.WhiteMate, ref examineBoard.StaleMate))
                {
                    if (examineBoard.BlackMate)
                    {
                        if (examineBoard.WhoseMove == ChessPieceColor.Black)
                        {
                            return(-32767 - depth);
                        }

                        return(32767 + depth);
                    }

                    // ReSharper disable once InvertIf
                    if (examineBoard.WhiteMate)
                    {
                        if (examineBoard.WhoseMove == ChessPieceColor.Black)
                        {
                            return(32767 + depth);
                        }

                        return(-32767 - depth);
                    }

                    //If Not Mate then StaleMate
                    return(0);
                }
            }

            positions.Sort(Sort);

            foreach (var move in positions)
            {
                //Make a copy
                var board = examineBoard.FastCopy();

                //Move Piece
                Board.MovePiece(board, move.SrcPosition, move.DstPosition, ChessPieceType.Queen);

                //We Generate Valid Moves for Board
                PieceValidMoves.GenerateValidMoves(board);

                if (board.BlackCheck)
                {
                    if (examineBoard.WhoseMove == ChessPieceColor.Black)
                    {
                        continue;
                    }
                }

                if (board.WhiteCheck)
                {
                    if (examineBoard.WhoseMove == ChessPieceColor.White)
                    {
                        continue;
                    }
                }

                var value = -AlphaBeta(board,
                                       (byte)(depth - 1),
                                       -beta,
                                       -alpha,
                                       ref nodesSearched);

                if (value >= beta)
                {
                    return(beta);
                }
                if (value > alpha)
                {
                    alpha = value;
                }
            }

            return(alpha);
        }
        // Not used anymore
        // ReSharper disable once UnusedMember.Local
        private static int MinMax(Board examineBoard, byte depth)
        {
            if (depth == 0)
            {
                //Evaluate Score
                Evaluation.EvaluateBoardScore(examineBoard);
                //Invert Score to support Negamax
                return(SideToMoveScore(examineBoard.Score, examineBoard.WhoseMove));
            }

            var positions = EvaluateMoves(examineBoard, depth);

            if (examineBoard.WhiteCheck || examineBoard.BlackCheck || positions.Count == 0)
            {
                if (SearchForMate(examineBoard.WhoseMove, examineBoard, ref examineBoard.BlackMate,
                                  ref examineBoard.WhiteMate, ref examineBoard.StaleMate))
                {
                    if (examineBoard.BlackMate)
                    {
                        if (examineBoard.WhoseMove == ChessPieceColor.Black)
                        {
                            return(-32767 - depth);
                        }

                        return(32767 + depth);
                    }

                    // ReSharper disable once InvertIf
                    if (examineBoard.WhiteMate)
                    {
                        if (examineBoard.WhoseMove == ChessPieceColor.Black)
                        {
                            return(32767 + depth);
                        }

                        return(-32767 - depth);
                    }

                    //If Not Mate then StaleMate
                    return(0);
                }
            }

            var bestScore = -32767;

            foreach (var move in positions)
            {
                //Make a copy
                var board = examineBoard.FastCopy();

                //Move Piece
                Board.MovePiece(board, move.SrcPosition, move.DstPosition, ChessPieceType.Queen);

                //We Generate Valid Moves for Board
                PieceValidMoves.GenerateValidMoves(board);

                if (board.BlackCheck)
                {
                    if (examineBoard.WhoseMove == ChessPieceColor.Black)
                    {
                        continue;
                    }
                }

                if (board.WhiteCheck)
                {
                    if (examineBoard.WhoseMove == ChessPieceColor.White)
                    {
                        continue;
                    }
                }

                var value = -MinMax(board, (byte)(depth - 1));

                if (value > bestScore)
                {
                    bestScore = value;
                }
            }

            return(bestScore);
        }
        private static ResultBoards GetSortValidMoves(Board examineBoard)
        {
            var sortValidMoves = new ResultBoards {
                Positions = new List <Board>(30)
            };

            piecesRemaining = 0;

            for (byte x = 0; x < 64; x++)
            {
                var sqr = examineBoard.Squares[x];

                //Make sure there is a piece on the square
                if (sqr.Piece == null)
                {
                    continue;
                }

                piecesRemaining++;

                //Make sure the color is the same color as the one we are moving.
                if (sqr.Piece.PieceColor != examineBoard.WhoseMove)
                {
                    continue;
                }

                //For each valid move for this piece
                foreach (var dst in sqr.Piece.ValidMoves)
                {
                    //We make copies of the board and move so that we can move it without effecting the parent board
                    var board = examineBoard.FastCopy();

                    //Make move so we can examine it
                    Board.MovePiece(board, x, dst, ChessPieceType.Queen);

                    //We Generate Valid Moves for Board
                    PieceValidMoves.GenerateValidMoves(board);

                    //Invalid Move
                    if (board.WhiteCheck && examineBoard.WhoseMove == ChessPieceColor.White)
                    {
                        continue;
                    }

                    //Invalid Move
                    if (board.BlackCheck && examineBoard.WhoseMove == ChessPieceColor.Black)
                    {
                        continue;
                    }

                    //We calculate the board score
                    Evaluation.EvaluateBoardScore(board);

                    //Invert Score to support Negamax
                    board.Score = SideToMoveScore(board.Score, board.WhoseMove);

                    sortValidMoves.Positions.Add(board);
                }
            }

            sortValidMoves.Positions.Sort(Sort);
            return(sortValidMoves);
        }