Add one killer move per ply
This commit is contained in:
@@ -2,7 +2,7 @@ use crate::board::board::{Board, Color, PieceType};
|
|||||||
use crate::board::game::Game;
|
use crate::board::game::Game;
|
||||||
use crate::board::state::{Castle, State};
|
use crate::board::state::{Castle, State};
|
||||||
use crate::search::transposition_table::TranspositionTable;
|
use crate::search::transposition_table::TranspositionTable;
|
||||||
use crate::search::MAX_TT_SIZE;
|
use crate::search::{MAX_DEPTH, MAX_TT_SIZE};
|
||||||
use String as FenError;
|
use String as FenError;
|
||||||
|
|
||||||
pub fn from_fen(fen: &str) -> Result<Game, FenError> {
|
pub fn from_fen(fen: &str) -> Result<Game, FenError> {
|
||||||
@@ -37,6 +37,7 @@ pub fn from_fen(fen: &str) -> Result<Game, FenError> {
|
|||||||
mailbox,
|
mailbox,
|
||||||
hash,
|
hash,
|
||||||
tt: TranspositionTable::new(MAX_TT_SIZE),
|
tt: TranspositionTable::new(MAX_TT_SIZE),
|
||||||
|
killer: [None; MAX_DEPTH as usize],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
board::fen::from_fen,
|
board::fen::from_fen,
|
||||||
movegen::r#move::{Move, MoveType},
|
movegen::r#move::{Move, MoveType},
|
||||||
search::{transposition_table::TranspositionTable, MAX_TT_SIZE},
|
search::{transposition_table::TranspositionTable, MAX_DEPTH, MAX_TT_SIZE},
|
||||||
};
|
};
|
||||||
use String as FenError;
|
use String as FenError;
|
||||||
|
|
||||||
@@ -29,6 +29,7 @@ pub struct Game {
|
|||||||
pub mailbox: Mailbox,
|
pub mailbox: Mailbox,
|
||||||
pub hash: ZobristHash,
|
pub hash: ZobristHash,
|
||||||
pub tt: TranspositionTable,
|
pub tt: TranspositionTable,
|
||||||
|
pub killer: [Option<Move>; MAX_DEPTH as usize],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Game {
|
impl Game {
|
||||||
@@ -39,6 +40,7 @@ impl Game {
|
|||||||
mailbox: Mailbox::from_board(&Board::startpos()),
|
mailbox: Mailbox::from_board(&Board::startpos()),
|
||||||
hash: zobrist_keys().calculate_hash(&Board::startpos()),
|
hash: zobrist_keys().calculate_hash(&Board::startpos()),
|
||||||
tt: TranspositionTable::new(MAX_TT_SIZE),
|
tt: TranspositionTable::new(MAX_TT_SIZE),
|
||||||
|
killer: [None; MAX_DEPTH as usize],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -173,6 +173,13 @@ impl Move {
|
|||||||
pub fn parse_into_str(&self) -> String {
|
pub fn parse_into_str(&self) -> String {
|
||||||
format!("{self:?}")
|
format!("{self:?}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn is_capture(&self) -> bool {
|
||||||
|
matches!(
|
||||||
|
self.move_type,
|
||||||
|
MoveType::Capture | MoveType::PromotionCapture(_)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -1,10 +1,19 @@
|
|||||||
use crate::{board::mailbox::Mailbox, movegen::r#move::Move};
|
use crate::{board::mailbox::Mailbox, movegen::r#move::Move};
|
||||||
|
|
||||||
pub fn score_move(mailbox: &Mailbox, mv: Move, tt_move: Option<Move>) -> i32 {
|
pub fn score_move(
|
||||||
|
mailbox: &Mailbox,
|
||||||
|
mv: Move,
|
||||||
|
killer_move: Option<Move>,
|
||||||
|
tt_move: Option<Move>,
|
||||||
|
) -> i32 {
|
||||||
if Some(mv) == tt_move {
|
if Some(mv) == tt_move {
|
||||||
return -100;
|
return -100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if Some(mv) == killer_move {
|
||||||
|
return -90;
|
||||||
|
}
|
||||||
|
|
||||||
let aggressor = mailbox.piece_at(mv.src).expect("No aggressor found.");
|
let aggressor = mailbox.piece_at(mv.src).expect("No aggressor found.");
|
||||||
mailbox.piece_at(mv.dst).map_or(100, |victim| {
|
mailbox.piece_at(mv.dst).map_or(100, |victim| {
|
||||||
aggressor.0.idx() as i32 - (victim.0.idx() * 8) as i32
|
aggressor.0.idx() as i32 - (victim.0.idx() * 8) as i32
|
||||||
@@ -30,11 +39,11 @@ mod tests {
|
|||||||
let castle = Move::with_type(Square::E1, Square::C1, MoveType::Castle);
|
let castle = Move::with_type(Square::E1, Square::C1, MoveType::Castle);
|
||||||
|
|
||||||
let mut moves = vec![castle, queen_takes_pawn, pawn_takes_queen];
|
let mut moves = vec![castle, queen_takes_pawn, pawn_takes_queen];
|
||||||
moves.sort_unstable_by_key(|mv| score_move(&game.mailbox, *mv, None));
|
moves.sort_unstable_by_key(|mv| score_move(&game.mailbox, *mv, None, None));
|
||||||
|
|
||||||
assert_eq!(moves, vec![pawn_takes_queen, queen_takes_pawn, castle]);
|
assert_eq!(moves, vec![pawn_takes_queen, queen_takes_pawn, 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, None, Some(castle)));
|
||||||
|
|
||||||
assert_eq!(moves, vec![castle, pawn_takes_queen, queen_takes_pawn]);
|
assert_eq!(moves, vec![castle, pawn_takes_queen, queen_takes_pawn]);
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,12 @@ pub fn negamax(
|
|||||||
}
|
}
|
||||||
|
|
||||||
moves.sort_unstable_by_key(|mv| {
|
moves.sort_unstable_by_key(|mv| {
|
||||||
score_move(&game.mailbox, *mv, tt_entry.and_then(|entry| entry.mv))
|
score_move(
|
||||||
|
&game.mailbox,
|
||||||
|
*mv,
|
||||||
|
game.killer[plies as usize],
|
||||||
|
tt_entry.and_then(|entry| entry.mv),
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
for mv in moves {
|
for mv in moves {
|
||||||
@@ -88,6 +93,9 @@ pub fn negamax(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if score >= beta {
|
if score >= beta {
|
||||||
|
if !mv.is_capture() {
|
||||||
|
game.killer[plies as usize] = Some(mv);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,12 @@ pub fn quiescence(
|
|||||||
}
|
}
|
||||||
|
|
||||||
moves.sort_unstable_by_key(|mv| {
|
moves.sort_unstable_by_key(|mv| {
|
||||||
score_move(&game.mailbox, *mv, tt_entry.and_then(|entry| entry.mv))
|
score_move(
|
||||||
|
&game.mailbox,
|
||||||
|
*mv,
|
||||||
|
None,
|
||||||
|
tt_entry.and_then(|entry| entry.mv),
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
for mv in moves {
|
for mv in moves {
|
||||||
|
|||||||
Reference in New Issue
Block a user