Implement PeSTO eval
This commit is contained in:
@@ -204,6 +204,17 @@ impl PieceType {
|
|||||||
pub const fn idx(self) -> usize {
|
pub const fn idx(self) -> usize {
|
||||||
self as usize
|
self as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn score(self) -> i32 {
|
||||||
|
match self {
|
||||||
|
Self::Pawn => 100,
|
||||||
|
Self::Knight => 320,
|
||||||
|
Self::Bishop => 330,
|
||||||
|
Self::Rook => 500,
|
||||||
|
Self::Queen => 900,
|
||||||
|
Self::King => 20000,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
|
|
||||||
|
|||||||
@@ -1,119 +0,0 @@
|
|||||||
use strum::IntoEnumIterator;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
board::{
|
|
||||||
bitboard::{self, lsb},
|
|
||||||
board::{Board, Color, PieceType},
|
|
||||||
},
|
|
||||||
evaluation::psqt::{mirror_index, piece_square_score},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::psqt::piece_square_score_endgame;
|
|
||||||
|
|
||||||
pub const fn material_score(piece_type: PieceType) -> i32 {
|
|
||||||
match piece_type {
|
|
||||||
PieceType::Pawn => 100,
|
|
||||||
PieceType::Knight => 320,
|
|
||||||
PieceType::Bishop => 330,
|
|
||||||
PieceType::Rook => 500,
|
|
||||||
PieceType::Queen => 900,
|
|
||||||
PieceType::King => 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_end_game(board: &Board) -> bool {
|
|
||||||
PieceType::iter().fold(0, |acc, p| {
|
|
||||||
acc + bitboard::bit_count(board.pieces[p]) * material_score(p) as usize
|
|
||||||
}) < 2000
|
|
||||||
}
|
|
||||||
|
|
||||||
fn evaluate_side_for(board: &Board, color: Color) -> i32 {
|
|
||||||
let psqt = if is_end_game(board) {
|
|
||||||
piece_square_score_endgame
|
|
||||||
} else {
|
|
||||||
piece_square_score
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut total_score = 0;
|
|
||||||
|
|
||||||
PieceType::iter().for_each(|piece_type| {
|
|
||||||
let mut bitboard = board.pieces[piece_type] & board.color[color];
|
|
||||||
while bitboard != 0 {
|
|
||||||
let psqt_index = match color {
|
|
||||||
Color::White => lsb(bitboard),
|
|
||||||
Color::Black => mirror_index(lsb(bitboard)),
|
|
||||||
};
|
|
||||||
|
|
||||||
total_score += material_score(piece_type);
|
|
||||||
total_score += psqt(piece_type, psqt_index);
|
|
||||||
bitboard &= bitboard - 1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
total_score
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn evaluate_position(board: &Board) -> i32 {
|
|
||||||
let total_white_score = evaluate_side_for(board, Color::White);
|
|
||||||
let total_black_score = evaluate_side_for(board, Color::Black);
|
|
||||||
|
|
||||||
match board.state.current_player() {
|
|
||||||
Color::White => total_white_score - total_black_score,
|
|
||||||
Color::Black => total_black_score - total_white_score,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::{
|
|
||||||
board::{
|
|
||||||
board::{Color, PieceType},
|
|
||||||
fen::from_fen,
|
|
||||||
},
|
|
||||||
evaluation::evaluation::{evaluate_position, evaluate_side_for, material_score},
|
|
||||||
};
|
|
||||||
|
|
||||||
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_material_score() -> Result<(), String> {
|
|
||||||
assert_eq!(100, material_score(PieceType::Pawn));
|
|
||||||
assert_eq!(320, material_score(PieceType::Knight));
|
|
||||||
assert_eq!(330, material_score(PieceType::Bishop));
|
|
||||||
assert_eq!(500, material_score(PieceType::Rook));
|
|
||||||
assert_eq!(900, material_score(PieceType::Queen));
|
|
||||||
assert_eq!(0, material_score(PieceType::King));
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_evaluate_side_for() -> Result<(), String> {
|
|
||||||
let game = from_fen(FEN_QUIET[0])?;
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
evaluate_side_for(&game.board, Color::White),
|
|
||||||
evaluate_side_for(&game.board, Color::Black)
|
|
||||||
);
|
|
||||||
|
|
||||||
let game_2 = from_fen(FEN_QUIET[1])?;
|
|
||||||
let evaluate_white = evaluate_side_for(&game_2.board, Color::White);
|
|
||||||
let evaluate_black = evaluate_side_for(&game_2.board, Color::Black);
|
|
||||||
|
|
||||||
assert_eq!(4005, evaluate_white);
|
|
||||||
assert_eq!(3965, evaluate_black);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_evaluate_position() -> Result<(), String> {
|
|
||||||
let game = from_fen(FEN_QUIET[1])?;
|
|
||||||
assert_eq!(40, evaluate_position(&game.board));
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
pub mod evaluation;
|
pub mod pesto;
|
||||||
pub mod psqt;
|
|
||||||
|
|
||||||
pub const MAX_SCORE: i32 = 100000;
|
pub const MAX_SCORE: i32 = 100000;
|
||||||
pub const MIN_SCORE: i32 = -100000;
|
pub const MIN_SCORE: i32 = -100000;
|
||||||
|
|||||||
263
src/evaluation/pesto.rs
Normal file
263
src/evaluation/pesto.rs
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
|
use crate::board::{
|
||||||
|
board::{Color, PieceType},
|
||||||
|
game::Game,
|
||||||
|
};
|
||||||
|
|
||||||
|
const fn mg_piece_value(piece_type: PieceType) -> i32 {
|
||||||
|
match piece_type {
|
||||||
|
PieceType::Pawn => 82,
|
||||||
|
PieceType::Knight => 337,
|
||||||
|
PieceType::Bishop => 365,
|
||||||
|
PieceType::Rook => 477,
|
||||||
|
PieceType::Queen => 1025,
|
||||||
|
PieceType::King => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn eg_piece_value(piece_type: PieceType) -> i32 {
|
||||||
|
match piece_type {
|
||||||
|
PieceType::Pawn => 94,
|
||||||
|
PieceType::Knight => 281,
|
||||||
|
PieceType::Bishop => 297,
|
||||||
|
PieceType::Rook => 512,
|
||||||
|
PieceType::Queen => 936,
|
||||||
|
PieceType::King => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const MG_PAWN_TABLE: [i32; 64] = [
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
98, 134, 61, 95, 68, 126, 34, -11,
|
||||||
|
-6, 7, 26, 31, 65, 56, 25, -20,
|
||||||
|
-14, 13, 6, 21, 23, 12, 17, -23,
|
||||||
|
-27, -2, -5, 12, 17, 6, 10, -25,
|
||||||
|
-26, -4, -4, -10, 3, 3, 33, -12,
|
||||||
|
-35, -1, -20, -23, -15, 24, 38, -22,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
];
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const EG_PAWN_TABLE: [i32; 64] = [
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
178, 173, 158, 134, 147, 132, 165, 187,
|
||||||
|
94, 100, 85, 67, 56, 53, 82, 84,
|
||||||
|
32, 24, 13, 5, -2, 4, 17, 17,
|
||||||
|
13, 9, -3, -7, -7, -8, 3, -1,
|
||||||
|
4, 7, -6, 1, 0, -5, -1, -8,
|
||||||
|
13, 8, 8, 10, 13, 0, 2, -7,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
];
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const MG_KNIGHT_TABLE: [i32; 64] = [
|
||||||
|
-167, -89, -34, -49, 61, -97, -15, -107,
|
||||||
|
-73, -41, 72, 36, 23, 62, 7, -17,
|
||||||
|
-47, 60, 37, 65, 84, 129, 73, 44,
|
||||||
|
-9, 17, 19, 53, 37, 69, 18, 22,
|
||||||
|
-13, 4, 16, 13, 28, 19, 21, -8,
|
||||||
|
-23, -9, 12, 10, 19, 17, 25, -16,
|
||||||
|
-29, -53, -12, -3, -1, 18, -14, -19,
|
||||||
|
-105, -21, -58, -33, -17, -28, -19, -23,
|
||||||
|
];
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const EG_KNIGHT_TABLE: [i32; 64] = [
|
||||||
|
-58, -38, -13, -28, -31, -27, -63, -99,
|
||||||
|
-25, -8, -25, -2, -9, -25, -24, -52,
|
||||||
|
-24, -20, 10, 9, -1, -9, -19, -41,
|
||||||
|
-17, 3, 22, 22, 22, 11, 8, -18,
|
||||||
|
-18, -6, 16, 25, 16, 17, 4, -18,
|
||||||
|
-23, -3, -1, 15, 10, -3, -20, -22,
|
||||||
|
-42, -20, -10, -5, -2, -20, -23, -44,
|
||||||
|
-29, -51, -23, -15, -22, -18, -50, -64,
|
||||||
|
];
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const MG_BISHOP_TABLE: [i32; 64] = [
|
||||||
|
-29, 4, -82, -37, -25, -42, 7, -8,
|
||||||
|
-26, 16, -18, -13, 30, 59, 18, -47,
|
||||||
|
-16, 37, 43, 40, 35, 50, 37, -2,
|
||||||
|
-4, 5, 19, 50, 37, 37, 7, -2,
|
||||||
|
-6, 13, 13, 26, 34, 12, 10, 4,
|
||||||
|
0, 15, 15, 15, 14, 27, 18, 10,
|
||||||
|
4, 15, 16, 0, 7, 21, 33, 1,
|
||||||
|
-33, -3, -14, -21, -13, -12, -39, -21,
|
||||||
|
];
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const EG_BISHOP_TABLE: [i32; 64] = [
|
||||||
|
-14, -21, -11, -8, -7, -9, -17, -24,
|
||||||
|
-8, -4, 7, -12, -3, -13, -4, -14,
|
||||||
|
2, -8, 0, -1, -2, 6, 0, 4,
|
||||||
|
-3, 9, 12, 9, 14, 10, 3, 2,
|
||||||
|
-6, 3, 13, 19, 7, 10, -3, -9,
|
||||||
|
-12, -3, 8, 10, 13, 3, -7, -15,
|
||||||
|
-14, -18, -7, -1, 4, -9, -15, -27,
|
||||||
|
-23, -9, -23, -5, -9, -16, -5, -17,
|
||||||
|
];
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const MG_ROOK_TABLE: [i32; 64] = [
|
||||||
|
32, 42, 32, 51, 63, 9, 31, 43,
|
||||||
|
27, 32, 58, 62, 80, 67, 26, 44,
|
||||||
|
-5, 19, 26, 36, 17, 45, 61, 16,
|
||||||
|
-24, -11, 7, 26, 24, 35, -8, -20,
|
||||||
|
-36, -26, -12, -1, 9, -7, 6, -23,
|
||||||
|
-45, -25, -16, -17, 3, 0, -5, -33,
|
||||||
|
-44, -16, -20, -9, -1, 11, -6, -71,
|
||||||
|
-19, -13, 1, 17, 16, 7, -37, -26,
|
||||||
|
];
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const EG_ROOK_TABLE: [i32; 64] = [
|
||||||
|
13, 10, 18, 15, 12, 12, 8, 5,
|
||||||
|
11, 13, 13, 11, -3, 3, 8, 3,
|
||||||
|
7, 7, 7, 5, 4, -3, -5, -3,
|
||||||
|
4, 3, 13, 1, 2, 1, -1, 2,
|
||||||
|
3, 5, 8, 4, -5, -6, -8, -11,
|
||||||
|
-4, 0, -5, -1, -7, -12, -8, -16,
|
||||||
|
-6, -6, 0, 2, -9, -9, -11, -3,
|
||||||
|
-9, 2, 3, -1, -5, -13, 4, -20,
|
||||||
|
];
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const MG_QUEEN_TABLE: [i32; 64] = [
|
||||||
|
-28, 0, 29, 12, 59, 44, 43, 45,
|
||||||
|
-24, -39, -5, 1, -16, 57, 28, 54,
|
||||||
|
-13, -17, 7, 8, 29, 56, 47, 57,
|
||||||
|
-27, -27, -16, -16, -1, 17, -2, 1,
|
||||||
|
-9, -26, -9, -10, -2, -4, 3, -3,
|
||||||
|
-14, 2, -11, -2, -5, 2, 14, 5,
|
||||||
|
-35, -8, 11, 2, 8, 15, -3, 1,
|
||||||
|
-1, -18, -9, 10, -15, -25, -31, -50,
|
||||||
|
];
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const EG_QUEEN_TABLE: [i32; 64] = [
|
||||||
|
-9, 22, 22, 27, 27, 19, 10, 20,
|
||||||
|
-17, 20, 32, 41, 58, 25, 30, 0,
|
||||||
|
-20, 6, 9, 49, 47, 35, 19, 9,
|
||||||
|
3, 22, 24, 45, 57, 40, 57, 36,
|
||||||
|
-18, 28, 19, 47, 31, 34, 39, 23,
|
||||||
|
-16, -27, 15, 6, 9, 17, 10, 5,
|
||||||
|
-22, -23, -30, -16, -16, -23, -36, -32,
|
||||||
|
-33, -28, -22, -43, -5, -32, -20, -41,
|
||||||
|
];
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const MG_KING_TABLE: [i32; 64] = [
|
||||||
|
-65, 23, 16, -15, -56, -34, 2, 13,
|
||||||
|
29, -1, -20, -7, -8, -4, -38, -29,
|
||||||
|
-9, 24, 2, -16, -20, 6, 22, -22,
|
||||||
|
-17, -20, -12, -27, -30, -25, -14, -36,
|
||||||
|
-49, -1, -27, -39, -46, -44, -33, -51,
|
||||||
|
-14, -14, -22, -46, -44, -30, -15, -27,
|
||||||
|
1, 7, -8, -64, -43, -16, 9, 8,
|
||||||
|
-15, 36, 12, -54, 8, -28, 24, 14,
|
||||||
|
];
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const EG_KING_TABLE: [i32; 64] = [
|
||||||
|
-74, -35, -18, -18, -11, 15, 4, -17,
|
||||||
|
-12, 17, 14, 17, 17, 38, 23, 11,
|
||||||
|
10, 17, 23, 15, 20, 45, 44, 13,
|
||||||
|
-8, 22, 24, 27, 26, 33, 26, 3,
|
||||||
|
-18, -4, 21, 24, 27, 23, 9, -11,
|
||||||
|
-19, -3, 11, 21, 23, 16, 7, -9,
|
||||||
|
-27, -11, 4, 13, 14, 4, -5, -17,
|
||||||
|
-53, -34, -21, -11, -28, -14, -24, -43
|
||||||
|
];
|
||||||
|
|
||||||
|
const fn mg_psqt(piece_type: PieceType) -> &'static [i32; 64] {
|
||||||
|
match piece_type {
|
||||||
|
PieceType::Pawn => &MG_PAWN_TABLE,
|
||||||
|
PieceType::Knight => &MG_KNIGHT_TABLE,
|
||||||
|
PieceType::Bishop => &MG_BISHOP_TABLE,
|
||||||
|
PieceType::Rook => &MG_ROOK_TABLE,
|
||||||
|
PieceType::Queen => &MG_QUEEN_TABLE,
|
||||||
|
PieceType::King => &MG_KING_TABLE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn eg_psqt(piece_type: PieceType) -> &'static [i32; 64] {
|
||||||
|
match piece_type {
|
||||||
|
PieceType::Pawn => &EG_PAWN_TABLE,
|
||||||
|
PieceType::Knight => &EG_KNIGHT_TABLE,
|
||||||
|
PieceType::Bishop => &EG_BISHOP_TABLE,
|
||||||
|
PieceType::Rook => &EG_ROOK_TABLE,
|
||||||
|
PieceType::Queen => &EG_QUEEN_TABLE,
|
||||||
|
PieceType::King => &EG_KING_TABLE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static PESTO: LazyLock<Pesto> = LazyLock::new(Pesto::init);
|
||||||
|
|
||||||
|
pub fn pesto() -> &'static Pesto {
|
||||||
|
&PESTO
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Pesto {
|
||||||
|
mg_table: [[[i32; 2]; 6]; 64],
|
||||||
|
eg_table: [[[i32; 2]; 6]; 64],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pesto {
|
||||||
|
pub fn init() -> Self {
|
||||||
|
let mut mg_table = [[[0; 2]; 6]; 64];
|
||||||
|
let mut eg_table = [[[0; 2]; 6]; 64];
|
||||||
|
|
||||||
|
for pt in PieceType::iter() {
|
||||||
|
for sq in 0..64 {
|
||||||
|
mg_table[sq][pt][Color::White] = mg_piece_value(pt) + mg_psqt(pt)[sq ^ 56];
|
||||||
|
eg_table[sq][pt][Color::White] = eg_piece_value(pt) + eg_psqt(pt)[sq ^ 56];
|
||||||
|
|
||||||
|
mg_table[sq][pt][Color::Black] = mg_piece_value(pt) + mg_psqt(pt)[sq];
|
||||||
|
eg_table[sq][pt][Color::Black] = eg_piece_value(pt) + eg_psqt(pt)[sq];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Self { mg_table, eg_table }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn eval(&self, game: &Game) -> i32 {
|
||||||
|
let mut mg = [0, 0];
|
||||||
|
let mut eg = [0, 0];
|
||||||
|
let mut phase = 0;
|
||||||
|
|
||||||
|
for sq in 0..64 {
|
||||||
|
if let Some((piece_type, color)) = game.mailbox.piece_at(sq) {
|
||||||
|
mg[color] += self.mg_table[sq][piece_type][color];
|
||||||
|
eg[color] += self.eg_table[sq][piece_type][color];
|
||||||
|
phase += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let (cp, np) = (game.current_player(), game.next_player());
|
||||||
|
let mg_score = mg[cp] - mg[np];
|
||||||
|
let eg_score = eg[cp] - eg[np];
|
||||||
|
let mg_phase = std::cmp::min(phase, 24);
|
||||||
|
let eg_phase = 24 - mg_phase;
|
||||||
|
|
||||||
|
(mg_score * mg_phase + eg_score * eg_phase) / 24
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::board::game::Game;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_pesto_eval_startpost() {
|
||||||
|
let game = Game::new();
|
||||||
|
let pesto = pesto();
|
||||||
|
let eval = pesto.eval(&game);
|
||||||
|
|
||||||
|
assert_eq!(eval, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
use crate::board::board::PieceType;
|
|
||||||
|
|
||||||
pub const fn piece_square_score(piece_type: PieceType, index: usize) -> i32 {
|
|
||||||
match piece_type {
|
|
||||||
PieceType::Pawn => PAWN_PSQT[index],
|
|
||||||
PieceType::Knight => KNIGHT_PSQT[index],
|
|
||||||
PieceType::Bishop => BISHOP_PSQT[index],
|
|
||||||
PieceType::Rook => ROOK_PSQT[index],
|
|
||||||
PieceType::Queen => QUEEN_PSQT[index],
|
|
||||||
PieceType::King => KING_MIDGAME_PSQT[index],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn piece_square_score_endgame(piece_type: PieceType, index: usize) -> i32 {
|
|
||||||
match piece_type {
|
|
||||||
PieceType::Pawn => PAWN_PSQT[index],
|
|
||||||
PieceType::Knight => KNIGHT_PSQT[index],
|
|
||||||
PieceType::Bishop => BISHOP_PSQT[index],
|
|
||||||
PieceType::Rook => ROOK_PSQT[index],
|
|
||||||
PieceType::Queen => QUEEN_PSQT[index],
|
|
||||||
PieceType::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::board::PieceType,
|
|
||||||
board::square::Square,
|
|
||||||
evaluation::psqt::{mirror_index, piece_square_score},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_piece_square_score() -> Result<(), String> {
|
|
||||||
assert_eq!(50, piece_square_score(PieceType::Pawn, Square::A7));
|
|
||||||
assert_eq!(-40, piece_square_score(PieceType::Knight, Square::B1));
|
|
||||||
assert_eq!(0, piece_square_score(PieceType::Bishop, Square::D2));
|
|
||||||
assert_eq!(-5, piece_square_score(PieceType::Rook, Square::A2));
|
|
||||||
assert_eq!(5, piece_square_score(PieceType::Queen, Square::D3));
|
|
||||||
assert_eq!(30, piece_square_score(PieceType::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(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
use crate::{
|
use crate::{board::mailbox::Mailbox, movegen::r#move::Move};
|
||||||
board::mailbox::Mailbox, evaluation::evaluation::material_score, movegen::r#move::Move,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn sort_moves(mut moves: Vec<Move>, mailbox: &Mailbox, tt_move: Option<Move>) -> Vec<Move> {
|
pub fn sort_moves(mut moves: Vec<Move>, mailbox: &Mailbox, tt_move: Option<Move>) -> Vec<Move> {
|
||||||
if let Some(tt_move) = tt_move {
|
if let Some(tt_move) = tt_move {
|
||||||
@@ -17,7 +15,7 @@ pub fn sort_moves(mut moves: Vec<Move>, mailbox: &Mailbox, tt_move: Option<Move>
|
|||||||
|
|
||||||
const fn mvv_lva(mailbox: &Mailbox, mv: Move) -> i32 {
|
const fn mvv_lva(mailbox: &Mailbox, mv: Move) -> i32 {
|
||||||
match (mailbox.piece_at(mv.src), mailbox.piece_at(mv.dst)) {
|
match (mailbox.piece_at(mv.src), mailbox.piece_at(mv.dst)) {
|
||||||
(Some(aggressor), Some(victim)) => material_score(victim.0) - material_score(aggressor.0),
|
(Some(aggressor), Some(victim)) => victim.0.score() - aggressor.0.score(),
|
||||||
_ => -1000,
|
_ => -1000,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
|
|
||||||
use crate::{board::game::Game, evaluation::evaluation::evaluate_position};
|
use crate::{board::game::Game, evaluation::pesto::pesto};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
move_ordering,
|
move_ordering,
|
||||||
@@ -12,7 +12,7 @@ pub fn quiescence(game: &mut Game, mut alpha: i32, beta: i32, time_info: &TimeIn
|
|||||||
bail!("Time is up! In Quiescence");
|
bail!("Time is up! In Quiescence");
|
||||||
}
|
}
|
||||||
|
|
||||||
let stand_pat = evaluate_position(&game.board);
|
let stand_pat = pesto().eval(game);
|
||||||
|
|
||||||
if stand_pat >= beta {
|
if stand_pat >= beta {
|
||||||
return Ok(beta);
|
return Ok(beta);
|
||||||
|
|||||||
Reference in New Issue
Block a user