正确实施Zobrist Hashing

时间:2012-04-08 23:49:22

标签: hash chess

我目前正在我的国际象棋引擎中添加换位表,而且我在逐步更新Zobrist键方面遇到了问题。我did some research并实施了基本想法,但它没有像我期望的那样表现。我遇到的问题是等效的电路板位置并不总是具有相同的键。例如,在起始位置,如果两个玩家只是移动一个骑士然后将其移回,那么该钥匙将与起始位置的钥匙不同。但是,再次执行此操作(移动骑士)并返回到起始位置导致原始键。因此,对于每个玩家来说,这样的序列的周期似乎是4个动作,当它应该是2时。

有没有人遇到过这样的问题或者能想到解决方案?我已经包含了make / unmake方法的相关部分。我不包括边移动,铸造权等;他们不应该影响我提出的具体情况。 HashValue存储随机值,第一个索引是片段类型,第二个索引是正方形。

void Make(Move m) {
    ZobristKey ^= HashValue[Piece[m.From].Type][m.From];
    ZobristKey ^= HashValue[Piece[m.From].Type][m.To];
    ZobristKey ^= HashValue[Piece[m.To].Type][m.To];
    //rest of make move
}

void Unmake(Move m) {
    ZobristKey ^= HashValue[m.Captured.Type][m.To];
    ZobristKey ^= HashValue[Element[m.To].Type][m.To];
    ZobristKey ^= HashValue[Element[m.To].Type][m.From];
    //rest of unmake
}

1 个答案:

答案 0 :(得分:2)

Make_a_move() {
    hashval ^= Zobrist_array[oldpos][piece];
    hashval ^= Zobrist_array[newpos][piece];
    /* if there is a capture */
    hashval ^= Zobrist_array[otherpos][otherpiece];
    }

Undo_a_move() {
    hashval ^= Zobrist_array[oldpos][piece];
    hashval ^= Zobrist_array[newpos][piece];
    /* if there was a capture */
    hashval ^= Zobrist_array[otherpos][otherpiece];
    }

Castling可以看作是两次移动的总和(显然没有捕获)

促销可以被视为从棋盘上移除棋子(从2或7位置)并添加新棋子(在1或8位置)