Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions eval/src/hand_crafted_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,11 @@ impl HandCraftedEval {
fn add_pst(&mut self, p: Piece, square: Square, diff: i8) {
let pst = PIECE_TABLE_REFS[p.piece_type().idx()].pst;
match p.piece_side() {
Side::White => self.pst_scores += diff as Score * pst[square.idx()],
Side::Black => self.pst_scores -= diff as Score * pst[square.flip_vertical().idx()],
Side::White => self.pst_scores += diff as Score * pst[square.fold_to_queenside().idx()],
Side::Black => {
self.pst_scores -=
diff as Score * pst[square.flip_vertical().fold_to_queenside().idx()]
}
}
#[cfg(feature = "trace")]
self.coeffs.add_pst(p, square, diff);
Expand Down Expand Up @@ -347,7 +350,7 @@ impl HandCraftedEval {
);
while white_passed != Bitboard::EMPTY {
let square = white_passed.square_scan_forward_reset();
self.passed_pawn_scores += params::PASSED_PAWN[square.idx()];
self.passed_pawn_scores += params::PASSED_PAWN[square.fold_to_queenside().idx()];
self.passed_pawn_scores += params::PASSED_PAWN_RELATIVE_TO_FRIENDLY_KING
[(OFFSET_RELATIVE_TO_KING
+ square.relative_to(eval_data.kings[Side::White as usize]))
Expand Down Expand Up @@ -382,7 +385,8 @@ impl HandCraftedEval {
);
while black_passed != Bitboard::EMPTY {
let square = black_passed.square_scan_forward_reset();
self.passed_pawn_scores -= params::PASSED_PAWN[square.flip_vertical().idx()];
self.passed_pawn_scores -=
params::PASSED_PAWN[square.flip_vertical().fold_to_queenside().idx()];
self.passed_pawn_scores -= params::PASSED_PAWN_RELATIVE_TO_FRIENDLY_KING
[(OFFSET_RELATIVE_TO_KING
+ square
Expand Down
169 changes: 56 additions & 113 deletions eval/src/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ use movegen::{file::File, rank::Rank, square::Square};

use crate::{score_pair::ScorePair, Score};

pub type PieceSquareTable = [ScorePair; 64];
// Piece square tables:
// We use symmetrical PSTs, so we only define values for half the board. Squares
// on the kingside (right side) will be mirrored to the queenside (left side)
// during evaluation.
const PST_LEN: usize = 32;
pub type PieceSquareTable = [ScorePair; PST_LEN];

pub const KNIGHT_MOB_LEN: usize = 9;
pub const BISHOP_MOB_LEN: usize = 14;
Expand All @@ -27,7 +32,7 @@ const MATERIAL_PAWN: ScorePair = ScorePair(0, 0);
pub const TEMPO: ScorePair = ScorePair(29, 29);

#[rustfmt::skip]
const PASSED_PAWN_MG_EG: ([Score; 32], [Score; 32]) = (
const PASSED_PAWN_MG_EG: ([Score; PST_LEN], [Score; PST_LEN]) = (
[
0, 0, 0, 0,
0, 0, 0, 0,
Expand Down Expand Up @@ -329,11 +334,8 @@ const PASSED_PAWN_RELATIVE_TO_ENEMY_KING_MG_EG: (
],
);

// Piece square tables:
// We only define values for the queenside (left side) and mirror them to the
// kingside (right side) so that we end up with symmetrical PSTs.
#[rustfmt::skip]
const PST_PAWN_MG_EG: ([Score; 32], [Score; 32]) = (
const PST_PAWN_MG_EG: ([Score; PST_LEN], [Score; PST_LEN]) = (
[
0, 0, 0, 0,
111, 153, 152, 164,
Expand All @@ -356,7 +358,7 @@ const PST_PAWN_MG_EG: ([Score; 32], [Score; 32]) = (
],
);
#[rustfmt::skip]
const PST_KNIGHT_MG_EG: ([Score; 32], [Score; 32]) = (
const PST_KNIGHT_MG_EG: ([Score; PST_LEN], [Score; PST_LEN]) = (
[
185, 278, 255, 307,
300, 294, 398, 325,
Expand All @@ -379,7 +381,7 @@ const PST_KNIGHT_MG_EG: ([Score; 32], [Score; 32]) = (
],
);
#[rustfmt::skip]
const PST_BISHOP_MG_EG: ([Score; 32], [Score; 32]) = (
const PST_BISHOP_MG_EG: ([Score; PST_LEN], [Score; PST_LEN]) = (
[
303, 309, 292, 252,
296, 356, 337, 342,
Expand All @@ -402,7 +404,7 @@ const PST_BISHOP_MG_EG: ([Score; 32], [Score; 32]) = (
],
);
#[rustfmt::skip]
const PST_ROOK_MG_EG: ([Score; 32], [Score; 32]) = (
const PST_ROOK_MG_EG: ([Score; PST_LEN], [Score; PST_LEN]) = (
[
540, 567, 560, 560,
564, 539, 560, 550,
Expand All @@ -425,7 +427,7 @@ const PST_ROOK_MG_EG: ([Score; 32], [Score; 32]) = (
],
);
#[rustfmt::skip]
const PST_QUEEN_MG_EG: ([Score; 32], [Score; 32]) = (
const PST_QUEEN_MG_EG: ([Score; PST_LEN], [Score; PST_LEN]) = (
[
958, 968, 965, 987,
983, 957, 946, 883,
Expand All @@ -448,7 +450,7 @@ const PST_QUEEN_MG_EG: ([Score; 32], [Score; 32]) = (
],
);
#[rustfmt::skip]
const PST_KING_MG_EG: ([Score; 32], [Score; 32]) = (
const PST_KING_MG_EG: ([Score; PST_LEN], [Score; PST_LEN]) = (
[
15, 8, 33, 5,
-13, 3, 35, -1,
Expand All @@ -471,21 +473,37 @@ const PST_KING_MG_EG: ([Score; 32], [Score; 32]) = (
],
);

const fn human_readable_to_file_rank(piece_value: Score, pst: [Score; 32]) -> [Score; 64] {
let mut res = [0; 64];
const fn human_readable_to_file_rank(
material_value: Score,
pst: [Score; PST_LEN],
) -> [Score; PST_LEN] {
let mut res = [0; PST_LEN];
let mut idx = 0;
while idx < 32 {
while idx < PST_LEN {
let rank = 7 - idx / 4;
let file = idx % 4;
let new_idx = Square::from_file_and_rank(File::from_idx(file), Rank::from_idx(rank)).idx();
let mirrored_idx = Square::from_idx(new_idx).mirror_horizontal().idx();
res[new_idx] = piece_value + pst[idx];
res[mirrored_idx] = piece_value + pst[idx];
res[new_idx] = material_value + pst[idx];
idx += 1;
}
res
}

const fn convert_pst(
material_value: ScorePair,
mg_eg: ([Score; PST_LEN], [Score; PST_LEN]),
) -> PieceSquareTable {
let mg = human_readable_to_file_rank(material_value.0, mg_eg.0);
let eg = human_readable_to_file_rank(material_value.1, mg_eg.1);
let mut table = [ScorePair(0, 0); PST_LEN];
let mut idx = 0;
while idx < PST_LEN {
table[idx] = ScorePair(mg[idx], eg[idx]);
idx += 1;
}
table
}

const fn convert_square_relative_to(
mg_eg: (
[Score; PIECE_RELATIVE_TO_KING_LEN],
Expand Down Expand Up @@ -594,89 +612,14 @@ pub const PASSED_PAWN_RELATIVE_TO_FRIENDLY_KING: [ScorePair; PASSED_PAWNS_RELATI
pub const PASSED_PAWN_RELATIVE_TO_ENEMY_KING: [ScorePair; PASSED_PAWNS_RELATIVE_TO_KING_LEN] =
convert_passed_pawn_relative_to(PASSED_PAWN_RELATIVE_TO_ENEMY_KING_MG_EG);

pub const PASSED_PAWN: PieceSquareTable = {
let mg = human_readable_to_file_rank(0, PASSED_PAWN_MG_EG.0);
let eg = human_readable_to_file_rank(0, PASSED_PAWN_MG_EG.1);
let mut table = [ScorePair(0, 0); 64];
let mut idx = 0;
while idx < 64 {
table[idx] = ScorePair(mg[idx], eg[idx]);
idx += 1;
}
table
};

pub const PST_PAWN: PieceSquareTable = {
let mg = human_readable_to_file_rank(MATERIAL_PAWN.0, PST_PAWN_MG_EG.0);
let eg = human_readable_to_file_rank(MATERIAL_PAWN.1, PST_PAWN_MG_EG.1);
let mut table = [ScorePair(0, 0); 64];
let mut idx = 0;
while idx < 64 {
table[idx] = ScorePair(mg[idx], eg[idx]);
idx += 1;
}
table
};

pub const PST_KNIGHT: PieceSquareTable = {
let mg = human_readable_to_file_rank(MATERIAL_KNIGHT.0, PST_KNIGHT_MG_EG.0);
let eg = human_readable_to_file_rank(MATERIAL_KNIGHT.1, PST_KNIGHT_MG_EG.1);
let mut table = [ScorePair(0, 0); 64];
let mut idx = 0;
while idx < 64 {
table[idx] = ScorePair(mg[idx], eg[idx]);
idx += 1;
}
table
};

pub const PST_BISHOP: PieceSquareTable = {
let mg = human_readable_to_file_rank(MATERIAL_BISHOP.0, PST_BISHOP_MG_EG.0);
let eg = human_readable_to_file_rank(MATERIAL_BISHOP.1, PST_BISHOP_MG_EG.1);
let mut table = [ScorePair(0, 0); 64];
let mut idx = 0;
while idx < 64 {
table[idx] = ScorePair(mg[idx], eg[idx]);
idx += 1;
}
table
};

pub const PST_ROOK: PieceSquareTable = {
let mg = human_readable_to_file_rank(MATERIAL_ROOK.0, PST_ROOK_MG_EG.0);
let eg = human_readable_to_file_rank(MATERIAL_ROOK.1, PST_ROOK_MG_EG.1);
let mut table = [ScorePair(0, 0); 64];
let mut idx = 0;
while idx < 64 {
table[idx] = ScorePair(mg[idx], eg[idx]);
idx += 1;
}
table
};

pub const PST_QUEEN: PieceSquareTable = {
let mg = human_readable_to_file_rank(MATERIAL_QUEEN.0, PST_QUEEN_MG_EG.0);
let eg = human_readable_to_file_rank(MATERIAL_QUEEN.1, PST_QUEEN_MG_EG.1);
let mut table = [ScorePair(0, 0); 64];
let mut idx = 0;
while idx < 64 {
table[idx] = ScorePair(mg[idx], eg[idx]);
idx += 1;
}
table
};
pub const PASSED_PAWN: PieceSquareTable = convert_pst(ScorePair(0, 0), PASSED_PAWN_MG_EG);

pub const PST_KING: PieceSquareTable = {
let mg = human_readable_to_file_rank(MATERIAL_KING.0, PST_KING_MG_EG.0);
let eg = human_readable_to_file_rank(MATERIAL_KING.1, PST_KING_MG_EG.1);
let mut table = [ScorePair(0, 0); 64];
let mut idx = 0;
while idx < 64 {
table[idx] = ScorePair(mg[idx], eg[idx]);
idx += 1;
}
table
};
pub const PST_PAWN: PieceSquareTable = convert_pst(MATERIAL_PAWN, PST_PAWN_MG_EG);
pub const PST_KNIGHT: PieceSquareTable = convert_pst(MATERIAL_KNIGHT, PST_KNIGHT_MG_EG);
pub const PST_BISHOP: PieceSquareTable = convert_pst(MATERIAL_BISHOP, PST_BISHOP_MG_EG);
pub const PST_ROOK: PieceSquareTable = convert_pst(MATERIAL_ROOK, PST_ROOK_MG_EG);
pub const PST_QUEEN: PieceSquareTable = convert_pst(MATERIAL_QUEEN, PST_QUEEN_MG_EG);
pub const PST_KING: PieceSquareTable = convert_pst(MATERIAL_KING, PST_KING_MG_EG);

#[cfg(test)]
mod tests {
Expand All @@ -697,19 +640,19 @@ mod tests {
];

let res = super::human_readable_to_file_rank(100, arr);
assert_eq!(156, res[Square::A1.idx()]);
assert_eq!(148, res[Square::A2.idx()]);
assert_eq!(100, res[Square::A8.idx()]);
assert_eq!(157, res[Square::B1.idx()]);
assert_eq!(149, res[Square::B2.idx()]);
assert_eq!(142, res[Square::C3.idx()]);
assert_eq!(135, res[Square::D4.idx()]);
assert_eq!(127, res[Square::E5.idx()]);
assert_eq!(118, res[Square::F6.idx()]);
assert_eq!(109, res[Square::G7.idx()]);
assert_eq!(101, res[Square::G8.idx()]);
assert_eq!(156, res[Square::H1.idx()]);
assert_eq!(108, res[Square::H7.idx()]);
assert_eq!(100, res[Square::H8.idx()]);
assert_eq!(156, res[Square::A1.fold_to_queenside().idx()]);
assert_eq!(148, res[Square::A2.fold_to_queenside().idx()]);
assert_eq!(100, res[Square::A8.fold_to_queenside().idx()]);
assert_eq!(157, res[Square::B1.fold_to_queenside().idx()]);
assert_eq!(149, res[Square::B2.fold_to_queenside().idx()]);
assert_eq!(142, res[Square::C3.fold_to_queenside().idx()]);
assert_eq!(135, res[Square::D4.fold_to_queenside().idx()]);
assert_eq!(127, res[Square::E5.fold_to_queenside().idx()]);
assert_eq!(118, res[Square::F6.fold_to_queenside().idx()]);
assert_eq!(109, res[Square::G7.fold_to_queenside().idx()]);
assert_eq!(101, res[Square::G8.fold_to_queenside().idx()]);
assert_eq!(156, res[Square::H1.fold_to_queenside().idx()]);
assert_eq!(108, res[Square::H7.fold_to_queenside().idx()]);
assert_eq!(100, res[Square::H8.fold_to_queenside().idx()]);
}
}