stub: static exchange evaluation
not yet used, but will be useful hopefully
This commit is contained in:
parent
1d651de4a0
commit
a36f394b99
133
src/eval.rs
133
src/eval.rs
@ -13,7 +13,7 @@ Copyright © 2024 dogeystamp <dogeystamp@disroot.org>
|
||||
|
||||
//! Position evaluation.
|
||||
|
||||
use crate::{Board, Color, Piece, Square, N_COLORS, N_PIECES, N_SQUARES};
|
||||
use crate::prelude::*;
|
||||
use core::cmp::{max, min};
|
||||
use core::ops::Index;
|
||||
|
||||
@ -29,6 +29,23 @@ pub trait Eval {
|
||||
fn eval(&self) -> EvalInt;
|
||||
}
|
||||
|
||||
pub trait EvalSEE {
|
||||
/// Evaluate the outcome of an exchange at a square (static exchange evaluation).
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * dest: Square where the exchange happens.
|
||||
/// * first_move_side: Side to move first in the exchange.
|
||||
///
|
||||
/// This function may panic if a piece already at the destination is the same color as the side
|
||||
/// to move.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Expected gain from this exchange.
|
||||
fn eval_see(&self, dest: Square, first_move_side: Color) -> EvalInt;
|
||||
}
|
||||
|
||||
pub(crate) mod eval_score {
|
||||
//! Opaque "score" counters to be used in the board.
|
||||
|
||||
@ -195,7 +212,7 @@ pub const PST_MIDGAME: Pst = Pst([
|
||||
-5, 0, 0, 0, 0, 0, 0, -5, // 2
|
||||
-5, -3, 0, 0, 0, 2, -3, -5, // 1
|
||||
// a b c d e f g h
|
||||
], 500),
|
||||
], Piece::Rook.value()),
|
||||
|
||||
// bishop
|
||||
make_pst([
|
||||
@ -208,7 +225,7 @@ pub const PST_MIDGAME: Pst = Pst([
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // 2
|
||||
0, 0, -10, 0, 0, -10, 0, 0, // 1
|
||||
// a b c d e f g h
|
||||
], 300),
|
||||
], Piece::Bishop.value()),
|
||||
|
||||
// knight
|
||||
make_pst([
|
||||
@ -221,7 +238,7 @@ pub const PST_MIDGAME: Pst = Pst([
|
||||
-100, 1, 0, 0, 0, 0, 0,-100, // 2
|
||||
-100,-100,-100,-100,-100,-100,-100,-100, // 1
|
||||
// a b c d e f g h
|
||||
], 300),
|
||||
], Piece::Knight.value()),
|
||||
|
||||
// king
|
||||
make_pst([
|
||||
@ -234,7 +251,7 @@ pub const PST_MIDGAME: Pst = Pst([
|
||||
-70, -70, -70, -70, -70, -70, -70, -70, // 2
|
||||
0, 0, 10, 0, 0, 0, 20, 0, // 1
|
||||
// a b c d e f g h
|
||||
], 20_000),
|
||||
], Piece::King.value()),
|
||||
|
||||
// queen
|
||||
make_pst([
|
||||
@ -247,7 +264,7 @@ pub const PST_MIDGAME: Pst = Pst([
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // 2
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // 1
|
||||
// a b c d e f g h
|
||||
], 900),
|
||||
], Piece::Queen.value()),
|
||||
|
||||
// pawn
|
||||
make_pst([
|
||||
@ -260,7 +277,7 @@ pub const PST_MIDGAME: Pst = Pst([
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // 2
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // 1
|
||||
// a b c d e f g h
|
||||
], 100),
|
||||
], Piece::Pawn.value()),
|
||||
]);
|
||||
|
||||
#[rustfmt::skip]
|
||||
@ -276,7 +293,7 @@ pub const PST_ENDGAME: Pst = Pst([
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // 2
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // 1
|
||||
// a b c d e f g h
|
||||
], 500),
|
||||
], Piece::Rook.value()),
|
||||
|
||||
// bishop
|
||||
make_pst([
|
||||
@ -289,7 +306,7 @@ pub const PST_ENDGAME: Pst = Pst([
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // 2
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // 1
|
||||
// a b c d e f g h
|
||||
], 300),
|
||||
], Piece::Bishop.value()),
|
||||
|
||||
// knight
|
||||
make_pst([
|
||||
@ -302,7 +319,7 @@ pub const PST_ENDGAME: Pst = Pst([
|
||||
-100, 0, 0, 0, 0, 0, 0,-100, // 2
|
||||
-100,-100,-100,-100,-100,-100,-100,-100, // 1
|
||||
// a b c d e f g h
|
||||
], 300),
|
||||
], Piece::Knight.value()),
|
||||
|
||||
// king
|
||||
make_pst([
|
||||
@ -315,7 +332,7 @@ pub const PST_ENDGAME: Pst = Pst([
|
||||
-100, -20, -15, -13, -13, -15, -20,-100, // 2
|
||||
-100,-100, -90, -70, -70, -90,-100,-100, // 1
|
||||
// a b c d e f g h
|
||||
], 20_000),
|
||||
], Piece::King.value()),
|
||||
|
||||
// queen
|
||||
make_pst([
|
||||
@ -328,7 +345,7 @@ pub const PST_ENDGAME: Pst = Pst([
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // 2
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // 1
|
||||
// a b c d e f g h
|
||||
], 900),
|
||||
], Piece::Queen.value()),
|
||||
|
||||
// pawn
|
||||
make_pst([
|
||||
@ -341,7 +358,7 @@ pub const PST_ENDGAME: Pst = Pst([
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // 2
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // 1
|
||||
// a b c d e f g h
|
||||
], 100),
|
||||
], Piece::Pawn.value()),
|
||||
]);
|
||||
|
||||
/// Centipawn, signed, eval metrics.
|
||||
@ -399,6 +416,66 @@ impl Eval for Board {
|
||||
}
|
||||
}
|
||||
|
||||
impl EvalSEE for Board {
|
||||
fn eval_see(&self, dest: Square, first_mv_side: Color) -> EvalInt {
|
||||
let attackers = self.gen_attackers(dest, false, None);
|
||||
|
||||
// indexed by the Piece enum order
|
||||
let mut atk_qty = [[0u8; N_PIECES]; N_COLORS];
|
||||
|
||||
// counting sort
|
||||
for (attacker, _src) in attackers {
|
||||
atk_qty[attacker.col as usize][attacker.pc as usize] += 1;
|
||||
}
|
||||
|
||||
let dest_pc = self.get_piece(dest);
|
||||
|
||||
// it doesn't make sense if the piece already on the square is first to move
|
||||
debug_assert!(!dest_pc.is_some_and(|pc| pc.col == first_mv_side));
|
||||
|
||||
// Simulate the exchange.
|
||||
//
|
||||
// Returns the expected gain for the side in the exchange.
|
||||
//
|
||||
// TODO: promotions aren't accounted for.
|
||||
fn sim_exchange(
|
||||
side: Color,
|
||||
dest_pc: Option<ColPiece>,
|
||||
atk_qty: &mut [[u8; N_PIECES]; N_COLORS],
|
||||
) -> EvalInt {
|
||||
use Piece::*;
|
||||
let val_idxs = [Pawn, Knight, Bishop, Rook, Queen, King];
|
||||
|
||||
let mut ptr = 0;
|
||||
let mut eval = 0;
|
||||
|
||||
// while the count of this piece is zero, move to the next piece
|
||||
while atk_qty[side as usize][val_idxs[ptr] as usize] == 0 {
|
||||
ptr += 1;
|
||||
if ptr == N_PIECES {
|
||||
return eval;
|
||||
}
|
||||
}
|
||||
let cur_pc = val_idxs[ptr];
|
||||
let pc_ptr = cur_pc as usize;
|
||||
|
||||
debug_assert!(atk_qty[side as usize][pc_ptr] > 0);
|
||||
atk_qty[side as usize][pc_ptr] -= 1;
|
||||
|
||||
if let Some(dest_pc) = dest_pc {
|
||||
eval += dest_pc.pc.value();
|
||||
// this player may either give up now, or capture. pick the best (max score).
|
||||
// anything the other player gains is taken from us, hence the minus.
|
||||
eval = max(0, eval - sim_exchange(side.flip(), Some(dest_pc), atk_qty))
|
||||
}
|
||||
|
||||
eval
|
||||
}
|
||||
|
||||
sim_exchange(first_mv_side, dest_pc, &mut atk_qty)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -415,4 +492,34 @@ mod tests {
|
||||
assert!(eval1 > 0, "got eval {eval1} ({:?})", board1.eval);
|
||||
assert!(eval2 < 0, "got eval {eval2} ({:?})", board2.eval);
|
||||
}
|
||||
|
||||
/// Static exchange evaluation tests.
|
||||
#[test]
|
||||
fn test_see_eval() {
|
||||
// set side to move appropriately in the fen
|
||||
//
|
||||
// otherwise the exchange doesn't work
|
||||
let test_cases = [
|
||||
(
|
||||
// fen
|
||||
"8/4n3/8/2qRr3/8/4N3/8/8 b - - 0 1",
|
||||
// square where exchange happens
|
||||
"d5",
|
||||
// expected (signed) value gain of exchange
|
||||
Piece::Rook.value(),
|
||||
),
|
||||
(
|
||||
"8/8/4b3/2kq4/2PKP3/8/8/8 w - - 0 1",
|
||||
"d5",
|
||||
Piece::Queen.value(),
|
||||
),
|
||||
];
|
||||
|
||||
for (fen, dest, expected) in test_cases {
|
||||
let board = Board::from_fen(fen).unwrap();
|
||||
let dest: Square = dest.parse().unwrap();
|
||||
let res = board.eval_see(dest, board.turn);
|
||||
assert_eq!(res, expected, "failed {}", fen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
78
src/lib.rs
78
src/lib.rs
@ -29,6 +29,7 @@ pub mod prelude;
|
||||
|
||||
use crate::fen::{FromFen, ToFen, START_POSITION};
|
||||
use crate::hash::Zobrist;
|
||||
use crate::movegen::GenAttackers;
|
||||
use eval::eval_score::EvalScores;
|
||||
|
||||
pub const BOARD_WIDTH: usize = 8;
|
||||
@ -45,13 +46,13 @@ pub const N_COLORS: usize = 2;
|
||||
|
||||
impl Color {
|
||||
/// Return opposite color (does not assign).
|
||||
pub fn flip(self) -> Self {
|
||||
pub const fn flip(self) -> Self {
|
||||
match self {
|
||||
Color::White => Color::Black,
|
||||
Color::Black => Color::White,
|
||||
}
|
||||
}
|
||||
pub fn sign(&self) -> i8 {
|
||||
pub const fn sign(&self) -> i8 {
|
||||
match self {
|
||||
Color::White => 1,
|
||||
Color::Black => -1,
|
||||
@ -79,6 +80,21 @@ pub enum Piece {
|
||||
}
|
||||
pub const N_PIECES: usize = 6;
|
||||
|
||||
impl Piece {
|
||||
/// Get a piece's base value.
|
||||
pub const fn value(&self) -> crate::eval::EvalInt {
|
||||
use Piece::*;
|
||||
(match self {
|
||||
Rook => 6,
|
||||
Bishop => 3,
|
||||
Knight => 3,
|
||||
King => 200,
|
||||
Queen => 9,
|
||||
Pawn => 1,
|
||||
}) * 100
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PieceErr;
|
||||
|
||||
/// Color and piece.
|
||||
@ -482,6 +498,16 @@ impl Board {
|
||||
(0..N_SQUARES).map(Square::try_from).map(|x| x.unwrap())
|
||||
}
|
||||
|
||||
/// Get the 8th rank from a given player's perspective.
|
||||
///
|
||||
/// Useful for promotions.
|
||||
pub fn last_rank(pl: Color) -> usize {
|
||||
match pl {
|
||||
Color::White => usize::from(BOARD_HEIGHT) - 1,
|
||||
Color::Black => 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new piece in a location, and pop any existing piece in the destination.
|
||||
pub fn set_piece(&mut self, sq: Square, pc: ColPiece) -> Option<ColPiece> {
|
||||
let dest_pc = self.del_piece(sq);
|
||||
@ -563,47 +589,13 @@ impl Board {
|
||||
/// Is a given player in check?
|
||||
pub fn is_check(&self, pl: Color) -> bool {
|
||||
for src in self[pl][Piece::King] {
|
||||
macro_rules! detect_checker {
|
||||
($dirs: ident, $pc: pat, $keep_going: expr) => {
|
||||
for dir in $dirs.into_iter() {
|
||||
let (mut r, mut c) = src.to_row_col_signed();
|
||||
loop {
|
||||
let (nr, nc) = (r + dir.0, c + dir.1);
|
||||
if let Ok(sq) = Square::from_row_col_signed(nr, nc) {
|
||||
if let Some(pc) = self.get_piece(sq) {
|
||||
if matches!(pc.pc, $pc) && pc.col != pl {
|
||||
return true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (!($keep_going)) {
|
||||
break;
|
||||
}
|
||||
r = nr;
|
||||
c = nc;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let dirs_white_pawn = [(-1, 1), (-1, -1)];
|
||||
let dirs_black_pawn = [(1, 1), (1, -1)];
|
||||
|
||||
use Piece::*;
|
||||
|
||||
use movegen::{DIRS_DIAG, DIRS_KNIGHT, DIRS_STAR, DIRS_STRAIGHT};
|
||||
|
||||
detect_checker!(DIRS_DIAG, Bishop | Queen, true);
|
||||
detect_checker!(DIRS_STRAIGHT, Rook | Queen, true);
|
||||
detect_checker!(DIRS_STAR, King, false);
|
||||
detect_checker!(DIRS_KNIGHT, Knight, false);
|
||||
match pl {
|
||||
Color::White => detect_checker!(dirs_black_pawn, Pawn, false),
|
||||
Color::Black => detect_checker!(dirs_white_pawn, Pawn, false),
|
||||
if self
|
||||
.gen_attackers(src, true, Some(pl.flip()))
|
||||
.into_iter()
|
||||
.next()
|
||||
.is_some()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
|
185
src/movegen.rs
185
src/movegen.rs
@ -454,6 +454,134 @@ impl ToUCIAlgebraic for Move {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GenAttackers {
|
||||
/// Generate attackers/attacks for a given square.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `dest`: Square that is attacked.
|
||||
/// * `single`: Exit early if any attack is found.
|
||||
/// * `filter_color`: Matches only attackers of this color, if given.
|
||||
fn gen_attackers(
|
||||
&self,
|
||||
dest: Square,
|
||||
single: bool,
|
||||
filter_color: Option<Color>,
|
||||
) -> impl IntoIterator<Item = (ColPiece, Move)>;
|
||||
}
|
||||
|
||||
impl GenAttackers for Board {
|
||||
fn gen_attackers(
|
||||
&self,
|
||||
dest: Square,
|
||||
single: bool,
|
||||
filter_color: Option<Color>,
|
||||
) -> impl IntoIterator<Item = (ColPiece, Move)> {
|
||||
let mut ret: Vec<(ColPiece, Move)> = Vec::new();
|
||||
|
||||
/// Filter attackers and add them to the return vector.
|
||||
///
|
||||
/// Returns true if attacker was added.
|
||||
fn push_ans(
|
||||
pc: ColPiece,
|
||||
sq: Square,
|
||||
dest: Square,
|
||||
ret: &mut Vec<(ColPiece, Move)>,
|
||||
filter_color: Option<Color>,
|
||||
) -> bool {
|
||||
if let Some(filter_color) = filter_color {
|
||||
if filter_color != pc.col {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
let (r, _c) = dest.to_row_col();
|
||||
let is_promotion = matches!(pc.pc, Piece::Pawn) && r == Board::last_rank(pc.col);
|
||||
|
||||
if is_promotion {
|
||||
use PromotePiece::*;
|
||||
for prom_pc in [Queen, Knight, Rook, Bishop] {
|
||||
ret.push((
|
||||
pc,
|
||||
Move {
|
||||
src: sq,
|
||||
dest,
|
||||
move_type: MoveType::Promotion(prom_pc),
|
||||
},
|
||||
));
|
||||
}
|
||||
} else {
|
||||
ret.push((
|
||||
pc,
|
||||
Move {
|
||||
src: sq,
|
||||
dest,
|
||||
move_type: MoveType::Normal,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
macro_rules! detect_checker {
|
||||
($dirs: ident, $pc: pat, $color: pat, $keep_going: expr) => {
|
||||
for dir in $dirs.into_iter() {
|
||||
let (mut r, mut c) = dest.to_row_col_signed();
|
||||
loop {
|
||||
let (nr, nc) = (r + dir.0, c + dir.1);
|
||||
if let Ok(sq) = Square::from_row_col_signed(nr, nc) {
|
||||
if let Some(pc) = self.get_piece(sq) {
|
||||
if matches!(pc.pc, $pc) && matches!(pc.col, $color) {
|
||||
let added = push_ans(pc, sq, dest, &mut ret, filter_color);
|
||||
if single && added {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (!($keep_going)) {
|
||||
break;
|
||||
}
|
||||
r = nr;
|
||||
c = nc;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// inverted because our perspective is from the attacked square
|
||||
let dirs_white_pawn = [(-1, 1), (-1, -1)];
|
||||
let dirs_black_pawn = [(1, 1), (1, -1)];
|
||||
|
||||
use Piece::*;
|
||||
|
||||
macro_rules! both {
|
||||
() => {
|
||||
Color::White | Color::Black
|
||||
};
|
||||
}
|
||||
|
||||
detect_checker!(DIRS_DIAG, Bishop | Queen, both!(), true);
|
||||
detect_checker!(DIRS_STRAIGHT, Rook | Queen, both!(), true);
|
||||
// this shouldn't happen in legal chess but we're using this function in a pseudo-legal
|
||||
// move gen context
|
||||
detect_checker!(DIRS_STAR, King, both!(), false);
|
||||
detect_checker!(DIRS_KNIGHT, Knight, both!(), false);
|
||||
|
||||
if filter_color.is_none_or(|c| matches!(c, Color::Black)) {
|
||||
detect_checker!(dirs_black_pawn, Pawn, Color::Black, false);
|
||||
}
|
||||
if filter_color.is_none_or(|c| matches!(c, Color::White)) {
|
||||
detect_checker!(dirs_white_pawn, Pawn, Color::White, false);
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum MoveGenType {
|
||||
/// Legal move generation.
|
||||
@ -561,6 +689,7 @@ fn move_slider(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_legal(board: &mut Board, mv: Move) -> bool {
|
||||
// mut required for check checking
|
||||
// disallow friendly fire
|
||||
@ -678,10 +807,7 @@ impl MoveGenInternal for Board {
|
||||
for src in squares!(Pawn) {
|
||||
let (r, c) = src.to_row_col_signed();
|
||||
|
||||
let last_row = match self.turn {
|
||||
Color::White => isize::try_from(BOARD_HEIGHT).unwrap() - 1,
|
||||
Color::Black => 0,
|
||||
};
|
||||
let last_row = isize::try_from(Board::last_rank(self.turn)).unwrap();
|
||||
|
||||
let nr = r + isize::from(self.turn.sign());
|
||||
let is_promotion = nr == last_row;
|
||||
@ -763,10 +889,11 @@ impl MoveGenInternal for Board {
|
||||
}
|
||||
}
|
||||
}
|
||||
ret.into_iter().filter(move |mv| match gen_type {
|
||||
ret.retain(move |mv| match gen_type {
|
||||
MoveGenType::Legal => is_legal(self, *mv),
|
||||
MoveGenType::_Pseudo => true,
|
||||
})
|
||||
});
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
@ -1156,6 +1283,18 @@ mod tests {
|
||||
let all_cases = check_cases.iter().chain(¬_check_cases);
|
||||
for (fen, expected) in all_cases {
|
||||
let board = Board::from_fen(fen).unwrap();
|
||||
eprintln!(
|
||||
"got attackers {:?} for {}",
|
||||
board
|
||||
.gen_attackers(
|
||||
board[Color::White][Piece::King].into_iter().next().unwrap(),
|
||||
false,
|
||||
Some(Color::Black)
|
||||
)
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>(),
|
||||
fen
|
||||
);
|
||||
assert_eq!(board.is_check(Color::White), *expected, "failed on {}", fen);
|
||||
|
||||
let board_anti = board.flip_colors();
|
||||
@ -1431,4 +1570,38 @@ mod tests {
|
||||
assert_eq!(mv.to_uci_algebraic(), tc);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gen_attackers() {
|
||||
let test_cases = [(
|
||||
// fen
|
||||
"3q4/3rn3/3r2b1/3rb3/rnpkbN2/2qKK2r/1nPPpN2/2rr4 w - - 0 1",
|
||||
// attacked square
|
||||
"d3",
|
||||
// expected results
|
||||
"c3 c2 e3 b4 d4 e4 f2 f4 c4 b2",
|
||||
)];
|
||||
|
||||
for (fen, attacked, expected) in test_cases {
|
||||
let mut expected = expected
|
||||
.split_whitespace()
|
||||
.map(str::parse::<Square>)
|
||||
.map(|x| x.expect("test case has invalid square"))
|
||||
.collect::<Vec<_>>();
|
||||
expected.sort();
|
||||
|
||||
let attacked = attacked.parse::<Square>().unwrap();
|
||||
|
||||
let board = Board::from_fen(fen).unwrap();
|
||||
|
||||
let mut attackers = board
|
||||
.gen_attackers(attacked, false, None)
|
||||
.into_iter()
|
||||
.map(|(_pc, mv)| mv.src)
|
||||
.collect::<Vec<_>>();
|
||||
attackers.sort();
|
||||
|
||||
assert_eq!(attackers, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,9 +13,15 @@ Copyright © 2024 dogeystamp <dogeystamp@disroot.org>
|
||||
|
||||
//! Prelude that you can import entirely to use the library conveniently.
|
||||
|
||||
pub use crate::eval::{eval_metrics, EvalMetrics, EvalInt, Eval};
|
||||
pub use crate::coordination::{
|
||||
GoMessage, MsgBestmove, MsgToEngine, MsgToMain, UCIMode, UCIModeMachine, UCIModeTransition,
|
||||
};
|
||||
pub use crate::eval::{eval_metrics, Eval, EvalInt, EvalMetrics};
|
||||
pub use crate::fen::{FromFen, ToFen};
|
||||
pub use crate::movegen::{FromUCIAlgebraic, Move, MoveGen, ToUCIAlgebraic};
|
||||
pub use crate::search::{best_line, best_move, SearchEval, TranspositionTable, EngineState, SearchConfig, TimeLimits};
|
||||
pub use crate::{Board, Color, BOARD_HEIGHT, BOARD_WIDTH, N_COLORS, N_PIECES, N_SQUARES, ColPiece, Piece};
|
||||
pub use crate::coordination::{UCIMode, UCIModeTransition, UCIModeMachine, MsgBestmove, MsgToMain, MsgToEngine, GoMessage};
|
||||
pub use crate::movegen::{FromUCIAlgebraic, GenAttackers, Move, MoveGen, ToUCIAlgebraic};
|
||||
pub use crate::search::{
|
||||
best_line, best_move, EngineState, SearchConfig, SearchEval, TimeLimits, TranspositionTable,
|
||||
};
|
||||
pub use crate::{
|
||||
Board, ColPiece, Color, Piece, BOARD_HEIGHT, BOARD_WIDTH, N_COLORS, N_PIECES, N_SQUARES, Square,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user