2012-04-08 7 views
1

J'ajoute actuellement des tables de transposition dans mon moteur d'échecs, et je rencontre des problèmes avec la mise à jour incrémentale des touches Zobrist. J'ai did some research et mis en œuvre l'idée de base, mais il ne se comporte pas comme je l'espère. Le problème que j'ai rencontré était que les positions équivalentes de la carte n'ont pas toujours les mêmes clés. Par exemple, dans la position de départ, si les deux joueurs ont simplement déplacé un chevalier puis l'ont déplacé, la clé sera différente de celle de la position de départ. Cependant, faire cela à nouveau (déplacer les chevaliers) et revenir à la position de départ donnerait résultat dans la clé d'origine. Il semble donc que la période pour une telle séquence est de 4 coups pour chaque joueur, alors qu'elle devrait juste être de 2.Mise en œuvre correcte du hachage Zobrist

Quelqu'un a-t-il rencontré un tel problème ou peut-il penser à une solution? J'ai inclus les parties pertinentes de mes méthodes make/unmake. Je ne comprends pas les droits de déplacement latéral, les droits de châteaux, etc. ils ne devraient pas affecter le cas particulier que j'ai soulevé. HashValue stocke les valeurs aléatoires, le premier index étant le type de pièce et le second étant le carré.

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

Normalement, make et unmake doivent être identiques. (XOR est symétrique) Le hachage ne doit pas refléter les mouvements, mais les morceaux sur le plateau. Capture d'une pièce: = enlever sa valeur du hachage. Déplacer une pièce: = enlever la position précédente du hachage + ajouter la nouvelle position au hachage. (roque et en-passant sont un peu différent) – wildplasser

+0

Oui, je crois que c'est ce que fait mon code. Il y a aussi le reste du code make/unmake qui doit être pris en compte, c'est pourquoi les carrés "to" et "from" changent; la pièce qui était à "from" dans la méthode make n'est clairement plus là dans la méthode unmake. –

+0

Non, le code Make() ne devrait avoir que deux composants: un pour enlever la pièce de l'ancienne position, et un pour l'ajouter à la nouvelle position. (et éventuellement un composant supplémentaire pour retirer une pièce capturée) – wildplasser

Répondre

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]; 
    } 

Roque peut être considérée comme la somme de deux mouvements (sans capture, évidemment)

promotion peut être considérée comme la suppression d'un pion de la carte (à partir de la position 2 ou 7) et ajouter la nouvelle pièce (à la position 1 ou 8)