A Rust library for chess move generation
Generate legal moves:
```rust use shakmaty::{Chess, Position};
let pos = Chess::default(); let legals = pos.legalmoves(); asserteq!(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 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.
Board
and added
Setup::promoted()
instead. This is used only by Crazyhouse. All other
variants will return Bitboard(0)
. Removed FenOpts::promoted()
accordingly. Moved fen::board_fen()
as a method to Board
.Horde
.step
that implements the nightly Step
trait for
File
, Rank
and Square
.Bitboard
respect Display
formatting options.File::offset()
.Eq
and Hash
for Chess
and Pieces
.arrayvec
to 0.7.x. MoveList
is now using const generics.Hash
for Move
, Outcome
, and Fen
.f32
, f64
, u128
, and i128
conversions.std::num::TryFromIntError
.MoveList
instead of using it as an out parameter.
Return value optimization by hand is no longer required.ByColor
, used as Material
and ByColor<RemainingChecks>
.PlayError
.variants
module to variant
. Now gated behind a non-default
feature variant
.Uci::to_move()
where king captures unmoved rook.PositionErrorKinds::IMPOSSIBLE_CHECK
.CastlingMode
, now required for
FromSetup::from_setup(..., mode)
, the VariantPosition
analogon,
Fen::position(mode)
, and exposed by Castles::mode()
.Uci::from_move()
now takes the mode as context instead of the position.
Give pos.castles().mode()
for the old behavior.Uci::from_standard()
.PositionError
. The original error kinds are available as
PositionError::kinds()
. There are now methods to safely ignore particular
errors.PositionErrorKinds::IMPOSSIBLE_MATERIAL
. Can be ignored using
PositionError::ignore_impossible_material()
for the previous behavior.PositionErrorKinds::IMPOSSIBLE_CHECK
.BAD_CASTLING_RIGHTS
to INVALID_CASTLING_RIGHTS
.IllegalMoveError
. In the context of UCI validation, replace with
IllegalUciError
. Position::play()
instead returns the original position
as the error.fullmoves
from u32
to NonZeroU32
everywhere.Castles::from_setup()
.Square::with_rank_of()
.Giveaway
in favor of Antichess
(where players start without
castling rights).swap_turn()
if en passant square exists. Would always fail, now
discards the en passant square.Move::to_uci()
convenience method.CastlingSide::{king,rook}_to_file()
.Variant::distinguishes_promoted()
.Variant::uci()
and Variant::from_uci()
.Position::is_irreversible()
. Moves that cede
en passant are now considered irreversible.From<Role>
for nonzero integer types.BB_BETWEEN
table and compute it from rays at
runtime, to improve cache efficiency.arrayvec
to 0.5.x, which comes with significant performance
improvements.Giveaway
position now has castling rights.#[repr(align)] enum
and reverse_bits()
stabilized in Rust 1.37.{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.