public static String AsciiBoard(Board board, List <Move> moves = null, bool displayCount = false) { if (moves == null) { moves = new List <Move>(); } moves = moves.Where(move => board.IsLegalMove(move)).ToList(); StringBuilder ascii = new StringBuilder(); ascii.Append("+---------------+\n"); for (int row = 7; row >= 0; row--) { ascii.Append("|"); for (int column = 0; column < 8; column++) { var position = row * BoardStateOffset.ROW_OFFSET + column; var piece = board.GetPiece(position); var movesOnPosition = moves.Count(move => move.targetPosition == position); if (movesOnPosition > 0) { if (movesOnPosition < 10 && displayCount) { ascii.Append(movesOnPosition); } else { ascii.Append("x"); } } else { ascii.Append(PieceParser.ToChar(piece)); } if (column != 7) { ascii.Append(" "); } } ascii.Append($"| {(row + 1)}\n"); } ascii.Append("+---------------+\n"); ascii.Append(" A B C D E F G H"); return(ascii.ToString()); }
public static String BoardToFen(Board board, int move = 0) { StringBuilder fen = new StringBuilder(); for (int row = 7; row >= 0; row--) { int count = 0; for (int column = 0; column < 8; column++) { var position = row * BoardStateOffset.ROW_OFFSET + column; var piece = board.GetPiece(position); //var piece = Board.GetPiece(board, position); char c = PieceParser.ToChar(piece); if (c == '_') { count++; } else { if (count != 0) { fen.Append(count); count = 0; } fen.Append(c); } } if (count != 0) { fen.Append(count); } if (row != 0) { fen.Append("/"); } } fen.Append(" "); fen.Append(board.IsWhiteTurnBool ? "w" : "b"); fen.Append(" "); CastlingBits castlingBits = board.CastlingBits; if (castlingBits == CastlingBits.EMPTY) { fen.Append("-"); } else { if ((castlingBits & CastlingBits.WHITE_KING_SIDE_CASTLE) != CastlingBits.EMPTY) { fen.Append("K"); } if ((castlingBits & CastlingBits.WHITE_QUEEN_SIDE_CASTLE) != CastlingBits.EMPTY) { fen.Append("Q"); } if ((castlingBits & CastlingBits.BLACK_KING_SIDE_CASTLE) != CastlingBits.EMPTY) { fen.Append("k"); } if ((castlingBits & CastlingBits.BLACK_QUEEN_SIDE_CASTLE) != CastlingBits.EMPTY) { fen.Append("q"); } } fen.Append(" "); fen.Append(board.EnPassantTarget != EnPassant.NO_ENPASSANT ? BoardPosition.ReadablePosition(board.EnPassantTarget) : "-"); fen.Append(" "); fen.Append(board.HalfTurnCounter); fen.Append(" "); fen.Append(move); return(fen.ToString()); }
// based on rules from https://en.wikipedia.org/wiki/Algebraic_notation_(chess) // Notice the parameter legalMoves only contains legal moves public string StandardAlgebraicNotation(Move move, List <Move> legalMoves) { StringBuilder san = new StringBuilder(); var piece = GetPiece(move.fromPosition); if (((MoveFlags)move.moveFlags & MoveFlags.CASTLING) == MoveFlags.CASTLING) { if (move.targetPosition < move.fromPosition) { // castle queen side san.Append("O-O-O"); } else { // castle king side san.Append("O-O"); } } else { var isPawn = (piece & Piece.PIECE_MASK) == Piece.PAWN; if (!isPawn) { // all pieces other pawns display their piece name var pChar = PieceParser.ToChar(piece); san.Append(pChar.ToString().ToUpper()); } int fromRow = move.fromPosition / BoardStateOffset.ROW_OFFSET; int fromColumn = move.fromPosition - (fromRow * BoardStateOffset.ROW_OFFSET); bool sameColumns = false; bool sameRows = false; bool isAmbigious = false; foreach (var possibleMove in legalMoves) { // check all other moves of the same piece type if they can move to the same position if (possibleMove.targetPosition == move.targetPosition && // check if it can reach the same square possibleMove.fromPosition != move.fromPosition && // check if not the same piece piece == GetPiece(possibleMove.fromPosition)) // check it is the same type of piece { isAmbigious = true; int possibleFromRow = possibleMove.fromPosition / BoardStateOffset.ROW_OFFSET; int possibleFromColumn = possibleMove.fromPosition - (possibleFromRow * BoardStateOffset.ROW_OFFSET); if (possibleFromColumn == fromColumn) { sameColumns = true; } if (possibleFromRow == fromRow) { sameRows = true; } } } if (isPawn) { if ((Piece)move.capturedPiece != Piece.EMPTY) { // when pawn captures always specify the starting column san.Append(Convert.ToChar('a' + (fromColumn))); } } else { if (isAmbigious) { // disambiguating moves if (sameColumns && sameRows) { san.Append(Convert.ToChar('a' + (fromColumn))); san.Append((fromRow + 1).ToString()); } else if (sameColumns) { san.Append((fromRow + 1).ToString()); } else { san.Append(Convert.ToChar('a' + (fromColumn))); } } } if ((Piece)move.capturedPiece != Piece.EMPTY) { san.Append("x"); } int targetRow = move.targetPosition / BoardStateOffset.ROW_OFFSET; int targetColumn = move.targetPosition - (targetRow * BoardStateOffset.ROW_OFFSET); san.Append(Convert.ToChar('a' + (targetColumn))).Append((targetRow + 1).ToString()); Piece promotion = (Piece)move.promotion; if (promotion != Piece.EMPTY) { san.Append("=").Append(PieceParser.ToChar(promotion).ToString().ToUpper()); } } Move(move); // check for checkmate // after the move is played check if the current players king is attacked if (Attacked(GetKingPosition(IsWhiteTurn), IsWhiteTurn)) { var winner = detectWinner(GetMoves()); if (winner == Winner.WINNER_BLACK || winner == Winner.WINNER_WHITE) { //san += "#"; san.Append("#"); } else { //san += "+"; san.Append("+"); } } UndoMove(move); return(san.ToString()); }
public static ChessState GameToState(ChessGame game) { var chessState = new ChessState(); //var moves = board.GetMoves().Where(move => board.IsLegalMove(move)); var moves = game.Moves(); for (int column = 0; column < 8; column++) { for (int row = 0; row < 8 * BoardStateOffset.ROW_OFFSET; row += BoardStateOffset.ROW_OFFSET) { var position = row + column; Piece piece = game.board.GetPiece(position); if (piece != Piece.EMPTY) { var from = BoardPosition.x88PositionToCoordinate(position); var chessPiece = new ChessPiece() { piece = PieceParser.ToChar(piece).ToString(), row = from.row, column = from.column, isWhite = (piece & Piece.IS_WHITE) == Piece.IS_WHITE }; chessState.pieces.Add(chessPiece); foreach (var move in moves) { if (move.move.fromPosition == position) { var to = BoardPosition.x88PositionToCoordinate(move.move.targetPosition); chessPiece.options.Add(new PieceOption() { row = to.row, column = to.column, isPromotion = (Piece)move.move.promotion != Piece.EMPTY, isCastle = ((MoveFlags)move.move.moveFlags & MoveFlags.CASTLING) == MoveFlags.CASTLING, isEnpassant = (((MoveFlags)move.move.moveFlags & MoveFlags.ENPASSANT) == MoveFlags.ENPASSANT), san = move.san }); } } } } } var winner = game.Winner(); if (winner == Winner.DRAW) { chessState.isDraw = true; } else if (winner == Winner.WINNER_BLACK) { chessState.blackWins = true; } else if (winner == Winner.WINNER_WHITE) { chessState.whiteWins = true; } chessState.fen = game.FEN; return(chessState); }