Commit graph

261 commits

Author SHA1 Message Date
eaab34587c [board, explorer, moves] Make Board::active_color private
Make the struct attribute private, and export two new methods. A getter, active_color(),
and a setter, set_active_color().

Update all references to the attribute to use the methods.
2025-06-02 17:29:52 -07:00
cae93cb090 [board, position] Return replaced piece when placing a piece with PlacePieceStrategy::Replace
When place_piece() is called with PlacePieceStrategy::Replace, return the replaced
piece in the Ok() variant of the Result as an Option<Piece>.

Plumb this new return type through Board and Position.
2025-06-02 15:54:00 -07:00
09fbe1be22 [board] Make Board::pieces private
Do not allow direct access to the internal piece set. Update call sites to use
Board API instead.
2025-06-02 15:46:10 -07:00
f47654cc98 [board] Trying out a new naming convention in the check methods
I've been bothered by certain instances where the color has already been unwrapped
from an Option<Color> but a subsequent call takes an Option, so you have to rewrap
it to call the method. I might be overthinking this…

For the Board::*_color_is_in_check set of methods, try out this naming convention:

active_color_is_in_check()
: Operates directly on the Board's active color, no unwrapping required
color_is_in_check()
: Takes an Option<Color> and unwraps it with the active color if None is given
unwrapped_color_is_in_check()
: Takes a Color and operates on it. This method is called by the two above, but
is also public.
2025-06-01 19:07:58 -07:00
724a98c2e2 [board] Implement iter() on board
This iterator yields (Square, Piece) tuples for all pieces on the board.
2025-06-01 17:28:47 -07:00
40e8e055f9 [board, moves, position] Move make_move routines to moves crate
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.
2025-05-31 19:04:21 -07:00
c3a43fd2ed [board, moves] Update some comments and docs 2025-05-31 15:14:24 -07:00
086f9c5666 [board] Replace PieceSet's derived Hash and PartialEq with bespoke implementation
The piece set duplicates some data to make lookups more efficient. Only use the
necessary, unique data for these functions.
2025-05-31 15:07:20 -07:00
eb6f2000a9 [board, moves, position] Implement KingMoveGenerator
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. 🙃
2025-05-26 23:37:33 -07:00
f005d94fc2 [bitboard, board, core, moves] Implement SliderMoveGenerator
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.
2025-05-26 17:41:43 -07:00
faca844733 [moves] Knight move generator and tests 2025-05-25 11:05:10 -07:00
ab587f379f [board] Fix a bug in PieceSet::opposing_occupancy
This method should compute occupancy of everything except the provided color. Instead
it was computing the inverse.
2025-05-24 17:54:46 -07:00
1da08df430 [board] Implement a couple handy piece getters
Board::find_pieces returns a BitBoard for all the pieces matching the given Piece.

Board::enemies returns a BitBoard of all the enemy pieces of a given Color.

Board::pawns returns a BitBoard of all the pawns of a given Color.
2025-05-23 18:39:18 -07:00
994f17091b [board] Implement Board::unwrap_color
Unwrap an Option<Color> using the board's active color in the default case.
2025-05-23 18:37:13 -07:00
3684e9b425 [board, core, bitboard] Clean up casts between Rank, File and BitBoard
Let BitBoard::rank and BitBoard::file take a Rank and File directly, instead of a
u8 by reference. And then make the Rank/File::as_index const and return a value
rather than a reference.

