diff --git a/src/board/board.rs b/src/board/board.rs index 9dfa20b..6f470b0 100644 --- a/src/board/board.rs +++ b/src/board/board.rs @@ -192,17 +192,6 @@ impl PieceType { pub const fn idx(self) -> usize { self as usize } - - pub const fn score(self) -> i32 { - match self { - Self::Pawn => 100, - Self::Knight => 320, - Self::Bishop => 330, - Self::Rook => 500, - Self::Queen => 900, - Self::King => 20000, - } - } } use std::ops::{Index, IndexMut}; diff --git a/src/search/move_ordering.rs b/src/search/move_ordering.rs index ae6f46f..7402897 100644 --- a/src/search/move_ordering.rs +++ b/src/search/move_ordering.rs @@ -1,22 +1,14 @@ use crate::{board::mailbox::Mailbox, movegen::r#move::Move}; -pub fn sort_moves(mut moves: Vec, mailbox: &Mailbox, tt_move: Option) -> Vec { - if let Some(tt_move) = tt_move { - if let Some(tt_move_index) = moves.iter().position(|&mv| mv == tt_move) { - moves.swap_remove(tt_move_index); - moves.insert(0, tt_move); - return moves; - } +pub fn score_move(mailbox: &Mailbox, mv: Move, tt_move: Option) -> i32 { + if Some(mv) == tt_move { + return -100; } - moves.sort_unstable_by_key(|mv| std::cmp::Reverse(mvv_lva(mailbox, *mv))); - moves -} - -const fn mvv_lva(mailbox: &Mailbox, mv: Move) -> i32 { - match (mailbox.piece_at(mv.src), mailbox.piece_at(mv.dst)) { - (Some(aggressor), Some(victim)) => victim.0.score() - aggressor.0.score(), - _ => -1000, + let aggressor = mailbox.piece_at(mv.src).expect("No aggressor found."); + match mailbox.piece_at(mv.dst) { + Some(victim) => aggressor.0.idx() as i32 - (victim.0.idx() * 8) as i32, + None => 100, } } @@ -25,17 +17,28 @@ mod tests { use crate::{ board::{fen::from_fen, square::Square}, movegen::r#move::{Move, MoveType}, - search::move_ordering::mvv_lva, }; - const FEN: &'static str = "1r2k2r/2P1pq1p/2npb3/1p3ppP/p3P3/P2B1Q2/1P1PNPP1/R3K2R w KQk g6 0 1"; + use super::score_move; + + const FEN: &'static str = "1r2k2r/2P1p2p/2npb1q1/1p3ppP/p3P3/P2B1Q2/1P1PNPP1/R3K2R w KQk - 0 1"; #[test] - fn test_score_by_mvv_lva() -> Result<(), String> { + fn test_score_move() -> Result<(), String> { let game = from_fen(FEN)?; - let f3f5 = Move::with_type(Square::F3, Square::F5, MoveType::Capture); + let queen_takes_pawn = Move::with_type(Square::F3, Square::F5, MoveType::Capture); + let pawn_takes_queen = Move::with_type(Square::H5, Square::G6, MoveType::Capture); + let castle = Move::with_type(Square::E1, Square::C1, MoveType::Castle); - assert_eq!(mvv_lva(&game.mailbox, f3f5), -800); + let mut moves = vec![castle, queen_takes_pawn, pawn_takes_queen]; + moves.sort_unstable_by_key(|mv| score_move(&game.mailbox, *mv, None)); + + 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))); + + assert_eq!(moves, vec![castle, pawn_takes_queen, queen_takes_pawn]); Ok(()) } diff --git a/src/search/negamax.rs b/src/search/negamax.rs index 7bf0476..bb5207f 100644 --- a/src/search/negamax.rs +++ b/src/search/negamax.rs @@ -6,7 +6,7 @@ use crate::{ }; use super::{ - move_ordering, + move_ordering::score_move, quiescence::quiescence, time::{hard_limit, TimeInfo}, transposition_table::TTEntry, @@ -33,14 +33,14 @@ pub fn negamax( return Ok(q_score); } - let color = game.current_player(); - let mut best_move = None; - let mut best_score = MIN_SCORE; let mut legal_moves = 0; - let all_moves = game.board.pseudo_moves_all(); - + let color = game.current_player(); + let mut best_score = MIN_SCORE; + let mut best_move = None; + let mut moves = game.board.pseudo_moves_all(); let tt_move = game.tt.lookup(game.hash).and_then(|entry| entry.mv); - let moves = move_ordering::sort_moves(all_moves, &game.mailbox, tt_move); + + moves.sort_unstable_by_key(|mv| score_move(&game.mailbox, *mv, tt_move)); for mv in moves { game.make_move(&mv); diff --git a/src/search/quiescence.rs b/src/search/quiescence.rs index 01b44db..0644a9d 100644 --- a/src/search/quiescence.rs +++ b/src/search/quiescence.rs @@ -3,7 +3,7 @@ use anyhow::{bail, Result}; use crate::{board::game::Game, evaluation::pesto::pesto}; use super::{ - move_ordering, + move_ordering::score_move, time::{hard_limit, TimeInfo}, }; @@ -23,10 +23,11 @@ pub fn quiescence(game: &mut Game, mut alpha: i32, beta: i32, time_info: &TimeIn } let color = game.current_player(); - let all_moves = game.board.pseudo_moves_all_captures(); - let tt_move = game.tt.lookup(game.hash).and_then(|entry| entry.mv); - let moves = move_ordering::sort_moves(all_moves, &game.mailbox, tt_move); let mut best_score = stand_pat; + let mut moves = game.board.pseudo_moves_all_captures(); + let tt_move = game.tt.lookup(game.hash).and_then(|entry| entry.mv); + + moves.sort_unstable_by_key(|mv| score_move(&game.mailbox, *mv, tt_move)); for mv in moves { game.make_move(&mv);