A Rust library for chess move generation
-
Generate legal moves:
use shakmaty::{Chess, Position}; let pos = Chess::default(); let legals = pos.legal_moves(); assert_eq!(legals.len(), 20);
-
Play moves:
use shakmaty::{Square, Move, Role}; // 1. e4 let pos = pos.play(&Move::Normal { role: Role::Pawn, from: Square::E2, to: Square::E4, capture: None, promotion: None, })?;
-
Detect game end conditions:
pos.is_checkmate()
,pos.is_stalemate()
,pos.is_insufficient_material()
,pos.outcome()
. -
Read and write FENs, SANs and UCIs.
-
Supports all Lichess variants: Standard chess, Chess960, Antichess, Atomic, King of the Hill, Three-Check, Crazyhouse, Racing Kings and Horde. Provides vocabulary to implement other variants.
-
Bitboards and compact fixed shift magic attack tables.
-
Probe Syzygy tablebases with shakmaty-syzygy.
Simple perft of the initial position. No hashtables. i7-6850K CPU @ 3.60GHz.
perft | 4 | 5 |
---|---|---|
shakmaty 0.16.0 | 1.0 ms | 24.1 ms |
jordanbray/chess 3.1.1 | 0.8 ms | 18.6 ms |
Stockfish 8 (x86-64-bmi2) | 4 ms | 33 ms |
It should be noted that Stockfish is not optimized for perft speed and also maintains additional data structures for evaluation. Newer versions of Stockfish put even less emphasis on this.
- 0.19.0
- Update
arrayvec
to 0.7.x.MoveList
is now using const generics. - Derive
Hash
forMove
,Outcome
, andFen
. - Eliminate unsafe usage where no longer required for performance. Justify remaining cases.
- Update
- 0.18.0
- Remove
f32
,f64
,u128
, andi128
conversions. - Use
std::num::TryFromIntError
. - Functions now return
MoveList
instead of using it as an out parameter. Return value optimization by hand is no longer required. - Introduce
ByColor
, used asMaterial
andByColor<RemainingChecks>
. - Introduce
PlayError
. - Renamed
variants
module tovariant
. Now gated behind a non-default featurevariant
.
- Remove
- 0.17.2
- Parse
Uci::to_move()
where king captures unmoved rook.
- Parse
- 0.17.1
- Also reject checker aligned with king and en passant square with
PositionErrorKinds::IMPOSSIBLE_CHECK
.
- Also reject checker aligned with king and en passant square with
- 0.17.0
- Introduce
CastlingMode
, now required forFromSetup::from_setup(..., mode)
, theVariantPosition
analogon,Fen::position(mode)
, and exposed byCastles::mode()
. Uci::from_move()
now takes the mode as context instead of the position. Givepos.castles().mode()
for the old behavior.- Add
Uci::from_standard()
. - Rework
PositionError
. The original error kinds are available asPositionError::kinds()
. There are now methods to safely ignore particular errors. - Reject setups with impossible (i.e., too much) material with the new
PositionErrorKinds::IMPOSSIBLE_MATERIAL
. Can be ignored usingPositionError::ignore_impossible_material()
for the previous behavior. - Reject setups with multiple aligned sliding checkers with the new
PositionErrorKinds::IMPOSSIBLE_CHECK
. - Rename
BAD_CASTLING_RIGHTS
toINVALID_CASTLING_RIGHTS
. - Remove
IllegalMoveError
. In the context of UCI validation, replace withIllegalUciError
.Position::play()
instead returns the original position as the error. - Change
fullmoves
fromu32
toNonZeroU32
everywhere. - Remove public
Castles::from_setup()
. - Remove
Square::with_rank_of()
. - Remove
Giveaway
in favor ofAntichess
(where players start without castling rights). - Fix
swap_turn()
if en passant square exists. Would always fail, now discards the en passant square. - Add
Move::to_uci()
convenience method. - Add
CastlingSide::{king,rook}_to_file()
. - Add
Variant::distinguishes_promoted()
. - Add
Variant::uci()
andVariant::from_uci()
. - Future proof error types (remove some implemented traits and available constructors).
- Introduce
- 0.16.4
- Fix insufficient material detection with same-color bishops on both sides.
- Document limitations of
Position::is_irreversible()
. Moves that cede en passant are now considered irreversible.
- 0.16.3
- Implement
From<Role>
for nonzero integer types. - Performance: Remove internal
BB_BETWEEN
table and compute it from rays at runtime, to improve cache efficiency. - Support Miri.
- Implement
- 0.16.2
- Fix Racing Kings game end detection: Black cannot catch up if their own pieces block the goal.
- Pawn drops in Crazyhouse are now considered zeroing.
- 0.16.1
- Fix (impossible) Crazyhouse insufficient material.
- Fix (impossible) castling rights of exploded king in Atomic chess.
- 0.16.0
- Update
arrayvec
to 0.5.x, which comes with significant performance improvements. - The default
Giveaway
position now has castling rights.
- Update
- 0.15.3
- Follow FICS rules in Atomic castling edge cases.
- Use
#[repr(align)] enum
andreverse_bits()
stabilized in Rust 1.37.
- 0.15.2
- In Horde chess, allow double pawn moves from the first rank.
- Added
{Square,Bitboard}::{flip_anti_diagonal,rotate_90,rotate_180,rotate_270}()
.
- 0.15.1
- FEN parser was expecting
~
before promoted pieces, but it should be after.
- FEN parser was expecting
- 0.15.0
- Moved
Position::from_setup()
to a seperate new traitFromSetup
. - Square and file/rank index calculations are now performed with
u32
andi32
, which is more performant than using the narrower typesu8
andi8
. The types are still#[repr(u8)]
. - Renamed
Square::combine()
toSquare::with_rank_of()
. - Added
Fen::from_setup()
. - Added
FenOpts::scid()
for Scid/Lichess compatible FEN formatting. Of course the parser also accepts these formats. - Added
variant::Variant
andVariantPosition
for runtime selected chess variants. Limited to the built in variants. - Added
{Material,MaterialSide}::is_empty()
.
- Moved
- 0.14.1
TryFrom
now available on stable.
- 0.14.0
SanPlus::from_move()
no longer requires the move to be legal, which was an undocumented requirement. The newSanPlus::from_move_and_play_unchecked()
is closest to the previous behavior.- Added
San::disambiguate()
andSanSuffix::from_position()
. - Implement
TryFrom
for various types on nightly. - Implement
Add
,AddAssign
,Sub
,SubAssign
forMaterial
andMaterialSide
. - Added
CastlingSide::from_{king|queen}_side()
. - Use
u32
fordepth
argument ofperft()
.
- 0.13.1
- Performance improvements on nightly (aligned
Move
enum).
- Performance improvements on nightly (aligned
- 0.13.0
- Replaced
SanPlus::check
andSanPlus::checkmate
withsan::Suffix
enum. - Renamed
{Rank,File}::rotate()
toflip_diagonal()
. - Renamed
Bitboard::flip()
totoggle()
. - Added
Square::coords()
. - Added
Bitboard::flip_{vertical,horizontal,diagonal}()
. - Added
Position::promotion_moves()
. - Derive
Hash
onBoard
,FenOpts
,San
,SanPlus
,Suffix
,Color
,Role
,Piece
,RemainingChecks
,CastlingSide
, andUci
. - Minimum Rust version 1.31.0.
- Replaced
- 0.12.0
Setup::halfmove_clock()
is nowSetup::halfmoves()
.- New conversions:
f32::from(file)
,f64::from(rank)
. - Replace
Pockets
andPocket
by more generalMaterial
andMaterialSide
. Note that theirDisplay
andFromStr
implementations differ. - Unify naming of error types.
- 0.11.2
- Fix Atomic insufficient material: KQN can mate.
- 0.11.1
- Fix Chess960 should not allow a-side castling over a blocking h-side rook.
- 0.11.0
Outcome
is nowCopy
.Position::castling_uncovers_rank_attack()
is no longer public.
- 0.10.0
- Add
File
,Rank
. These are now returned bySquare::{file, rank}
.Square::from_coords(file, rank)
takes the new types and is no longer fallible. Bitboard
is nowIntoIterator
instead ofIterator
itself. MethodsBitboard::{first, last, count, is_empty}
remain.Bitboard::{add, flip, discard, with, without}
are now generic overInto<Bitboard>
. Alternative methods*_all
have been removed.Bitboard::relative_shift(color, shift: u8)
now takesu32
.shakmaty::CarryRippler
is nowshakmaty::bitboard::CarryRippler
.- Add new methods:
Bitboard::{pop_front, pop_back, is_disjoint, is_subset, is_superset}
. - Add
Position::has_insufficient_material(color)
.
- Add
- 0.9.0
- Remove
uci
,chess960_uci
,san
andsan_plus
that were deprecated in 0.8.1. - Rename
*::from_bytes()
to*::from_ascii()
. - Take small copy types by value:
Piece::char()
,CastlingSide::*
. - Add
Castles::has(color, side)
. fen::{board_fen, epd, fen}
are now shortcuts for formatting with default options.- Minimum rust version 1.27.0 (i128 conversions again, fused iterators again,
Option::filter()
,dyn Trait
). - Eliminate many uses of unsafe, including
TrustedLen
impls, at minor cost.
- Remove
- 0.8.1
- Make
Role
discriminants public. - Put
San
,SanPlus
andUci
constructors onSan
,SanPlus
andUci
respectively.
- Make
- 0.8.0
- Revert fused iterators and u128. Minimum Rust version back to 1.23.0.
- Change
Role
discriminants. Now starting withPawn = 1
. - Performance improvements (~12% faster perft).
- Switch benchmarks to
criterion.rs
.
- 0.7.2
- Add
Outcome.winner()
.
- Add
- 0.7.1
- Minimum Rust version 1.26.0 (fused iterators, u128 conversions).
- 0.7.0
- Reintroduce the remaining Lichess variants:
Crazyhouse
,KingOfTheHill
,ThreeCheck
,Horde
,RacingKings
. - Expose
Position.castles()
and replacePosition.is_chess960()
withPosition.castles().is_chess960()
. - Fix insufficient material: KNvK was not given as drawn due to a typo.
- Fix insufficient material in
Atomic
: Two knights of different colors are not safe. - Let
Pockets.count()
andPocket.count()
returnusize
.
- Reintroduce the remaining Lichess variants:
- 0.6.7
- Giveaway starting position should have no castling rights.
- 0.6.6
- Fix missing king promotions in Giveaway.
- 0.6.5
- Validate color of missing king in atomic chess.
- Clear move buffers before generating variant moves.
- 0.6.4
- Reintroduce
Giveaway
andAtomic
chess variants.
- Reintroduce
- 0.6.3
- New method
Move.is_zeroing()
.
- New method
- 0.6.2
- Make unit error types (
InvalidSquareName
,InvalidUci
,InvalidSan
) completely public. - Documentation, coding style and debugging tweaks.
- Make unit error types (
- 0.6.1
- Expose
attacks::bishop_mask
andattacks::rook_mask
. - Eliminate almost all unchecked indexing.
- Expose
- 0.6.0
- Split
impl From<Move> for Uci
intouci()
andchess960_uci()
. - Fix display of pawn drops.
- Move generating methods clear the move buffer (and therefor no longer panic on too full buffers).
- Added
Position.is_chess960()
,Bitboard.without_all()
,Role.upper_char()
,Board.stepper()
.
- Split
- 0.5.1
- Fix
Uci::to_move()
for en passant moves. Thanks zxqfl.
- Fix
- 0.5.0
- Use
u64
instead ofusize
forperft()
. - Export error type
InvalidSquareName
. - New methods:
CastlingSide.is_{queen|king}_side()
,San.matches()
,Move.is_capture()
,Move.is_promotion()
,Move.castling_side()
,Position.is_check()
. - Derive
Ord
andPartialOrd
forRole
. - Support running benchmarks on stable.
- Use
- 0.4.2
- Fix build error on beta due to the new nightly
option_filter
feature. - Fix unterminated code block in documentation.
- Fix build error on beta due to the new nightly
- 0.4.1
- Fix build error due to the new nightly
option_filter
feature.
- Fix build error due to the new nightly
- 0.4.0
- Rename
Color::from_bool()
toColor::from_white()
, addColor::from_black()
. - Add
Move::role()
,Move::is_en_passant()
andMove::is_castle()
. - Add
Position::en_passant_moves()
andPosition::capture_moves()
. - Implement
BitXor<bool>
forColor
. - Implement
FusedIterator
andTrustedLen
onBitboard
.
- Rename
- 0.3.0
- Switch to
#[repr(i8)]
forSquare
. Implement all lossless integer conversionsFrom<Square>
. - Add
Square::flip_horizontal()
,flip_vertical()
andflip_diagonal()
. - Efficiently implement
CarryRippler::last()
by @nvzqz. - Eliminate some unchecked indexing by @nvzqz.
- Faster ASCII case conversions and tests by @nvzqz.
- Switch to
- 0.2.0
Square
is now a#[repr(u8)]
enum.- Use
bitflags
forPositionError
. - Rename
RemainingChecks::subtract()
todecrement()
. - Add
Position::swap_turn()
.
- 0.1.0
- First release with support for stable Rust.
Shakmaty is licensed under the GPL-3.0 (or any later version at your option). See the COPYING file for the full license text.