/// <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); }