shakmaty
A Rust library for chess move generation
Features
-
Generate legal moves:
use ; let pos = default; let legals = pos.legals; assert_eq!; -
Play moves:
use ; // 1. e4 let pos = pos.play?; -
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.
Documentation
Benchmarks
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.
Changelog
- 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), theVariantPositionanalogon,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_RIGHTStoINVALID_CASTLING_RIGHTS. - Remove
IllegalMoveError. In the context of UCI validation, replace withIllegalUciError.Position::play()instead returns the original position as the error. - Change
fullmovesfromu32toNonZeroU32everywhere. - Remove public
Castles::from_setup(). - Remove
Square::with_rank_of(). - Remove
Giveawayin 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_BETWEENtable 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
arrayvecto 0.5.x, which comes with significant performance improvements. - The default
Giveawayposition now has castling rights.
- Update
- 0.15.3
- Follow FICS rules in Atomic castling edge cases.
- Use
#[repr(align)] enumandreverse_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
u32andi32, which is more performant than using the narrower typesu8andi8. 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::VariantandVariantPositionfor runtime selected chess variants. Limited to the built in variants. - Added
{Material,MaterialSide}::is_empty().
- Moved
- 0.14.1
TryFromnow 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
TryFromfor various types on nightly. - Implement
Add,AddAssign,Sub,SubAssignforMaterialandMaterialSide. - Added
CastlingSide::from_{king|queen}_side(). - Use
u32fordepthargument ofperft().
- 0.13.1
- Performance improvements on nightly (aligned
Moveenum).
- Performance improvements on nightly (aligned
- 0.13.0
- Replaced
SanPlus::checkandSanPlus::checkmatewithsan::Suffixenum. - Renamed
{Rank,File}::rotate()toflip_diagonal(). - Renamed
Bitboard::flip()totoggle(). - Added
Square::coords(). - Added
Bitboard::flip_{vertical,horizontal,diagonal}(). - Added
Position::promotion_moves(). - Derive
HashonBoard,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
PocketsandPocketby more generalMaterialandMaterialSide. Note that theirDisplayandFromStrimplementations 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
Outcomeis 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. Bitboardis nowIntoIteratorinstead ofIteratoritself. MethodsBitboard::{first, last, count, is_empty}remain.Bitboard::{add, flip, discard, with, without}are now generic overInto<Bitboard>. Alternative methods*_allhave been removed.Bitboard::relative_shift(color, shift: u8)now takesu32.shakmaty::CarryRippleris 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,sanandsan_plusthat 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
TrustedLenimpls, at minor cost.
- Remove
- 0.8.1
- Make
Rolediscriminants public. - Put
San,SanPlusandUciconstructors onSan,SanPlusandUcirespectively.
- Make
- 0.8.0
- Revert fused iterators and u128. Minimum Rust version back to 1.23.0.
- Change
Rolediscriminants. 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
GiveawayandAtomicchess 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_maskandattacks::rook_mask. - Eliminate almost all unchecked indexing.
- Expose
- 0.6.0
- Split
impl From<Move> for Uciintouci()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
u64instead ofusizeforperft(). - 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
OrdandPartialOrdforRole. - Support running benchmarks on stable.
- Use
- 0.4.2
- Fix build error on beta due to the new nightly
option_filterfeature. - 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_filterfeature.
- 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
FusedIteratorandTrustedLenonBitboard.
- 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
Squareis now a#[repr(u8)]enum.- Use
bitflagsforPositionError. - Rename
RemainingChecks::subtract()todecrement(). - Add
Position::swap_turn().
- 0.1.0
- First release with support for stable Rust.
License
Shakmaty is licensed under the GPL-3.0 (or any later version at your option). See the COPYING file for the full license text.