/// <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 }
/// <summary> /// Sets the captured piece. /// </summary> /// <param name="piece">The piece</param> internal void SetCapture(Piece piece) { capture = piece; }
/// <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"); } }
/// <summary> /// Constructor. /// </summary> /// <param name="squares"></param> /// <param name="status"></param> public Board(Piece[] squares, BoardStatus status) { this.squares = squares; this.status = status; }
/// <summary> /// Gets a board in the starting position. /// </summary> /// <returns></returns> public static Board GetStartingBoard() { Piece[] squares = new Piece[SquareNo]; BoardStatus status = new BoardStatus(); squares[A8] = new BlackRook(); squares[B8] = new BlackKnight(); squares[C8] = new BlackBishop(); squares[D8] = new BlackQueen(); squares[E8] = new BlackKing(); squares[F8] = new BlackBishop(); squares[G8] = new BlackKnight(); squares[H8] = new BlackRook(); for (int sqIndex = SideSquareNo; sqIndex < SideSquareNo * 2; sqIndex++) { squares[sqIndex] = new BlackPawn(); } for (int sqIndex = SideSquareNo * (SideSquareNo - 2); sqIndex < SideSquareNo * (SideSquareNo - 1); sqIndex++) { squares[sqIndex] = new WhitePawn(); } squares[A1] = new WhiteRook(); squares[B1] = new WhiteKnight(); squares[C1] = new WhiteBishop(); squares[D1] = new WhiteQueen(); squares[E1] = new WhiteKing(); squares[F1] = new WhiteBishop(); squares[G1] = new WhiteKnight(); squares[H1] = new WhiteRook(); status.WhiteTurn = true; status.WhiteCouldCastleLong = status.WhiteCouldCastleShort = status.BlackCouldCastleLong = status.BlackCouldCastleShort = true; status.EnPassantTarget = null; status.Ply = 0; status.Moves = 1; return new Board(squares, status); }
/// <summary> /// Makes the move, it doesn't check if it's a valid move. /// </summary> /// <param name="board">The board</param> internal virtual void Make(Board board) { capture = board[to];// set the capture board[to] = board[from];// put the piece on ending square board[from] = null;// empty the starting square board.Status = after;// set the board status to the after board status }