SebLague / Chess-Coding-Adventure

A work-in-progress chess bot written in C#
https://youtu.be/U4ogK0MIzqk
MIT License
1.45k stars 303 forks source link

Zobrist Key not updating properly #14

Open Eliagiac opened 1 year ago

Eliagiac commented 1 year ago

When performing a double pawn push, the board's Zobrist Key is not updated correctly. This can be verified by comparing the key after the move is made with the result of Zobrist.CalculateZobristKey().

This is because, on line 170 of Board.cs, the old en passant square is removed from the key only in case it wasn't zero. That means if the en passant square used to be null and is then updated, the old one will not be removed from the key.

Instead, when any part of the key changes, two operations always need to happen: key ^= oldValue and key ^= newValue. Note that this is necessary even when the en passant square is null because, as shown on line 14 of Zobrist.cs, the enPassantFile is always part of the key, even if it's 0.

A simple way to fix this would be to remove lines 148 and 171, and instead always update the key both at the beginning of the MakeMove function as well as at the end. This ensures that the currently stored value is always removed and then updated with whatever the new value is. The same is true for the UnmakeMove function, where currently the old value is only removed if it's not zero (when it should instead always be removed) and the new value is only added if it's not zero (when, again, it should always be added).

A possibly faster alternative would be to check if the two values match, and only if they don't update the key, but I doubt that would make any difference in performance.

This issue is most noticeable in the opening book, where most of the keys are incorrect. If this is fixed, the book will have to be regenerated.

SebLague commented 1 year ago

Thanks! I'll take a closer look when I have some to work on this game.