Clearly you want something that is incremental even more than you would for smaller boards. So I suggest you still use zobrist, but instead of a table of random numbers you use a simple hash function to produce the individual key elements - assuming you are not willing to eat the memory which is what this thread is about.hgm wrote:Normally we construct a hash key by adding (or XORing) a number of Zobrist keys from a two-dimensional table key[coloredPieceType][square]. Now is the board gets large, and the number of piece types gets large too, this table would becoe intolarably large. For instance, in Taikyoku Shogi the board is 36x36 (1296 squares), and each side has 209 piece types (with somewhat less promoted types). That would make some 700,000 keys, which for a 64-bit key would require 5.6MB! That would not even fit the L2 or L3 cache! (OK, perhaps it can be compressed to 1 byte per key, by overlapping them, but that still nearly fills the L2 cache of the smaller CPUs....)
Do there exist less memory-hungry techniques for producing a hash key? E.g. if I would factorize the individual keys,
key[coloredPieceType][square] = key1[coloredPieceType]*key2[square]
so that I could do that multiplication during key update, would that result in any undesirable effects? I could not think of any obvious disadvantage, provided the key1 and key2 arrays are thoroughly random, with a range much larger than the number of pieces or squares (so that any pair of keys is extremely unlikely to have the same difference).
I'd much rather use a 10.4KB and a 4.8KB table, and do a multiplication in MakeMove, than having to access a 5.6MB table. Multiplications are pretty cheap, nowadays!
So zobrist_table[ colorType ] [ square ]
is replaced by the function zobFunc( colorTyp, square ) which is really a hash function on it's 2 arguments.
There are many fast hash functions that will work - an I don't think they have to be exceptional good hash functions - you just need to pick very fast ones that are good enough. You could have a table of constants, one for each square and multipy them to colorType to produce your key - I don't know how well that would work or whether the constants would have to be carefully picked or not - but for any given move application you would have to call this routine only a couple of times since it's still zobrist hashing at the outer level.
Don