正确实施Zobrist Hashing [英] Correctly Implementing Zobrist Hashing

查看:511
本文介绍了正确实施Zobrist Hashing的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前在我的国际象棋引擎中添加转置表,并且我在增量更新Zobrist键时遇到了问题。我做了一些研究并实施了这个基本想法,但它并没有像我期望的那样行事。我遇到的问题是相同的电路板位置并不总是具有相同的键。例如,在起始位置,如果两名球员刚刚移动一名骑士然后将其移回,则键将与起始位置不同。但是,再次执行此操作(移动骑士)并返回到起始位置会导致原始密钥。因此,对于每个玩家来说,这样的顺序似乎是4次移动,当它应该是2时。

有没有人遇到过这样的问题,或者可以想出解决方案?我已经包含了我的make / unmake方法的相关部分。我不包括一边移动,castling权利等;他们不应该影响我提出的具体情况。 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];
//制作移动的其余部分
}

void Unmake(Move m){
ZobristKey ^ = HashValue [m.Captured.Type] [m.To] ;
ZobristKey ^ = HashValue [元素[m.To] .Type] [m.To];
ZobristKey ^ = HashValue [Element [m.To] .Type] [m.From];
//其余的取消制作
}


解决方案

  Make_a_move(){
hashval ^ = Zobrist_array [oldpos] [piece];
hashval ^ = Zobrist_array [newpos] [piece];
/ *如果有捕获* /
hashval ^ = Zobrist_array [otherpos] [otherpiece];
}

Undo_a_move(){
hashval ^ = Zobrist_array [oldpos] [piece];
hashval ^ = Zobrist_array [newpos] [piece];
/ *如果有捕获* /
hashval ^ = Zobrist_array [otherpos] [otherpiece];
}

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



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


I'm currently adding transposition tables in my chess engine, and I'm having issues with incrementally updating Zobrist keys. I did some research and implemented the basic idea, but it's not behaving as I expect. The problem I encountered was that equivalent board positions do not always have the same keys. For example, in the starting position, if both players just moved a knight and then moved it back, the key would be different from that of the starting position. However, doing this again (moving the knights) and returning to the starting position would result in the original key. So it seems that the period for such sequence is 4 moves for each player, when it should just be 2.

Has anyone encountered such a problem or can think of solution? I've included the relevant portions of my make/unmake methods. I don't include side-to-move, castling rights, etc; they shouldn't affect the particular case I brought up. HashValue stores the random values, with the first index being the piece type and second being the square.

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
}

解决方案

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 can be seen as the sum of two moves (without capture, obviously)

Promotion can be treated as removing a pawn from the board (from the 2 or 7 position) and adding the new piece (at the 1 or 8 position)

这篇关于正确实施Zobrist Hashing的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