Answers.Body: <p>Here's how I update the Zobrist hash in <a href="http://www.madchess.net/" rel="nofollow noreferrer">MadChess</a>, my chess engine.  MadChess uses "mailbox" board representation (uses an int[] to represent pieces on the board), not bitboards.</p>
  
  <p>The Board constructor:
  </p>
  
  <pre><code>// Create Zobrist position keys.
  _piecesSquaresInitialKey = ULongRandom.Next();
  _pieceSquareKeys = new ulong[13][];
  for (int piece = 0; piece &lt; 13; piece++)
  {
      _pieceSquareKeys[piece] = new ulong[64];
      for (int square = 0; square &lt; 64; square++)
      {
          _pieceSquareKeys[piece][square] = ULongRandom.Next();
      }
  }
  _sideToMoveKeys = new[] { ULongRandom.Next(), ULongRandom.Next() };
  _castlingKeys = new ulong[16];
  {
      for (int castlingRights = 0; castlingRights &lt; 16; castlingRights++)
      {
          _castlingKeys[castlingRights] = ULongRandom.Next();
      }
  }
  _enPassantKeys = new ulong[64];
  for (int square = 0; square &lt; 64; square++)
  {
      _enPassantKeys[square] = ULongRandom.Next();
  }
  </code></pre>
  
  <p>This is called every time a piece is added or removed from a square:
  </p>
  
  <pre><code>private void UpdatePiecesSquaresKey(int Piece, int Square)
  {
      ulong pieceSquareKey = _pieceSquareKeys[Piece][Square];
      // XOR square piece key.
      CurrentPosition.PiecesSquaresKey ^= pieceSquareKey;
      #if DEBUG
      // Verify incrementally updated pieces squares key matches fully updated pieces squares key.
      ulong fullyUpdatedPiecesSquaresKey = _piecesSquaresInitialKey;
      for (int square = 0; square &lt; 64; square++)
      {
          int piece = CurrentPosition.Squares[square];
          if (piece != Engine.Piece.None)
          {
              pieceSquareKey = _pieceSquareKeys[piece][square];
              fullyUpdatedPiecesSquaresKey ^= pieceSquareKey;
          }
      }
      Debug.Assert(fullyUpdatedPiecesSquaresKey == CurrentPosition.PiecesSquaresKey);
      #endif
  }
  </code></pre>
  
  <p>This combines all the board state keys to produce a position key:
  </p>
  
  <pre><code>private ulong GetPositionKey()
  {
      ulong sideToMoveKey = CurrentPosition.WhiteMove ? _sideToMoveKeys[0] : _sideToMoveKeys[1];
      ulong castlingKey = _castlingKeys[CurrentPosition.Castling];
      ulong enPassantKey = CurrentPosition.EnPassantSquare == Square.Illegal ? _enPassantKeys[0] : _enPassantKeys[CurrentPosition.EnPassantSquare];
      // XOR keys.
      return CurrentPosition.PiecesSquaresKey ^ sideToMoveKey ^ castlingKey ^ enPassantKey;
  }
  </code></pre>
  
  <p>This is called when all pieces are removed from the board (prior to setting up a new position from a FEN string):
  </p>
  
  <pre><code>private void Reset(bool PreserveMoveCount)
  {
      // Reset position index, position, key, and stats.
      _positionIndex = 0;
      CurrentPosition.Reset();
      CurrentPosition.PiecesSquaresKey = _piecesSquaresInitialKey;
      if (!PreserveMoveCount)
      {
          // Reset nodes.
          Nodes = 0L;
          NodesInfoUpdate = UciStream.NodesInfoInterval;
      }
  }
  </code></pre>
  
  <p>This generates a random unsigned long (64 bit integer):
  </p>
  
  <pre><code>public static class ULongRandom
  {
      private static readonly byte[] _buffer = new byte[sizeof(ulong)];
      private static readonly Random _random = new Random();
  
  
      public static ulong Next()
      {
          _random.NextBytes(_buffer);
          return BitConverter.ToUInt64(_buffer, 0);
      }
  }
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-12-04T03:49:55.190Z
Answers.LastActivityDate: 2017-12-04T06:18:24.757Z
Answers.LastEditDate: 2017-12-04T06:18:24.757Z
Answers.UserDisplayName: Erik Madsen
Answers.Body: <p>I believe you're talking about <strong>Zobrist Hashing</strong>.</p>
  
  <blockquote>
    <p>a technique to transform a board position of arbitrary size into a number of a set length, with an equal distribution over all possible numbers</p>
  </blockquote>
  
  <p><a href="https://chessprogramming.wikispaces.com/Zobrist+Hashing" rel="noreferrer">https://chessprogramming.wikispaces.com/Zobrist+Hashing</a></p>
  
  <p>Why Zobrist?</p>
  
  <ul>
  <li>Rather than computing the hash for the entire board every time, the hash value of a board can be updated simply by XORing out the bitstring(s) for positions that have changed. That makes the hashing algorithm very efficient for chess engines.</li>
  </ul>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-09-23T00:47:13.917Z
