예제 #1
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) == 3 && Board.Rank(board.Status.EnPassantTarget.Value) == 2 &&
          Math.Abs(Board.File(from) - Board.File(to)) == 1); // it's a diagonal move
 }
예제 #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
 }
예제 #3
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) == Board.SideSquareNo - 2 && Board.Rank(to) == Board.SideSquareNo - 4 &&
          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
 }
예제 #4
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);
 }
예제 #5
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
 }
예제 #6
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 WhitePiece));                        // it's not occupied by a same side piece
 }
예제 #7
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
 }
예제 #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) &&
          (
              (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
          ));
 }
예제 #9
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));
 }
예제 #10
0
파일: Utils.cs 프로젝트: vgichar/shah
        /// <summary>
        /// Gets the square notation.
        /// </summary>
        /// <param name="position">The position</param>
        /// <returns></returns>
        public static string GetNotation(int position)
        {
            if (position < 0 || position > 63)
            {
                return(null);
            }

            StringBuilder sb = new StringBuilder(2);

            sb.Append((char)((Board.File(position)) + 'a'));
            sb.Append((char)('8' - Board.Rank(position)));

            return(sb.ToString());
        }
예제 #11
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 BlackPiece                             // 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
 }
예제 #12
0
파일: Utils.cs 프로젝트: vgichar/shah
        /// <summary>
        /// Gets a move from its SAN (standard algebraic notation).
        /// Throws ArgumentException if it's not a valid move.
        /// </summary>
        /// <param name="game">The game</param>
        /// <param name="san">The SAN string</param>
        /// <returns></returns>
        public static Move GetSANMove(ValilGame game, string san)
        {
            // the game must not be null
            if (game == null)
            {
                throw new ArgumentNullException("game", Resources.NullGameMsg);
            }

            // the SAN string must not be null
            if (san == null)
            {
                throw new ArgumentNullException("san", Resources.NullSANMsg);
            }

            Move move = null;

            // if it's a short castling move
            if (san == "O-O")
            {
                foreach (Move m in game.PossibleMoves)
                {
                    if (m is CastlingMove && (m.To == Board.G1 || m.To == Board.G8))
                    {
                        move = m;
                        break;
                    }
                }
            }
            // if it's a long castling move
            else if (san == "O-O-O")
            {
                foreach (Move m in game.PossibleMoves)
                {
                    if (m is CastlingMove && (m.To == Board.C1 || m.To == Board.C8))
                    {
                        move = m;
                        break;
                    }
                }
            }
            else
            {
                int index = san.Length - 1;

                // remove chess and checkmate representation (if any)
                if (index > -1 && (san[index] == '+' || san[index] == '#'))
                {
                    index--;
                }

                if (index < 1)
                {
                    throw new ArgumentException(Resources.IllegalSANFormatMsg, "san");
                }

                // get the promotion (if any)
                char prom = '\0';
                if (san[index - 1] == '=')
                {
                    prom   = san[index];
                    index -= 2;
                }

                if (index < 1 || san[index - 1] < 'a' || san[index - 1] > 'h' || san[index] < '1' || san[index] > '8')
                {
                    throw new ArgumentException(Resources.IllegalSANFormatMsg, "san");
                }

                // get the ending square
                int to = Utils.GetPosition(san[index - 1], san[index]);
                index -= 2;


                // remove capture char (if any)
                if (index > -1 && san[index] == 'x')
                {
                    index--;
                }

                // get the rank of the starting square (if any)
                int?rank = null;
                if (index > -1 && san[index] >= '1' && san[index] <= '8')
                {
                    rank = GetRank(san[index]);
                    index--;
                }

                // get the file of the starting square (if any)
                int?file = null;
                if (index > -1 && san[index] >= 'a' && san[index] <= 'h')
                {
                    file = GetFile(san[index]);
                    index--;
                }

                // get piece type char (if any)
                char pieceChar = 'P';
                if (index > -1)
                {
                    pieceChar = san[index];
                    index--;
                }

                // look into possible moves
                foreach (Move m in game.PossibleMoves)
                {
                    if (
                        m.To == to &&                                                                    // the ending squares match
                        (file == null || (file != null && Board.File(m.From) == file.Value)) &&          // the starting squares files match (if any)
                        (rank == null || (rank != null && Board.Rank(m.From) == rank.Value)) &&          // the starting squares ranks match (if any)
                        pieceTypeToUpperCharConversion[game.CurrentBoard[m.From].GetType()] == pieceChar // the piece type chars match
                        )
                    {
                        move = m;
                        break;
                    }
                }

                // if it's a promotion move, set the promotion
                if (move is PromotionMove)
                {
                    (move as PromotionMove).PromotionType = GetPromotionType(game.CurrentBoard.Status.WhiteTurn, prom);
                }
            }

            if (move != null)
            {
                return(move);
            }
            else
            {
                throw new ArgumentException(Resources.IllegalSANMoveMsg, "san");
            }
        }
