diff --git a/src/lib.rs b/src/lib.rs index 53d8caea..1a52611d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -111,4 +111,4 @@ pub use crate::setup::{Castles, Setup}; pub use crate::movelist::MoveList; pub use crate::position::{Chess, Outcome, Position, FromSetup, PlayError, PositionError, PositionErrorKinds}; pub use crate::perft::perft; -pub use crate::zobrist::{Zobrist, zobrist_from_pos}; +pub use crate::zobrist::{Zobrist, ZobristHashable, zobrist_from_pos}; diff --git a/src/position.rs b/src/position.rs index 06e2f0a3..92a4f626 100644 --- a/src/position.rs +++ b/src/position.rs @@ -30,6 +30,7 @@ use crate::types::{CastlingSide, CastlingMode, Move, Piece, Role, RemainingCheck use crate::material::Material; use crate::setup::{Castles, EpSquare, Setup, SwapTurn}; use crate::movelist::MoveList; +use crate::zobrist::ZobristHashable; /// Outcome of a game. #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] @@ -671,6 +672,8 @@ impl Position for Chess { fn variant_outcome(&self) -> Option { None } } +impl ZobristHashable for Chess {} + #[cfg(feature = "variant")] pub(crate) mod variant { use super::*; @@ -1022,6 +1025,8 @@ pub(crate) mod variant { } } + impl ZobristHashable for Antichess {} + /// A King of the Hill position. #[derive(Clone, Debug, Default)] pub struct KingOfTheHill { @@ -1109,6 +1114,8 @@ pub(crate) mod variant { } } + impl ZobristHashable for KingOfTheHill {} + /// A Three-Check position. #[derive(Clone, Debug, Default)] pub struct ThreeCheck { @@ -1532,6 +1539,8 @@ pub(crate) mod variant { } } + impl ZobristHashable for RacingKings {} + /// A Horde position. #[derive(Clone, Debug)] pub struct Horde { @@ -1931,6 +1940,8 @@ pub(crate) mod variant { } } + impl ZobristHashable for Horde {} + fn add_king_promotions(moves: &mut MoveList) { let mut king_promotions = MoveList::new(); diff --git a/src/zobrist.rs b/src/zobrist.rs index 98ffdbda..5a074c35 100644 --- a/src/zobrist.rs +++ b/src/zobrist.rs @@ -4,20 +4,27 @@ use std::num::NonZeroU32; include!(concat!(env!("OUT_DIR"), "/zobrist.rs")); // generated by build.rs +/// Used to discriminate which variants support Zobrist hashing. +pub trait ZobristHashable {} + +pub trait PositionHashable: Position + ZobristHashable {} // trait alias + #[derive(Debug)] -pub struct Zobrist

{ - pos: P, +pub struct Zobrist { + pos: PositionHashable, zobrist: u64 } -impl Zobrist

{ +impl ZobristHashable for Zobrist

{} + +impl Zobrist

{ /// Computes the zobrist hash of the current game state pub fn hash(&self) -> u64 { self.zobrist } } -impl Default for Zobrist

{ +impl Default for Zobrist

{ fn default() -> Self { let pos = P::default(); let board = pos.board(); @@ -35,7 +42,7 @@ impl Default for Zobrist

{ } } -impl FromSetup for Zobrist

{ +impl FromSetup for Zobrist

{ fn from_setup(setup: &dyn Setup, mode: CastlingMode) -> Result> { // create the underlying from the setup let pos = match P::from_setup(setup, mode) { @@ -48,7 +55,7 @@ impl FromSetup for Zobrist

{ } // Simply call through to the underlying methods -impl Setup for Zobrist

{ +impl Setup for Zobrist

{ #[inline(always)] fn board(&self) -> &Board { self.pos.board() @@ -91,7 +98,7 @@ impl Setup for Zobrist

{ } // call through to the underlying methods for everything except `play_unchecked` -impl Position for Zobrist

{ +impl Position for Zobrist

{ #[inline(always)] fn legal_moves(&self) -> MoveList { self.pos.legal_moves() @@ -215,7 +222,7 @@ fn zobrist_from_board(board: &Board) -> u64 { } /// Computes the Zobrist hash given a position. -pub fn zobrist_from_pos(pos: &T) -> u64 { +pub fn zobrist_from_pos(pos: &T) -> u64 { // compute the zobrist hash from the pieces on the board let mut zobrist = zobrist_from_board(&pos.board()); @@ -266,7 +273,7 @@ fn castle(color :Color, castle: CastlingSide) -> u64 { #[cfg(test)] mod zobrist_tests { - use crate::{Square, Piece, Chess, Position, CastlingMode, Move}; + use crate::{Square, Piece, Chess, PositionHashable, CastlingMode, Move}; use crate::fen::{epd, Fen}; use crate::zobrist::{square, Zobrist}; use std::collections::{HashSet, HashMap};