Exemple #1
0
        public bool MovePiece(byte srcPosition, byte dstPosition)
        {
            Piece piece = this.ChessBoard.Squares[(int)srcPosition].Piece;

            this.PreviousChessBoard = new Board(this.ChessBoard);
            this.UndoChessBoard     = new Board(this.ChessBoard);
            this.UndoGameBook       = new List <OpeningMove>((IEnumerable <OpeningMove>) this.CurrentGameBook);
            Board.MovePiece(this.ChessBoard, srcPosition, dstPosition, this.PromoteToPieceType);
            this.ChessBoard.LastMove.GeneratePGNString(this.ChessBoard);
            PieceValidMoves.GenerateValidMoves(this.ChessBoard);
            Evaluation.EvaluateBoardScore(this.ChessBoard);
            if (piece.PieceColor == ChessPieceColor.White)
            {
                if (this.ChessBoard.WhiteCheck)
                {
                    this.ChessBoard = new Board(this.PreviousChessBoard);
                    PieceValidMoves.GenerateValidMoves(this.ChessBoard);
                    return(false);
                }
            }
            else if (piece.PieceColor == ChessPieceColor.Black && this.ChessBoard.BlackCheck)
            {
                this.ChessBoard = new Board(this.PreviousChessBoard);
                PieceValidMoves.GenerateValidMoves(this.ChessBoard);
                return(false);
            }
            this.MoveHistory.Push(this.ChessBoard.LastMove);
            ChessEngine.Engine.Engine.CheckForMate(this.WhoseMove, ref this.ChessBoard);
            this.PieceTakenAdd(this.ChessBoard.LastMove);
            if (this.ChessBoard.WhiteMate || this.ChessBoard.BlackMate)
            {
                this.LastMove.PgnMove += "#";
            }
            else if (this.ChessBoard.WhiteCheck || this.ChessBoard.BlackCheck)
            {
                this.LastMove.PgnMove += "+";
            }
            return(true);
        }
Exemple #2
0
        public void AiPonderMove()
        {
            Thinking = true;

            /* Fix added to prevent premature declaration of checkmate against computer's king.
             *
             * The original version only looked at squares that were available for the black king to move to PRIOR to white's latest move.
             * So... suppose you had a situation like this:
             *	r4r2/pppb1p1k/8/3p2Q1/q4P2/2np4/6PP/5RK1/ w - 0 27
             *  ... and moved the white queen from G5 to H5.
             *	At the start of white's move, the black king has 5 possible moves... 4 of which are attackable by white, and noted by
             *	GenerateValidMoves in WhiteAttackBoard[]. When AiPonderMove executes, it immediately eliminates those 4 squares as options
             *	for the black king, even though 2 of them are now safe because no white piece can attack them. However, square 7 is now
             *	directly in the queen's attack path, so it's eliminated as an option as well. Boom, premature checkmate... game over.
             */
            ChessBoard.BlackMate = false;
            ChessBoard.WhiteMate = false;
            PieceValidMoves.GenerateValidMoves(ChessBoard);

            NodesSearched = 0;

            var resultBoards = new ResultBoards();

            resultBoards.Positions = new List <Board>();

            if (CheckForMate(WhoseMove, ref ChessBoard))
            {
                Thinking = false;
                return;
            }

            MoveContent 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++)
            {
                Square 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);

            if (CheckForMate(WhoseMove, ref ChessBoard))
            {
                Thinking = false;

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

                return;
            }

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

            Thinking = false;
        }
Exemple #3
0
 public int EvaluateBoardScore()
 {
     Evaluation.EvaluateBoardScore(ChessBoard);
     return(ChessBoard.Score);
 }
Exemple #4
0
        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 (Position move in positions)
            {
                if (StaticExchangeEvaluation(examineBoard.Squares[move.DstPosition]) >= 0)
                {
                    continue;
                }

                //Make a copy
                Board 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)
                    {
                        //Invalid Move
                        continue;
                    }
                }

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

                int 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);
        }
Exemple #5
0
        private static ResultBoards GetSortValidMoves(Board examineBoard)
        {
            ResultBoards succ = new ResultBoards
            {
                Positions = new List <Board>(30)
            };

            piecesRemaining = 0;

            for (byte x = 0; x < 64; x++)
            {
                Square 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 (byte dst in sqr.Piece.ValidMoves)
                {
                    //We make copies of the board and move so that we can move it without effecting the parent board
                    Board 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);

                    succ.Positions.Add(board);
                }
            }

            succ.Positions.Sort(Sort);
            return(succ);
        }
