[LIB-9] Separate chesshog-format module
[chesshog.git] / chesshog-format / src / main / java / org / hedgecode / chess / fen / FEN.java
diff --git a/chesshog-format/src/main/java/org/hedgecode/chess/fen/FEN.java b/chesshog-format/src/main/java/org/hedgecode/chess/fen/FEN.java
new file mode 100644 (file)
index 0000000..36a781c
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * 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);
+    }
+
+}