timecat 1.52.0

A NNUE-based chess engine that implements the Negamax algorithm and can be integrated into any project as a library. It features move generation, advanced position evaluation through NNUE, and move searching capabilities.
Documentation
use super::*;

#[rustfmt::skip]
static PSQT_ARRAY: [Score; 768] = [
    // Pawn Opening Phase:
      0,  0,  0,  0,  0,  0,  0,  0,
     50, 50, 50, 50, 50, 50, 50, 50,
     10, 20, 30, 40, 40, 30, 20, 10,
      5, 10, 20, 35, 35, 20, 10,  5,
      0,  5, 10, 30, 30, 10,  5,  0,
      5, -5,-10, 20, 20,-10, -5,  5,
      5, 10, 10,-20,-20, 10, 10,  5,
      0,  0,  0,  0,  0,  0,  0,  0,
    
    // Pawn Endgame Phase:
     60, 60, 60, 60, 60, 60, 60, 60,
     50, 50, 50, 50, 50, 50, 50, 50,
     40, 40, 40, 40, 40, 40, 40, 40,
     30, 30, 30, 30, 30, 30, 30, 30,
     20, 20, 20, 20, 20, 20, 20, 20,
     10, 10, 10, 10, 10, 10, 10, 10,
      0,  0,  0,  0,  0,  0,  0,  0,
      0,  0,  0,  0,  0,  0,  0,  0,

    // Knight Opening Phase:
    -50,-40,-30,-30,-30,-30,-40,-50,
    -40,-20,  0, 10, 10,  0,-20,-40,
    -30,  0, 15, 20, 20, 15,  0,-30,
    -30,  5, 20, 25, 25, 20,  5,-30,
    -30,  5, 20, 25, 25, 20,  5,-30,
    -30,  0, 15, 20, 20, 15,  0,-30,
    -40,-20,  0, 10, 10,  0,-20,-40,
    -50,-40,-30,-30,-30,-30,-40,-50,

    // Knight Endgame Phase:
    -50,-40,-30,-30,-30,-30,-40,-50,
    -40,-20,-10,  0,  0,-10,-20,-40,
    -30,-10, 10, 20, 20, 10,-10,-30,
    -30,  0, 20, 25, 25, 20,  0,-30,
    -30,  0, 20, 25, 25, 20,  0,-30,
    -30,-10, 10, 20, 20, 10,-10,-30,
    -40,-20,-10,  0,  0,-10,-20,-40,
    -50,-40,-30,-30,-30,-30,-40,-50,

    // Bishop Opening Phase:
    -20,-10,-10,-10,-10,-10,-10,-20,
    -10,  0,  5, 10, 10,  5,  0,-10,
    -10,  5, 10, 15, 15, 10,  5,-10,
    -10, 10, 10, 20, 20, 10, 10,-10,
    -10,  5, 15, 20, 20, 15,  5,-10,
    -10, 10, 10, 20, 20, 10, 10,-10,
    -10,  5,  5,  5,  5,  5,  5,-10,
    -20,-10,-10,-10,-10,-10,-10,-20,

    // Bishop Endgame Phase:
    -20,-10,-10,-10,-10,-10,-10,-20,
    -10,  0,  0, 10, 10,  0,  0,-10,
    -10,  0, 10, 20, 20, 10,  0,-10,
    -10, 10, 10, 30, 30, 10, 10,-10,
    -10, 10, 10, 30, 30, 10, 10,-10,
    -10,  0, 10, 20, 20, 10,  0,-10,
    -10,  0,  0, 10, 10,  0,  0,-10,
    -20,-10,-10,-10,-10,-10,-10,-20,

    // Rook Opening Phase:
      0,  0,  5, 10, 10,  5,  0,  0,
      5, 10, 10, 10, 10, 10, 10,  5,
      0,  5,  5,  5,  5,  5,  5,  0,
      0,  5,  5,  5,  5,  5,  5,  0,
      0,  5,  5,  5,  5,  5,  5,  0,
      0,  5,  5,  5,  5,  5,  5,  0,
      5, 10, 10, 10, 10, 10, 10,  5,
      0,  0,  5, 10, 10,  5,  0,  0,
    
    // Rook Endgame Phase:
     40, 50, 50, 50, 50, 50, 50, 40,
     50, 60, 60, 60, 60, 60, 60, 50,
     40, 50, 50, 50, 50, 50, 50, 40,
     40, 50, 50, 50, 50, 50, 50, 40,
     40, 50, 50, 50, 50, 50, 50, 40,
     40, 50, 50, 50, 50, 50, 50, 40,
     50, 60, 60, 60, 60, 60, 60, 50,
     40, 50, 50, 50, 50, 50, 50, 40,

    // Queen Opening Phase:
    -20,-10,-10, -5, -5,-10,-10,-20,
    -10,  0,  5,  5,  5,  5,  0,-10,
    -10,  5,  5, 10, 10,  5,  5,-10,
     -5,  0, 10, 10, 10, 10,  0, -5,
      0,  5, 10, 10, 10, 10,  5,  0,
    -10,  5,  5, 10, 10,  5,  5,-10,
    -10,  0,  5,  5,  5,  5,  0,-10,
    -20,-10,-10, -5, -5,-10,-10,-20,

    // Queen Endgame Phase:
    -20,-10,-10, -5, -5,-10,-10,-20,
    -10,  0,  5,  5,  5,  5,  0,-10,
    -10,  5,  5, 10, 10,  5,  5,-10,
     -5,  0, 10, 10, 10, 10,  0, -5,
     -5,  0, 10, 10, 10, 10,  0, -5,
    -10,  5,  5, 10, 10,  5,  5,-10,
    -10,  0,  5,  5,  5,  5,  0,-10,
    -20,-10,-10, -5, -5,-10,-10,-20,

    // King Opening Phase:
    -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,
    -20,-30,-30,-40,-40,-30,-30,-20,
    -10,-15,-20,-20,-20,-20,-15,-10,
     20, 20,  0,  0,  0,  0, 20, 20,
     20, 30, 10,  0,  0, 10, 30, 20,
    
    // King Endgame Phase:
    -50,-40,-30,-30,-30,-30,-40,-50,
    -40,-20,-10,  0,  0,-10,-20,-40,
    -40,-10, 20, 30, 30, 20,-10,-40,
    -30,  0, 30, 40, 40, 30,  0,-30,
    -30,  0, 30, 40, 40, 30,  0,-30,
    -40,-10, 20, 30, 30, 20,-10,-40,
    -40,-30,  0,  0,  0,  0,-30,-40,
    -50,-40,-40,-30,-30,-40,-40,-50,
];