Exemple #6
0
        public void AiPonderMove()
        {
            Thinking      = true;
            NodesSearched = 0;

            var resultBoards = new ResultBoards();

            resultBoards.Positions = new List <Board>();

            if (CheckForMate(WhoseMove, ref ChessBoard))
            {
                Thinking = false;
                return;
            }

            MoveContent bestMove = new MoveContent();

            //If there is no playbook move search for the best move
            if (FindPlayBookMove(ref bestMove, ChessBoard, OpeningBook) == false ||
                ChessBoard.FiftyMove > 45 || ChessBoard.RepeatedMove >= 2)
            {
                if (FindPlayBookMove(ref bestMove, ChessBoard, CurrentGameBook) == false ||
                    ChessBoard.FiftyMove > 45 || 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++)
            {
                Square 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);

            if (CheckForMate(WhoseMove, ref ChessBoard))
            {
                Thinking = false;

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

                return;
            }

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

            Thinking = false;
        }
Exemple #7
0
        public void AiPonderMove()
        {
            Thinking = true;

            /* Fix added to prevent premature declaration of checkmate against computer's king.
             *
             * The original version only looked at squares that were available for the black king to move to PRIOR to white's latest move.
             * So... suppose you had a situation like this:
             *	r4r2/pppb1p1k/8/3p2Q1/q4P2/2np4/6PP/5RK1/ w - 0 27
             *  ... and moved the white queen from G5 to H5.
             *	At the start of white's move, the black king has 5 possible moves... 4 of which are attackable by white, and noted by
             *	GenerateValidMoves in WhiteAttackBoard[]. When AiPonderMove executes, it immediately eliminates those 4 squares as options
             *	for the black king, even though 2 of them are now safe because no white piece can attack them. However, square 7 is now
             *	directly in the queen's attack path, so it's eliminated as an option as well. Boom, premature checkmate... game over.
             *
             *	The time it takes to regenerate the valid moves is nontrivial under Android. To improve performance,
             *	my fix regenerates the valid moves ONLY when it might prevent a game-ending premature declaration
             *	of checkmate, unless the difficulty is set to Hard or VeryHard (in which case it runs every time).
             *	Even a novice player is likely to get confused if the engine declares checkmate for no apparent reason,
             *	but the bug's more insidious manifestations at the two easiest difficulty levels help to make the computer a tiny bit easier
             *	to beat by giving it a blind spot that a player can exploit, the same way HUMAN opponents have blind spots and weaknesses of their own.
             */
            if (ChessBoard.BlackMate || ChessBoard.WhiteMate || (GameDifficulty == Difficulty.VeryHard) || (GameDifficulty == Difficulty.Hard))
            {
                ChessBoard.BlackMate = false;
                ChessBoard.WhiteMate = false;
                PieceValidMoves.GenerateValidMoves(ChessBoard);
            }

            NodesSearched = 0;

            var resultBoards = new ResultBoards();

            resultBoards.Positions = new List <Board>();

            if (CheckForMate(WhoseMove, ref ChessBoard))
            {
                Thinking = false;
                return;
            }

            MoveContent bestMove = new MoveContent();

            //If there is no playbook move search for the best move
            if (FindPlayBookMove(ref bestMove, ChessBoard, OpeningBook) == false ||
                ChessBoard.FiftyMove > 45 || ChessBoard.RepeatedMove >= 2)
            {
                if (FindPlayBookMove(ref bestMove, ChessBoard, CurrentGameBook) == false ||
                    ChessBoard.FiftyMove > 45 || 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++)
            {
                Square 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);

            if (CheckForMate(WhoseMove, ref ChessBoard))
            {
                Thinking = false;

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

                return;
            }

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

            Thinking = false;
        }
Exemple #8
0
        /// <summary>
        /// Process incoming commands
        /// </summary>
        /// <param name="input">Incoming string from interface</param>
        public void Comunication(string input)
        {
            string command     = input.Split(' ').First();
            string messageBody = input.Substring(command.Length).Trim();

            switch (command)
            {
            case "protover":
            {
                if (messageBody == "2")
                {
                    Console.WriteLine(@"feature  setboard=1 usermove=1 colors=0 reuse=1 time=1 myname=""The Turk"" name=1 done=1");
                }
                break;
            }

            case "force":
            {
                force = force ? false : true;
                break;
            }

            case "new":
            {
                engine.Board.SetUpBoard();
                GameHistory.Clear();
                force = true;
                break;
            }

            case "setboard":
            {
                engine.Board.Fen = messageBody;
                GameHistory.Clear();
                break;
            }

            case "quit":
            {
                Environment.Exit(Environment.ExitCode);
                break;
            }

            case "usermove":
            {
                ReceivedMove(messageBody);
                if (force)         //Make move after received a move
                {
                    Console.WriteLine("force mode is on");
                    var result = engine.Search(timer.timeForPerMove);
                    Console.WriteLine("move " + result.BestLine.First().IONotation());
                    engine.Board.MakeMove(result.BestLine.First());
                    GameHistory.Push(result.BestLine.First());
                }
                break;
            }

            case "go":
            {
                force = true;
                var result = engine.Search(timer.timeForPerMove);
                Console.WriteLine("move " + result.BestLine.First().IONotation());
                engine.Board.MakeMove(result.BestLine.First());
                GameHistory.Push(result.BestLine.First());
                break;
            }

            case "undo":
            {
                engine.Board.TakeBackMove(GameHistory.Pop());
                break;
            }

            case "level":
            {
                timer = new ChessClock(messageBody);
                break;
            }

            case "st":
            {
                timer = new ChessClock("0 0 " + messageBody);
                break;
            }

            case "fen":     //just for testing purposes
            {
                engine.Board.Fen = "rn4kr/4p1bp/2pp4/1p3P1Q/2P1P3/6R1/PBp3PP/RN4K1 w - - 0 24 ";
                GameHistory.Clear();
                break;
            }

            case "score":     //just for testing purposes
            {
                var score = Evaluation.Evaluate(engine.Board);
                engine.Board.ShowBoard();
                Console.WriteLine("score : " + score);
                break;
            }

            case "show":     //just for testing purposes
            {
                engine.Board.ShowBoard();
                break;
            }
            }
        }