zchess 0.1.0

(WIP) A library for calculating chess moves in a 3-dimensional space.
Documentation
// bitflags...
use bitflags::bitflags;

// types...
use crate::types::color::Color;

bitflags! {
    /// Represents a chess piece.
    #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
    #[repr(transparent)]
    pub struct Piece: u16 {
        /// A pawn.
        const P = 0x0001;

        /// A knight.
        const N = 0x0002;

        /// A bishop.
        const B = 0x0004;

        /// A rook.
        const R = 0x0008;

        /// A queen.
        const Q = 0x0010;

        /// A king.
        const K = 0x0020;
 
        /// A black piece.
        const BLACK = 0x2000;

        /// A white piece.
        const WHITE = 0x4000;

        /// A moved piece.
        const MOVED = 0x8000;

    }
}

impl Piece {
    /// Sets the [`Piece`] as one that has been moved.
    pub fn conquer(&mut self) {
        self.insert(Self::MOVED)
    }

    /// Sets the [`Piece`] as one that has not been moved.
    pub fn retreat(&mut self) {
        self.remove(Self::MOVED)
    }

    /// Returns whether the [`Piece`] is a piece and a color (i.e., a useable piece).
    pub fn useable(&self) -> bool {
        self.is_piece() && self.is_color()
    }

    /// Returns whether the [`Piece`] meets the requirements for capturing the other [`Piece`].
    pub fn capturable(&self, other: Self) -> bool {
        self.is_enemy(other) && !other.intersects(Self::K)
    }

    /// Returns whether the [`Piece`] meets the requirements for castling.
    pub fn castleable(&self) -> bool {
        self.intersects(Self::R | Self::K) && !self.is_moved()
    }

    /// Returns whether the [`Piece`] meets the requirements for a pawn's double-square move.
    pub fn doubleable(&self) -> bool {
        self.intersects(Self::P) && !self.is_moved()
    }

    /// Returns whether the [`Piece`] meets the requirements for en-passant.
    pub fn enpassable(&self) -> bool {
        self.intersects(Self::P) && !self.is_moved()
    }

    /// Returns whether the [`Piece`] meets the requirements for being promoted from.
    pub fn promotable(&self) -> bool {
        self.intersects(Self::P)
    }

    /// Returns whether the [`Piece`] meets the requirements for being promoted to.
    pub fn switchable(&self) -> bool {
        self.intersects(Self::N | Self::B | Self::R | Self::Q)
    }

    /// Returns whether the [`Piece`] is flagged as some color.
    fn is_color(&self) -> bool {
        self.intersects(Self::BLACK | Self::WHITE)
    }

    /// Returns whether the [`Piece`]s are not flagged with the same color.
    fn is_enemy(&self, other: Self) -> bool {
        !self.intersection(other).intersects(Self::BLACK | Self::WHITE)
    }

    /// Returns whether the [`Piece`] is flagged as being moved.
    fn is_moved(&self) -> bool {
        self.intersects(Self::MOVED)
    }

    /// Returns whether the [`Piece`] is flagged as some piece.
    fn is_piece(&self) -> bool {
        self.intersects(Self::P | Self::N | Self::B | Self::R | Self::Q | Self::K)
    }
}

impl From<Color> for Piece {
    fn from(value: Color) -> Self {
        match value {
            Color::Black => Self::BLACK,
            Color::White => Self::WHITE,
        }
    }
}