From 420e32fe86e98996bd8677033e2d29c44f513510 Mon Sep 17 00:00:00 2001 From: dogeystamp Date: Sat, 26 Oct 2024 16:43:06 -0400 Subject: [PATCH] feat: basic basic eval --- src/eval.rs | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 2 files changed, 73 insertions(+) create mode 100644 src/eval.rs diff --git a/src/eval.rs b/src/eval.rs new file mode 100644 index 0000000..8167f3d --- /dev/null +++ b/src/eval.rs @@ -0,0 +1,72 @@ +/* + +This file is part of chess_inator. + +chess_inator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. + +chess_inator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with chess_inator. If not, see https://www.gnu.org/licenses/. + +Copyright © 2024 dogeystamp +*/ + +//! Position evaluation. + +use crate::{Board, Color, N_PIECES}; + +/// Signed centipawn type. +/// +/// Positive is good for White, negative good for Black. +type EvalInt = i16; + +pub trait Eval { + /// Evaluate a position and assign it a score. + fn eval(&self) -> EvalInt; +} + +impl Eval for Board { + fn eval(&self) -> EvalInt { + use crate::Piece::*; + let mut score: EvalInt = 0; + + // scores in centipawns for each piece + let material_score: [EvalInt; N_PIECES] = [ + 500, // rook + 300, // bishop + 300, // knight + 20000, // king + 900, // queen + 100, // pawn + ]; + + for pc in [Rook, Queen, Pawn, Knight, Bishop, King] { + let tally_white = self.pl(Color::White).board(pc).0.count_ones(); + let tally_black = self.pl(Color::Black).board(pc).0.count_ones(); + let tally = + EvalInt::try_from(tally_white).unwrap() - EvalInt::try_from(tally_black).unwrap(); + + score += material_score[pc as usize] * tally; + } + + score + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::fen::FromFen; + + /// Sanity check. + #[test] + fn test_eval() { + let board1 = Board::from_fen("4k3/8/8/8/8/8/PPPPPPPP/RNBQKBNR w KQ - 0 1").unwrap(); + let eval1 = board1.eval(); + let board2 = Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/8/4K3 w kq - 0 1").unwrap(); + let eval2 = board2.eval(); + + assert!(eval1 > 0, "got eval {eval1}"); + assert!(eval2 < 0, "got eval {eval2}"); + } +} diff --git a/src/lib.rs b/src/lib.rs index b480aad..2de6234 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,7 @@ Copyright © 2024 dogeystamp use std::fmt::Display; use std::str::FromStr; +pub mod eval; pub mod fen; pub mod movegen;