Commit graph

48 commits

Author SHA1 Message Date
146e4d34d3 [core] Fix an incorrect assertion in the Score doc test
Negate with - instead of with !.
2025-07-12 20:27:47 -07:00
b505606925 [core] Export Score::CENTIPAWNS_PER_POINT to the crate
This constant is a conversion factor of points to the internal fixed point unit
of centipawns. Points are more familiar to people because pawns are worth 1 pt.

Calculate the scores of the various piece shapes with this constant.
2025-07-12 20:27:47 -07:00
b3ff8dec49 [core] Make Shape::is_promotable() const 2025-07-12 20:27:47 -07:00
1ae6d5df48 [core, position] Rename the type of Score's inner value → Value 2025-06-24 20:01:05 -07:00
4e80cc36ca [core] Implement Display for Score 2025-06-24 15:20:31 -07:00
80ac8ea036 [core] Import std::fmt and remove std:: from Display symbol spelling 2025-06-24 15:18:49 -07:00
abaf277fb4 [core] Use the matches! macro to calculate the value of Shape::is_promotable
I learned about this macro a little while ago and it's better than writing out
a match block by hand, and also doesn't require static or const data, like the
previous implementation did.
2025-06-20 14:25:10 -07:00
7f25548335 [board, core, position] A simple static evaluation method for scoring positions
Implement a new Evaluator struct that evaluates a Board and returns a score. This
evaluation mechanism uses only a material balance function. It doesn't account
for anything else.

Supporting this, add a Counts struct to the internal piece set structure of a
Board. This struct is responsible for keeping counts of how many pieces of each
shape are on the board for each color. Export a count_piece() method on Board
that returns a count of the number of pieces of a particular color and shape.

Implement a newtype wrapper around i32 called Score that represents the score of
a position in centipawns, i.e. hundredths of a pawn. Add piece values to the
Shape enum.
2025-06-20 14:23:57 -07:00
481ae70698 [core] Directly index the array of Squares with a given index
In Square::from_index_unchecked, instead of using TryFrom to convert the index
to a square, just index directly into the Square::ALL array. This function is
already marked unsafe.
2025-06-19 14:32:07 -07:00
f0b6cb5f08 [core] Do a little cleanup in core::coordinates
Import std::fmt and remove some commented out code.
2025-06-16 08:58:22 -07:00
3951af76cb [core, moves, position] Implement parsing long algebraic moves
UCI uses a move format it calls "long algebraic". They look like either "e2e4"
for a regular move, or "h7h8q" for a promotion. Implement parsing these move
strings as a two step process. First define an AlgebraicMoveComponents struct
in the moves crate that implements FromStr. This struct reads out an origin
square, a target square, and an optional promotion shape from a string. Then,
implement a pair of methods on Position that take the move components struct
and return a fully encoded Move struct with them.

This process is required because the algebraic string is not enough by itself to
know what kind of move was made. The current position is required to understand
that.

Implement Shape::is_promotable().

Add a NULL move to the Move struct. I'm not sure what this is used for yet, but
the UCI spec specifically calls out a string that encodes a null move, so I added
it. It may end up being unused!

Do a little bit of cleanup in the core crate as well. Use deeper imports (import
std::fmt instead of requring the fully qualified type path) and remove some
unnecessary From implementations.

This commit is also the first instance (I think) of defining an errors module
in lib.rs for the core crate that holds the various error types the crate exports.
2025-06-16 08:57:48 -07:00
659ffb6130 [core] Remove an unused import 2025-06-08 17:34:52 -07:00
ae0ae49093 [core] Remove PlacedPiece
This has been deprecated for a while now. Finally remove it!
2025-06-08 17:18:41 -07:00
e2ce778247 [core, moves] Improve bounds checking of Square::neighbor
Remove the <n> argument from this method. I think it was a bad idea to begin with
but at the time I was looking for an expedient solution for getting neighbor
squares 2 squares away.

Overhaul bounds checking in this method so horizontal (west and east) bounds are
checked in addition to vertical (north and south) bounds. For the diagonal
directions in particular, it was easy to generate some bogus neighbor squares
because this method didn't check for wrapping when calculating horizontal
neighbors.
2025-06-07 20:06:14 -07:00
6d0df32f74 [core] Random Number Generator
Implement a random number generator as a thin wrapper around rand::StdRng. Provide
some default seed data to get consistent random numbers.
2025-06-02 15:44:38 -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
af2bff348f [core] Add an Option<i8> argument to Square::neighbor
This argument allows computing the neighbor n squares away along the direction.
Technically, squares n>1 are not neighbors… but this is a convenient calculation.
2025-05-23 18:34:19 -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
a92ec9aba3 [board] Add an option to display a board with ASCII characters 2025-05-23 09:53:59 -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
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
9010f1e9c2 [explorer, moves, core] Improve error handling in explorer
Implement thiserror::Error for a bunch of error types, and remove string errors
from the implementation of the command handler in explorer.