Answers.LastActivityDate: 2017-09-23T00:47:13.917Z
Answers.UserDisplayName: SmallChess
Body: <p>Is there a standardized method for generation of hash keys for chess positions. I want to implement hash key generation in my program, so wanted to know the best way to do it.
  It would be great if someone can provide details on how the opening books do their hashing (.bin?).</p>
  
  <p>Thanks!</p>
  
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-09-22T17:49:17.273Z
Comments.Text: In theory, *any* hash will work, even the built-in provided by the programming language.
Comments.UserDisplayName: Glorfindel
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-09-22T23:02:08.273Z
Comments.Text: Generating a hash has nothing to do with chess. It is a general programming issue which has built-in solutions in many programming languages.
Comments.UserDisplayName: Brian Towers
Tags: <engines><programming>
Title: How to generate hash keys for chess positions
ThreadText: # How to generate hash keys for chess positions
  
  (Asked by: username_0 on 2017-09-22)
  
  Is there a standardized method for generation of hash keys for chess positions. I want to implement hash key generation in my program, so wanted to know the best way to do it.
  It would be great if someone can provide details on how the opening books do their hashing (.bin?).
  
  Thanks!
  
  **Tags:** engines, programming
  
  > **Comments:**
  > **username_1**: In theory, *any* hash will work, even the built-in provided by the programming language.  
  > **username_2**: Generating a hash has nothing to do with chess. It is a general programming issue which has built-in solutions in many programming languages.  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_4 on 2017-09-23. Score: 5 | Accepted answer
  
  I believe you're talking about **Zobrist Hashing**.
  
  > a technique to transform a board position of arbitrary size into a number of a set length, with an equal distribution over all possible numbers
  
  <https://chessprogramming.wikispaces.com/Zobrist+Hashing>
  
  Why Zobrist?
  
  * Rather than computing the hash for the entire board every time, the hash value of a board can be updated simply by XORing out the bitstring(s) for positions that have changed. That makes the hashing algorithm very efficient for chess engines.
  
  
  ---
  
  ### Answer by username_3 on 2017-12-04. Score: 2
  
  Here's how I update the Zobrist hash in MadChess, my chess engine.  MadChess uses "mailbox" board representation (uses an int[] to represent pieces on the board), not bitboards.
  The Board constructor:
  
  // Create Zobrist position keys.
  _piecesSquaresInitialKey = ULongRandom.Next();
  _pieceSquareKeys = new ulong[13][];
  for (int piece = 0; piece < 13; piece++)
  {
      _pieceSquareKeys[piece] = new ulong[64];
      for (int square = 0; square < 64; square++)
      {
          _pieceSquareKeys[piece][square] = ULongRandom.Next();
      }
  }
  _sideToMoveKeys = new[] { ULongRandom.Next(), ULongRandom.Next() };
  _castlingKeys = new ulong[16];
  {
      for (int castlingRights = 0; castlingRights < 16; castlingRights++)
      {
          _castlingKeys[castlingRights] = ULongRandom.Next();
      }
  }
  _enPassantKeys = new ulong[64];
  for (int square = 0; square < 64; square++)
  {
      _enPassantKeys[square] = ULongRandom.Next();
  }
  
  This is called every time a piece is added or removed from a square:
  
  private void UpdatePiecesSquaresKey(int Piece, int Square)
  {
      ulong pieceSquareKey = _pieceSquareKeys[Piece][Square];
      // XOR square piece key.
      CurrentPosition.PiecesSquaresKey ^= pieceSquareKey;
      #if DEBUG
      // Verify incrementally updated pieces squares key matches fully updated pieces squares key.
      ulong fullyUpdatedPiecesSquaresKey = _piecesSquaresInitialKey;
      for (int square = 0; square < 64; square++)
      {
          int piece = CurrentPosition.Squares[square];
          if (piece != Engine.Piece.None)
          {
              pieceSquareKey = _pieceSquareKeys[piece][square];
              fullyUpdatedPiecesSquaresKey ^= pieceSquareKey;
          }
      }
      Debug.Assert(fullyUpdatedPiecesSquaresKey == CurrentPosition.PiecesSquaresKey);
      #endif
  }
  
  This combines all the board state keys to produce a position key:
  
  private ulong GetPositionKey()
  {
      ulong sideToMoveKey = CurrentPosition.WhiteMove ? _sideToMoveKeys[0] : _sideToMoveKeys[1];
      ulong castlingKey = _castlingKeys[CurrentPosition.Castling];
      ulong enPassantKey = CurrentPosition.EnPassantSquare == Square.Illegal ? _enPassantKeys[0] : _enPassantKeys[CurrentPosition.EnPassantSquare];
      // XOR keys.
      return CurrentPosition.PiecesSquaresKey ^ sideToMoveKey ^ castlingKey ^ enPassantKey;
  }
  
  This is called when all pieces are removed from the board (prior to setting up a new position from a FEN string):
  
  private void Reset(bool PreserveMoveCount)
  {
      // Reset position index, position, key, and stats.
      _positionIndex = 0;
      CurrentPosition.Reset();
      CurrentPosition.PiecesSquaresKey = _piecesSquaresInitialKey;
      if (!PreserveMoveCount)
      {
          // Reset nodes.
          Nodes = 0L;
          NodesInfoUpdate = UciStream.NodesInfoInterval;
      }
  }
  
  This generates a random unsigned long (64 bit integer):
  
  public static class ULongRandom
  {
      private static readonly byte[] _buffer = new byte[sizeof(ulong)];
      private static readonly Random _random = new Random();
  
  
      public static ulong Next()
      {
          _random.NextBytes(_buffer);
          return BitConverter.ToUInt64(_buffer, 0);
      }
  }
  
  
  ---
  
  