//Copy Constructor
        internal Board(Board board)
        {
            Squares = new Square[64];

            for (byte x = 0; x < 64; x++)
            {
                if (board.Squares[x].Piece != null)
                {
                    Squares[x] = new Square(board.Squares[x].Piece);
                }
            }

            WhiteAttackBoard = new bool[64];
            BlackAttackBoard = new bool[64];

            for (byte x = 0; x < 64; x++)
            {
                WhiteAttackBoard[x] = board.WhiteAttackBoard[x];
                BlackAttackBoard[x] = board.BlackAttackBoard[x];
            }

            EndGamePhase = board.EndGamePhase;

            HalfMoveClock = board.HalfMoveClock;
            RepeatedMove  = board.RepeatedMove;

            WhiteCastled = board.WhiteCastled;
            BlackCastled = board.BlackCastled;

            WhiteCanCastle = board.WhiteCanCastle;
            BlackCanCastle = board.BlackCanCastle;

            WhiteKingPosition = board.WhiteKingPosition;
            BlackKingPosition = board.BlackKingPosition;

            BlackCheck        = board.BlackCheck;
            WhiteCheck        = board.WhiteCheck;
            StaleMate         = board.StaleMate;
            WhiteMate         = board.WhiteMate;
            BlackMate         = board.BlackMate;
            WhoseMove         = board.WhoseMove;
            EnPassantPosition = board.EnPassantPosition;
            EnPassantColor    = board.EnPassantColor;

            Score = board.Score;

            LastMove = new MoveContent(board.LastMove);

            MoveCount = board.MoveCount;
        }
        internal static void SaveCurrentGameMove(Board currentBoard, Board previousBoard,
                                                 ICollection <OpeningMove> gameBook, MoveContent bestMove)
        {
            try
            {
                var move = new OpeningMove
                {
                    StartingFEN = Board.Fen(true,
                                            previousBoard),
                    EndingFEN = Board.Fen(true,
                                          currentBoard)
                };

                move.Moves.Add(bestMove);

                gameBook.Add(move);

                foreach (var move1 in gameBook)
                {
                    byte repeatedMoves = 0;

                    foreach (var move2 in gameBook)
                    {
                        if (move1.EndingFEN == move2.EndingFEN)
                        {
                            repeatedMoves++;
                        }
                    }

                    if (previousBoard.RepeatedMove >= repeatedMoves)
                    {
                        continue;
                    }

                    previousBoard.RepeatedMove = repeatedMoves;
                    currentBoard.RepeatedMove  = repeatedMoves;
                }

                if (currentBoard.RepeatedMove >= 3)
                {
                    currentBoard.StaleMate = true;
                }
            }
            catch (Exception)
            {
                // ignored
            }
        }
        public Board()
        {
            Squares = new Square[64];

            for (byte i = 0; i < 64; i++)
            {
                Squares[i] = new Square();
            }

            LastMove = new MoveContent();

            BlackCanCastle = true;
            WhiteCanCastle = true;

            WhiteAttackBoard = new bool[64];
            BlackAttackBoard = new bool[64];
        }
        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;
        }
        // ReSharper disable IdentifierTypo
        internal static MoveContent IterativeSearch(Board examineBoard,
                                                    byte depth,
                                                    ref int nodesSearched,
                                                    ref int nodesQuiessence,
                                                    ref string pvLine,
                                                    ref byte plyDepthReached,
                                                    ref byte rootMovesSearched,
                                                    List <OpeningMove> currentGameBook)
        {
            var       pvChild = new List <Position>();
            var       alpha   = -400000000;
            const int beta    = 400000000;

            var bestMove = new MoveContent();

            //We are going to store our result boards here
            var succ = GetSortValidMoves(examineBoard);

            rootMovesSearched = (byte)succ.Positions.Count;

            if (rootMovesSearched == 1)
            {
                return(succ.Positions[0].LastMove);
            }

            foreach (var pos in succ.Positions)
            {
                var value = -AlphaBeta(pos,
                                       1,
                                       -beta,
                                       -alpha,
                                       ref nodesSearched,
                                       ref nodesQuiessence,
                                       ref pvChild,
                                       true);

                //Can I make an instant mate?
                if (value >= 32767)
                {
                    return(pos.LastMove);
                }
            }

            var currentBoard = 0;

            alpha = -400000000;

            succ.Positions.Sort(Sort);

            depth--;

            plyDepthReached = ModifyDepth(depth, succ.Positions.Count);

            foreach (var pos in succ.Positions)
            {
                currentBoard++;

                progress = (int)(currentBoard / (decimal)succ.Positions.Count * 100);

                pvChild = new List <Position>();

                var value = -AlphaBeta(pos,
                                       depth,
                                       -beta,
                                       -alpha,
                                       ref nodesSearched,
                                       ref nodesQuiessence,
                                       ref pvChild,
                                       false);

                if (value >= 32767)
                {
                    return(pos.LastMove);
                }

                if (examineBoard.RepeatedMove == 2)
                {
                    var fen = Board.Fen(true, pos);

                    foreach (var move in currentGameBook)
                    {
                        if (move.EndingFEN == fen)
                        {
                            value = 0;
                            break;
                        }
                    }
                }

                pos.Score = value;

                //If value is greater then alpha this is the best board
                // ReSharper disable once InvertIf
                if (value > alpha || alpha == -400000000)
                {
                    pvLine = pos.LastMove.ToString();

                    foreach (var pvPos in pvChild)
                    {
                        pvLine += " " + pvPos.ToString();
                    }

                    alpha    = value;
                    bestMove = pos.LastMove;
                }
            }

            plyDepthReached++;
            progress = 100;

            return(bestMove);
        }