Clean up parsing of basic types all over the place.

Update Cargo files to include thiserror and anyhow.
2025-05-19 14:18:31 -07:00
cd3efa61c9 [core] Fix the coordinate tests
Use symbols instead of magic numbers.
2025-05-19 08:35:35 -07:00
b229049e27 [board, core] Update error types to use thiserror::Error 2025-05-19 08:34:32 -07:00
091cc99cb3 WIP 2025-05-08 17:37:51 -07:00
ee51a13870 Rename Square::from_index → from_index_unchecked 2024-07-13 08:10:21 -07:00
7c65232c35 [core] Improve API of Shape and Color
Clean up type and method declarations by using better type spelling. Use more
standard method spelling for iterators. Implement some useful traits.
2024-07-13 07:34:50 -07:00
534c022981 [core] Add #[must_use] to several methods in coordinates 2024-07-13 07:21:21 -07:00
a2d0c638d0 [core] Address clippy suggestions; clean up unit tests
In coordinates.rs:

- Add some [must_use] decorators to some getters
- Rewrite some unit tests to remove the .expect() and use ? instead
2024-04-25 08:05:07 -07:00
1b63f56042 [bitboard, core] Make library getters const; parameterize Library attributes
- Add chessfriend_core::Color::NUM
- All the library getters can be const.
- Use the constants from the core library to define the length of the slices in
  the Library struct.
2024-04-25 07:59:39 -07:00
27a36565f3 [bitboard,core,position] Address a bunch of clippy warnings 2024-03-14 17:00:46 -07:00
89802be53d [core] Address some clippy linter errors in core/coordinate.rs 2024-03-10 09:16:21 -07:00
82aa7a2b01 [core] Rewrite Direction as a coordinate_enum!
- Order the values of Direction in a clockwise fashion
- Implement Direction::opposite() to return the opposing direction
- Make some small changes to the macros in this file to improve readability, maybe.
2024-03-08 08:17:54 -08:00
d20119dfe3 [position] Make Shape::to_ascii() const 2024-03-01 15:24:43 -08:00
2a6b098cb8 Fix the pawn unit tests 2024-02-25 10:51:27 -08:00
0201668563 [core] Move the Unicode piece table to a helper to_unicode() method on Piece 2024-02-11 09:58:18 -07:00
a5e8f33afe [core] Implement Square::file_rank()
Returns a tuple of the square's file and rank.
2024-02-05 13:59:58 -08:00
1d7dada987 [bitboard, core, position] Implement proper castle move generation
Add a field to MoveSet called special that flags special moves that should be
generated in the iter() method. This field is a u8. It only tracks castles in
the first and second bits (kingside and queenside, respectively). The move iterator
chains two maps over Option<()> that produce the kingside and queenside castle
moves.

With that done, finish the implementation of Position::player_can_castle by
adding checks for whether the squares between the rook and king are clear, and
that the king would not pass through a check. This is done with BitBoards!

Finally, implement some logic in PositionBuilder that updates the position's
castling flags based on the positions of king and rooks.

Supporting changes:
- Add Color:ALL and iterate on that slice
- Add Castle::ALL and iterator on that slice
- Add a CastlingParameters struct that contains BitBoard properties that describe
  squares that should be clear of pieces and squares that should not be attacked.
2024-01-29 14:46:41 -08:00
1f78d4811a [core] Declare Rank::PAWN_STARTING_RANKS
This is a slice that declares the pawn starting ranks for each color.
2024-01-29 14:46:16 -08:00
21c81f237a [core] Implement as_index() for range_bound_struct 2024-01-29 14:46:16 -08:00
164fe94bc0 [board] Implement danger squares for the current player
This concept comes from [1]. Danger squares are the squares a king cannot move to
because it would permit the opposing player to capture the king on their next
turn.

[1]: https://peterellisjones.com/posts/generating-legal-chess-moves-efficiently/
2024-01-28 09:08:22 -08:00
f08a4c66a1 [core] Use TryFromCharError in TryFrom<char> for Color 2024-01-26 12:58:51 -08:00
8b2a3926b3 [core,board] Move board::piece to core
Break up types in core into finer grained modules.
Update all the imports.
2024-01-24 17:08:27 -08:00
b0b22048a8 [core] Rename (once again) chess_core → chessfriend_core 2024-01-24 08:48:19 -08:00
eab30cc33b [core] Rename the directory chess_core → core
I think this is sufficient.
2024-01-24 08:33:07 -08:00
3c3a62345d [core] Rename core → chess_core 2024-01-24 08:29:16 -08:00
406631b617 [core] Move the contents of board::square to core::coordinates
Export Square, Rank, and File from the core crate.
2024-01-24 08:25:56 -08:00
7e08a9adc4 [core] Create a core crate 2024-01-24 08:24:59 -08:00