2012-04-08 4 views
1

В настоящее время я добавляю таблицы транспозиций в свой шахматный движок, и у меня возникают проблемы с постепенным обновлением ключей Zobrist. I did some research и реализовали основную идею, но она не ведет себя так, как я ожидаю. Проблема, с которой я столкнулся, заключалась в том, что эквивалентные позиции плат не всегда имеют одинаковые ключи. Например, в исходном положении, если оба игрока просто переместили рыцаря, а затем вернули его, ключ будет отличаться от положения стартовой позиции. Однако, повторив это (перемещая рыцарей) и вернувшись в исходное положение , вы получите в исходном ключе. Таким образом, кажется, что период для такой последовательности составляет 4 хода для каждого игрока, когда он должен быть равен 2.Правильное внедрение Zobrist Hashing

Неужели кто-нибудь столкнулся с такой проблемой или может придумать решение? Я включил соответствующие части методов 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

Обычно make и unmake должны быть одинаковыми. (XOR является симметричным) Хэш не должен отражать ходы, а фигуры на доске. Захват фрагмента: = удаление его значения из хэша. Перемещение куска: = удаление предыдущей позиции из хеша + добавление новой позиции в хэш. (состояние рокинга и en-passant немного отличается) – wildplasser

+0

Да, я считаю, что это то, что делает мой код. Кроме того, необходимо учитывать остальную часть кода make/unmake, поэтому «квадраты» и «от» меняются; кусок, который был «из» в методе make, явно не существует в методе unmake. –

+0

Нет, код Make() должен содержать только два компонента: один для удаления фрагмента из старой позиции и один для добавления в новый posisiton. (и, возможно, дополнительный компонент для удаления захваченного фрагмента) – wildplasser

ответ

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

Рокировка можно рассматривать как сумму двух ходов (без захвата, очевидно)

Promotion можно рассматривать как удаление пешку с доски (из положения 2 или 7) и добавление новой детали (в позиции 1 или 8)