pub fn get_psqt_score_index_opening(piece: Piece, mut square: Square) -> usize {
    if piece.get_color() == White {
        square = square.horizontal_mirror();
    }
    (piece.get_piece_type().to_index() << 7) ^ square.to_index()
}

#[inline]
pub fn get_psqt_score_index_endgame(piece: Piece, square: Square) -> usize {
    get_psqt_score_index_opening(piece, square) ^ 64
}

#[inline]
pub fn get_psqt_score_opening(piece: Piece, square: Square) -> Score {
    *get_item_unchecked!(PSQT_ARRAY, get_psqt_score_index_opening(piece, square))
}

#[inline]
pub fn get_psqt_score_endgame(piece: Piece, square: Square) -> Score {
    *get_item_unchecked!(PSQT_ARRAY, get_psqt_score_index_endgame(piece, square))
}

pub fn get_psqt_score(piece: Piece, mut square: Square, alpha: f64) -> Score {
    let alpha = (1000.0 * alpha) as i32;
    if piece.get_color() == White {
        square = square.horizontal_mirror();
    }
    let opening_index = (piece.get_piece_type().to_index() << 7) ^ square.to_index();
    let opening_score = *get_item_unchecked!(PSQT_ARRAY, opening_index) as i32;
    let endgame_score = *get_item_unchecked!(PSQT_ARRAY, opening_index ^ 64) as i32;
    ((alpha * opening_score + (1000 - alpha) + endgame_score) / 1000) as Score
}