X-Git-Url: https://git.hedgecode.org/?p=chesshog.git;a=blobdiff_plain;f=chesshog-dbetude%2Fsrc%2Fmain%2Fjava%2Forg%2Fhedgecode%2Fchess%2FEtudeUtils.java;fp=chesshog-dbetude%2Fsrc%2Fmain%2Fjava%2Forg%2Fhedgecode%2Fchess%2FEtudeUtils.java;h=268ca540e73e13b579e52404b3c093324ec1170b;hp=0000000000000000000000000000000000000000;hb=4d2b7f345d8079775373d95ab7c1a486cac96519;hpb=ccafd673bfcda89a75f428e58dc06525e1b0a368 diff --git a/chesshog-dbetude/src/main/java/org/hedgecode/chess/EtudeUtils.java b/chesshog-dbetude/src/main/java/org/hedgecode/chess/EtudeUtils.java new file mode 100644 index 0000000..268ca54 --- /dev/null +++ b/chesshog-dbetude/src/main/java/org/hedgecode/chess/EtudeUtils.java @@ -0,0 +1,182 @@ +/* + * 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; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.hedgecode.chess.position.Color; +import org.hedgecode.chess.position.ColorPiece; +import org.hedgecode.chess.position.Piece; +import org.hedgecode.chess.position.Position; +import org.hedgecode.chess.position.Positions; +import org.hedgecode.chess.position.Square; +import org.hedgecode.chess.position.SquareSort; + +/** + * + * + * @author Dmitry Samoshin aka gotty + */ +public final class EtudeUtils { + + private static final byte PIECE_MASK = 0b1111; + private static final byte PIECE_LENGTH = 4; + + private static final byte NUM_WHITE_PAWN = 0; + private static final byte NUM_WHITE_KNIGHT = 1; + private static final byte NUM_WHITE_BISHOP = 2; + private static final byte NUM_WHITE_ROOK = 3; + private static final byte NUM_WHITE_QUEEN = 4; + + private static final byte NUM_BLACK_PAWN = 5; + private static final byte NUM_BLACK_KNIGHT = 6; + private static final byte NUM_BLACK_BISHOP = 7; + private static final byte NUM_BLACK_ROOK = 8; + private static final byte NUM_BLACK_QUEEN = 9; + + private static final byte BLOB_PIECE_EMPTY = 0b0000; + + private static final byte BLOB_WHITE_PAWN = 0b0001; + private static final byte BLOB_WHITE_KNIGHT = 0b0010; + private static final byte BLOB_WHITE_BISHOP = 0b0011; + private static final byte BLOB_WHITE_ROOK = 0b0100; + private static final byte BLOB_WHITE_QUEEN = 0b0101; + private static final byte BLOB_WHITE_KING = 0b0110; + + private static final byte BLOB_BLACK_PAWN = 0b1001; + private static final byte BLOB_BLACK_KNIGHT = 0b1010; + private static final byte BLOB_BLACK_BISHOP = 0b1011; + private static final byte BLOB_BLACK_ROOK = 0b1100; + private static final byte BLOB_BLACK_QUEEN = 0b1101; + private static final byte BLOB_BLACK_KING = 0b1110; + + private static final Map PIECE_NUMBERS = new HashMap() { + { + put(ColorPiece.WHITE_PAWN, NUM_WHITE_PAWN); put(ColorPiece.BLACK_PAWN, NUM_BLACK_PAWN); + put(ColorPiece.WHITE_KNIGHT, NUM_WHITE_KNIGHT); put(ColorPiece.BLACK_KNIGHT, NUM_BLACK_KNIGHT); + put(ColorPiece.WHITE_BISHOP, NUM_WHITE_BISHOP); put(ColorPiece.BLACK_BISHOP, NUM_BLACK_BISHOP); + put(ColorPiece.WHITE_ROOK, NUM_WHITE_ROOK); put(ColorPiece.BLACK_ROOK, NUM_BLACK_ROOK); + put(ColorPiece.WHITE_QUEEN, NUM_WHITE_QUEEN); put(ColorPiece.BLACK_QUEEN, NUM_BLACK_QUEEN); + } + }; + + private static final Map BLOB_PIECES = new HashMap() { + { + put(ColorPiece.WHITE_PAWN, BLOB_WHITE_PAWN); put(ColorPiece.BLACK_PAWN, BLOB_BLACK_PAWN); + put(ColorPiece.WHITE_KNIGHT, BLOB_WHITE_KNIGHT); put(ColorPiece.BLACK_KNIGHT, BLOB_BLACK_KNIGHT); + put(ColorPiece.WHITE_BISHOP, BLOB_WHITE_BISHOP); put(ColorPiece.BLACK_BISHOP, BLOB_BLACK_BISHOP); + put(ColorPiece.WHITE_ROOK, BLOB_WHITE_ROOK); put(ColorPiece.BLACK_ROOK, BLOB_BLACK_ROOK); + put(ColorPiece.WHITE_QUEEN, BLOB_WHITE_QUEEN); put(ColorPiece.BLACK_QUEEN, BLOB_BLACK_QUEEN); + put(ColorPiece.WHITE_KING, BLOB_WHITE_KING); put(ColorPiece.BLACK_KING, BLOB_BLACK_KING); + } + }; + + public static BigInteger hashPosition(Position position) { + StringBuilder sb = new StringBuilder(); + sb.append( + numSquare( + kingSquare(Color.WHITE, position) + ) + ).append( + numSquare( + kingSquare(Color.BLACK, position) + ) + ); + int empty = 0; + for (Map.Entry entry : position.getSquares(SquareSort.A8H1).entrySet()) { + ColorPiece colorPiece = entry.getValue(); + if (colorPiece != null && !Piece.KING.equals(colorPiece.piece())) { + if (empty > 0) + sb.append(empty); + sb.append( + PIECE_NUMBERS.get(colorPiece) + ); + empty = 0; + } else { + ++empty; + } + } + if (empty > 0) + sb.append(empty); + + return new BigInteger( + sb.toString() /* todo: SQL: NUMERIC(64,0) */ + ); + } + + public static byte[] blobPosition(Position position) { + byte[] blob = new byte[Square.getSize() * Square.getSize()]; + int i = 0; + for (Map.Entry entry : position.getSquares(SquareSort.A8H1).entrySet()) { + ColorPiece colorPiece = entry.getValue(); + blob[i++] = colorPiece != null ? BLOB_PIECES.get(colorPiece) : BLOB_PIECE_EMPTY; + } + return compress(blob); + } + + private static Square kingSquare(Color color, Position position) { + Square kingSquare = null; + + Map king = position.getSquarePieces(color, Piece.KING); + + if (king.isEmpty() || king.size() > 1) + throw new RuntimeException("Incorrect position"); // todo + + for (Square square : king.keySet()) { + kingSquare = square; + } + return kingSquare; + } + + private static int numSquare(Square square) { + int v = square.getV() + 1; + int h = Square.getSize() - square.getH(); + return Square.getSize() * (h - 1) + v; + } + + private static byte[] compress(byte[] bytes) { + byte[] cmpBytes = new byte[bytes.length / 2]; + byte high, low; + int i = 0; + for (int j = 0; j < cmpBytes.length; ++j) { + high = (byte) ((bytes[i++] & PIECE_MASK) << PIECE_LENGTH); + low = (byte) (bytes[i++] & PIECE_MASK); + cmpBytes[j] = (byte) (high | low); + } + return cmpBytes; + } + + private EtudeUtils() { + throw new AssertionError( + "No org.hedgecode.chess.EtudeUtils instances!" + ); + } + + + public static void main(String... args) { + System.out.println( + hashPosition(Positions.INITIAL.getPosition()) + ); + System.out.println( + Arrays.toString(blobPosition(Positions.INITIAL.getPosition())) + ); + } + +}