Implement a move generator that emits moves for the king(s) of a particular color.
There will, of course, only ever be one king per side in any valid board, but
this iterator can (in theory) handle multiple kings on the board. This iterator
is almost entirely copypasta of the SliderMoveGenerator. The major difference is
castling.
Castle moves are emitted by a helper CastleIterator type. This struct collects
information about whether the given color can castle on each side of the board
and then emits moves for each side, if indicated.
Do some light refactoring of the castle-related methods on Board to accommodate
this move generator. Remove the dependency on internal state and rename the
"can_castle" method to color_can_castle.
In order to facilitate creating castling moves without relying on Board, remove
the origin and target squares from the encoded castling move. Code that makes
a castling move already looks up castling parameters to move the king and rook to
the right squares, so encoding those squares was redundant. This change
necessitated some updates to position.
Lastly, bring in a handful of unit tests courtesy of Claude. Apparently, it's my
new best coding friend. 🙃
This generator produces moves for slider pieces: bishops, rooks, and queens. All
of these pieces behave identically, though with different sets of rays that
emanate from the origin square. Claude helped me significantly with the
implementation and unit testing. All the unit tests that took advantage of Claude
for implementation are marked as such with an _ai_claude suffix to the test name.
One unique aspect of this move generator that Claude suggested to me was to use
loop { } instead of a recursive call to next() when the internal iterators expire.
I may try to port this to the other move generators in the future.
To support this move generator, implement a Slider enum in core that represents
one of the three slider pieces.
Add Board::bishops(), Board::rooks() and Board::queens() to return BitBoards of
those pieces. These are analogous to the pawns() and knights() methods that return
their corresponding pieces.
Also in the board create, replace the separate sight method implementations with
a macro. These are all the same, but with a different sight method called under
the hood.
Finally, derive Clone and Debug for the bit_scanner types.
New convention: active_color_ methods operate on the active color of the Board.
Methods without that prefix take a color parameter and operate on that.
Refactor opposing_sight to do this.
Add a new Sight trait, implemented by PlacedPiece. The implementation of this
trait produces a BitBoard representing the squares visible to the placed piece.