示例#1
0
        /// <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(Game 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");
            }
        }
示例#2
0
        /// <summary>
        /// Get the SAN (standard algebraic notation) index for a move - move number and the side to move
        /// without checking the status of the game or if it's a valid move.
        /// </summary>
        /// <param name="game">The game</param>
        /// <returns></returns>
        public static string GetSANIndex(Game game)
        {
            // the game must not be null
            if (game == null) { throw new ArgumentNullException("game", "Resources.NullGameMsg"); }

            StringBuilder sb = new StringBuilder(5);

            // add move number
            sb.Append(game.CurrentBoard.Status.Moves.ToString(CultureInfo.InvariantCulture));

            // add side to move notation
            if (game.CurrentBoard.Status.WhiteTurn)
            {
                sb.Append('.');
            }
            else
            {
                sb.Append("...");
            }

            return sb.ToString();
        }
示例#3
0
        /// <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(Game 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();
        }
示例#4
0
        /// <summary>
        /// Gets the end of the SAN (standard algebraic notation) for a move - promotion and check/checkmate representation - after 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 GetSANEnd(Game 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(3);

            if (move is PromotionMove)
            {
                // add promotion notation
                sb.Append('=').Append(pieceTypeToUpperCharConversion[(move as PromotionMove).PromotionType]);
            }

            if (game.Status == GameStatus.Check)
            {
                // add check representation
                sb.Append('+');
            }
            else if (game.Status == GameStatus.Checkmate)
            {
                // add checkmate representation
                sb.Append('#');
            }

            return sb.ToString();
        }
示例#5
0
        /// <summary>
        /// Gets a move from its CAN (coordinate algebraic notation).
        /// Throws ArgumentException if it's not a valid move.
        /// </summary>
        /// <param name="game">The game</param>
        /// <param name="can">The CAN string</param>
        /// <returns></returns>
        public static Move GetCANMove(Game game, string can)
        {
            // the game must not be null
            if (game == null) { throw new ArgumentNullException("game", "Resources.NullGameMsg"); }

            // the CAN string must not be null
            if (can == null) { throw new ArgumentNullException("can", "Resources.NullCANMsg"); }

            // check if the string is well-formed
            if (can.Length < 4 || can[0] < 'a' || can[0] > 'h' || can[1] < '1' || can[1] > '8' || can[2] < 'a' || can[2] > 'h' || can[3] < '1' || can[3] > '8')
            {
                throw new ArgumentException("Resources.IllegalCANFormatMsg", "can");
            }

            // get the starting square
            int from = GetPosition(can[0], can[1]);

            // get the ending square
            int to = GetPosition(can[2], can[3]);

            // get the promotion
            Type promotionType = (can.Length > 4) ? GetPromotionType(game.CurrentBoard.Status.WhiteTurn, can[4]) : null;

            // look into the possible moves to find it
            Move move = game.GetMove(from, to, promotionType);

            if ((move == null) || (move is PromotionMove && (move as PromotionMove).PromotionType == null))
            {
                throw new ArgumentException("Resources.IllegalCANMoveMsg", "can");
            }

            return move;
        }