[board, core, position] A simple static evaluation method for scoring positions
Implement a new Evaluator struct that evaluates a Board and returns a score. This evaluation mechanism uses only a material balance function. It doesn't account for anything else. Supporting this, add a Counts struct to the internal piece set structure of a Board. This struct is responsible for keeping counts of how many pieces of each shape are on the board for each color. Export a count_piece() method on Board that returns a count of the number of pieces of a particular color and shape. Implement a newtype wrapper around i32 called Score that represents the score of a position in centipawns, i.e. hundredths of a pawn. Add piece values to the Shape enum.
This commit is contained in:
parent
481ae70698
commit
7f25548335
10 changed files with 249 additions and 10 deletions
62
position/src/evaluation.rs
Normal file
62
position/src/evaluation.rs
Normal file
|
@ -0,0 +1,62 @@
|
|||
// Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
use chessfriend_board::Board;
|
||||
use chessfriend_core::{Color, Piece, Shape, score::Score};
|
||||
|
||||
struct Evaluator;
|
||||
|
||||
impl Evaluator {
|
||||
pub fn evaluate_symmetric_unwrapped(board: &Board, color: Color) -> Score {
|
||||
let material_balance = Self::material_balance(board, color);
|
||||
|
||||
let to_move_factor = color.score_factor();
|
||||
|
||||
to_move_factor * material_balance
|
||||
}
|
||||
|
||||
/// Evaluate a board using the symmetric evaluation algorithm defined by
|
||||
/// Claude Shannon.
|
||||
fn material_balance(board: &Board, color: Color) -> Score {
|
||||
let other_color = color.other();
|
||||
|
||||
Shape::into_iter().fold(Score::zero(), |acc, shape| {
|
||||
let (active_pieces, other_pieces) = (
|
||||
board.count_piece(&Piece::new(color, shape)) as i32,
|
||||
board.count_piece(&Piece::new(other_color, shape)) as i32,
|
||||
);
|
||||
|
||||
let factor = shape.score() * (active_pieces - other_pieces);
|
||||
|
||||
acc + factor
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use chessfriend_board::fen;
|
||||
|
||||
#[test]
|
||||
fn pawn_material_balance() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let board = fen!("8/8/8/8/8/3P4/8/8 w - - 0 1")?;
|
||||
assert_eq!(
|
||||
Evaluator::material_balance(&board, Color::White),
|
||||
100i32.into()
|
||||
);
|
||||
|
||||
let board = fen!("8/8/3p4/8/8/3P4/8/8 w - - 0 1")?;
|
||||
assert_eq!(Evaluator::material_balance(&board, Color::White), 0.into());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn starting_position_is_even() {
|
||||
let board = Board::starting(None);
|
||||
assert_eq!(
|
||||
Evaluator::evaluate_symmetric_unwrapped(&board, Color::White),
|
||||
Evaluator::evaluate_symmetric_unwrapped(&board, Color::Black)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,11 +1,12 @@
|
|||
// Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
mod evaluation;
|
||||
mod position;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
pub use chessfriend_board::{fen, PlacePieceError, PlacePieceStrategy};
|
||||
pub use chessfriend_board::{PlacePieceError, PlacePieceStrategy, fen};
|
||||
pub use chessfriend_moves::{GeneratedMove, ValidateMove};
|
||||
pub use position::Position;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue