Implement piece/psqt scores and tests

This commit is contained in:
stefiosif
2024-08-12 21:40:42 +03:00
parent bac5c33e3f
commit 989a2e33c5
3 changed files with 261 additions and 0 deletions

116
src/evaluation.rs Normal file
View File

@@ -0,0 +1,116 @@
use u64 as Bitboard;
use crate::{
bitboard::lsb,
board::{Board, Color, Kind},
psqt::{mirror_index, piece_square_score},
};
const fn piece_score(kind: Kind) -> i32 {
match kind {
Kind::Pawn => 100,
Kind::Knight => 320,
Kind::Bishop => 330,
Kind::Rook => 500,
Kind::Queen => 900,
Kind::King => 20000,
}
}
fn evaluate_side(board: &Board, color: Color) -> i32 {
let mut total_score = 0;
let pieces = match color {
Color::White => &board.white_pieces,
Color::Black => &board.black_pieces,
};
for piece in pieces {
let (kind, mut bitboard): (Kind, Bitboard) = (piece.kind, piece.bitboard);
let mut score = 0;
while bitboard != 0 {
let psqt_index = match color {
Color::White => lsb(bitboard),
Color::Black => mirror_index(lsb(bitboard)),
};
score += piece_score(kind);
score += piece_square_score(kind, psqt_index);
bitboard &= bitboard - 1;
}
total_score += score;
}
total_score
}
pub fn evaluate_position(board: &Board, color: Color) -> i32 {
let total_white_score = evaluate_side(board, Color::White);
let total_black_score = evaluate_side(board, Color::Black);
let evaluation = total_white_score - total_black_score;
match color {
Color::White => evaluation,
Color::Black => -evaluation,
}
}
#[cfg(test)]
mod tests {
use crate::{
board::{Color, Kind},
evaluation::{evaluate_position, evaluate_side, piece_score},
fen::from_fen,
};
const FEN_QUIET: [&str; 2] = [
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
"rnbqkbnr/ppp2ppp/4p3/3pN3/3P4/8/PPP1PPPP/RNBQKB1R w KQkq - 0 1",
];
#[test]
fn test_piece_score() -> Result<(), String> {
assert_eq!(100, piece_score(Kind::Pawn));
assert_eq!(320, piece_score(Kind::Knight));
assert_eq!(330, piece_score(Kind::Bishop));
assert_eq!(500, piece_score(Kind::Rook));
assert_eq!(900, piece_score(Kind::Queen));
assert_eq!(20000, piece_score(Kind::King));
Ok(())
}
#[test]
fn test_evaluate_side() -> Result<(), String> {
let game = from_fen(FEN_QUIET[0])?;
assert_eq!(
evaluate_side(&game.board, Color::White),
evaluate_side(&game.board, Color::Black)
);
let game_2 = from_fen(FEN_QUIET[1])?;
let evaluate_white = evaluate_side(&game_2.board, Color::White);
let evaluate_black = evaluate_side(&game_2.board, Color::Black);
assert_eq!(24005, evaluate_white);
assert_eq!(23965, evaluate_black);
Ok(())
}
#[test]
fn test_evaluate() -> Result<(), String> {
let game = from_fen(FEN_QUIET[0])?;
assert_eq!(
evaluate_position(&game.board, Color::White),
evaluate_position(&game.board, Color::Black)
);
let game_2 = from_fen(FEN_QUIET[1])?;
assert_eq!(40, evaluate_position(&game_2.board, Color::White));
assert_eq!(-40, evaluate_position(&game_2.board, Color::Black));
Ok(())
}
}

View File

@@ -1,12 +1,14 @@
pub mod attack;
pub mod bitboard;
pub mod board;
pub mod evaluation;
pub mod fen;
pub mod game;
pub mod magic;
pub mod r#move;
pub mod movegen;
pub mod perft;
pub mod psqt;
pub mod search;
pub mod square;
pub mod state;

143
src/psqt.rs Normal file
View File

