Beispiel #1
0
 /// <summary>
 /// Checks if it's the two-squares move.
 /// </summary>
 /// <param name="board">The board</param>
 /// <param name="from">The starting square</param>
 /// <param name="to">The ending square</param>
 /// <returns></returns>
 public bool IsTwoSquaresMove(Board board, int from, int to)
 {
     return
         Board.Rank(from) == 1 && Board.Rank(to) == 3 &&
         Board.File(from) == Board.File(to) &&// the same file
         board[from + Board.SideSquareNo] == null && board[from + (Board.SideSquareNo << 1)] == null;// the first and second squares are empty
 }
Beispiel #2
0
 /// <summary>
 /// Checks if the piece might move on this "board", 
 /// from the "from" square to the "to" square according to the chess rules.
 /// It doesn't verify if its own king is in check after 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>
 public override bool MightMove(Board board, int from, int to)
 {
     return
         base.MightMove(board, from, to) &&
         Math.Abs(Board.File(from) - Board.File(to)) == Math.Abs(Board.Rank(from) - Board.Rank(to)) &&// it's a diagonal move
         board.IsPathClear(from, to);// the path is clear
 }
Beispiel #3
0
 /// <summary>
 /// Checks if the piece might move on this "board", 
 /// from the "from" square to the "to" square according to the chess rules.
 /// It doesn't verify if its own king is in check after 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>
 public override bool MightMove(Board board, int from, int to)
 {
     // the first condition for a piece to be able to move
     // is that starting square and the ending square be different
     // and the ending square be empty or opposite piece
     return from != to && !(board[to] is BlackPiece);
 }
Beispiel #4
0
 /// <summary>
 /// Checks if it's the en passant move.
 /// </summary>
 /// <param name="board">The board</param>
 /// <param name="from">The starting square</param>
 /// <param name="to">The ending square</param>
 /// <returns></returns>
 public bool IsEnPassantCaptureMove(Board board, int from, int to)
 {
     return
         board.Status.EnPassantTarget != null &&// there is a en passant target 
         to == board.Status.EnPassantTarget.Value && Board.Rank(from) == 4 && Board.Rank(board.Status.EnPassantTarget.Value) == 5 &&
         Math.Abs(Board.File(from) - Board.File(to)) == 1;// it's a diagonal move
 }
Beispiel #5
0
 /// <summary>
 /// Takes back the move, it doesn't check if it's a valid move
 /// </summary>
 /// <param name="board">The board</param>
 internal override void TakeBack(Board board)
 {
     board.Status = before;// set the board status to the before board status
     board[from] = board[to];// put the piece on the starting square
     board[Target] = capture;// put back the en passant target
     board[to] = null;// empty the ending square
 }
Beispiel #6
0
 /// <summary>
 /// Makes the move, it doesn't check if it's a valid move
 /// </summary>
 /// <param name="board">The board</param>
 internal override void Make(Board board)
 {
     capture = board[Target];// set the capture as the en passant target
     board[Target] = null;// empty the en passant target square
     board[to] = board[from];// put the piece on the ending square
     board[from] = null;// empty the starting square
     board.Status = after;// set the board status to the after board status
 }
Beispiel #7
0
 /// <summary>
 /// Verifies if the piece attacks the "to" square, on this board, from the "from" square.
 /// </summary>
 /// <param name="board">The board</param>
 /// <param name="from">The starting square</param>
 /// <param name="to">The ending square</param>
 /// <returns></returns>
 public override bool Attacks(Board board, int from, int to)
 {
     // castling is not considered an attack
     // so the king attacks the squares around him
     return
         base.MightMove(board, from, to) &&
         Math.Abs(Board.Rank(from) - Board.Rank(to)) <= 1 && Math.Abs(Board.File(from) - Board.File(to)) <= 1;
 }
Beispiel #8
0
 /// <summary>
 /// Checks if the piece might move on this "board", 
 /// from the "from" square to the "to" square according to the chess rules.
 /// It doesn't verify if its own king is in check after 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>
 public override bool MightMove(Board board, int from, int to)
 {
     return
         base.MightMove(board, from, to) &&
         Board.File(from) != Board.File(to) &&// the files are different
         Board.Rank(from) != Board.Rank(to) &&// the ranks are different
         (Math.Abs(Board.File(from) - Board.File(to)) + Math.Abs(Board.Rank(from) - Board.Rank(to))) == 3;// the rank difference plus file difference must be 3
 }
