lazychess 0.1.1

A fast, memory-efficient chess engine library for Rust
Documentation
use std::fmt;
use crate::types::{Color, Move, Piece, Square};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BoardPiece {
    pub piece: Piece,
    pub square: Square,
}
impl BoardPiece {
    pub fn new(piece: Piece, square: Square) -> Self { Self { piece, square } }
}

#[derive(Debug, Clone, PartialEq)]
pub enum Evaluation {
    Centipawn(i32),
    Mate(i32),
}
impl Evaluation {
    pub fn centipawn(&self) -> Option<i32> {
        match self { Evaluation::Centipawn(v) => Some(*v), _ => None }
    }
    pub fn mate_in(&self) -> Option<i32> {
        match self { Evaluation::Mate(v) => Some(*v), _ => None }
    }
    pub fn subjective(&self, color: Color) -> Evaluation {
        let flip = color == Color::Black;
        match self {
            Evaluation::Centipawn(v) => Evaluation::Centipawn(if flip { -v } else { *v }),
            Evaluation::Mate(v)      => Evaluation::Mate(if flip { -v } else { *v }),
        }
    }
    pub fn value(&self) -> i32 {
        match self { Evaluation::Centipawn(v) | Evaluation::Mate(v) => *v }
    }
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum ClassificationKind {
    Brilliant, Great, Best, Excellent, Good, Okay,
    Inaccuracy, Miss, Mistake, Blunder, Forced, Book, Risky,
}
impl fmt::Display for ClassificationKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match self {
            ClassificationKind::Brilliant  => "Brilliant",
            ClassificationKind::Great      => "Great",
            ClassificationKind::Best       => "Best",
            ClassificationKind::Excellent  => "Excellent",
            ClassificationKind::Good       => "Good",
            ClassificationKind::Okay       => "Okay",
            ClassificationKind::Inaccuracy => "Inaccuracy",
            ClassificationKind::Miss       => "Miss",
            ClassificationKind::Mistake    => "Mistake",
            ClassificationKind::Blunder    => "Blunder",
            ClassificationKind::Forced     => "Forced",
            ClassificationKind::Book       => "Book",
            ClassificationKind::Risky      => "Risky",
        };
        write!(f, "{s}")
    }
}

/// The full classification result for a single move.
#[derive(Debug, Clone)]
pub struct MoveClassification {
    /// SAN notation of the played move (e.g. `"Nf3+"`, `"O-O"`).
    pub san: String,
    /// UCI notation of the played move (e.g. `"g1f3"`).
    pub played_move: String,
    /// UCI notation of the engine's best move.
    pub best_move: String,
    /// Classification category.
    pub kind: ClassificationKind,
    /// Side that played this move.
    pub color: Color,
    /// Full-move number (1-based, increments after Black moves).
    pub move_number: u32,
    /// Expected point loss [0.0, 1.0].
    pub point_loss: f64,
    /// Move accuracy percentage [0.0, 100.0].
    pub accuracy: f64,
    /// Engine evaluation before the move (White's perspective).
    pub eval_before: Evaluation,
    /// Engine evaluation after the move (White's perspective).
    pub eval_after: Evaluation,
}

impl fmt::Display for MoveClassification {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{}. {} {} [{}]  best: {}  loss: {:.3}  accuracy: {:.1}%",
            self.move_number,
            self.san,
            self.played_move,
            self.kind,
            self.best_move,
            self.point_loss,
            self.accuracy,
        )
    }
}

#[derive(Debug)]
pub struct ClassificationContext<'a> {
    pub played_move:      &'a Move,
    pub best_move:        &'a Move,
    pub eval_before:      &'a Evaluation,
    pub eval_after:       &'a Evaluation,
    pub second_best_eval: Option<&'a Evaluation>,
    pub point_loss:       f64,
    pub is_book:          bool,
    pub is_forced:        bool,
    pub in_check_before:  bool,
    pub color:            Color,
}