timecat 1.52.0

A NNUE-based chess engine that implements the Negamax algorithm and can be integrated into any project as a library. It features move generation, advanced position evaluation through NNUE, and move searching capabilities.
Documentation
use super::*;
pub use Color::*;

macro_rules! generate_functions {
    ($func_name:ident, $black_rank:expr, $white_rank:expr) => {
        #[inline]
        pub fn $func_name(self) -> Rank {
            *get_item_unchecked!(const { [$black_rank, $white_rank] }, self.to_index())
        }

        paste!{
            #[inline]
            pub fn [<$func_name _bitboard>] (self) -> BitBoard {
                *get_item_unchecked!(const { [$black_rank.to_bitboard(), $white_rank.to_bitboard()] }, self.to_index())
            }
        }
    };
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Hash)]
pub enum Color {
    Black = 0,
    White = 1,
}

impl Color {
    #[inline]
    pub const unsafe fn from_int(int: u8) -> Self {
        std::mem::transmute(int)
    }

    #[inline]
    pub const unsafe fn from_index(index: usize) -> Self {
        Self::from_int(index as u8)
    }

    #[inline]
    pub const fn to_int(self) -> u8 {
        self as u8
    }

    #[inline]
    pub const fn to_index(self) -> usize {
        self as usize
    }

    #[inline]
    pub fn to_my_backrank(self) -> Rank {
        self.to_first_rank()
    }

    #[inline]
    pub fn to_their_backrank(self) -> Rank {
        self.to_eighth_rank()
    }

    #[inline]
    pub fn to_my_backrank_bitboard(self) -> BitBoard {
        self.to_first_rank_bitboard()
    }

    #[inline]
    pub fn to_their_backrank_bitboard(self) -> BitBoard {
        self.to_eighth_rank_bitboard()
    }

    generate_functions!(to_first_rank, Rank::Eighth, Rank::First);
    generate_functions!(to_second_rank, Rank::Seventh, Rank::Second);
    generate_functions!(to_third_rank, Rank::Sixth, Rank::Third);
    generate_functions!(to_fourth_rank, Rank::Fifth, Rank::Fourth);
    generate_functions!(to_fifth_rank, Rank::Fourth, Rank::Fifth);
    generate_functions!(to_sixth_rank, Rank::Third, Rank::Sixth);
    generate_functions!(to_seventh_rank, Rank::Second, Rank::Seventh);
    generate_functions!(to_eighth_rank, Rank::First, Rank::Eighth);
}

impl Not for Color {
    type Output = Self;

    #[inline]
    fn not(self) -> Self {
        *get_item_unchecked!(const { [White, Black] }, self.to_index())
    }
}

impl fmt::Display for Color {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{}",
            get_item_unchecked!(const { ["Black", "White"] }, self.to_index())
        )
    }
}

impl FromStr for Color {
    type Err = TimecatError;

    fn from_str(s: &str) -> Result<Self> {
        match s.to_lowercase().as_str() {
            "b" | "black" => Ok(Black),
            "w" | "white" => Ok(White),
            _ => Err(TimecatError::InvalidColorString {
                s: s.to_string().into(),
            }),
        }
    }
}

#[cfg(feature = "pyo3")]
impl<'source> FromPyObject<'source> for Color {
    fn extract_bound(ob: &Bound<'source, PyAny>) -> PyResult<Self> {
        if let Ok(boolean) = ob.extract::<bool>() {
            return if boolean {
                Ok(Self::White)
            } else {
                Ok(Self::Black)
            };
        }
        if let Ok(s) = ob.extract::<&str>()
            && let Ok(color) = s.parse()
        {
            return Ok(color);
        }
        Err(Pyo3Error::Pyo3TypeConversionError {
            from: ob.to_string().into(),
            to: std::any::type_name::<Self>().into(),
        }
        .into())
    }
}