Skip to content

Commit

Permalink
build position hashes
Browse files Browse the repository at this point in the history
  • Loading branch information
niklasf authored and ornicar committed Jan 26, 2018
1 parent 176ac14 commit 2b997f3
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 12 deletions.
2 changes: 1 addition & 1 deletion modules/game/src/main/BinaryFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ object BinaryFormat {
import scala.collection.JavaConversions.mapAsScalaMap
def decode(plies: Int, unusedPieces: Option[PieceMap]) = monitor(lila.mon.game.pgn.huffman.decode) {
HuffmanEncoder.decode(bytes.value, plies) match {
case (pgn, pieces, _) => pgn.toVector -> mapAsScalaMap(pieces).toMap
case (pgn, pieces, _, _) => pgn.toVector -> mapAsScalaMap(pieces).toMap
}
}
def update(moves: PgnMoves) = HuffmanBinPgn {
Expand Down
2 changes: 1 addition & 1 deletion modules/game/src/main/java/compression/game/Board.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import java.util.ArrayList;

public final class Board {
final class Board {
long pawns;
long knights;
long bishops;
Expand Down
24 changes: 21 additions & 3 deletions modules/game/src/main/java/compression/game/Encoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import java.util.regex.Pattern;
import java.util.regex.Matcher;

import java.nio.ByteBuffer;

import org.lichess.compression.BitReader;
import org.lichess.compression.BitWriter;

Expand Down Expand Up @@ -89,14 +91,17 @@ public static byte[] encode(String pgnMoves[]) {
return writer.toArray();
}

public static scala.Tuple3<String[], Map<chess.Pos, chess.Piece>, Set<chess.Pos>> decode(byte input[], int plies) {
public static scala.Tuple4<String[], Map<chess.Pos, chess.Piece>, Set<chess.Pos>, byte[]> decode(byte input[], int plies) {
BitReader reader = new BitReader(input);

String output[] = new String[plies];

Board board = new Board();
ArrayList<Move> legals = new ArrayList<Move>(80);

ByteBuffer positionHashBuffer = ByteBuffer.allocate(3 * plies);
appendHash(positionHashBuffer, board.zobristHash());

for (int i = 0; i <= plies; i++) {
board.legalMoves(legals);

Expand All @@ -109,13 +114,20 @@ public static scala.Tuple3<String[], Map<chess.Pos, chess.Piece>, Set<chess.Pos>
Move move = legals.get(Huffman.read(reader));
output[i] = san(move, legals);
board.play(move);

if (move.isZeroing()) positionHashBuffer.clear();
appendHash(positionHashBuffer, board.zobristHash());
}
}

return new scala.Tuple3<String[], Map<chess.Pos, chess.Piece>, Set<chess.Pos>>(
byte positionHashes[] = new byte[positionHashBuffer.remaining()];
positionHashBuffer.get(positionHashes);

return new scala.Tuple4<String[], Map<chess.Pos, chess.Piece>, Set<chess.Pos>, byte[]>(
output,
chessPieceMap(board),
chessPosSet(board.castlingRights & board.rooks));
chessPosSet(board.castlingRights & board.rooks),
positionHashes);
}

private static String san(Move move, ArrayList<Move> legals) {
Expand Down Expand Up @@ -170,6 +182,12 @@ private static String san(Move move, ArrayList<Move> legals) {
return "--";
}

private static void appendHash(ByteBuffer buffer, long hash) {
buffer.put((byte) (hash & 0xff));
buffer.put((byte) ((hash >> 8) & 0xff));
buffer.put((byte) ((hash >> 16) & 0xff));
}

private static chess.Role chessRole(Role role) {
switch (role) {
case PAWN: return chess.Pawn$.MODULE$;
Expand Down
9 changes: 2 additions & 7 deletions modules/game/src/test/HuffmanPgnTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class HuffmanPgnTest extends Specification {
forall(fixtures) { pgn =>
val pgnMoves = pgn.split(" ")
val encoded = GameEncoder.encode(pgnMoves)
val (decoded, _, _) = GameEncoder.decode(encoded, pgnMoves.size)
val (decoded, _, _, _) = GameEncoder.decode(encoded, pgnMoves.size)
pgnMoves must_== decoded
}
}
Expand All @@ -22,15 +22,10 @@ class HuffmanPgnTest extends Specification {
import scala.collection.JavaConversions.asScalaSet
val pgnMoves = "d4 h5 c4 Rh6 Nf3 Rh8".split(" ")
val encoded = GameEncoder.encode(pgnMoves)
val (_, _, unmovedRooks) = GameEncoder.decode(encoded, pgnMoves.size)
val (_, _, unmovedRooks, _) = GameEncoder.decode(encoded, pgnMoves.size)
asScalaSet(unmovedRooks) must_== Set(Pos.A1, Pos.H1, Pos.A8)
}

"zobrist hashes" in {
val board = new Board()
board.zobristHash must_== 0x463b96181691fc9cL
}

"pass perft test" in {
// Running the entire suite can take minutes.

Expand Down

0 comments on commit 2b997f3

Please sign in to comment.