--- /dev/null
+/*
+ * 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<Color, Character> COLORS = new HashMap<Color, Character>() {
+ {
+ put(Color.WHITE, WHITE);
+ put(Color.BLACK, BLACK);
+ }
+ };
+
+ private static final Map<ColorPiece, Character> PIECES = new HashMap<ColorPiece, Character>() {
+ {
+ 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<Color, Character> 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<ColorPiece, Character> 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);
+ }
+
+}