+++ /dev/null
-/*
- * Copyright (c) 2018. 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.tcd;
-
-import org.hedgecode.chess.position.Castle;
-import org.hedgecode.chess.position.Color;
-import org.hedgecode.chess.position.ParseException;
-import org.hedgecode.chess.position.Parser;
-import org.hedgecode.chess.position.Position;
-import org.hedgecode.chess.position.Positions;
-import org.hedgecode.chess.position.Square;
-
-/**
- * Tiny Chess Diagram (TCD) parser.
- *
- * @author Dmitry Samoshin aka gotty
- */
-public final class TCDParser implements Parser {
-
- private static Parser _instance = new TCDParser();
-
- private TCDParser() {
- }
-
- private final class TCDIterator {
-
- private byte[] bytes;
- private int pos;
- private boolean isHighPart;
-
- TCDIterator(byte[] bytes) {
- this.bytes = bytes;
- this.pos = 0;
- this.isHighPart = true;
- }
-
- boolean hasNext() {
- return (bytes.length > pos + 1) || (isHighPart && bytes.length > pos);
- }
-
- boolean isLast() {
- return !isHighPart && (bytes.length - 1 == pos);
- }
-
- byte next() throws ParseException {
- isHighPart = !isHighPart;
- if (isHighPart)
- pos++;
- return current();
- }
-
- byte current() throws ParseException {
- if (bytes.length <= pos)
- throw new ParseException("parse.tcd.index.out.of.bounds");
- byte frame = bytes[pos];
- if (isHighPart)
- frame = (byte) (frame >> TCD.FRAME_LENGTH);
- return (byte) (frame & TCD.FRAME_MASK);
- }
- }
-
- @Override
- public Position parse(String string) throws ParseException {
- return parse(
- string.getBytes()
- );
- }
-
- public Position parse(byte[] bytes) throws ParseException {
- TCD.replaceFrom(bytes);
- if (!TCD.isValid(bytes))
- throw new ParseException("parse.tcd.invalid.bytes");
- TCDIterator iterator = new TCDIterator(bytes);
- return _parse(iterator);
- }
-
- private Position _parse(TCDIterator iterator) throws ParseException {
- Position position;
-
- byte curr = iterator.current();
- byte next = iterator.next();
-
- if (TCD.isBlackWhite(curr, next)) {
- position = Positions.INITIAL.getPosition();
- curr = iterator.next();
- next = iterator.next();
- } else {
- position = Positions.EMPTY.getPosition();
- boolean isWhiteAssigned = false, isBlackAssigned = false;
- while (!isWhiteAssigned || !isBlackAssigned) {
- switch (curr) {
- case TCD.WHITE:
- _parsePieces(Color.WHITE, position, iterator);
- isWhiteAssigned = true;
- break;
- case TCD.BLACK:
- _parsePieces(Color.BLACK, position, iterator);
- isBlackAssigned = true;
- break;
- default:
- throw new ParseException("parse.tcd.incorrect.color");
- }
- curr = iterator.current();
- next = iterator.next();
- }
- }
-
- if (!TCD.isWhiteBlack(curr, next))
- throw new ParseException("parse.tcd.incorrect.end");
-
- _parseAddition(position, iterator);
-
- return position;
- }
-
- private void _parsePieces(Color color, Position position, TCDIterator iterator) throws ParseException {
- byte piece = iterator.current();
- while (TCD.isNotColor(piece)) {
- int pieceCount = iterator.next() + 1;
- for (int i = 0; i < pieceCount; ++i) {
- Square square = _parseSquare(iterator);
- switch (piece) {
- case TCD.PAWN:
- position.setPawn(color, square);
- break;
- case TCD.KNIGHT:
- position.setKnight(color, square);
- break;
- case TCD.BISHOP:
- position.setBishop(color, square);
- break;
- case TCD.ROOK:
- position.setRook(color, square);
- break;
- case TCD.QUEEN:
- position.setQueen(color, square);
- break;
- case TCD.KING:
- position.setKing(color, square);
- break;
- default:
- throw new ParseException("parse.tcd.incorrect.piece");
- }
- }
- piece = iterator.next();
- }
- }
-
- private void _parseAddition(Position position, TCDIterator iterator) throws ParseException {
- if (iterator.hasNext()) {
- byte frame = iterator.next();
- if (iterator.isLast() && frame != TCD.END) {
- throw new ParseException("parse.tcd.incorrect.end");
- } else {
- boolean isEndPosition = false;
- while (!isEndPosition) {
- switch (frame) {
- case TCD.MOVE:
- position.setMove(
- _parseMove(iterator)
- );
- break;
- case TCD.CASTLE_WHITE:
- position.setCastle(
- Color.WHITE, _parseCastle(iterator)
- );
- break;
- case TCD.CASTLE_BLACK:
- position.setCastle(
- Color.BLACK, _parseCastle(iterator)
- );
- break;
- case TCD.EN_PASSANT:
- position.setEnPassant(
- _parseSquare(iterator)
- );
- break;
- case TCD.HALFMOVE:
- position.setHalfMove(
- _parseNumber(iterator)
- );
- break;
- case TCD.FULLMOVE:
- position.setFullMove(
- _parseNumber(iterator)
- );
- break;
- default:
- throw new ParseException("parse.tcd.incorrect.addition");
- }
- isEndPosition = true;
- if (iterator.hasNext()) {
- frame = iterator.next();
- if (iterator.isLast() && frame != TCD.END) {
- throw new ParseException("parse.tcd.incorrect.end");
- }
- isEndPosition = iterator.isLast();
- }
- }
- }
- }
- }
-
- private Square _parseSquare(TCDIterator iterator) throws ParseException {
- byte vl = iterator.next();
- byte hl = iterator.next();
- return Square.getSquare(vl, hl);
- }
-
- private Color _parseMove(TCDIterator iterator) throws ParseException {
- byte frame = iterator.next();
- if (TCD.isNotColor(frame))
- throw new ParseException("parse.tcd.incorrect.move.color");
- return frame == TCD.WHITE ? Color.WHITE : Color.BLACK;
- }
-
- private Castle _parseCastle(TCDIterator iterator) throws ParseException {
- byte frame = iterator.next();
- if (TCD.isNotCastle(frame))
- throw new ParseException("parse.tcd.incorrect.castle");
- Castle castle = Castle.NONE;
- switch (frame) {
- case TCD.CASTLE_KING:
- castle = Castle.KING;
- break;
- case TCD.CASTLE_QUEEN:
- castle = Castle.QUEEN;
- break;
- case TCD.CASTLE_BOTH:
- castle = Castle.BOTH;
- break;
- }
- return castle;
- }
-
- private int _parseNumber(TCDIterator iterator) throws ParseException {
- return iterator.next() << (2 * TCD.FRAME_LENGTH)
- | iterator.next() << TCD.FRAME_LENGTH
- | iterator.next();
- }
-
- public static Parser getInstance() {
- return _instance;
- }
-
-
- public static void main(String[] args) throws ParseException {
- //Position position = getInstance().parse("A7ONMILHJJIFCJEDO0ECFD0OvFV+4fnNQwOYoWaG-h5pgG");
- //Position position = getInstance().parse("xG");
- Position position = getInstance().parse("A7ONMILHJJIFCJEDO0ECFDGOvFV+4fnNQwOYoWaG-h5pgG");
- System.out.println(position);
- }
-
-}