/// <summary>
        /// Generates the move.
        /// </summary>
        /// <param name="board">The board</param>
        /// <param name="from">The starting square</param>
        /// <param name="to">The ending square</param>
        /// <returns></returns>
        internal override Move GenerateMove(Board board, int from, int to)
        {
            Move move;

            // if it's an en passant capture
            if (IsEnPassantCaptureMove(board, from, to))
            {
                move = new EnPassantCaptureMove(board.Status, from, to);

                move.ChangeSideToMove();       // change the side to move
                move.SetEnPassantTarget(null); // reset the en passant target
                move.ResetPly();               // reset the ply

                // we need to verify for check
                move.Make(board);
                bool result = !board.WhiteKingInCheck();
                move.TakeBack(board);
                return(result ? move : null);
            }

            move = base.GenerateMove(board, from, to);


            if (move != null)
            {
                move.ResetPly();// reset the ply

                // if it's the two-squares move
                if (IsTwoSquaresMove(board, from, to))
                {
                    move.SetEnPassantTarget(to + Board.SideSquareNo);// set the en passant target
                }

                // if it's a promotion
                if (Board.Rank(to) == 0)
                {
                    // we don't need to verify for check again
                    // so the promotion delegate will not be triggered
                    // later we will change the promotion type as needed
                    move = new PromotionMove(board.Status, from, to);

                    move.ChangeSideToMove();                       // change the side to move
                    move.SetEnPassantTarget(null);                 // reset the en passant target
                    move.ResetPly();                               // reset the ply
                    (move as PromotionMove).SetCapture(board[to]); // the capture information is set
                }

                return(move);
            }
            else
            {
                return(null);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Generates the move.
        /// Adds check verification to move generation,
        /// returns null if its own king will be in check.
        /// </summary>
        /// <param name="board">The board</param>
        /// <param name="from">The starting square</param>
        /// <param name="to">The ending square</param>
        /// <returns></returns>
        internal override Move GenerateMove(Board board, int from, int to)
        {
            Move move = base.GenerateMove(board, from, to);

            if (move != null)
            {
                // verify for king in check
                move.Make(board);
                bool result = !board.WhiteKingInCheck();
                move.TakeBack(board);
                return(result ? move : null);
            }
            else
            {
                return(null);
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Generates the move.
        /// Adds check verification to move generation,
        /// returns null if its own king will be in check.
        /// </summary>
        /// <param name="board">The board</param>
        /// <param name="from">The starting square</param>
        /// <param name="to">The ending square</param>
        /// <returns></returns>
        internal override Move GenerateMove(Board board, int from, int to)
        {
            Move move = base.GenerateMove(board, from, to);

            if (move != null)
            {
                // verify for king in check 
                move.Make(board);
                bool result = !board.WhiteKingInCheck();
                move.TakeBack(board);
                return result ? move : null;
            }
            else
            {
                return null;
            }
        }
Esempio n. 4
0
File: Game.cs Progetto: vgichar/shah
 /// <summary>
 /// Verifies the current board for check.
 /// </summary>
 /// <returns></returns>
 private bool IsCheck()
 {
     return(currentBoard.Status.WhiteTurn ? currentBoard.WhiteKingInCheck() : currentBoard.BlackKingInCheck());
 }
Esempio n. 5
0
        /// <summary>
        /// Verifies if the board is in a valid state, throws ArgumentException if it's not.
        /// </summary>
        /// <param name="board">The board</param>
        public static void VerifyState(Board board)
        {
            // the board must not be null
            if (board == null)
            {
                throw new ArgumentNullException("board", Resources.NullBoardMsg);
            }

            // hastable to remember the number of each piece type
            // a pair consists in a piece type and the number of pieces on this board
            Dictionary <Type, int> pieceNo = new Dictionary <Type, int>(Piece.TypesNo);

            // initialize the values with 0
            foreach (Type type in pieceZobristIndexTable.Keys)
            {
                pieceNo[type] = 0;
            }

            // loop through the squares
            for (int sqIndex = 0; sqIndex < Board.SquareNo; sqIndex++)
            {
                if (board[sqIndex] != null)
                {
                    // increment the number of this piece type
                    Type type = board[sqIndex].GetType();
                    pieceNo[type] = pieceNo[type] + 1;

                    // check if the White Pawn has rank 1
                    if (type == typeof(WhitePawn) && Utils.GetRankNotation(sqIndex) == '1')
                    {
                        throw new ArgumentException(Resources.WhitePawnRank1Msg, "board");
                    }

                    // check if the Black Pawn has rank 8
                    if (type == typeof(BlackPawn) && Utils.GetRankNotation(sqIndex) == '8')
                    {
                        throw new ArgumentException(Resources.BlackPawnRank8Msg, "board");
                    }
                }
            }

            // if there are too many White pieces
            // check if the number of Pawns
            // plus the number of extra Queens, Rooks, Bishops, Knights
            // (which can result only by promotion) exceeds 8
            if ((pieceNo[typeof(WhitePawn)] + Math.Max(pieceNo[typeof(WhiteQueen)] - 1, 0) + Math.Max(pieceNo[typeof(WhiteRook)] - 2, 0) + Math.Max(pieceNo[typeof(WhiteBishop)] - 2, 0) + Math.Max(pieceNo[typeof(WhiteKnight)] - 2, 0)) > 8)
            {
                throw new ArgumentException(Resources.TooManyWhitePiecesMsg, "board");
            }

            // if there are too many Black pieces
            // check if the number of Pawns
            // plus the number of extra Queens, Rooks, Bishops, Knights
            // (which can result only by promotion) exceeds 8
            if ((pieceNo[typeof(BlackPawn)] + Math.Max(pieceNo[typeof(BlackQueen)] - 1, 0) + Math.Max(pieceNo[typeof(BlackRook)] - 2, 0) + Math.Max(pieceNo[typeof(BlackBishop)] - 2, 0) + Math.Max(pieceNo[typeof(BlackKnight)] - 2, 0)) > 8)
            {
                throw new ArgumentException(Resources.TooManyBlackPiecesMsg, "board");
            }

            // check for White King
            if (pieceNo[typeof(WhiteKing)] > 1)
            {
                throw new ArgumentException(Resources.MoreThanOneWhiteKingMsg, "board");
            }
            if (pieceNo[typeof(WhiteKing)] < 1)
            {
                throw new ArgumentException(Resources.NoWhiteKingMsg, "board");
            }

            // check for Black King
            if (pieceNo[typeof(BlackKing)] > 1)
            {
                throw new ArgumentException(Resources.MoreThanOneBlackKingMsg, "board");
            }
            if (pieceNo[typeof(BlackKing)] < 1)
            {
                throw new ArgumentException(Resources.NoBlackKingMsg, "board");
            }

            // check if the King and the Rook are in place for castling availability
            if (board.Status.WhiteCouldCastleShort && !(board[Board.E1] is WhiteKing && board[Board.H1] is WhiteRook))
            {
                throw new ArgumentException(Resources.IllegalWhiteKingShortCastlingMsg, "board");
            }

            // check if the King and the Rook are in place for castling availability
            if (board.Status.WhiteCouldCastleLong && !(board[Board.E1] is WhiteKing && board[Board.A1] is WhiteRook))
            {
                throw new ArgumentException(Resources.IllegalWhiteKingLongCastlingMsg, "board");
            }

            // check if the King and the Rook are in place for castling availability
            if (board.Status.BlackCouldCastleShort && !(board[Board.E8] is BlackKing && board[Board.H8] is BlackRook))
            {
                throw new ArgumentException(Resources.IllegalBlackKingShortCastlingMsg, "board");
            }

            // check if the King and the Rook are in place for castling availability
            if (board.Status.BlackCouldCastleLong && !(board[Board.E8] is BlackKing && board[Board.A8] is BlackRook))
            {
                throw new ArgumentException(Resources.IllegalBlackKingLongCastlingMsg, "board");
            }

            // check the en passant target
            if (
                board.Status.EnPassantTarget != null &&
                !(
                    (
                        Board.Rank(board.Status.EnPassantTarget.Value) == 5 && board.Status.BlackTurn &&                                            // the rank of en passant target is correct
                        board[board.Status.EnPassantTarget.Value - Board.SideSquareNo] is WhitePawn &&                                              // there is a pawn in front of the target
                        board[board.Status.EnPassantTarget.Value] == null && board[board.Status.EnPassantTarget.Value + Board.SideSquareNo] == null // the en passant target square and the one behind are empty

                    ) ||
                    (
                        Board.Rank(board.Status.EnPassantTarget.Value) == 2 && board.Status.WhiteTurn &&                                            // the rank of en passant target is correct
                        board[board.Status.EnPassantTarget.Value + Board.SideSquareNo] is BlackPawn &&                                              // there is a pawn in front of the target
                        board[board.Status.EnPassantTarget.Value] == null && board[board.Status.EnPassantTarget.Value - Board.SideSquareNo] == null // the en passant target square and the one behind are empty
                    )
                    )
                )
            {
                throw new ArgumentException(Resources.IllegalEPTargetMsg, "board");
            }

            // check if ply >= 0
            if (board.Status.Ply < 0)
            {
                throw new ArgumentException(Resources.NonNegativePlyMsg, "board");
            }

            // check if move number >= 1
            if (board.Status.Moves < 1)
            {
                throw new ArgumentException(Resources.PositiveMoveNoMsg, "board");
            }

            // check if the side which is not to move is in check
            if ((board.Status.WhiteTurn && board.BlackKingInCheck()) || (board.Status.BlackTurn && board.WhiteKingInCheck()))
            {
                throw new ArgumentException(Resources.NoSideNotToMoveCheckMsg, "board");
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Verifies if the board is in a valid state, throws ArgumentException if it's not.
        /// </summary>
        /// <param name="board">The board</param>
        public static void VerifyState(Board board)
        {
            // the board must not be null
            if (board == null) { throw new ArgumentNullException("board", "Resources.NullBoardMsg"); }

            // hastable to remember the number of each piece type
            // a pair consists in a piece type and the number of pieces on this board
            Dictionary<Type, int> pieceNo = new Dictionary<Type, int>(Piece.TypesNo);

            // initialize the values with 0
            foreach (Type type in pieceZobristIndexTable.Keys) { pieceNo[type] = 0; }

            // loop through the squares
            for (int sqIndex = 0; sqIndex < Board.SquareNo; sqIndex++)
            {
                if (board[sqIndex] != null)
                {
                    // increment the number of this piece type
                    Type type = board[sqIndex].GetType();
                    pieceNo[type] = pieceNo[type] + 1;

                    // check if the White Pawn has rank 1
                    if (type == typeof(WhitePawn) && Utils.GetRankNotation(sqIndex) == '1')
                    {
                        throw new ArgumentException("Resources.WhitePawnRank1Msg", "board");
                    }

                    // check if the Black Pawn has rank 8
                    if (type == typeof(BlackPawn) && Utils.GetRankNotation(sqIndex) == '8')
                    {
                        throw new ArgumentException("Resources.BlackPawnRank8Msg", "board");
                    }
                }
            }

            // if there are too many White pieces
            // check if the number of Pawns
            // plus the number of extra Queens, Rooks, Bishops, Knights
            // (which can result only by promotion) exceeds 8
            if ((pieceNo[typeof(WhitePawn)] + Math.Max(pieceNo[typeof(WhiteQueen)] - 1, 0) + Math.Max(pieceNo[typeof(WhiteRook)] - 2, 0) + Math.Max(pieceNo[typeof(WhiteBishop)] - 2, 0) + Math.Max(pieceNo[typeof(WhiteKnight)] - 2, 0)) > 8)
            {
                throw new ArgumentException("Resources.TooManyWhitePiecesMsg", "board");
            }

            // if there are too many Black pieces
            // check if the number of Pawns
            // plus the number of extra Queens, Rooks, Bishops, Knights
            // (which can result only by promotion) exceeds 8
            if ((pieceNo[typeof(BlackPawn)] + Math.Max(pieceNo[typeof(BlackQueen)] - 1, 0) + Math.Max(pieceNo[typeof(BlackRook)] - 2, 0) + Math.Max(pieceNo[typeof(BlackBishop)] - 2, 0) + Math.Max(pieceNo[typeof(BlackKnight)] - 2, 0)) > 8)
            {
                throw new ArgumentException("Resources.TooManyBlackPiecesMsg", "board");
            }

            // check for White King
            if (pieceNo[typeof(WhiteKing)] > 1)
            {
                throw new ArgumentException("Resources.MoreThanOneWhiteKingMsg", "board");
            }
            if (pieceNo[typeof(WhiteKing)] < 1)
            {
                throw new ArgumentException("Resources.NoWhiteKingMsg", "board");
            }

            // check for Black King
            if (pieceNo[typeof(BlackKing)] > 1)
            {
                throw new ArgumentException("Resources.MoreThanOneBlackKingMsg", "board");
            }
            if (pieceNo[typeof(BlackKing)] < 1)
            {
                throw new ArgumentException("Resources.NoBlackKingMsg", "board");
            }

            // check if the King and the Rook are in place for castling availability
            if (board.Status.WhiteCouldCastleShort && !(board[Board.E1] is WhiteKing && board[Board.H1] is WhiteRook))
            {
                throw new ArgumentException("Resources.IllegalWhiteKingShortCastlingMsg", "board");
            }

            // check if the King and the Rook are in place for castling availability
            if (board.Status.WhiteCouldCastleLong && !(board[Board.E1] is WhiteKing && board[Board.A1] is WhiteRook))
            {
                throw new ArgumentException("Resources.IllegalWhiteKingLongCastlingMsg", "board");
            }

            // check if the King and the Rook are in place for castling availability
            if (board.Status.BlackCouldCastleShort && !(board[Board.E8] is BlackKing && board[Board.H8] is BlackRook))
            {
                throw new ArgumentException("Resources.IllegalBlackKingShortCastlingMsg", "board");
            }

            // check if the King and the Rook are in place for castling availability
            if (board.Status.BlackCouldCastleLong && !(board[Board.E8] is BlackKing && board[Board.A8] is BlackRook))
            {
                throw new ArgumentException("Resources.IllegalBlackKingLongCastlingMsg", "board");
            }

            // check the en passant target
            if (
                board.Status.EnPassantTarget != null &&
                !(
                (
                Board.Rank(board.Status.EnPassantTarget.Value) == 5 && board.Status.BlackTurn &&// the rank of en passant target is correct
                board[board.Status.EnPassantTarget.Value - Board.SideSquareNo] is WhitePawn &&// there is a pawn in front of the target
                board[board.Status.EnPassantTarget.Value] == null && board[board.Status.EnPassantTarget.Value + Board.SideSquareNo] == null// the en passant target square and the one behind are empty

                ) ||
                (
                Board.Rank(board.Status.EnPassantTarget.Value) == 2 && board.Status.WhiteTurn &&// the rank of en passant target is correct
                board[board.Status.EnPassantTarget.Value + Board.SideSquareNo] is BlackPawn &&// there is a pawn in front of the target
                board[board.Status.EnPassantTarget.Value] == null && board[board.Status.EnPassantTarget.Value - Board.SideSquareNo] == null// the en passant target square and the one behind are empty
                )
                )
                )
            {
                throw new ArgumentException("Resources.IllegalEPTargetMsg", "board");
            }

            // check if ply >= 0
            if (board.Status.Ply < 0)
            {
                throw new ArgumentException("Resources.NonNegativePlyMsg", "board");
            }

            // check if move number >= 1
            if (board.Status.Moves < 1)
            {
                throw new ArgumentException("Resources.PositiveMoveNoMsg", "board");
            }

            // check if the side which is not to move is in check
            if ((board.Status.WhiteTurn && board.BlackKingInCheck()) || (board.Status.BlackTurn && board.WhiteKingInCheck()))
            {
                throw new ArgumentException("Resources.NoSideNotToMoveCheckMsg", "board");
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Generates the move.
        /// </summary>
        /// <param name="board">The board</param>
        /// <param name="from">The starting square</param>
        /// <param name="to">The ending square</param>
        /// <returns></returns>
        internal override Move GenerateMove(Board board, int from, int to)
        {
            Move move;

            // if it's an en passant capture
            if (IsEnPassantCaptureMove(board, from, to))
            {
                move = new EnPassantCaptureMove(board.Status, from, to);

                move.ChangeSideToMove();// change the side to move
                move.SetEnPassantTarget(null);// reset the en passant target
                move.ResetPly();// reset the ply

                // we need to verify for check
                move.Make(board);
                bool result = !board.WhiteKingInCheck();
                move.TakeBack(board);
                return result ? move : null;
            }

            move = base.GenerateMove(board, from, to);


            if (move != null)
            {
                move.ResetPly();// reset the ply

                // if it's the two-squares move
                if (IsTwoSquaresMove(board, from, to))
                {
                    move.SetEnPassantTarget(to + Board.SideSquareNo);// set the en passant target
                }

                // if it's a promotion
                if (Board.Rank(to) == 0)
                {
                    // we don't need to verify for check again
                    // so the promotion delegate will not be triggered
                    // later we will change the promotion type as needed
                    move = new PromotionMove(board.Status, from, to);

                    move.ChangeSideToMove();// change the side to move
                    move.SetEnPassantTarget(null);// reset the en passant target
                    move.ResetPly();// reset the ply
                    (move as PromotionMove).SetCapture(board[to]);// the capture information is set
                }

                return move;
            }
            else
            {
                return null;
            }
        }