@@ -0,0 +1,143 @@
use crate::board::Kind;
pub const fn piece_square_score(kind: Kind, index: usize) -> i32 {
match kind {
Kind::Pawn => PAWN_PSQT[index],
Kind::Knight => KNIGHT_PSQT[index],
Kind::Bishop => BISHOP_PSQT[index],
Kind::Rook => ROOK_PSQT[index],
Kind::Queen => QUEEN_PSQT[index],
Kind::King => KING_MIDGAME_PSQT[index],
}
}
pub const fn piece_square_score_endgame(kind: Kind, index: usize) -> i32 {
match kind {
Kind::Pawn => PAWN_PSQT[index],
Kind::Knight => KNIGHT_PSQT[index],
Kind::Bishop => BISHOP_PSQT[index],
Kind::Rook => ROOK_PSQT[index],
Kind::Queen => QUEEN_PSQT[index],
Kind::King => KING_ENDGAME_PSQT[index],
}
}
pub const fn mirror_index(idx: usize) -> usize {
63 - idx
}
#[rustfmt::skip]
const PAWN_PSQT: [i32; 64] = [
0, 0, 0, 0, 0, 0, 0, 0,
5, 10, 10,-20,-20, 10, 10, 5,
5, -5,-10, 0, 0,-10, -5, 5,
0, 0, 0, 20, 20, 0, 0, 0,
5, 5, 10, 25, 25, 10, 5, 5,
10, 10, 20, 30, 30, 20, 10, 10,
50, 50, 50, 50, 50, 50, 50, 50,
0, 0, 0, 0, 0, 0, 0, 0
];
#[rustfmt::skip]
const KNIGHT_PSQT: [i32; 64] = [
-50,-40,-30,-30,-30,-30,-40,-50,
-40,-20, 0, 5, 5, 0,-20,-40,
-30, 5, 10, 15, 15, 10, 5,-30,
-30, 0, 15, 20, 20, 15, 0,-30,
-30, 5, 15, 20, 20, 15, 5,-30,
-30, 0, 10, 15, 15, 10, 0,-30,
-40,-20, 0, 0, 0, 0,-20,-40,
-50,-40,-30,-30,-30,-30,-40,-50,
];
#[rustfmt::skip]
const BISHOP_PSQT: [i32; 64] = [
-20,-10,-10,-10,-10,-10,-10,-20,
-10, 5, 0, 0, 0, 0, 5,-10,
-10, 10, 10, 10, 10, 10, 10,-10,
-10, 0, 10, 10, 10, 10, 0,-10,
-10, 5, 5, 10, 10, 5, 5,-10,
-10, 0, 5, 10, 10, 5, 0,-10,
-10, 0, 0, 0, 0, 0, 0,-10,
-20,-10,-10,-10,-10,-10,-10,-20,
];
#[rustfmt::skip]
const ROOK_PSQT: [i32; 64] = [
0, 0, 0, 5, 5, 0, 0, 0,
-5, 0, 0, 0, 0, 0, 0, -5,
-5, 0, 0, 0, 0, 0, 0, -5,
-5, 0, 0, 0, 0, 0, 0, -5,
-5, 0, 0, 0, 0, 0, 0, -5,
-5, 0, 0, 0, 0, 0, 0, -5,
5, 10, 10, 10, 10, 10, 10, 5,
0, 0, 0, 0, 0, 0, 0, 0
];
#[rustfmt::skip]
const QUEEN_PSQT: [i32; 64] = [
-20,-10,-10, -5, -5,-10,-10,-20,
-10, 0, 5, 0, 0, 0, 0,-10,
-10, 5, 5, 5, 5, 5, 0,-10,
-5, 0, 5, 5, 5, 5, 0, -5,
0, 0, 5, 5, 5, 5, 0, -5,
-10, 0, 5, 5, 5, 5, 0,-10,
-10, 0, 0, 0, 0, 0, 0,-10,
-20,-10,-10, -5, -5,-10,-10,-20
];
#[rustfmt::skip]
const KING_MIDGAME_PSQT: [i32; 64] = [
20, 30, 10, 0, 0, 10, 30, 20,
20, 20, 0, 0, 0, 0, 20, 20,
-10,-20,-20,-20,-20,-20,-20,-10,
-20,-30,-30,-40,-40,-30,-30,-20,
-30,-40,-40,-50,-50,-40,-40,-30,
-30,-40,-40,-50,-50,-40,-40,-30,
-30,-40,-40,-50,-50,-40,-40,-30,
-30,-40,-40,-50,-50,-40,-40,-30
];
#[rustfmt::skip]
const KING_ENDGAME_PSQT: [i32; 64] = [
-50,-30,-30,-30,-30,-30,-30,-50,
-30,-30, 0, 0, 0, 0,-30,-30,
-30,-10, 20, 30, 30, 20,-10,-30,
-30,-10, 30, 40, 40, 30,-10,-30,
-30,-10, 30, 40, 40, 30,-10,-30,
-30,-10, 20, 30, 30, 20,-10,-30,
-30,-20,-10, 0, 0,-10,-20,-30,
-50,-40,-30,-20,-20,-30,-40,-50
];
#[cfg(test)]
mod tests {
use crate::{
board::Kind,
psqt::{mirror_index, piece_square_score},
square::Square,
};
#[test]
fn test_piece_square_score() -> Result<(), String> {
assert_eq!(50, piece_square_score(Kind::Pawn, Square::A7));
assert_eq!(-40, piece_square_score(Kind::Knight, Square::B1));
assert_eq!(0, piece_square_score(Kind::Bishop, Square::D2));
assert_eq!(-5, piece_square_score(Kind::Rook, Square::A2));
assert_eq!(5, piece_square_score(Kind::Queen, Square::D3));
assert_eq!(30, piece_square_score(Kind::King, Square::G1));
Ok(())
}
#[test]
fn test_mirror_index() -> Result<(), String> {
let a1_mirror = mirror_index(Square::A1);
assert_eq!(Square::H8, a1_mirror);
let d4_mirror = mirror_index(Square::D4);
assert_eq!(Square::E5, d4_mirror);
Ok(())
}
}