Beispiel #9
0
 /// <summary>
 /// Verifies if the king can castle short.
 /// </summary>
 /// <param name="board">The board</param>
 /// <param name="from">The starting square</param>
 /// <param name="to">The ending square</param>
 /// <returns></returns>
 public bool CanCastleShort(Board board, int from, int to)
 {
     return (
         from == Board.E1 && to == Board.G1 &&
         board.Status.WhiteCouldCastleShort &&//check if the king or the rook didn't already move 
         board.IsPathClear(Board.E1, Board.H1) &&// check if the path is clear 
         !board.IsAttackedByBlack(Board.E1) && !board.IsAttackedByBlack(Board.F1) && !board.IsAttackedByBlack(Board.G1)// check if the squares traversed by king are not attacked
         );
 }
Beispiel #10
0
 /// <summary>
 /// Verifies if the king can castle long.
 /// </summary>
 /// <param name="board">The board</param>
 /// <param name="from">The starting square</param>
 /// <param name="to">The ending square</param>
 /// <returns></returns>
 public bool CanCastleLong(Board board, int from, int to)
 {
     return (
         from == Board.E8 && to == Board.C8 &&
         board.Status.BlackCouldCastleLong &&//check if the king or the rook didn't already move
         board.IsPathClear(Board.A8, Board.E8) &&// check if the path is clear 
         !board.IsAttackedByWhite(Board.E8) && !board.IsAttackedByWhite(Board.D8) && !board.IsAttackedByWhite(Board.C8)// check if the squares traversed by king are not attacked
         );
 }
Beispiel #11
0
 /// <summary>
 /// Verifies if the piece attacks the "to" square, on this board, from the "from" square.
 /// </summary>
 /// <param name="board">The board</param>
 /// <param name="from">The starting square</param>
 /// <param name="to">The ending square</param>
 /// <returns></returns>
 public override bool Attacks(Board board, int from, int to)
 {
     // a pawn attacks one square in front diagonaly
     // and only if it's an empty square or an opposite side piece
     return
         Board.Rank(to) == Board.Rank(from) + 1 &&// it's on the front row
         Math.Abs(Board.File(to) - Board.File(from)) == 1 &&// it's a diagonal move 
         !(board[to] is BlackPiece);// it's not occupied by a same side piece
 }
Beispiel #12
0
 /// <summary>
 /// Checks if the piece might move on this "board", 
 /// from the "from" square to the "to" square according to the chess rules.
 /// It doesn't verify if its own king is in check after 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>
 public override bool MightMove(Board board, int from, int to)
 {
     return
         base.MightMove(board, from, to) &&
         (
         Board.File(from) == Board.File(to) ||// the same file
         Board.Rank(from) == Board.Rank(to)// the same rank
         ) &&
         board.IsPathClear(from, to);// the path is clear
 }
Beispiel #13
0
 /// <summary>
 /// Checks if the piece might move on this "board", 
 /// from the "from" square to the "to" square according to the chess rules.
 /// It doesn't verify if its own king is in check after 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>
 public override bool MightMove(Board board, int from, int to)
 {
     return
         base.MightMove(board, from, to) &&
         (
         (Math.Abs(Board.Rank(from) - Board.Rank(to)) <= 1 && Math.Abs(Board.File(from) - Board.File(to)) <= 1) ||// the king can move one square 
         CanCastleLong(board, from, to) ||// the king can castle long
         CanCastleShort(board, from, to)// the king can castle short
         );
 }
Beispiel #14
0
 /// <summary>
 /// Checks if the piece might move on this "board", 
 /// from the "from" square to the "to" square according to the chess rules.
 /// It doesn't verify if its own king is in check after 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>
 public override bool MightMove(Board board, int from, int to)
 {
     return
         base.MightMove(board, from, to) &&
         (
         Board.File(from) == Board.File(to) ||// the same file
         Board.Rank(from) == Board.Rank(to) ||// the same rank
         Math.Abs(Board.File(from) - Board.File(to)) == Math.Abs(Board.Rank(from) - Board.Rank(to))// it's a diagonal move
         ) &&
         board.IsPathClear(from, to);
 }
