[LIB-9] Separate chesshog-hedgefish module
[chesshog.git] / src / main / java / org / hedgecode / chess / fen / FEN.java
1 /*
2  * Copyright (c) 2018. Developed by Hedgecode.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.hedgecode.chess.fen;
18
19 import java.util.HashMap;
20 import java.util.Map;
21
22 import org.hedgecode.chess.position.Castle;
23 import org.hedgecode.chess.position.Color;
24 import org.hedgecode.chess.position.ColorPiece;
25 import org.hedgecode.chess.position.Piece;
26 import org.hedgecode.chess.position.Square;
27
28 /**
29  * Forsyth–Edwards Notation (FEN) constants.
30  *
31  * @author Dmitry Samoshin aka gotty
32  */
33 public final class FEN {
34
35     enum Fields {
36         PIECES     (0, "[pPnNbBrRqQkK1-8]+/?"),
37         MOVE       (1, "[wb]"),
38         CASTLE     (2, "[qQkK]+|-"),
39         EN_PASSANT (3, "[a-h][36]|-"),
40         HALFMOVE   (4, "[0-9]+"),
41         FULLMOVE   (5, "[1-9][0-9]*");
42
43         private int index;
44         private String regex;
45
46         Fields(int index, String regex) {
47             this.index = index;
48             this.regex = regex;
49         }
50
51         public int index() {
52             return index;
53         }
54
55         public String regex() {
56             return regex;
57         }
58     }
59
60     public static final char WHITE = 'w';
61     public static final char BLACK = 'b';
62     public static final char HYPHEN = '-';
63
64     public static final String FIELDS_SEP = " ";
65     public static final String LINE_SEP = "/";
66
67     public static final char WHITE_PAWN   = 'P';
68     public static final char WHITE_KNIGHT = 'N';
69     public static final char WHITE_BISHOP = 'B';
70     public static final char WHITE_ROOK   = 'R';
71     public static final char WHITE_QUEEN  = 'Q';
72     public static final char WHITE_KING   = 'K';
73
74     public static final char BLACK_PAWN   = 'p';
75     public static final char BLACK_KNIGHT = 'n';
76     public static final char BLACK_BISHOP = 'b';
77     public static final char BLACK_ROOK   = 'r';
78     public static final char BLACK_QUEEN  = 'q';
79     public static final char BLACK_KING   = 'k';
80
81     private static final Map<Color, Character> COLORS = new HashMap<Color, Character>() {
82         {
83             put(Color.WHITE, WHITE);
84             put(Color.BLACK, BLACK);
85         }
86     };
87
88     private static final Map<ColorPiece, Character> PIECES = new HashMap<ColorPiece, Character>() {
89         {
90             put(ColorPiece.WHITE_PAWN, WHITE_PAWN);     put(ColorPiece.BLACK_PAWN, BLACK_PAWN);
91             put(ColorPiece.WHITE_KNIGHT, WHITE_KNIGHT); put(ColorPiece.BLACK_KNIGHT, BLACK_KNIGHT);
92             put(ColorPiece.WHITE_BISHOP, WHITE_BISHOP); put(ColorPiece.BLACK_BISHOP, BLACK_BISHOP);
93             put(ColorPiece.WHITE_ROOK, WHITE_ROOK);     put(ColorPiece.BLACK_ROOK, BLACK_ROOK);
94             put(ColorPiece.WHITE_QUEEN, WHITE_QUEEN);   put(ColorPiece.BLACK_QUEEN, BLACK_QUEEN);
95             put(ColorPiece.WHITE_KING, WHITE_KING);     put(ColorPiece.BLACK_KING, BLACK_KING);
96         }
97     };
98
99     private FEN() {
100     }
101
102     public static Color getColor(char color) {
103         for (Map.Entry<Color, Character> entry : COLORS.entrySet()) {
104             if (entry.getValue() == color)
105                 return entry.getKey();
106         }
107         return null;
108     }
109
110     public static String getColor(Color color) {
111         return String.valueOf(
112                 color != null
113                         ? COLORS.get(color)
114                         : COLORS.get(Color.WHITE)
115         );
116     }
117
118     public static ColorPiece getColorPiece(char piece) {
119         for (Map.Entry<ColorPiece, Character> entry : PIECES.entrySet()) {
120             if (entry.getValue() == piece)
121                 return entry.getKey();
122         }
123         return null;
124     }
125
126     public static char getFenPiece(Color color, Piece piece) {
127         return getFenPiece(
128                 ColorPiece.getColorPiece(color, piece)
129         );
130     }
131
132     public static char getFenPiece(ColorPiece colorPiece) {
133         return PIECES.get(colorPiece);
134     }
135
136     public static Castle getCastle(Color color, String castles) {
137         Castle castle;
138         if (castles.indexOf(HYPHEN) >= 0) {
139             castle = Castle.NONE;
140         } else {
141             boolean isKing = false, isQueen = false;
142             switch (color) {
143                 case WHITE:
144                     isKing = (castles.indexOf(WHITE_KING) >= 0);
145                     isQueen = (castles.indexOf(WHITE_QUEEN) >= 0);
146                     break;
147                 case BLACK:
148                     isKing = (castles.indexOf(BLACK_KING) >= 0);
149                     isQueen = (castles.indexOf(BLACK_QUEEN) >= 0);
150                     break;
151             }
152             castle = isKing && isQueen ? Castle.BOTH
153                     : isKing ? Castle.KING
154                     : isQueen ? Castle.QUEEN
155                     : Castle.NONE;
156         }
157         return castle;
158     }
159
160     public static String getCastle(Castle whiteCastle, Castle blackCastle) {
161         StringBuilder sb = new StringBuilder();
162         switch (whiteCastle) {
163             case KING:
164                 sb.append(WHITE_KING);
165                 break;
166             case QUEEN:
167                 sb.append(WHITE_QUEEN);
168                 break;
169             case BOTH:
170                 sb.append(WHITE_KING).append(WHITE_QUEEN);
171                 break;
172         }
173         switch (blackCastle) {
174             case KING:
175                 sb.append(BLACK_KING);
176                 break;
177             case QUEEN:
178                 sb.append(BLACK_QUEEN);
179                 break;
180             case BOTH:
181                 sb.append(BLACK_KING).append(BLACK_QUEEN);
182                 break;
183         }
184         String castles = sb.toString();
185         return castles.isEmpty()
186                 ? String.valueOf(HYPHEN)
187                 : castles;
188     }
189
190     public static Square getEnPassant(String enPassant) {
191         if (enPassant.indexOf(HYPHEN) < 0) {
192             return Square.getSquare(enPassant);
193         }
194         return null;
195     }
196
197     public static String getEnPassant(Square square){
198         return (square != null)
199                 ? square.name().toLowerCase()
200                 : String.valueOf(HYPHEN);
201     }
202
203 }