2 * Copyright (c) 2018. Developed by Hedgecode.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org.hedgecode.chess;
19 import java.math.BigInteger;
20 import java.util.Arrays;
21 import java.util.HashMap;
24 import org.hedgecode.chess.position.Color;
25 import org.hedgecode.chess.position.ColorPiece;
26 import org.hedgecode.chess.position.Piece;
27 import org.hedgecode.chess.position.Position;
28 import org.hedgecode.chess.position.Positions;
29 import org.hedgecode.chess.position.Square;
30 import org.hedgecode.chess.position.SquareSort;
35 * @author Dmitry Samoshin aka gotty
37 public final class EtudeUtils {
39 private static final byte PIECE_MASK = 0b1111;
40 private static final byte PIECE_LENGTH = 4;
42 private static final byte NUM_WHITE_PAWN = 0;
43 private static final byte NUM_WHITE_KNIGHT = 1;
44 private static final byte NUM_WHITE_BISHOP = 2;
45 private static final byte NUM_WHITE_ROOK = 3;
46 private static final byte NUM_WHITE_QUEEN = 4;
48 private static final byte NUM_BLACK_PAWN = 5;
49 private static final byte NUM_BLACK_KNIGHT = 6;
50 private static final byte NUM_BLACK_BISHOP = 7;
51 private static final byte NUM_BLACK_ROOK = 8;
52 private static final byte NUM_BLACK_QUEEN = 9;
54 private static final byte BLOB_PIECE_EMPTY = 0b0000;
56 private static final byte BLOB_WHITE_PAWN = 0b0001;
57 private static final byte BLOB_WHITE_KNIGHT = 0b0010;
58 private static final byte BLOB_WHITE_BISHOP = 0b0011;
59 private static final byte BLOB_WHITE_ROOK = 0b0100;
60 private static final byte BLOB_WHITE_QUEEN = 0b0101;
61 private static final byte BLOB_WHITE_KING = 0b0110;
63 private static final byte BLOB_BLACK_PAWN = 0b1001;
64 private static final byte BLOB_BLACK_KNIGHT = 0b1010;
65 private static final byte BLOB_BLACK_BISHOP = 0b1011;
66 private static final byte BLOB_BLACK_ROOK = 0b1100;
67 private static final byte BLOB_BLACK_QUEEN = 0b1101;
68 private static final byte BLOB_BLACK_KING = 0b1110;
70 private static final Map<ColorPiece, Byte> PIECE_NUMBERS = new HashMap<ColorPiece, Byte>() {
72 put(ColorPiece.WHITE_PAWN, NUM_WHITE_PAWN); put(ColorPiece.BLACK_PAWN, NUM_BLACK_PAWN);
73 put(ColorPiece.WHITE_KNIGHT, NUM_WHITE_KNIGHT); put(ColorPiece.BLACK_KNIGHT, NUM_BLACK_KNIGHT);
74 put(ColorPiece.WHITE_BISHOP, NUM_WHITE_BISHOP); put(ColorPiece.BLACK_BISHOP, NUM_BLACK_BISHOP);
75 put(ColorPiece.WHITE_ROOK, NUM_WHITE_ROOK); put(ColorPiece.BLACK_ROOK, NUM_BLACK_ROOK);
76 put(ColorPiece.WHITE_QUEEN, NUM_WHITE_QUEEN); put(ColorPiece.BLACK_QUEEN, NUM_BLACK_QUEEN);
80 private static final Map<ColorPiece, Byte> BLOB_PIECES = new HashMap<ColorPiece, Byte>() {
82 put(ColorPiece.WHITE_PAWN, BLOB_WHITE_PAWN); put(ColorPiece.BLACK_PAWN, BLOB_BLACK_PAWN);
83 put(ColorPiece.WHITE_KNIGHT, BLOB_WHITE_KNIGHT); put(ColorPiece.BLACK_KNIGHT, BLOB_BLACK_KNIGHT);
84 put(ColorPiece.WHITE_BISHOP, BLOB_WHITE_BISHOP); put(ColorPiece.BLACK_BISHOP, BLOB_BLACK_BISHOP);
85 put(ColorPiece.WHITE_ROOK, BLOB_WHITE_ROOK); put(ColorPiece.BLACK_ROOK, BLOB_BLACK_ROOK);
86 put(ColorPiece.WHITE_QUEEN, BLOB_WHITE_QUEEN); put(ColorPiece.BLACK_QUEEN, BLOB_BLACK_QUEEN);
87 put(ColorPiece.WHITE_KING, BLOB_WHITE_KING); put(ColorPiece.BLACK_KING, BLOB_BLACK_KING);
91 public static BigInteger hashPosition(Position position) {
92 StringBuilder sb = new StringBuilder();
95 kingSquare(Color.WHITE, position)
99 kingSquare(Color.BLACK, position)
103 for (Map.Entry<Square, ColorPiece> entry : position.getSquares(SquareSort.A8H1).entrySet()) {
104 ColorPiece colorPiece = entry.getValue();
105 if (colorPiece != null && !Piece.KING.equals(colorPiece.piece())) {
109 PIECE_NUMBERS.get(colorPiece)
119 return new BigInteger(
120 sb.toString() /* todo: SQL: NUMERIC(64,0) */
124 public static byte[] blobPosition(Position position) {
125 byte[] blob = new byte[Square.getSize() * Square.getSize()];
127 for (Map.Entry<Square, ColorPiece> entry : position.getSquares(SquareSort.A8H1).entrySet()) {
128 ColorPiece colorPiece = entry.getValue();
129 blob[i++] = colorPiece != null ? BLOB_PIECES.get(colorPiece) : BLOB_PIECE_EMPTY;
131 return compress(blob);
134 private static Square kingSquare(Color color, Position position) {
135 Square kingSquare = null;
137 Map<Square, ColorPiece> king = position.getSquarePieces(color, Piece.KING);
139 if (king.isEmpty() || king.size() > 1)
140 throw new RuntimeException("Incorrect position"); // todo
142 for (Square square : king.keySet()) {
148 private static int numSquare(Square square) {
149 int v = square.getV() + 1;
150 int h = Square.getSize() - square.getH();
151 return Square.getSize() * (h - 1) + v;
154 private static byte[] compress(byte[] bytes) {
155 byte[] cmpBytes = new byte[bytes.length / 2];
158 for (int j = 0; j < cmpBytes.length; ++j) {
159 high = (byte) ((bytes[i++] & PIECE_MASK) << PIECE_LENGTH);
160 low = (byte) (bytes[i++] & PIECE_MASK);
161 cmpBytes[j] = (byte) (high | low);
166 private EtudeUtils() {
167 throw new AssertionError(
168 "No org.hedgecode.chess.EtudeUtils instances!"
173 public static void main(String... args) {
175 hashPosition(Positions.INITIAL.getPosition())
178 Arrays.toString(blobPosition(Positions.INITIAL.getPosition()))