В настоящее время я добавляю таблицы транспозиций в свой шахматный движок, и у меня возникают проблемы с постепенным обновлением ключей 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
}
Обычно make и unmake должны быть одинаковыми. (XOR является симметричным) Хэш не должен отражать ходы, а фигуры на доске. Захват фрагмента: = удаление его значения из хэша. Перемещение куска: = удаление предыдущей позиции из хеша + добавление новой позиции в хэш. (состояние рокинга и en-passant немного отличается) – wildplasser
Да, я считаю, что это то, что делает мой код. Кроме того, необходимо учитывать остальную часть кода make/unmake, поэтому «квадраты» и «от» меняются; кусок, который был «из» в методе make, явно не существует в методе unmake. –
Нет, код Make() должен содержать только два компонента: один для удаления фрагмента из старой позиции и один для добавления в новый posisiton. (и, возможно, дополнительный компонент для удаления захваченного фрагмента) – wildplasser