Beispiel #15
0
        /// <summary>
        /// Generates the move.
        /// In this class, the move is not verified if it puts its own king in check. 
        /// This is implemented in the BlackPiece and WhitePiece subclasses.
        /// </summary>
        /// <param name="board">The board</param>
        /// <param name="from">The starting square</param>
        /// <param name="to">The ending square</param>
        /// <returns></returns>
        internal virtual Move GenerateMove(Board board, int from, int to)
        {
            if (!MightMove(board, from, to)) { return null; }

            Move move = new Move(board.Status, from, to);


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

            if (board[to] == null)// if there is no capture
            {
                move.IncrementPly();// increment the ply 
            }
            else// if there is a capture
            {
                move.ResetPly();// reset the ply 

                // if there this moves captures a rook
                // and the ending squares is one of the board corners
                // reset castling availability
                if (board[to] is WhiteRook)
                {
                    if (to == Board.A1)
                    {
                        move.MakeWhiteLongCastlingUnavail();
                    }
                    else if (to == Board.H1)
                    {
                        move.MakeWhiteShortCastlingUnavail();
                    }
                }
                else if (board[to] is BlackRook)
                {
                    if (to == Board.A8)
                    {
                        move.MakeBlackLongCastlingUnavail();
                    }
                    else if (to == Board.H8)
                    {
                        move.MakeBlackShortCastlingUnavail();
                    }
                }
            }

            return move;
        }
Beispiel #16
0
        /// <summary>
        /// Makes the move, it doesn't check if it's a valid move.
        /// The capture must be set before making the move, othewise it throws InvalidOperationException.
        /// </summary>
        /// <param name="board">The board</param>
        internal override void Make(Board board)
        {
            if (promotionPiece != null)
            {
                // set the ending square
                board[to] = promotionPiece;
            }
            else
            {
                // if the promotion was not set throw an exception
                throw new InvalidOperationException(Resources.NoPromotionMsg);
            }

            promotedPiece = board[from];// set the promoted piece
            board[from] = null;// empty the starting square
            board.Status = after;// set the board status to the after board status
        }
Beispiel #17
0
 /// <summary>
 /// Checks if the piece might move on this "board", 
 /// from the "from" square to the "to" square according to the chess rules.
 /// It doesn't verify if its own king is in check after 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>
 public override bool MightMove(Board board, int from, int to)
 {
     return
         // a pawn can move one square in front to an empty square
         (
             to == from + Board.SideSquareNo &&// it's the front square
             board[to] == null// it's an empty square
         ) ||
         // a pawn can move one square in front diagonally if there is an opposite side piece
         (
             Board.Rank(to) == Board.Rank(from) + 1 &&// it's on the front row
             Math.Abs(Board.File(to) - Board.File(from)) == 1 &&// it's a diagonal move 
             board[to] is WhitePiece// it's an opposite side piece
         ) ||
            IsTwoSquaresMove(board, from, to) ||// it's the two-squares move
         IsEnPassantCaptureMove(board, from, to);// it's the en passant move
 }
Beispiel #18
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;
            }
        }
Beispiel #19
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)
            {
                move.IncrementMoves();// the number of moves is incremented after Black moves

                // verify for king in check 
                move.Make(board);
                bool result = !board.BlackKingInCheck();
                move.TakeBack(board);
                return result ? move : null;
            }
            else
            {
                return null;
            }
        }
Beispiel #20
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 = base.GenerateMove(board, from, to);

            // just reset castling availability 
            if (move != null)
            {
                if (from == Board.A1)
                {
                    move.MakeWhiteLongCastlingUnavail();
                }
                else if (from == Board.H1)
                {
                    move.MakeWhiteShortCastlingUnavail();
                }
                return move;
            }
            else
            {
                return null;
            }
        }
