[LIB-9] Separate chesshog-hedgefish module
[chesshog.git] / src / main / java / org / hedgecode / chess / ascii / ASCIIParser.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.ascii;
18
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.regex.Matcher;
22 import java.util.regex.Pattern;
23
24 import org.hedgecode.chess.Builders;
25 import org.hedgecode.chess.position.Color;
26 import org.hedgecode.chess.position.ParseException;
27 import org.hedgecode.chess.position.Parser;
28 import org.hedgecode.chess.position.Position;
29 import org.hedgecode.chess.position.Positions;
30 import org.hedgecode.chess.position.Square;
31
32 /**
33  * ASCII chess diagram parser.
34  *
35  * @author Dmitry Samoshin aka gotty
36  */
37 public final class ASCIIParser implements Parser {
38
39     private static final String LINE_REGEX = "\\r?\\n";
40     private static final String BAR_SQUARE_REGEX = String.format("[%s]", ASCII.BAR_REGEX);
41     private static final String DOT_SQUARE_REGEX = String.format("[^%s]+", ASCII.DOT_PIECE_REGEX);
42
43     private static final Pattern BAR_PATTERN =
44             Pattern.compile(
45                     String.format(
46                             "^.*[%s](([^%s]+[%s]){%d}[^%s]+)[%s].*$",
47                             ASCII.EDGE_REGEX, ASCII.BAR_REGEX, ASCII.BAR_REGEX,
48                             Square.getSize() - 1, ASCII.EDGE_REGEX, ASCII.EDGE_REGEX
49                     )
50             );
51
52     private static final Pattern DOT_PATTERN =
53             Pattern.compile(
54                     String.format(
55                             "^.*[%s](([^%s]+[%s]){%d}[^%s]+)[%s].*$",
56                             ASCII.DOT_EDGE, ASCII.DOT_PIECE_REGEX, ASCII.DOT_PIECE_REGEX,
57                             Square.getSize(), ASCII.DOT_PIECE_REGEX, ASCII.DOT_EDGE
58                     )
59             );
60
61     private static Parser _instance = new ASCIIParser();
62
63     private ASCIIParser() {
64     }
65
66     @Override
67     public Position parse(String string) throws ParseException {
68         return _parse(
69                 string.split(LINE_REGEX)
70         );
71     }
72
73     private Position _parse(String[] strings) throws ParseException {
74         String[] lines;
75         String squareRegex = BAR_SQUARE_REGEX;
76         lines = _parseLines(strings, BAR_PATTERN);
77         if (lines.length != Square.getSize()) {
78             squareRegex = DOT_SQUARE_REGEX;
79             lines = _parseLines(strings, DOT_PATTERN);
80             if (lines.length != Square.getSize())
81                 throw new ParseException("parse.ascii.incorrect.board");
82         }
83         Position position = Positions.EMPTY.getPosition();
84         _parsePieces(
85                 lines,
86                 position,
87                 squareRegex
88         );
89         return position;
90     }
91
92     private String[] _parseLines(String[] strings, Pattern linePattern) {
93         List<String> lines = new ArrayList<>();
94         for (String line : strings) {
95             Matcher matcher = linePattern.matcher(line);
96             if (matcher.find()) {
97                 lines.add(
98                         matcher.group(1).trim()
99                 );
100             }
101         }
102         return lines.toArray(
103                 new String[lines.size()]
104         );
105     }
106
107     private void _parsePieces(String[] lines, Position position, String squareRegex) throws ParseException {
108         for (int i = 0; i < lines.length; ++i) {
109             int line = lines.length - i;
110             String[] pieces = lines[i].split(squareRegex, -1);
111             if (pieces.length != Square.getSize())
112                 throw new ParseException("parse.ascii.incorrect.board");
113             for (int j = 0; j < pieces.length; ++j) {
114                 position.setPiece(
115                         ASCII.getColorPiece(pieces[j]),
116                         Square.getSquare(j, line - 1)
117                 );
118             }
119         }
120     }
121
122     public static Parser getInstance() {
123         return _instance;
124     }
125
126
127     public static void main(String[] args) throws ParseException {
128         ASCII.setType(ASCIIBoardType.DOT);
129         ASCII.setNotation(false);
130
131         // Position position = Positions.INITIAL.getPosition();
132         Position position = Positions.EMPTY.getPosition();
133         position.setKing(Color.WHITE, Square.A1);
134         position.setPawn(Color.WHITE, Square.A2);
135         position.setPawn(Color.WHITE, Square.E4);
136         position.setQueen(Color.WHITE, Square.A7);
137         position.setKing(Color.BLACK, Square.H8);
138         position.setPawn(Color.BLACK, Square.G7);
139         position.setPawn(Color.BLACK, Square.H7);
140         position.setKnight(Color.BLACK, Square.G2);
141         position.setBishop(Color.BLACK, Square.D4);
142         position.setRook(Color.BLACK, Square.E2);
143
144         String ascii = Builders.ASCII.builder().build(position);
145         System.out.println(
146                 ascii
147         );
148
149         position = getInstance().parse(ascii);
150
151         ASCII.setType(ASCIIBoardType.HYPHEN);
152         ascii = Builders.ASCII.builder().build(position);
153         System.out.println(
154                 ascii
155         );
156     }
157
158 }