Refactor time info, update zobrist to tuple struct, naming and clippy
This commit is contained in:
@@ -31,6 +31,7 @@ pub const fn lsb(bitboard: Bitboard) -> usize {
|
|||||||
bitboard.trailing_zeros() as usize
|
bitboard.trailing_zeros() as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub const fn bit_count(bitboard: Bitboard) -> usize {
|
pub const fn bit_count(bitboard: Bitboard) -> usize {
|
||||||
bitboard.count_ones() as usize
|
bitboard.count_ones() as usize
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,8 @@ impl Game {
|
|||||||
mailbox.set_piece_at(mv.dst, Some(piece_at_src));
|
mailbox.set_piece_at(mv.dst, Some(piece_at_src));
|
||||||
}
|
}
|
||||||
MoveType::Capture => {
|
MoveType::Capture => {
|
||||||
let piece_at_dst = piece_at_dst.expect("Expected piece at: {mv.dst}");
|
let piece_at_dst =
|
||||||
|
piece_at_dst.unwrap_or_else(|| panic!("Expected piece at: {}", mv.dst));
|
||||||
board.remove_opponent_piece(mv.dst, piece_at_dst.0);
|
board.remove_opponent_piece(mv.dst, piece_at_dst.0);
|
||||||
hash.update_capture(mv.src, mv.dst, piece_at_src.0, piece_at_dst.0, color);
|
hash.update_capture(mv.src, mv.dst, piece_at_src.0, piece_at_dst.0, color);
|
||||||
board.move_piece(mv.src, mv.dst, piece_at_src.0);
|
board.move_piece(mv.src, mv.dst, piece_at_src.0);
|
||||||
@@ -116,7 +117,8 @@ impl Game {
|
|||||||
mailbox.set_piece_at(mv.dst, Some((promote.into_piece_type(), color)));
|
mailbox.set_piece_at(mv.dst, Some((promote.into_piece_type(), color)));
|
||||||
}
|
}
|
||||||
MoveType::PromotionCapture(promote) => {
|
MoveType::PromotionCapture(promote) => {
|
||||||
let piece_at_dst = piece_at_dst.expect("Expected piece at dst: {mv.dst}");
|
let piece_at_dst =
|
||||||
|
piece_at_dst.unwrap_or_else(|| panic!("Expected piece at: {}", mv.dst));
|
||||||
board.remove_own_piece(mv.src, piece_at_src.0);
|
board.remove_own_piece(mv.src, piece_at_src.0);
|
||||||
board.remove_opponent_piece(mv.dst, piece_at_dst.0);
|
board.remove_opponent_piece(mv.dst, piece_at_dst.0);
|
||||||
board.promote_piece(mv.dst, promote);
|
board.promote_piece(mv.dst, promote);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
pub struct Square {}
|
pub struct Square {}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
impl Square {
|
impl Square {
|
||||||
pub const A1: usize = 0;
|
pub const A1: usize = 0;
|
||||||
pub const B1: usize = 1;
|
pub const B1: usize = 1;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ pub fn zobrist_keys() -> &'static ZobristKeys {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct ZobristKeys {
|
pub struct ZobristKeys {
|
||||||
piece_square_color: [[[u64; 2]; 6]; 64],
|
square_piece_color: [[[u64; 2]; 6]; 64],
|
||||||
en_passant: [u64; 8],
|
en_passant: [u64; 8],
|
||||||
castling_ability: [[u64; 2]; 4],
|
castling_ability: [[u64; 2]; 4],
|
||||||
side_to_move: u64,
|
side_to_move: u64,
|
||||||
@@ -30,8 +30,8 @@ impl ZobristKeys {
|
|||||||
|
|
||||||
for square in Square::A1..=Square::H8 {
|
for square in Square::A1..=Square::H8 {
|
||||||
for piece_idx in 0..6 {
|
for piece_idx in 0..6 {
|
||||||
keys.piece_square_color[square][piece_idx][0] = state.next_u64();
|
keys.square_piece_color[square][piece_idx][0] = state.next_u64();
|
||||||
keys.piece_square_color[square][piece_idx][1] = state.next_u64();
|
keys.square_piece_color[square][piece_idx][1] = state.next_u64();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ impl ZobristKeys {
|
|||||||
|
|
||||||
while bitboard != 0 {
|
while bitboard != 0 {
|
||||||
let square = lsb(bitboard);
|
let square = lsb(bitboard);
|
||||||
hash ^= self.piece_square_color[square][piece_type][Color::White];
|
hash ^= self.square_piece_color[square][piece_type][Color::White];
|
||||||
bitboard &= bitboard - 1;
|
bitboard &= bitboard - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ impl ZobristKeys {
|
|||||||
|
|
||||||
while bitboard != 0 {
|
while bitboard != 0 {
|
||||||
let square = lsb(bitboard);
|
let square = lsb(bitboard);
|
||||||
hash ^= self.piece_square_color[square][piece_type][Color::Black];
|
hash ^= self.square_piece_color[square][piece_type][Color::Black];
|
||||||
bitboard &= bitboard - 1;
|
bitboard &= bitboard - 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -87,7 +87,7 @@ impl ZobristKeys {
|
|||||||
impl Default for ZobristKeys {
|
impl Default for ZobristKeys {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
piece_square_color: [[[0; 2]; 6]; 64],
|
square_piece_color: [[[0; 2]; 6]; 64],
|
||||||
en_passant: [0; 8],
|
en_passant: [0; 8],
|
||||||
castling_ability: [[0; 2]; 4],
|
castling_ability: [[0; 2]; 4],
|
||||||
side_to_move: 0,
|
side_to_move: 0,
|
||||||
@@ -96,18 +96,16 @@ impl Default for ZobristKeys {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
|
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
|
||||||
pub struct ZobristHash {
|
pub struct ZobristHash(pub u64);
|
||||||
pub hash: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ZobristHash {
|
impl ZobristHash {
|
||||||
pub const fn new(hash: u64) -> Self {
|
pub const fn new(hash: u64) -> Self {
|
||||||
Self { hash }
|
Self(hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_side_to_move_key(&mut self) {
|
pub fn update_side_to_move_key(&mut self) {
|
||||||
let keys = zobrist_keys();
|
let keys = zobrist_keys();
|
||||||
self.hash ^= keys.side_to_move
|
self.0 ^= keys.side_to_move
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_castling_ability_keys(
|
pub fn update_castling_ability_keys(
|
||||||
@@ -116,16 +114,16 @@ impl ZobristHash {
|
|||||||
new_castling_ability: [Castle; 2],
|
new_castling_ability: [Castle; 2],
|
||||||
) {
|
) {
|
||||||
let keys = zobrist_keys();
|
let keys = zobrist_keys();
|
||||||
self.hash ^= keys.castling_ability[old_castling_ability[0]][0];
|
self.0 ^= keys.castling_ability[old_castling_ability[0]][0];
|
||||||
self.hash ^= keys.castling_ability[old_castling_ability[1]][1];
|
self.0 ^= keys.castling_ability[old_castling_ability[1]][1];
|
||||||
self.hash ^= keys.castling_ability[new_castling_ability[0]][0];
|
self.0 ^= keys.castling_ability[new_castling_ability[0]][0];
|
||||||
self.hash ^= keys.castling_ability[new_castling_ability[1]][1]
|
self.0 ^= keys.castling_ability[new_castling_ability[1]][1]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_quiet(&mut self, src: usize, dst: usize, piece_at_src: PieceType, color: Color) {
|
pub fn update_quiet(&mut self, src: usize, dst: usize, piece_at_src: PieceType, color: Color) {
|
||||||
let keys = zobrist_keys();
|
let keys = zobrist_keys();
|
||||||
self.hash ^= keys.piece_square_color[src][piece_at_src][color];
|
self.0 ^= keys.square_piece_color[src][piece_at_src][color];
|
||||||
self.hash ^= keys.piece_square_color[dst][piece_at_src][color];
|
self.0 ^= keys.square_piece_color[dst][piece_at_src][color];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_capture(
|
pub fn update_capture(
|
||||||
@@ -137,16 +135,16 @@ impl ZobristHash {
|
|||||||
color: Color,
|
color: Color,
|
||||||
) {
|
) {
|
||||||
let keys = zobrist_keys();
|
let keys = zobrist_keys();
|
||||||
self.hash ^= keys.piece_square_color[src][piece_at_src][color];
|
self.0 ^= keys.square_piece_color[src][piece_at_src][color];
|
||||||
self.hash ^= keys.piece_square_color[dst][piece_at_src][color];
|
self.0 ^= keys.square_piece_color[dst][piece_at_src][color];
|
||||||
self.hash ^= keys.piece_square_color[dst][piece_at_dst][color.opponent()]
|
self.0 ^= keys.square_piece_color[dst][piece_at_dst][color.opponent()]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_en_passant(&mut self, src: usize, dst: usize, ep_capture: usize, color: Color) {
|
pub fn update_en_passant(&mut self, src: usize, dst: usize, ep_capture: usize, color: Color) {
|
||||||
let keys = zobrist_keys();
|
let keys = zobrist_keys();
|
||||||
self.hash ^= keys.piece_square_color[src][PieceType::Pawn][color];
|
self.0 ^= keys.square_piece_color[src][PieceType::Pawn][color];
|
||||||
self.hash ^= keys.piece_square_color[dst][PieceType::Pawn][color];
|
self.0 ^= keys.square_piece_color[dst][PieceType::Pawn][color];
|
||||||
self.hash ^= keys.piece_square_color[ep_capture][PieceType::Pawn][color.opponent()]
|
self.0 ^= keys.square_piece_color[ep_capture][PieceType::Pawn][color.opponent()]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_double_push(
|
pub fn update_double_push(
|
||||||
@@ -157,18 +155,18 @@ impl ZobristHash {
|
|||||||
new_en_passant_target: Option<usize>,
|
new_en_passant_target: Option<usize>,
|
||||||
) {
|
) {
|
||||||
let keys = zobrist_keys();
|
let keys = zobrist_keys();
|
||||||
self.hash ^= keys.piece_square_color[src][PieceType::Pawn][color];
|
self.0 ^= keys.square_piece_color[src][PieceType::Pawn][color];
|
||||||
self.hash ^= keys.piece_square_color[dst][PieceType::Pawn][color];
|
self.0 ^= keys.square_piece_color[dst][PieceType::Pawn][color];
|
||||||
|
|
||||||
if let Some(new_en_passant) = new_en_passant_target {
|
if let Some(new_en_passant) = new_en_passant_target {
|
||||||
self.hash ^= keys.en_passant[square::to_file(new_en_passant)];
|
self.0 ^= keys.en_passant[square::to_file(new_en_passant)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_promotion(&mut self, src: usize, dst: usize, promote: &Promote, color: Color) {
|
pub fn update_promotion(&mut self, src: usize, dst: usize, promote: &Promote, color: Color) {
|
||||||
let keys = zobrist_keys();
|
let keys = zobrist_keys();
|
||||||
self.hash ^= keys.piece_square_color[src][PieceType::Pawn][color];
|
self.0 ^= keys.square_piece_color[src][PieceType::Pawn][color];
|
||||||
self.hash ^= keys.piece_square_color[dst][promote.into_piece_type()][color];
|
self.0 ^= keys.square_piece_color[dst][promote.into_piece_type()][color];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_promotion_capture(
|
pub fn update_promotion_capture(
|
||||||
@@ -180,9 +178,9 @@ impl ZobristHash {
|
|||||||
color: Color,
|
color: Color,
|
||||||
) {
|
) {
|
||||||
let keys = zobrist_keys();
|
let keys = zobrist_keys();
|
||||||
self.hash ^= keys.piece_square_color[src][PieceType::Pawn][color];
|
self.0 ^= keys.square_piece_color[src][PieceType::Pawn][color];
|
||||||
self.hash ^= keys.piece_square_color[dst][piece_at_dst][color.opponent()];
|
self.0 ^= keys.square_piece_color[dst][piece_at_dst][color.opponent()];
|
||||||
self.hash ^= keys.piece_square_color[dst][promote.into_piece_type()][color];
|
self.0 ^= keys.square_piece_color[dst][promote.into_piece_type()][color];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_castle(
|
pub fn update_castle(
|
||||||
@@ -195,16 +193,16 @@ impl ZobristHash {
|
|||||||
color: Color,
|
color: Color,
|
||||||
) {
|
) {
|
||||||
let keys = zobrist_keys();
|
let keys = zobrist_keys();
|
||||||
self.hash ^= keys.piece_square_color[src][piece_at_src][color];
|
self.0 ^= keys.square_piece_color[src][piece_at_src][color];
|
||||||
self.hash ^= keys.piece_square_color[dst][piece_at_src][color];
|
self.0 ^= keys.square_piece_color[dst][piece_at_src][color];
|
||||||
self.hash ^= keys.piece_square_color[rook_src][PieceType::Rook][color];
|
self.0 ^= keys.square_piece_color[rook_src][PieceType::Rook][color];
|
||||||
self.hash ^= keys.piece_square_color[rook_dst][PieceType::Rook][color];
|
self.0 ^= keys.square_piece_color[rook_dst][PieceType::Rook][color];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drop_en_passant_hash(&mut self, en_passant: Option<usize>) {
|
pub fn drop_en_passant_hash(&mut self, en_passant: Option<usize>) {
|
||||||
let keys = zobrist_keys();
|
let keys = zobrist_keys();
|
||||||
if let Some(ep) = en_passant {
|
if let Some(ep) = en_passant {
|
||||||
self.hash ^= keys.en_passant[square::to_file(ep)]
|
self.0 ^= keys.en_passant[square::to_file(ep)]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,13 +194,13 @@ pub fn rook_attacks_on_the_fly(bitboard: Bitboard, blocker: Bitboard) -> Bitboar
|
|||||||
attacks
|
attacks
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_occupancy(index: u64, relevant_bits: usize, mut attack_mask: Bitboard) -> Bitboard {
|
pub fn set_occupancy(idx: u64, relevant_bits: usize, mut attack_mask: Bitboard) -> Bitboard {
|
||||||
let mut occupancy = EMPTY;
|
let mut occupancy = EMPTY;
|
||||||
|
|
||||||
for bit in 0..relevant_bits {
|
for bit in 0..relevant_bits {
|
||||||
let square = lsb(attack_mask);
|
let square = lsb(attack_mask);
|
||||||
attack_mask &= !square_to_bitboard(square);
|
attack_mask &= !square_to_bitboard(square);
|
||||||
if have_common_bit(index, square_to_bitboard(bit)) {
|
if have_common_bit(idx, square_to_bitboard(bit)) {
|
||||||
occupancy |= square_to_bitboard(square);
|
occupancy |= square_to_bitboard(square);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,12 +269,12 @@ pub fn init_bishop_attacks() -> Box<[[Bitboard; 512]; 64]> {
|
|||||||
let attack_mask = bishop_masks[square];
|
let attack_mask = bishop_masks[square];
|
||||||
let occupancy_indices = square_to_bitboard(BISHOP_RELEVANT_BITS[square]);
|
let occupancy_indices = square_to_bitboard(BISHOP_RELEVANT_BITS[square]);
|
||||||
|
|
||||||
for index in 0..occupancy_indices {
|
for idx in 0..occupancy_indices {
|
||||||
let occupancy = set_occupancy(index, BISHOP_RELEVANT_BITS[square], attack_mask);
|
let occupancy = set_occupancy(idx, BISHOP_RELEVANT_BITS[square], attack_mask);
|
||||||
let magic_index = (occupancy.wrapping_mul(BISHOP_MAGIC[square])
|
let magic_idx = (occupancy.wrapping_mul(BISHOP_MAGIC[square])
|
||||||
>> (64 - BISHOP_RELEVANT_BITS[square])) as usize;
|
>> (64 - BISHOP_RELEVANT_BITS[square])) as usize;
|
||||||
|
|
||||||
bishop_atks[square][magic_index] =
|
bishop_atks[square][magic_idx] =
|
||||||
bishop_attacks_on_the_fly(square_to_bitboard(square), occupancy);
|
bishop_attacks_on_the_fly(square_to_bitboard(square), occupancy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -297,11 +297,11 @@ pub fn init_rook_attacks() -> HashMap<usize, HashMap<usize, Bitboard>> {
|
|||||||
|
|
||||||
for idx in 0..occupancy_indices {
|
for idx in 0..occupancy_indices {
|
||||||
let occupancy = set_occupancy(idx, ROOK_RELEVANT_BITS[square], attack_mask);
|
let occupancy = set_occupancy(idx, ROOK_RELEVANT_BITS[square], attack_mask);
|
||||||
let magic_index = (occupancy.wrapping_mul(ROOK_MAGIC[square])
|
let magic_idx = (occupancy.wrapping_mul(ROOK_MAGIC[square])
|
||||||
>> (64 - ROOK_RELEVANT_BITS[square])) as usize;
|
>> (64 - ROOK_RELEVANT_BITS[square])) as usize;
|
||||||
|
|
||||||
square_map.insert(
|
square_map.insert(
|
||||||
magic_index,
|
magic_idx,
|
||||||
rook_attacks_on_the_fly(square_to_bitboard(square), occupancy),
|
rook_attacks_on_the_fly(square_to_bitboard(square), occupancy),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,25 +9,26 @@ use crate::{
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
negamax,
|
negamax,
|
||||||
time::{hard_limit, TimeInfo},
|
time::TimeInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn iterative_deepening(
|
pub fn iterative_deepening(
|
||||||
game: &mut Game,
|
game: &mut Game,
|
||||||
max_depth: u8,
|
max_depth: u8,
|
||||||
time_info: &TimeInfo,
|
time: &TimeInfo,
|
||||||
) -> anyhow::Result<Option<Move>> {
|
) -> anyhow::Result<Option<Move>> {
|
||||||
let mut best_move = None;
|
let mut best_move = None;
|
||||||
|
|
||||||
for depth in 1..=max_depth {
|
for depth in 1..=max_depth {
|
||||||
if hard_limit(time_info.instant, time_info.time, time_info.inc) {
|
if time.exceed_hard_limit() {
|
||||||
return Ok(best_move);
|
return Ok(best_move);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut nodes = 0;
|
let mut nodes = 0;
|
||||||
let score = negamax::negamax(game, MIN_SCORE, MAX_SCORE, depth, 0, time_info, &mut nodes);
|
let score = negamax::negamax(game, MIN_SCORE, MAX_SCORE, depth, 0, time, &mut nodes);
|
||||||
|
|
||||||
if score.is_err() {
|
if let Err(e) = score {
|
||||||
|
write_response(&mut io::stdout(), &Response::Info(format!("{e}")))?;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,9 +38,9 @@ pub fn iterative_deepening(
|
|||||||
&mut io::stdout(),
|
&mut io::stdout(),
|
||||||
&log_depth_results(
|
&log_depth_results(
|
||||||
depth,
|
depth,
|
||||||
time_info.instant.elapsed().as_millis() as u64,
|
time.instant.elapsed().as_millis() as u64,
|
||||||
nodes,
|
nodes,
|
||||||
time_info.nps(nodes),
|
time.nps(nodes),
|
||||||
score?,
|
score?,
|
||||||
best_move,
|
best_move,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -6,10 +6,9 @@ pub fn score_move(mailbox: &Mailbox, mv: Move, tt_move: Option<Move>) -> i32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let aggressor = mailbox.piece_at(mv.src).expect("No aggressor found.");
|
let aggressor = mailbox.piece_at(mv.src).expect("No aggressor found.");
|
||||||
match mailbox.piece_at(mv.dst) {
|
mailbox.piece_at(mv.dst).map_or(100, |victim| {
|
||||||
Some(victim) => aggressor.0.idx() as i32 - (victim.0.idx() * 8) as i32,
|
aggressor.0.idx() as i32 - (victim.0.idx() * 8) as i32
|
||||||
None => 100,
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -35,7 +34,6 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(moves, vec![pawn_takes_queen, queen_takes_pawn, castle]);
|
assert_eq!(moves, vec![pawn_takes_queen, queen_takes_pawn, castle]);
|
||||||
|
|
||||||
let castle = Move::with_type(Square::E1, Square::C1, MoveType::Castle);
|
|
||||||
moves.sort_unstable_by_key(|mv| score_move(&game.mailbox, *mv, Some(castle)));
|
moves.sort_unstable_by_key(|mv| score_move(&game.mailbox, *mv, Some(castle)));
|
||||||
|
|
||||||
assert_eq!(moves, vec![castle, pawn_takes_queen, queen_takes_pawn]);
|
assert_eq!(moves, vec![castle, pawn_takes_queen, queen_takes_pawn]);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use crate::{
|
|||||||
use super::{
|
use super::{
|
||||||
move_ordering::score_move,
|
move_ordering::score_move,
|
||||||
quiescence::quiescence,
|
quiescence::quiescence,
|
||||||
time::{hard_limit, TimeInfo},
|
time::TimeInfo,
|
||||||
transposition_table::TTEntry,
|
transposition_table::TTEntry,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -18,11 +18,11 @@ pub fn negamax(
|
|||||||
beta: i32,
|
beta: i32,
|
||||||
depth: u8,
|
depth: u8,
|
||||||
plies: u8,
|
plies: u8,
|
||||||
time_info: &TimeInfo,
|
time: &TimeInfo,
|
||||||
nodes: &mut u64,
|
nodes: &mut u64,
|
||||||
) -> Result<i32> {
|
) -> Result<i32> {
|
||||||
if hard_limit(time_info.instant, time_info.time, time_info.inc) {
|
if time.exceed_hard_limit() {
|
||||||
bail!("Time is up! In Negamax");
|
bail!("Hard limit exceeded in negamax");
|
||||||
}
|
}
|
||||||
|
|
||||||
if plies != 0 && game.in_repetition() {
|
if plies != 0 && game.in_repetition() {
|
||||||
@@ -31,7 +31,7 @@ pub fn negamax(
|
|||||||
|
|
||||||
if depth == 0 {
|
if depth == 0 {
|
||||||
let q_score =
|
let q_score =
|
||||||
quiescence(game, alpha, beta, time_info, nodes).map_err(|e| anyhow!("{e}"))?;
|
quiescence(game, alpha, beta, time, nodes).map_err(|e| anyhow!("{e}"))?;
|
||||||
return Ok(q_score);
|
return Ok(q_score);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ pub fn negamax(
|
|||||||
*nodes += 1;
|
*nodes += 1;
|
||||||
|
|
||||||
let score = if legal_moves == 1 {
|
let score = if legal_moves == 1 {
|
||||||
-negamax(game, -beta, -alpha, depth - 1, plies + 1, time_info, nodes)?
|
-negamax(game, -beta, -alpha, depth - 1, plies + 1, time, nodes)?
|
||||||
} else {
|
} else {
|
||||||
let mut score = -negamax(
|
let mut score = -negamax(
|
||||||
game,
|
game,
|
||||||
@@ -63,11 +63,11 @@ pub fn negamax(
|
|||||||
-alpha,
|
-alpha,
|
||||||
depth - 1,
|
depth - 1,
|
||||||
plies + 1,
|
plies + 1,
|
||||||
time_info,
|
time,
|
||||||
nodes,
|
nodes,
|
||||||
)?;
|
)?;
|
||||||
if score > alpha && score < beta {
|
if score > alpha && score < beta {
|
||||||
score = -negamax(game, -beta, -alpha, depth - 1, plies + 1, time_info, nodes)?;
|
score = -negamax(game, -beta, -alpha, depth - 1, plies + 1, time, nodes)?;
|
||||||
}
|
}
|
||||||
score
|
score
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,18 +4,18 @@ use crate::{board::game::Game, evaluation::pesto::pesto};
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
move_ordering::score_move,
|
move_ordering::score_move,
|
||||||
time::{hard_limit, TimeInfo},
|
time::TimeInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn quiescence(
|
pub fn quiescence(
|
||||||
game: &mut Game,
|
game: &mut Game,
|
||||||
mut alpha: i32,
|
mut alpha: i32,
|
||||||
beta: i32,
|
beta: i32,
|
||||||
time_info: &TimeInfo,
|
time: &TimeInfo,
|
||||||
total_nodes_searched: &mut u64,
|
total_nodes_searched: &mut u64,
|
||||||
) -> Result<i32> {
|
) -> Result<i32> {
|
||||||
if hard_limit(time_info.instant, time_info.time, time_info.inc) {
|
if time.exceed_hard_limit() {
|
||||||
bail!("Time is up! In Quiescence");
|
bail!("Hard limit exceeded in quiescence");
|
||||||
}
|
}
|
||||||
|
|
||||||
let stand_pat = pesto().eval(game);
|
let stand_pat = pesto().eval(game);
|
||||||
@@ -44,7 +44,7 @@ pub fn quiescence(
|
|||||||
}
|
}
|
||||||
*total_nodes_searched += 1;
|
*total_nodes_searched += 1;
|
||||||
|
|
||||||
let score = -quiescence(game, -beta, -alpha, time_info, &mut 0)?;
|
let score = -quiescence(game, -beta, -alpha, time, &mut 0)?;
|
||||||
game.unmake_move();
|
game.unmake_move();
|
||||||
|
|
||||||
if score > best_score {
|
if score > best_score {
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ impl TimeInfo {
|
|||||||
pub fn nps(&self, nodes: u64) -> u64 {
|
pub fn nps(&self, nodes: u64) -> u64 {
|
||||||
((nodes * 1_000_000) as u128).div_ceil(self.instant.elapsed().as_micros()) as u64
|
((nodes * 1_000_000) as u128).div_ceil(self.instant.elapsed().as_micros()) as u64
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hard_limit(time_now: Instant, time: u128, inc: u128) -> bool {
|
pub fn exceed_hard_limit(&self) -> bool {
|
||||||
time_now.elapsed().as_millis() >= time / HARD_LIMIT_DIVISION + inc / 2
|
self.instant.elapsed().as_millis() >= self.time / HARD_LIMIT_DIVISION + self.inc / 2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,15 +17,15 @@ impl TranspositionTable {
|
|||||||
pub fn lookup(&self, zobrist_hash: ZobristHash) -> Option<&TTEntry> {
|
pub fn lookup(&self, zobrist_hash: ZobristHash) -> Option<&TTEntry> {
|
||||||
let entry = self
|
let entry = self
|
||||||
.positions
|
.positions
|
||||||
.get((zobrist_hash.hash % self.size) as usize)
|
.get((zobrist_hash.0 % self.size) as usize)
|
||||||
.and_then(|entry| entry.as_ref());
|
.and_then(|entry| entry.as_ref());
|
||||||
|
|
||||||
entry
|
entry
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, tt_entry: TTEntry) {
|
pub fn insert(&mut self, tt_entry: TTEntry) {
|
||||||
let index = (tt_entry.hash.hash % self.size) as usize;
|
let idx = (tt_entry.hash.0 % self.size) as usize;
|
||||||
self.positions[index] = Some(tt_entry);
|
self.positions[idx] = Some(tt_entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user