Beispiel #21
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 a castling move
            // CanCastleLong already verifies if the king will 
            // end in check so we don't have to verify it again
            if (CanCastleLong(board, from, to))
            {
                move = new CastlingMove(board.Status, Board.E1, Board.C1, new Move(board.Status, Board.A1, Board.D1));

                move.ChangeSideToMove();// change side to move 
                move.MakeWhiteLongCastlingUnavail();// reset castling availability
                move.MakeWhiteShortCastlingUnavail();// reset castling availability
                move.SetEnPassantTarget(null);// reset en passant target
                move.IncrementPly();// increment the ply

                return move;
            }

            // if it's a castling move
            // CanCastleShort already verifies if the king will 
            // end in check so we don't have to verify it again
            if (CanCastleShort(board, from, to))
            {
                move = new CastlingMove(board.Status, Board.E1, Board.G1, new Move(board.Status, Board.H1, Board.F1));

                move.ChangeSideToMove();// change side to move 
                move.MakeWhiteLongCastlingUnavail();// reset castling availability
                move.MakeWhiteShortCastlingUnavail();// reset castling availability
                move.SetEnPassantTarget(null);// reset en passant target
                move.IncrementPly();// increment the ply

                return move;
            }

            // if it's a regular move
            // just reset castling availability
            move = base.GenerateMove(board, from, to);
            if (move != null)
            {
                move.MakeWhiteLongCastlingUnavail();
                move.MakeWhiteShortCastlingUnavail();

                return move;
            }
            else
            {
                return null;
            }
        }
Beispiel #22
0
        /// <summary>
        /// Gets the board FEN (Forsyth-Edwards notation).
        /// </summary>
        /// <param name="board">The board</param>
        /// <returns></returns>
        public static string GetFEN(Board board)
        {
            // the board must not be null
            if (board == null) { throw new ArgumentNullException("board", "Resources.NullBoardMsg"); }

            StringBuilder sb = new StringBuilder(80);

            int emptySqNo = 0;

            for (int sqIndex = 0; sqIndex < Board.SquareNo; sqIndex++)
            {
                // if the end of row is reached
                if (sqIndex % Board.SideSquareNo == 0 && sqIndex > 0)
                {
                    // write the number of empty squares (if any) and reset it
                    if (emptySqNo != 0)
                    {
                        sb.Append(emptySqNo.ToString(CultureInfo.InvariantCulture));
                        emptySqNo = 0;
                    }

                    sb.Append('/');// write '/'
                }

                //if there is a piece on this square
                if (board[sqIndex] != null)
                {
                    // write the number of empty squares (if any) and reset it
                    if (emptySqNo != 0)
                    {
                        sb.Append(emptySqNo.ToString(CultureInfo.InvariantCulture));
                        emptySqNo = 0;
                    }

                    sb.Append(pieceTypeToCharConversion[board[sqIndex].GetType()]);// write piece char representation

                }
                // if the square is empty
                else
                {
                    emptySqNo++;// increment the number of empty squares
                }
            }
            // write the number of empty squares (if any)
            if (emptySqNo != 0)
            {
                sb.Append(emptySqNo.ToString(CultureInfo.InvariantCulture));
            }

            sb.Append(' ').Append(board.Status.WhiteTurn ? 'w' : 'b');// write the side to move char

            // write castling availability chars
            if (board.Status.WhiteCouldCastleLong || board.Status.WhiteCouldCastleShort || board.Status.BlackCouldCastleLong || board.Status.BlackCouldCastleShort)
            {
                sb.Append(' ');
                if (board.Status.WhiteCouldCastleShort) { sb.Append('K'); }
                if (board.Status.WhiteCouldCastleLong) { sb.Append('Q'); }
                if (board.Status.BlackCouldCastleShort) { sb.Append('k'); }
                if (board.Status.BlackCouldCastleLong) { sb.Append('q'); }
            }
            else
            {
                sb.Append(' ').Append('-');
            }

            // write en passant target notation
            sb.Append(' ').Append((board.Status.EnPassantTarget != null ? GetNotation(board.Status.EnPassantTarget.Value) : "-"));

            // write ply
            sb.Append(' ').Append(board.Status.Ply.ToString(CultureInfo.InvariantCulture));

            // write move number
            sb.Append(' ').Append(board.Status.Moves.ToString(CultureInfo.InvariantCulture));

            return sb.ToString();
        }
