/* * Copyright (c) 2018-2019. Developed by Hedgecode. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hedgecode.chess.fen; import java.util.HashMap; import java.util.Map; import org.hedgecode.chess.position.Castle; import org.hedgecode.chess.position.Color; import org.hedgecode.chess.position.ColorPiece; import org.hedgecode.chess.position.Piece; import org.hedgecode.chess.position.Square; /** * Forsyth–Edwards Notation (FEN) constants. * * @author Dmitry Samoshin aka gotty */ public final class FEN { enum Fields { PIECES (0, "[pPnNbBrRqQkK1-8]+/?"), MOVE (1, "[wb]"), CASTLE (2, "[qQkK]+|-"), EN_PASSANT (3, "[a-h][36]|-"), HALFMOVE (4, "[0-9]+"), FULLMOVE (5, "[1-9][0-9]*"); private int index; private String regex; Fields(int index, String regex) { this.index = index; this.regex = regex; } public int index() { return index; } public String regex() { return regex; } } public static final char WHITE = 'w'; public static final char BLACK = 'b'; public static final char HYPHEN = '-'; public static final String FIELDS_SEP = " "; public static final String LINE_SEP = "/"; public static final char WHITE_PAWN = 'P'; public static final char WHITE_KNIGHT = 'N'; public static final char WHITE_BISHOP = 'B'; public static final char WHITE_ROOK = 'R'; public static final char WHITE_QUEEN = 'Q'; public static final char WHITE_KING = 'K'; public static final char BLACK_PAWN = 'p'; public static final char BLACK_KNIGHT = 'n'; public static final char BLACK_BISHOP = 'b'; public static final char BLACK_ROOK = 'r'; public static final char BLACK_QUEEN = 'q'; public static final char BLACK_KING = 'k'; private static final Map COLORS = new HashMap() { { put(Color.WHITE, WHITE); put(Color.BLACK, BLACK); } }; private static final Map PIECES = new HashMap() { { put(ColorPiece.WHITE_PAWN, WHITE_PAWN); put(ColorPiece.BLACK_PAWN, BLACK_PAWN); put(ColorPiece.WHITE_KNIGHT, WHITE_KNIGHT); put(ColorPiece.BLACK_KNIGHT, BLACK_KNIGHT); put(ColorPiece.WHITE_BISHOP, WHITE_BISHOP); put(ColorPiece.BLACK_BISHOP, BLACK_BISHOP); put(ColorPiece.WHITE_ROOK, WHITE_ROOK); put(ColorPiece.BLACK_ROOK, BLACK_ROOK); put(ColorPiece.WHITE_QUEEN, WHITE_QUEEN); put(ColorPiece.BLACK_QUEEN, BLACK_QUEEN); put(ColorPiece.WHITE_KING, WHITE_KING); put(ColorPiece.BLACK_KING, BLACK_KING); } }; private FEN() { } public static Color getColor(char color) { for (Map.Entry entry : COLORS.entrySet()) { if (entry.getValue() == color) return entry.getKey(); } return null; } public static String getColor(Color color) { return String.valueOf( color != null ? COLORS.get(color) : COLORS.get(Color.WHITE) ); } public static ColorPiece getColorPiece(char piece) { for (Map.Entry entry : PIECES.entrySet()) { if (entry.getValue() == piece) return entry.getKey(); } return null; } public static char getFenPiece(Color color, Piece piece) { return getFenPiece( ColorPiece.getColorPiece(color, piece) ); } public static char getFenPiece(ColorPiece colorPiece) { return PIECES.get(colorPiece); } public static Castle getCastle(Color color, String castles) { Castle castle; if (castles.indexOf(HYPHEN) >= 0) { castle = Castle.NONE; } else { boolean isKing = false, isQueen = false; switch (color) { case Color.WHITE: isKing = (castles.indexOf(WHITE_KING) >= 0); isQueen = (castles.indexOf(WHITE_QUEEN) >= 0); break; case Color.BLACK: isKing = (castles.indexOf(BLACK_KING) >= 0); isQueen = (castles.indexOf(BLACK_QUEEN) >= 0); break; } castle = isKing && isQueen ? Castle.BOTH : isKing ? Castle.KING : isQueen ? Castle.QUEEN : Castle.NONE; } return castle; } public static String getCastle(Castle whiteCastle, Castle blackCastle) { StringBuilder sb = new StringBuilder(); switch (whiteCastle) { case Castle.KING: sb.append(WHITE_KING); break; case Castle.QUEEN: sb.append(WHITE_QUEEN); break; case Castle.BOTH: sb.append(WHITE_KING).append(WHITE_QUEEN); break; } switch (blackCastle) { case Castle.KING: sb.append(BLACK_KING); break; case Castle.QUEEN: sb.append(BLACK_QUEEN); break; case Castle.BOTH: sb.append(BLACK_KING).append(BLACK_QUEEN); break; } String castles = sb.toString(); return castles.isEmpty() ? String.valueOf(HYPHEN) : castles; } public static Square getEnPassant(String enPassant) { if (enPassant.indexOf(HYPHEN) < 0) { return Square.getSquare(enPassant); } return null; } public static String getEnPassant(Square square){ return (square != null) ? square.name().toLowerCase() : String.valueOf(HYPHEN); } }