All this allows you to convert between Rank, File, and BitBoard at compile tile
(i.e. as a const method) rather than needing to do runtime stuff.
2025-05-23 18:32:18 -07:00
5c5d9d5018 [board] Remove some dead code from Board 2025-05-23 14:14:49 -07:00
b8a51990a3 [board, position] Implement some methods to check for whether a king is in check
Remove some dead code from Position.
2025-05-23 09:57:48 -07:00
0abe9b6c19 [board, position] Add a color argument to opposing_sight
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.
2025-05-23 09:56:47 -07:00
a92ec9aba3 [board] Add an option to display a board with ASCII characters 2025-05-23 09:53:59 -07:00
ddd14e8999 [board] Define two new types for the Clock properties of Board
Helpful for other parts of the code.
2025-05-23 09:53:29 -07:00
d5c0330fbe [board] Add PieceSet::find_pieces
Takes a Piece and returns a BitBoard representing where pieces of that shape and
color are on the board.
2025-05-23 09:52:22 -07:00
e89bca9877 [board] Remove empty errors module 2025-05-21 10:09:55 -07:00
dbca7b4f88 [position, board] Move castle, movement, and sight modules to the board crate
Nothing about this code depends on Position, so push it down to a lower layer.
2025-05-21 10:08:59 -07:00
7c9c5484ba [position, board] Remove a bunch of dead code 2025-05-20 19:29:39 -07:00
54ac88aaf7 [board] Remove some old PlacedPiece code 2025-05-19 16:50:44 -07:00
0c1863acb9 [board, core, moves, position] Implement castling
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.
2025-05-19 16:50:30 -07:00
6e0e33b5f9 [board] Remove the FromIterator<PlacedPiece> impl for PieceSet 2025-05-19 08:37:04 -07:00
67448b44d7 [board] Clean up variables names in piece_sets.rs so creating an error is a little more succinct 2025-05-19 08:36:44 -07:00
c7be0e3e2b [board] Remove the PlacedPiece import from fen.rs 2025-05-19 08:35:56 -07:00
b229049e27 [board, core] Update error types to use thiserror::Error 2025-05-19 08:34:32 -07:00
5553bab659 [board] Teach DiagramFormatter how to highlight and mark squares
Add two BitBoard attributes to the struct that mark squares that should be marked
or highlighted.

Empty marked squares are shown with an asterisk (*). Marked squares with a piece
don't have any change of appearance. (Something I'm still thinking about.)

Highlighted squares are shown with the ANSI escape sequence for Reverse Video.
2025-05-16 07:49:09 -07:00
3b5b2f16a3 [board] Add occupancy methods that return BitBoards 2025-05-16 07:47:28 -07:00
424d348b2d WIP 2025-05-08 17:37:59 -07:00
091cc99cb3 WIP 2025-05-08 17:37:51 -07:00
867deafd13 [board] A ton of API refinements 2025-05-03 16:02:56 -07:00
99dd2d1be2 [board] Remove the Builder 2025-05-03 15:48:06 -07:00
b0c4039920 [board] Remove Board::new() 2025-05-02 15:42:06 -07:00
bb8d5a6aa3 [board] Replace Flags with castle::Rights 2025-05-02 15:41:45 -07:00
cd60a453aa [board] Replace active player and move properties on Board with MoveCounter instance 2025-05-02 15:18:37 -07:00
58cbe07136 [board] Implement PieceSet::mailbox() method to return a reference to its Mailbox 2025-05-02 15:05:39 -07:00
bf535f876a [board] Update call to BitBoard::occupied_squares to take an IterationDirection 2025-05-02 15:05:05 -07:00
0b100d5f14 [board] Remove Flags struct, replace it with Castle and supporting structs
Encapsulate castling rights within a small module. Castle provides the API to the
rest of the board package. Rights encodes the castling rights for each player.
Parameters defines castling parameters for each player.
2025-05-02 15:03:48 -07:00
9f2bfc0457 [board] Replace the length of the Builder::kings array with Color::NUM instead of constant 2 2025-05-02 14:49:16 -07:00
46b19ff616 [board] Implement Mailbox::from_iter as a reduce (aka fold) over the incoming iterator 2025-05-02 14:48:37 -07:00
72fd938238 [board] Implement Copy for Mailbox struct 2025-05-02 14:48:01 -07:00
c733342fca [board] Add MoveCounter struct to track current color, half move counter, and full move counter 2025-05-02 14:42:31 -07:00
30188d478e [board] Convert &BitBoard to BitBoard for several Board methods
I don't think passing by reference buys much for BitBoard. So simplify the
logic and borrowing semantics to make these easier to work with.
2024-07-13 12:03:19 -07:00
7ec72035ae [board] Remove en passant test helper method 2024-07-13 12:01:01 -07:00
d221de700d [board] Copy edit and add new documentation to Board 2024-07-13 12:00:02 -07:00
c297e4cbfa [board] Replace implementation of Board::piece_on_square with a simpler one
Now that board has a Mailbox, the implementation of this routine can be greatly
simplified. Instead of needing to iterate through all BitBoards to find the
occupied square, just consult the mailbox.
2024-07-13 11:57:57 -07:00