Commit graph

96 commits

Author SHA1 Message Date
942d9fe47b [explorer, moves, position] Implement a moves command in explorer
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.
2025-05-28 16:25:55 -07:00
43abbe3fe2 [position] Register a captured piece in the MoveRecord
For unmake_move, so the captured piece can be restored.
2025-05-28 16:23:46 -07:00
19c6c6701a [position] Fix broken tests build
The make_move tests were trying to access the last capture piece directly from a
slice of captures pieces (implementation prior to CapturesList). Implement
CapturesList::last() to return an Option<&Piece> and use it in the tests.
2025-05-27 12:04:24 -07:00
085697d38f [position] Remove position::position module
Move the implementation of Position to the top-level position.rs file.
2025-05-27 11:59:42 -07:00
db489af50b [position] Move unmake move stuff to an unmake_move module 2025-05-27 11:52:17 -07:00
a8ea248972 [position] Derive Default implementation for Position 2025-05-27 11:51:08 -07:00
e3ca466737 [position] Move capture list to a CapturesList struct
This one has a custom Display implementation for easier integration with Positon's.
2025-05-27 11:51:08 -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
5466693c1b [position] Remove empty implementation of Position::unmake_move 2025-05-23 18:39:38 -07:00
588f049290 [position] Remove display module 2025-05-23 14:15:38 -07:00
a9268ad194 [position] Add move tracking to Position
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.
2025-05-23 10:00:20 -07:00
05c62dcd99 [position] Remove CastleEvaluationError from this crate
It moved to board.
2025-05-23 09:58:29 -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
609cda0fe5 [position] Remove castle module (it went to board) 2025-05-23 09:50:57 -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
9a4fa827f9 [position] Add two new negative tests for making pawn moves
- Ensure you cannot move a pawn to the last rank without a promotion move.
- Ensure a pawn cannot make an illegal move, and that the board state remains
  as it was before the move was attempted.
2025-05-21 09:51:16 -07:00
85c1a395c4 [position] Streamline the implementation of castling_{king,rook}
Instead of using .and_then with an if/else, use .filter and pass the predicate.
Saves a few lines.
2025-05-21 08:26:34 -07:00
feaa81bbd8 [position, moves] Implement some castling tests
Add white castling for both wings. Found some bugs in how king sight is computed
while writing these.

In order for the king to perform the castle, the Movement bitboard needs to return
the two squares the king can castle to. That means anytime movement is calculated
for the king, the (relatively expensive) castling evaluation needs to happen.

Write two new helper static functions to create a Move for castling and promotion
moves. Since structs cannot have any functions with the same name, the two methods
that return properties related to those moves (Move::castle and Move::promotion)
need to be renamed. They're now called Move::castle_wing and Move::promotion_shape.
2025-05-21 08:25:49 -07:00
7c9c5484ba [position, board] Remove a bunch of dead code 2025-05-20 19:29:39 -07:00
039fd2b080 [position, board, core, moves] Implement a bunch of make_move code
Implement making double push and promotion moves. Then write several tests to
exercise these. Add convenient static functions to the Move struct to build moves
quickly, without using the Builder.

Add a is_promotable_rank() method to Rank to check that a rank can be used for
promotion moves.

The tests found and fixed a bug in pawn movement where the en passant square was
being discarded when deciding whether an e.p. move can be made.
2025-05-20 19:29:02 -07:00
6591619e32 [position] Misc changes
- Add a captures list to the Position struct
- Implement ToFenStr
- Update the imports list, which has been sorely out-of-date in the tree for many commits now.
2025-05-19 17:00:48 -07:00
97552302cb [position] Move castle evaluation code to its own submodule of position
Move the tests too.
2025-05-19 16:59:13 -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
a78526befa [position] Move make_move to its own module: position::make_move
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.
2025-05-18 08:12:10 -07:00
669a7c00ec [position] Add thiserror dependency 2025-05-18 08:07:12 -07:00
f1431ea4e9 [position] Move postion/mod.rs -> position.rs 2025-05-08 17:54:49 -07:00
424d348b2d WIP 2025-05-08 17:37:59 -07:00
091cc99cb3 WIP 2025-05-08 17:37:51 -07:00
90657e3818 [position] Rewrite sight methods in terms of Board and pass BitBoard arguments by value 2024-07-13 12:08:20 -07:00
f96fa79dc1 [position] Remove fen.rs 2024-07-13 08:14:33 -07:00
1f3c90ff35 [position] Print the chess board diagram with box drawing characters 2024-03-25 10:38:02 -07:00
21b58a6422 [position] Update the danger_squares unit test to use assert_eq_bitboards!() 2024-03-14 17:01:28 -07:00
27a36565f3 [bitboard,core,position] Address a bunch of clippy warnings 2024-03-14 17:00:46 -07:00
d0abbd8f93 [position] Rever the const-ness of Position's initializers
Apparently you can't actually do that. :( You can't call trait methods in const
contexts.
2024-03-10 09:18:08 -07:00
a65c0c8ef1 [position] Make the Position initializer methods const
Position::empty() and Position::starting can both be const. Neat!
2024-03-08 08:18:49 -08:00
20182d4035 [position] Implement an assert_eq_bitboards! macro
This one helps with printing BitBoards if the assertion fails.
2024-03-08 08:08:52 -08:00
069f94e8c2 [position] Refactor sight routines
- Break out the actual routines into file-private helper functions
- Declare traits for each piece type that call the corresponding helper function
- Implement these traits on PlacedPiece

The sight routines changed slightly such that they include the player's own pieces
in the resulting BitBoard. The tests neeeded to be updated to account for this.
2024-03-08 08:04:21 -08:00
f0b9681cef [position] Add a doc comment to PieceBitBoards::all_pieces; remove unused empty_squares 2024-03-01 15:26:01 -08:00
8a1b16d553 Export the fen! macro 2024-02-25 14:51:32 -08:00
8f07e08500 Fix a couple of the obscure en passant cases from PEJ 2024-02-25 14:51:25 -08:00
673d57c02e Remove some unused imports from position::check 2024-02-25 14:12:51 -08:00
5f1fce6cc2 Fix the remaining tests
Well… all the tests except the Peter Ellis Jones tests.

Pass around whole EnPassant types instead of pulling out just the e.p. square.
Make sure that Castling moves have their target and origin squares populated.
Add a color field to the Castle move style to make this possible.
2024-02-25 12:38:55 -08:00
d2fe546824 Remove some unused variables from tests in the king move generator 2024-02-25 10:52:10 -08:00
2a6b098cb8 Fix the pawn unit tests 2024-02-25 10:51:27 -08:00
63c03fb879 Delete the position::r#move module 2024-02-25 09:54:03 -08:00
d668091d0d Replace uses of types in r#move with types from the moves package types 2024-02-25 09:52:40 -08:00
aaad991899 Replace crate::r#move::castle::Castle with moves::Castle 2024-02-25 09:46:59 -08:00
36db46ac18 Move position::tests → testing
Expand information printed in assert_move_list
2024-02-25 09:20:45 -08:00
f23967f4f3 Rename MoveGenerator::bitboard → _test_bitboard
This method is only used by tests. Mark it with cfg(test) and prefix it with _test
to indicate that fact.
2024-02-11 10:29:09 -07:00