Implement a bishop move generator using the "classical" approach.
This approach walks each ray to find blockers and then masks out friendly pieces.
This is not efficient compared to other approaches, but it's much easier to implement.
Implement a rook move generator using the "classical" approach.
This approach walks each ray to find blockers and then masks out friendly pieces.
This is not efficient compared to other approaches, but it's much easier to implement.
This bit scanner iterates populated bits in a BitBoard from the trailing (least-significant) end.
Rename BitScanner → LeadingBitScanner.
Factor implementation of these two into a macro.
Clean up iterator returned by BitBoard::occupied_squares
Implement BitBoard::occupied_squares_trailing
While implementing these move generators, I realized I was duplicating a lot of code. So, I started thinking about how to do less of that. I create a MoveGeneratorInternal trait that these move generators implement. This trait provides default implementations of several methods.
I also discovered that I needed a way to keep track of move sets per piece for each kind (shape) of piece. The new move generators, and the generators still to come, can now keep track of moves per piece separately in MoveSet instances.
- Clean up operator traits: remove the & versions and make the macro do more with less input
- Implement From<Square> for BitBoards: simplify conversion of Squares to BitBoards
- Take BitBoards by value in several places
- Clean up unit tests
Use the generated knight_moves BitBoards from bitboard::MoveLibrary to generate knight moves.
This commit doesn't yet implement computing bitboards for knight moves.
I was given some guidance[1] on the Rust developer forums that my approach of
implementing Iterator on these types wasn't quite right.
> In general, iterators are distinct data structures than the primary struct
that owns the data, in part due to issues like this, but also due to concerns
around iterator invalidation and the need to carry around iteration state more
generally.
I took this to heart and replace the Iterator implementations with an iter()
method that returns an `impl Iterator<Item=Move>`. This works so much better and
lets me delete a bunch of code!
Additionally, the iter() methods on the piece-wise move generator types return
`impl Iterator<Item=&Move>`, and then the top-level Moves::iter() returns a
.cloned().
Overall I'm really happy with this!
[1]: https://users.rust-lang.org/t/tricky-lifetime-may-not-live-long-enough-error-on-an-iterator-wrapping-a-boxed-iterator/104650/3
This struct computes and stores piece moves per square to speed up computation
of move lists.
Initialize a `static mut` instance once via std::sync::Once, and return a static
reference to it. So far, it computes king and knight moves.
Make BitBoard::empty() and MoveLibrary::new() const functions, enabling static
construction of the MOVE_LIBRARY instance without needing to wrap it in an
Option.
Generate moves for kings.
This struct is trying out a different approach to iterators where the type
itself isn't one, but it has an iter() method that returns an iterator over all
the move lists.
This struct also builds all the moves up front, in new() before the new instance
is returned.
Holy heck I went on a *journey* here. Ultimately, I needed to implement my own
index-based iterator instead of using the Vec's Iterator.
This type establishes some patterns I want to carry forward to other move
generators.
1. The use of a Parameters struct to fully parameterize the move generation
per-color. That lets these types only need a single color-based branch
2. A list of move lists, one list for each of captures, promotions, and quiet
moves.
3. An index-based move iterator.
4. Separate impl for generating bitboard representations of these moves
Additional changes:
- Implement BitBoard::from_square()
- Implement a Square::e5() for tests
This class doesn't implement en passant yet. It also doesn't yet have tests for
the bitboard stuff.
BitBoard::file returns a BitBoard representing the 0-indexed file.
fmt::Display prints a grid of bits in the standard orientation (white on bottom, left to right)
Add asserts to the rank and file constructors to catch out of bounds arguments.