예제 #13
0
파일: Utils.cs 프로젝트: vgichar/shah
        /// <summary>
        /// Gets the begin of the SAN (standard algebraic notation) for a move - without promotion or check/checkmate representation -  before the move is made
        /// without checking the status of the game or if it's a valid move.
        /// </summary>
        /// <param name="game">The game</param>
        /// <param name="move">The move</param>
        /// <returns></returns>
        public static string GetSANBegin(ValilGame game, Move move)
        {
            // the game must not be null
            if (game == null)
            {
                throw new ArgumentNullException("game", Resources.NullGameMsg);
            }

            // the move must not be null
            if (move == null)
            {
                throw new ArgumentNullException("move", Resources.NullMoveMsg);
            }

            StringBuilder sb = new StringBuilder(6);

            //if it's a castling move
            if (move is CastlingMove)
            {
                if (move.To == Board.G1 || move.To == Board.G8)
                {
                    // short castling
                    sb.Append("O-O");
                }
                else if (move.To == Board.C1 || move.To == Board.C8)
                {
                    // long castling
                    sb.Append("O-O-O");
                }
            }
            else
            {
                // add piece type and disambiguation
                char p = pieceTypeToUpperCharConversion[game.CurrentBoard[move.From].GetType()];
                if (p == 'P')
                {
                    // if the pawn captures, add the starting square file
                    if (move.HasCapture)
                    {
                        sb.Append(GetFileNotation(move.From));
                    }
                }
                else
                {
                    // add piece char
                    sb.Append(p);

                    // add disambiguation

                    // disambigutationList will contain starting squares that contain the same
                    // type of piece and that can move to the same ending square as "move"
                    List <int> disambiguationList = new List <int>(5);
                    foreach (Move m in game.PossibleMoves)
                    {
                        if (m.To == move.To && m.From != move.From && game.CurrentBoard[m.From].ToString() == game.CurrentBoard[move.From].ToString())
                        {
                            disambiguationList.Add(m.From);
                        }
                    }

                    if (disambiguationList.Count > 0)
                    {
                        // see if the file is unique
                        bool isFileUnique = true;
                        foreach (int from in disambiguationList)
                        {
                            if (Board.File(move.From) == Board.File(from))
                            {
                                isFileUnique = false;
                                break;
                            }
                        }

                        if (isFileUnique)
                        {
                            // insert file
                            sb.Append(Utils.GetFileNotation(move.From));
                        }
                        else
                        {
                            // see if the rank is unique
                            bool isRankUnique = true;
                            foreach (int from in disambiguationList)
                            {
                                if (Board.Rank(move.From) == Board.Rank(from))
                                {
                                    isRankUnique = false;
                                    break;
                                }
                            }

                            if (isRankUnique)
                            {
                                // insert rank
                                sb.Append(Utils.GetRankNotation(move.From));
                            }
                            else
                            {
                                // both file and rank are not unique, insert both of them
                                sb.Append(Utils.GetNotation(move.From));
                            }
                        }
                    }
                }

                // if there is a capture, add capture notation
                if (move.HasCapture)
                {
                    sb.Append('x');
                }

                // add destination square
                sb.Append(GetNotation(move.To));
            }

            return(sb.ToString());
        }
예제 #14
0
파일: Utils.cs 프로젝트: vgichar/shah
        /// <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)));
        }
예제 #15
0
파일: Utils.cs 프로젝트: vgichar/shah
 /// <summary>
 /// Gets the file char for a square.
 /// </summary>
 /// <param name="position">The position</param>
 /// <returns></returns>
 private static char GetFileNotation(int position)
 {
     return((char)((Board.File(position)) + 'a'));
 }