예제 #1
0
        /// <summary>
        /// The "main" method of this class, returns a correct move from a string essentially
        /// <example>
        /// <code>
        /// Grid board = new Grid();
        /// Move e4 = Move.FromUCI(board, "e2e4");
        /// </code>
        /// The example above will return a move with all the features that containst:
        /// Good move printing
        /// MoveType detection
        /// Promotion pieces
        /// Castltes
        /// </example>
        /// <see cref="Grid"/>
        /// <see cref="Piece"/>
        /// <see cref="Move.MoveTypeIdentifier(Grid, Tile, Tile)"
        /// </summary>
        /// <param name="board">The current board <see cref="Grid"/></param>
        /// <param name="uci">A uci string <example>"e2e4"</example> (must be lower case)</param>
        /// <param name="promotionPiece">Optional paramter for promotion piece, the MakeMove in <see cref="Grid"/> will handle it automatically</param>
        /// <returns>A move <see cref="Move"/></returns>
        /// <exception cref="ArgumentException">Will be thrown if the uci string length is different from 4</exception>
        /// <exception cref="InvalidMoveException">
        /// Will be thrown from a few reasons, mainly Invalid moves, like source tile has no piece etc'
        /// And also from wrong promotion
        /// </exception>
        public static Move FromUCI(Grid board, string uci, Piece promotionPiece = null)
        {
            Move move = null;

            if (uci.Length != 4)
            {
                throw new ArgumentException("UCI must be 4 characters");
            }

            int startX = (int)(uci[0] - 'a');
            int startY = int.Parse(uci[1].ToString()) - 1;
            int endX   = (int)(uci[2] - 'a');
            int endY   = int.Parse(uci[3].ToString()) - 1;

            Tile start = board.GetTile(startX, startY);
            Tile end   = board.GetTile(endX, endY);

            if (start.Piece == null)
            {
                throw new InvalidMoveException("Source tile has no piece");
            }

            if (end.Piece != null)
            {
                if (start.Piece.IsWhite == end.Piece.IsWhite)
                {
                    throw new InvalidMoveException("Source tile piece and destination tile piece are of the same team");
                }
            }

            if (promotionPiece == null)
            {
                MoveType temp = MoveType.Normal;
                move = new Move(start, end, board.CurrentPlayer, Move.MoveTypeIdentifier(board, start, end, ref temp));
                move.additionalMoveType = temp;
                return(move);
            }
            //promotion move
            Pawn pawn = start.Piece as Pawn;

            if (pawn == null)
            {
                throw new InvalidMoveException("Source tile must contain pawn");
            }

            if (pawn.IsWhite)
            {
                if (end.Y != 7)
                {
                    throw new InvalidMoveException("Destination tile must be the last rank");
                }
            }
            else
            {
                if (end.Y != 0)
                {
                    throw new InvalidMoveException("Destination tile must be the first rank");
                }
            }

            //check if promotion piece is not pawn
            if (promotionPiece is Pawn)
            {
                throw new InvalidMoveException("Can't promote to pawn");
            }

            move = new Move(start, end, board.CurrentPlayer, MoveType.Promotion, promotionPiece);
            return(move);
        }