<commit_before>//! Facilities for implementing static position evaluation.
//!
//! # Static position evaluation
//!
//! An evaluation function is used to heuristically determine the
//! relative value of a position, i.e. the chances of winning. If we
//! could see to the end of the game in every line, the evaluation
//! would only have values of "loss", "draw", and "win". In practice,
//! however, we do not know the exact value of a position, so we must
//! make an approximation. Beginning chess players learn to do this
//! starting with the value of the pieces themselves. Computer
//! evaluation functions also use the value of the material as the
//! most significant aspect and then add other considerations.
//!
//! Static evaluation is an evaluation that considers only the static
//! material and positional properties of the current position,
//! without analyzing any tactical variations. Therefore, if the
//! position has pending tactical threats, the static evaluation will
//! be grossly incorrect.
//!
//! Writing a new static evaluator is as simple as defining a type
//! that implements the `BoardEvaluator` trait. Then you pass that as
//! a type parameter to `Position`.
//!
//! # Writing your own move generator
//!
//! The generation of moves is at the heart of every chess
//! engine. `Position` implements a very fast move generator, and
//! also: quiescence search, static exchange evaluation, move legality
//! check, hashing. Re-writing those things is a lot of work. Still,
//! if you decide to do this, you should write your own implementation
//! of the `SearchNode` trait.
mod notation;
mod rules;
pub mod tables;
pub mod bitsets;
pub mod evaluators;

use std::mem::uninitialized;
use std::cell::Cell;
use chesstypes::*;
use chesstypes::moves::{get_aux_data, get_dest_square, get_orig_square, get_move_type};
use search::MoveStack;
use uci::SetOption;
use board::notation::parse_fen;
use board::bitsets::*;
use board::tables::{BoardGeometry, ZobristArrays};
pub use board::rules::Position;


/// A trait used to statically evaluate positions.
pub trait BoardEvaluator: Clone + Send + SetOption {
    /// Creates a new instance and binds it to a given position.
    ///
    /// When a new instance is created, it is bound to a particular
    /// chess position (given by the `board` parameter). And for a
    /// moment, this is the only position that can be correctly
    /// evaluated. The instance then can be re-bound to the next (or
    /// the previous) position in the line of play by issuing calls to
    /// `will_do_move` and `done_move` methods (or respectively,
    /// `will_undo_move` and `undone_move` methods) .
    fn new(board: &Board<Self>) -> Self;

    /// Evaluates the the position to which the instance is bound.
    ///
    /// `board` points to the position to which the instance is bound.
    ///
    /// The returned value must be between `VALUE_EVAL_MIN` and
    /// `VALUE_EVAL_MAX`.
    fn evaluate(&self, board: &Board<Self>) -> Value;

    /// Returns whether the position is zugzwangy.
    ///
    /// In many endgame positions there is a relatively high
    /// probability of zugzwang occurring. For such positions, this
    /// method returns `true`.
    fn is_zugzwangy(&self) -> bool;

    /// Updates evaluator's state to keep up with a move that will be
    /// played.
    ///
    /// `board` points to the position to which the instance is bound.
    ///
    /// `m` is a legal move, or (if not in check) a "null move".
    #[inline]
    #[allow(unused_variables)]
    fn will_do_move(&mut self, board: &Board<Self>, m: Move) {}

    /// Updates evaluator's state to keep up with a move that was
    /// played.
    ///
    /// `board` points to the new position to which the instance is
    /// bound.
    #[inline]
    #[allow(unused_variables)]
    fn done_move(&mut self, board: &Board<Self>, m: Move) {}

    /// Updates evaluator's state to keep up with a move that will be
    /// taken back.
    ///
    /// `board` points to the position to which the instance is bound.
    #[inline]
    #[allow(unused_variables)]
    fn will_undo_move(&mut self, board: &Board<Self>, m: Move) {}

    /// Updates evaluator's state in accordance with a move that was
    /// taken back.
    ///
    /// `board` points to the new position to which the instance is
    /// bound.
    #[inline]
    #[allow(unused_variables)]
    fn undone_move(&mut self, board: &Board<Self>, m: Move) {}
}


