Declare a MakeMove trait and export it from chessfriend_moves. Declare a
BoardProvider trait that both Board and Position implement.
Implement the MakeMove trait for all types that implement BoardProvider, and move
all the move making code to the moves crate.
This change makes it possible to make moves directly on a Board, rather than
requiring a Position. The indirection of declaring and implementing the trait
in the moves crate is required because chessfriend_board is a dependency of
chessfriend_moves. So, it would be a layering violation for Board to implement
make_move() directly. The board crate cannot link the moves crate because that
would introduce a circular dependency.
The moves command writes all possible moves to the terminal.
Move the previous implementation of the moves command, which marked squares that
a piece could move to, to a 'movement' command.
Create a new MoveRecord struct that tracks the move (aka ply) and irreversible
board properties. This should make it easier to unmake moves in the future.
Implement a new method on Position that evaluates whether the active color can castle
on a given wing of the board. Then, implement making a castling move in the position.
Make a new Wing enum in the core crate to specify kingside or queenside. Replace the
Castle enum from the board crate with this one. This caused a lot of churn...
Along the way fix a bunch of tests.
Note: there's still no way to actually make a castling move in explorer.
Rework sight.rs and add a new module, movement.rs, to calculate piece sight and
movement. I discovered during this process that "sight" and "movement" are different
because pawns (in particular) can move in ways that don't follow their sight lines.
The routines in the movement module account for this, but also pass through to the
sight routines for other pieces.