A Rust library for chess move generation
Generate legal moves:
```rust use shakmaty::{Chess, Position};
let pos = Chess::default(); let legals = pos.legals(); assert_eq!(legals.len(), 20); ```
Play moves:
```rust 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 standard chess, Chess960, Giveaway, 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 | 1.4 ms | 33.8 ms jordanbray/chess | 1.3 ms | 28.7 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.
{Square,Bitboard}::{flip_anti_diagonal,rotate_90,rotate_180,rotate_270}()
.~
before promoted pieces, but it should be
after.Position::from_setup()
to a seperate new trait FromSetup
.u32
and
i32
, which is more performant than using the narrower types u8
and
i8
. The types are still #[repr(u8)]
.Square::combine()
to Square::with_rank_of()
.Fen::from_setup()
.FenOpts::scid()
for Scid/Lichess compatible FEN formatting.
Of course the parser also accepts these formats.variant::Variant
and VariantPosition
for runtime selected
chess variants. Limited to the built in variants.{Material,MaterialSide}::is_empty()
.TryFrom
now available on stable.SanPlus::from_move()
no longer requires the move to be legal, which
was an undocumented requirement. The new
SanPlus::from_move_and_play_unchecked()
is closest to the previous
behavior.San::disambiguate()
and SanSuffix::from_position()
.TryFrom
for various types on nightly.Add
, AddAssign
, Sub
, SubAssign
for Material
and
MaterialSide
.CastlingSide::from_{king|queen}_side()
.u32
for depth
argument of perft()
.Move
enum).SanPlus::check
and SanPlus::checkmate
with san::Suffix
enum.{Rank,File}::rotate()
to flip_diagonal()
.Bitboard::flip()
to toggle()
.Square::coords()
.Bitboard::flip_{vertical,horizontal,diagonal}()
.Position::promotion_moves()
.Hash
on Board
, FenOpts
, San
, SanPlus
, Suffix
, Color
,
Role
, Piece
, RemainingChecks
, CastlingSide
, and Uci
.Setup::halfmove_clock()
is now Setup::halfmoves()
.f32::from(file)
, f64::from(rank)
.Pockets
and Pocket
by more general Material
and
MaterialSide
. Note that their Display
and FromStr
implementations
differ.Outcome
is now Copy
.Position::castling_uncovers_rank_attack()
is no longer public.File
, Rank
. These are now returned by Square::{file, rank}
.
Square::from_coords(file, rank)
takes the new types and is no longer
fallible.Bitboard
is now IntoIterator
instead of Iterator
itself.
Methods Bitboard::{first, last, count, is_empty}
remain.Bitboard::{add, flip, discard, with, without}
are now generic over
Into<Bitboard>
. Alternative methods *_all
have been removed.Bitboard::relative_shift(color, shift: u8)
now takes u32
.shakmaty::CarryRippler
is now shakmaty::bitboard::CarryRippler
.Bitboard::{pop_front, pop_back, is_disjoint, is_subset, is_superset}
.Position::has_insufficient_material(color)
.uci
, chess960_uci
, san
and san_plus
that were deprecated
in 0.8.1.*::from_bytes()
to *::from_ascii()
.Piece::char()
, CastlingSide::*
.Castles::has(color, side)
.fen::{board_fen, epd, fen}
are now shortcuts for formatting with
default options.Option::filter()
, dyn Trait
).TrustedLen
impls, at minor cost.Role
discriminants public.San
, SanPlus
and Uci
constructors on San
, SanPlus
and Uci
respectively.Role
discriminants. Now starting with Pawn = 1
.criterion.rs
.Outcome.winner()
.Crazyhouse
, KingOfTheHill
,
ThreeCheck
, Horde
, RacingKings
.Position.castles()
and replace Position.is_chess960()
with
Position.castles().is_chess960()
.Atomic
: Two knights of different colors
are not safe.Pockets.count()
and Pocket.count()
return usize
.Giveaway
and Atomic
chess variants.Move.is_zeroing()
.InvalidSquareName
, InvalidUci
, InvalidSan
)
completely public.attacks::bishop_mask
and attacks::rook_mask
.impl From<Move> for Uci
into uci()
and chess960_uci()
.Position.is_chess960()
, Bitboard.without_all()
, Role.upper_char()
, Board.stepper()
.Uci::to_move()
for en passant moves. Thanks zxqfl.u64
instead of usize
for perft()
.InvalidSquareName
.CastlingSide.is_{queen|king}_side()
, San.matches()
, Move.is_capture()
, Move.is_promotion()
, Move.castling_side()
, Position.is_check()
.Ord
and PartialOrd
for Role
.option_filter
feature.option_filter
feature.Color::from_bool()
to Color::from_white()
,
add Color::from_black()
.Move::role()
, Move::is_en_passant()
and Move::is_castle()
.Position::en_passant_moves()
and Position::capture_moves()
.BitXor<bool>
for Color
.FusedIterator
and TrustedLen
on Bitboard
.#[repr(i8)]
for Square
. Implement all lossless integer
conversions From<Square>
.Square::flip_horizontal()
, flip_vertical()
and flip_diagonal()
.CarryRippler::last()
by @nvzqz.Square
is now a #[repr(u8)]
enum.bitflags
for PositionError
.RemainingChecks::subtract()
to decrement()
.Position::swap_turn()
.Shakmaty is licensed under the GPL-3.0 (or any later version at your option). See the COPYING file for the full license text.