Module: PGN::Zobrist

Defined in:
lib/pgn/zobrist.rb

Overview

Zobrist hashing keys for incremental position hashing. All keys are fixed 64-bit pseudo-random Integers generated once at load time from a frozen seed so hashes are stable for the life of the process.

Indexing is by 0x88 square index (0..127); off-board indices are allocated but never read.

Constant Summary collapse

SEED =
0x1234_5678_9abc_def1
PIECES =
%w[P N B R Q K p n b r q k].freeze
TABLE =
PIECES.to_h { |piece| [piece, Array.new(128) { rand64 }] }.freeze
SIDE =
rand64
CASTLING =
{ 'K' => rand64, 'Q' => rand64, 'k' => rand64, 'q' => rand64 }.freeze
EP_FILE =
Array.new(8) { rand64 }.freeze

Class Method Summary collapse

Class Method Details

.seed(board, player, castling, en_passant) ⇒ Integer

Returns the Zobrist hash of the position.

Parameters:

  • board (PGN::Board)
  • player (Symbol)

    :white or :black

  • castling (Array<String>)

    e.g. %w[K Q k q]

  • en_passant (String, nil)

    e.g. "e3" or nil

Returns:

  • (Integer)

    the Zobrist hash of the position



38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/pgn/zobrist.rb', line 38

def self.seed(board, player, castling, en_passant)
  h = 0
  0.upto(7) do |rank|
    0.upto(7) do |file|
      idx = board.index_for(file, rank)
      piece = board.at_index(idx)
      h ^= TABLE[piece][idx] if piece
    end
  end
  h ^= SIDE if player == :black
  castling.to_a.each { |right| h ^= CASTLING[right] if CASTLING.key?(right) }
  h ^= EP_FILE[Board::FILE_TO_INDEX[en_passant[0]]] if en_passant && !en_passant.empty?
  h
end