/// Holds a chess position.
#[derive(Clone)]
pub struct Board<E: BoardEvaluator> {
    geometry: &'static BoardGeometry,
    zobrist: &'static ZobristArrays,
    evaluator: E,

    /// The placement of the pieces on the board.
    pieces: PiecesPlacement,

    /// The side to move.
    to_move: Color,

    /// The castling rights for both players.
    castling_rights: CastlingRights,

    /// If the previous move was a double pawn push, contains pushed
    /// pawn's file (a value between 0 and 7). Otherwise contains `8`.
    en_passant_file: usize,

    /// This will always be equal to `self.pieces.color[WHITE] |
    /// self.pieces.color[BLACK]`
    _occupied: Bitboard,

    /// Lazily calculated bitboard of all checkers --
    /// `BB_UNIVERSAL_SET` if not calculated yet.
    _checkers: Cell<Bitboard>,
}


// In a nutshell: `Board` can generate all possible moves in the
// current position, play a selected move, and take it back. It can
// also play a "null move" which can be used to selectively prune the
// search tree. `Board` does not try to be too clever. In particular,
// it is completely unaware of repeating positions and
// rule-50. Although `Board` is able to statically evaluate the
// position, it delagates this to `BoardEvaluator`.
//
// Note that many of the implemented methods are private -- they are
// used solely by the module `board::rules`.
impl<E: BoardEvaluator> Board<E> {
    /// Creates a new instance.
    ///
    /// Verifies that the position is legal.
    fn from_raw_parts(pieces: &PiecesPlacement,
                      to_move: Color,
                      castling_rights: CastlingRights,
                      en_passant_square: Option<Square>)
                      -> Result<Board<E>, String> {<commit_msg>update comment<commit_after>//! Facilities for implementing static position evaluation.
//!
//! # Static position evaluation
//!
//! An evaluation function is used to heuristically determine the
//! relative value of a position, i.e. the chances of winning. If we
//! could see to the end of the game in every line, the evaluation
//! would only have values of "loss", "draw", and "win". In practice,
//! however, we do not know the exact value of a position, so we must
//! make an approximation. Beginning chess players learn to do this
//! starting with the value of the pieces themselves. Computer
//! evaluation functions also use the value of the material as the
//! most significant aspect and then add other considerations.
//!
//! Static evaluation is an evaluation that considers only the static
//! material and positional properties of the current position,
//! without analyzing any tactical variations. Therefore, if the
//! position has pending tactical threats, the static evaluation will
//! be grossly incorrect.
//!
//! Writing a new static evaluator is as simple as defining a type
//! that implements the `BoardEvaluator` trait. Then you pass that as
//! a type parameter to `Position`.
//!
//! # Writing your own move generator
//!
//! The generation of moves is at the heart of every chess
//! engine. `Position` implements a very fast move generator, and
//! also: quiescence search, static exchange evaluation, move legality
//! check, hashing. Re-writing those things is a lot of work. Still,
//! if you decide to do this, you should write your own implementation
//! of the `SearchNode` trait.
mod notation;
mod rules;
pub mod tables;
pub mod bitsets;
pub mod evaluators;

use std::mem::uninitialized;
use std::cell::Cell;
use chesstypes::*;
use chesstypes::moves::{get_aux_data, get_dest_square, get_orig_square, get_move_type};
use search::MoveStack;
use uci::SetOption;
use board::notation::parse_fen;
use board::bitsets::*;
use board::tables::{BoardGeometry, ZobristArrays};
pub use board::rules::Position;


/// A trait used to statically evaluate positions.
pub trait BoardEvaluator: Clone + Send + SetOption {
    /// Creates a new instance and binds it to a given position.
    ///
    /// When a new instance is created, it is bound to a particular
    /// chess position (given by the `board` parameter). And for a
    /// moment, this is the only position that can be correctly
    /// evaluated. The instance then can be re-bound to the next (or
    /// the previous) position in the line of play by issuing calls to
    /// `will_do_move` and `done_move` methods (or respectively,
    /// `will_undo_move` and `undone_move` methods) .
    fn new(board: &Board<Self>) -> Self;

    /// Evaluates the the position to which the instance is bound.
    ///
    /// `board` points to the position to which the instance is bound.
    ///
    /// The returned value must be between `VALUE_EVAL_MIN` and
    /// `VALUE_EVAL_MAX`.
    fn evaluate(&self, board: &Board<Self>) -> Value;

    /// Returns whether the position is zugzwangy.
    ///
    /// In many endgame positions there is a relatively high
    /// probability of zugzwang occurring. For such positions, this
    /// method returns `true`.
    fn is_zugzwangy(&self) -> bool;

    /// Updates evaluator's state to keep up with a move that will be
    /// played.
    ///
    /// `board` points to the position to which the instance is bound.
    ///
    /// `m` is a legal move, or (if not in check) a "null move".
    #[inline]
    #[allow(unused_variables)]
    fn will_do_move(&mut self, board: &Board<Self>, m: Move) {}

    /// Updates evaluator's state to keep up with a move that was
    /// played.
    ///
    /// `board` points to the new position to which the instance is
    /// bound.
    #[inline]
    #[allow(unused_variables)]
    fn done_move(&mut self, board: &Board<Self>, m: Move) {}

    /// Updates evaluator's state to keep up with a move that will be
    /// taken back.
    ///
    /// `board` points to the position to which the instance is bound.
    #[inline]
    #[allow(unused_variables)]
    fn will_undo_move(&mut self, board: &Board<Self>, m: Move) {}

    /// Updates evaluator's state in accordance with a move that was
    /// taken back.
    ///
    /// `board` points to the new position to which the instance is
    /// bound.
    #[inline]
    #[allow(unused_variables)]
    fn undone_move(&mut self, board: &Board<Self>, m: Move) {}
}


/// Holds a chess position.
#[derive(Clone)]
pub struct Board<E: BoardEvaluator> {
    geometry: &'static BoardGeometry,
    zobrist: &'static ZobristArrays,
    evaluator: E,

    /// The placement of the pieces on the board.
    pieces: PiecesPlacement,

    /// The side to move.
    to_move: Color,

    /// The castling rights for both players.
    castling_rights: CastlingRights,

    /// If the previous move was a double pawn push, contains pushed
    /// pawn's file (a value between 0 and 7). Otherwise contains `8`.
    en_passant_file: usize,

    /// This will always be equal to `self.pieces.color[WHITE] |
    /// self.pieces.color[BLACK]`
    _occupied: Bitboard,

    /// Lazily calculated bitboard of all checkers --
    /// `BB_UNIVERSAL_SET` if not calculated yet.
    _checkers: Cell<Bitboard>,
}


// In a nutshell: `Board` can generate all possible moves in the
// current position, play a selected move, and take it back. It can
// also play a "null move" which can be used to selectively prune the
// search tree. `Board` does not try to be too clever. In particular,
// it is completely unaware of repeating positions and
// rule-50. Although `Board` is able to statically evaluate the
// position and decide if it is zugzwangy, it delegates this to
// `BoardEvaluator`.
//
// Note that many of the implemented methods are private -- they are
// used solely by the module `board::rules`.
impl<E: BoardEvaluator> Board<E> {
    /// Creates a new instance.
    ///
    /// Verifies that the position is legal.
    fn from_raw_parts(pieces: &PiecesPlacement,
                      to_move: Color,
                      castling_rights: CastlingRights,
                      en_passant_square: Option<Square>)
                      -> Result<Board<E>, String> {
{'fraction_non_alphanumeric': 0.11025641025641025, 'fraction_numerical': 0.0008012820512820513, 'mean_word_length': 2.8485969781066913, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6491617', 'n_tokens_mistral': 3571, 'n_tokens_neox': 3439, 'n_words': 1553}