use crate::color::Color;
use crate::piece::Piece;
use crate::position::Position;
use crate::square::Square;
pub const ADVANCED_VALUE: i32 = 3;
pub const MATE_VALUE: i32 = 10_000;
pub const BAN_VALUE: i32 = MATE_VALUE - 100;
pub const WIN_VALUE: i32 = MATE_VALUE - 200;
pub const NULL_OKAY_MARGIN: i32 = 200;
pub const DRAW_VALUE: i32 = 20;
pub const PST: [[i16; 90]; 7] = {
const KING_OR_PAWN: [i16; 90] = [
0, 0, 0, 11, 15, 11, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 7, 0, 7, 0, 15, 0, 7, 0, 7, 7, 0, 13, 0, 16, 0, 13, 0, 7, 14, 18, 20, 27, 29, 27, 20, 18, 14, 19, 23, 27, 29, 30, 29, 27, 23, 19, 19, 24, 32, 37, 37, 37, 32, 24, 19, 19, 24, 34, 42, 44, 42, 34, 24, 19, 9, 9, 9, 11, 13, 11, 9, 9, 9,
];
const ADVISOR_OR_BISHOP: [i16; 90] = [
0, 0, 20, 20, 0, 20, 20, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 18, 0, 0, 20, 23, 20, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
];
const KNIGHT: [i16; 90] = [
88, 85, 90, 88, 90, 88, 90, 85, 88, 85, 90, 92, 93, 78, 93, 92, 90, 85, 93, 92, 94, 95, 92, 95, 94, 92, 93, 92, 94, 98, 95, 98, 95, 98, 94, 92, 90, 98, 101, 102, 103, 102, 101, 98, 90, 90, 100, 99, 103, 104, 103, 99, 100, 90, 93, 108, 100, 107, 100, 107, 100, 108, 93, 92, 98, 99, 103, 99, 103, 99, 98, 92, 90, 96, 103, 97, 94, 97, 103, 96, 90, 90, 90, 90, 96, 90, 96, 90, 90, 90, ];
const ROOK: [i16; 90] = [
194, 206, 204, 212, 200, 212, 204, 206, 194, 200, 208, 206, 212, 200, 212, 206, 208, 200, 198, 208, 204, 212, 212, 212, 204, 208, 198, 204, 209, 204, 212, 214, 212, 204, 209, 204, 208, 212, 212, 214, 215, 214, 212, 212, 208, 208, 211, 211, 214, 215, 214, 211, 211, 208, 206, 213, 213, 216, 216, 216, 213, 213, 206, 206, 208, 207, 214, 216, 214, 207, 208, 206, 206, 212, 209, 216, 233, 216, 209, 212, 206, 206, 208, 207, 213, 214, 213, 207, 208, 206, ];
const CANNON: [i16; 90] = [
96, 96, 97, 99, 99, 99, 97, 96, 96, 96, 97, 98, 98, 98, 98, 98, 97, 96, 97, 96, 100, 99, 101, 99, 100, 96, 97, 96, 96, 96, 96, 96, 96, 96, 96, 96, 95, 96, 99, 96, 100, 96, 99, 96, 95, 96, 96, 96, 96, 100, 96, 96, 96, 96, 96, 99, 99, 98, 100, 98, 99, 99, 96, 97, 97, 96, 91, 92, 91, 96, 97, 97, 98, 98, 96, 92, 89, 92, 96, 98, 98, 100, 100, 96, 91, 90, 91, 96, 100, 100, ];
[KING_OR_PAWN, ADVISOR_OR_BISHOP, ADVISOR_OR_BISHOP, KNIGHT, ROOK, CANNON, KING_OR_PAWN]
};
#[inline]
pub const fn psq_value(piece: Piece, sq: Square) -> i16 {
let idx = match piece.color() {
Color::Red => sq.raw() as usize,
Color::Black => sq.flip_rank().raw() as usize,
};
PST[piece.kind().index()][idx]
}
#[inline]
pub fn evaluate(pos: &Position) -> i32 {
let red_score = pos.psq_score() + ADVANCED_VALUE;
match pos.side_to_move() {
Color::Red => red_score,
Color::Black => -red_score,
}
}
#[inline]
pub fn draw_value(ply_from_root: u32) -> i32 { if ply_from_root & 1 == 0 { -DRAW_VALUE } else { DRAW_VALUE } }
#[cfg(test)]
mod tests {
use super::*;
use crate::fen::STARTING_FEN;
use crate::piece::PieceType;
#[test]
fn startpos_is_balanced() {
let pos = Position::from_fen(STARTING_FEN).unwrap();
let s = evaluate(&pos);
assert!(s.abs() <= ADVANCED_VALUE + 1, "startpos score = {s}");
}
#[test]
fn rook_initial_psq_matches() {
let sq = Square::from_iccs("a0").unwrap();
let piece = Piece::new(Color::Red, PieceType::Rook);
assert_eq!(psq_value(piece, sq), 194);
}
}