Beispiel #23
0
 /// <summary>
 /// Takes back the move, it doesn't check if it's a valid move.
 /// </summary>
 /// <param name="board">The board</param>
 internal virtual void TakeBack(Board board)
 {
     board.Status = before;// set the board status to the before board status
     board[from] = board[to];// put the piece on starting square
     board[to] = capture;// put back the capture
 }
Beispiel #24
0
        /// <summary>
        /// Computes the board hash using Zobrist method.
        /// </summary>
        /// <param name="board">The board</param>
        /// <returns></returns>
        public static int GetHash(Board board)
        {
            // the board must not be null
            if (board == null) { throw new ArgumentNullException("board", "Resources.NullBoardMsg"); }

            long hash = 0;

            // loop through the squares
            for (int sqIndex = 0; sqIndex < Board.SquareNo; sqIndex++)
            {
                // if the square is not empty
                if (board[sqIndex] != null)
                {
                    // XOR the Zobrist key which coresponds to type of piece and for this square
                    // to find the key index, offset the key index of the type by the square number
                    hash ^= zobristKeys[pieceZobristIndexTable[board[sqIndex].GetType()] + sqIndex];
                }
            }

            // if White is to move, XOR the corresponding Zobrist key
            if (board.Status.WhiteTurn)
            {
                hash ^= zobristKeys[Piece.TypesNo * Board.SquareNo];
            }

            // if the Kings could castle, the corresponding Zobrist keys
            if (board.Status.WhiteCouldCastleLong)
            {
                hash ^= zobristKeys[Piece.TypesNo * Board.SquareNo + 1];
            }
            if (board.Status.WhiteCouldCastleShort)
            {
                hash ^= zobristKeys[Piece.TypesNo * Board.SquareNo + 2];
            }
            if (board.Status.BlackCouldCastleLong)
            {
                hash ^= zobristKeys[Piece.TypesNo * Board.SquareNo + 3];
            }
            if (board.Status.BlackCouldCastleShort)
            {
                hash ^= zobristKeys[Piece.TypesNo * Board.SquareNo + 4];
            }

            // if there is an en passant target, XOR the corresponding Zobrist key
            if (board.Status.EnPassantTarget != null)
            {
                // the en passant targets have rank 2 or 5
                if (Board.Rank(board.Status.EnPassantTarget.Value) == 2)
                {
                    hash ^= zobristKeys[Piece.TypesNo * Board.SquareNo + 5 + Board.File(board.Status.EnPassantTarget.Value)];
                }
                else if (Board.Rank(board.Status.EnPassantTarget.Value) == 5)
                {
                    hash ^= zobristKeys[Piece.TypesNo * Board.SquareNo + 13 + Board.File(board.Status.EnPassantTarget.Value)];
                }

            }

            // XOR the first 4 bytes with the last 4 bytes to return an 32-bit integer
            return (int)((hash & 0xFFFFFFFF) ^ (hash >> 32));
        }
Beispiel #25
0
        /// <summary>
        /// Gets a board from its FEN (Forsyth-Edwards notation).
        /// Throws ArgumentException if it's not a valid position.
        /// </summary>
        /// <param name="fen">The FEN string</param>
        /// <returns></returns>
        public static Board GetFENBoard(string fen)
        {
            try
            {
                // the FEN string must not be null
                if (fen == null) { throw new ArgumentNullException("fen", "Resources.NullFENMsg"); }

                Piece[] squares = new Piece[Board.SquareNo];
                BoardStatus status = new BoardStatus();

                Piece piece;
                int index = 0, pos = 0;

                while (fen[index] != ' ')
                {
                    // get the piece from its char representation
                    piece = GetPieceFromChar(fen[index]);

                    // if there is a piece
                    if (piece != null)
                    {
                        squares[pos++] = piece;// put the piece on board
                    }
                    // if there is a number
                    else if (fen[index] >= '1' && fen[index] <= '8')
                    {
                        pos += fen[index] - '0';// skip empty squares
                    }
                    // if there another char than '/' throw exception
                    else if (fen[index] != '/')
                    {
                        throw new ArgumentException("Resources.IllegalFENFormatMsg", "fen");
                    }

                    index++;
                }

                index++;

                // set side to move
                if (fen[index] == 'w')
                {
                    status.WhiteTurn = true;
                }
                else if (fen[index] == 'b')
                {
                    status.BlackTurn = true;
                }
                else
                {
                    throw new ArgumentException("Resources.IllegalFENFormatMsg", "fen");
                }

                index += 2;

                // set castling availability
                if (fen[index] == '-')
                {
                    index++;
                }
                else
                {
                    do
                    {
                        switch (fen[index])
                        {
                            case 'K':
                                status.WhiteCouldCastleShort = true;
                                break;
                            case 'Q':
                                status.WhiteCouldCastleLong = true;
                                break;
                            case 'k':
                                status.BlackCouldCastleShort = true;
                                break;
                            case 'q':
                                status.BlackCouldCastleLong = true;
                                break;
                            default:
                                throw new ArgumentException("Resources.IllegalFENFormatMsg", "fen");
                        }
                    }
                    while (fen[++index] != ' ');
                }

                index++;

                // set en passant target
                if (fen[index] == '-')
                {
                    status.EnPassantTarget = null;
                    index++;
                }
                else
                {
                    // checks if the square notation is correct
                    if (fen[index] < 'a' || fen[index] > 'h' || fen[index + 1] < '1' || fen[index + 1] > '8')
                    {
                        throw new ArgumentException("Resources.IllegalFENFormatMsg", "fen");
                    }

                    status.EnPassantTarget = GetPosition(fen[index], fen[index + 1]);

                    index += 2;
                }

                index++;

                // set ply
                try
                {
                    status.Ply = Int32.Parse(fen.Substring(index, fen.IndexOf(' ', index) - index), CultureInfo.InvariantCulture);
                }
                catch
                {
                    throw new ArgumentException("Resources.IllegalFENFormatMsg", "fen");
                }

                index = fen.IndexOf(' ', index) + 1;

                // set move number
                try
                {
                    status.Moves = Int32.Parse(fen.Substring(index), CultureInfo.InvariantCulture);
                }
                catch
                {
                    throw new ArgumentException("Resources.IllegalFENFormatMsg", "fen");
                }

                Board board = new Board(squares, status);

                // verfies if the board is in valid state, throws ArgumentException if it's not
                VerifyState(board);

                return board;
            }
            // if the FEN string was too short
            catch (IndexOutOfRangeException)
            {
                throw new ArgumentException("Resources.IllegalFENFormatMsg", "fen");
            }
        }
Beispiel #26
0
 /// <summary>
 /// Verifies if the piece attacks the "to" square, on this board, from the "from" square.
 /// </summary>
 /// <param name="board">The board</param>
 /// <param name="from">The starting square</param>
 /// <param name="to">The ending square</param>
 /// <returns></returns>
 public virtual bool Attacks(Board board, int from, int to)
 {
     return MightMove(board, from, to);// usually a piece attacks a square if it can move there
 }
Beispiel #27
0
 /// <summary>
 /// Checks if the piece might move on this "board", 
 /// from the "from" square to the "to" square according to the chess rules.
 /// It doesn't verify if its own king is in check after 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>
 public abstract bool MightMove(Board board, int from, int to);
Beispiel #28
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");
            }
        }
Beispiel #29
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
                move.IncrementMoves();// increment the number of moves

                // we need to verify for check
                move.Make(board);
                bool result = !board.BlackKingInCheck();
                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))
                {
                    // set the en passant target
                    move.SetEnPassantTarget(to - Board.SideSquareNo);
                }

                // if it's a promotion
                if (Board.Rank(to) == Board.SideSquareNo - 1)
                {
                    // 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.IncrementMoves();// increment the number of moves
                    (move as PromotionMove).SetCapture(board[to]);// the capture information is set
                }

                return move;
            }
            else
            {
                return null;
            }
        }
 /// <summary>
 /// Takes back the move, it doesn't check if it's a valid move.
 /// </summary>
 /// <param name="board">The board</param>
 internal override void TakeBack(Board board)
 {
     board.Status = before;// set the board status to the before board status
     board[from] = promotedPiece;// put the promoted piece on starting square
     board[to] = capture;// put back the capture
 }