Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions src/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use crate::{
search::{
Depth, MAX_DEPTH, Searcher,
game_history::GameHistory,
picker::MovePicker,
score_table::{DEFAULT_TABLE_SIZE_MB, ScoreTable},
status::{SearchStatus, SearchStatusValue},
},
Expand Down Expand Up @@ -111,10 +110,11 @@ impl Engine {

status.set(SearchStatusValue::Stopped);

if let Some(best_move) = pv.first().cloned().or_else(|| {
let mut picker = MovePicker::new(&position, false, None, [None, None]);
picker.next().map(|mov| mov.to_string())
}) {
if let Some(best_move) = pv
.first()
.cloned()
.or_else(|| position.moves(MoveStage::All).into_iter().next().map(|m| m.to_string()))
{
if let Some(ponder_move) = pv.get(1) {
println!("bestmove {} ponder {}", best_move, ponder_move);
} else {
Expand Down
14 changes: 6 additions & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,16 @@ use crate::{
repl::{Command, DumpCommand, PositionCommand, repl},
time::get_duration,
},
moves::{Move, generate::magics::save_magics},
moves::generate::magics::save_magics,
position::{
Position,
MoveStage, Position,
color::Color,
fen::{KIWIPETE_POSITION, START_POSITION},
hash::save_zobrist_numbers,
},
search::{
game_history::GameHistory,
perft::perft,
picker::MovePicker,
score_table::{DEFAULT_TABLE_SIZE_MB, MAX_TABLE_SIZE_MB, MIN_TABLE_SIZE_MB},
status::SearchStatusValue,
},
Expand Down Expand Up @@ -157,14 +156,13 @@ fn main() {
engine.score_table.lock().unwrap().clear();
}
Command::List => {
let picker = MovePicker::new(&engine.position, false, None, [None, None]);
let moves = picker.into_iter().collect::<Vec<Move>>();
let fmt = moves.iter().map(|m| format!("{} ", m)).collect::<String>();
let mut moves = engine.position.moves(MoveStage::All);
let fmt = moves.into_iter().map(|m| format!("{} ", m)).collect::<String>();
println!("{}\n{} moves", fmt, moves.len());
}
Command::Move { r#move } => {
let picker = MovePicker::new(&engine.position, false, None, [None, None]);
if let Some(mov) = picker.into_iter().find(|&m| m.to_string() == r#move) {
let mut moves = engine.position.moves(MoveStage::All);
if let Some(mov) = moves.into_iter().find(|&m| m.to_string() == r#move) {
let reversible = mov.is_reversible(&engine.position);
engine.position = engine.position.make_move(mov);
engine.game_history.lock().unwrap().push(&engine.position, reversible);
Expand Down
7 changes: 4 additions & 3 deletions src/moves/generate/castle.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use crate::moves::vec::MoveVec;
use crate::moves::{Move, MoveFlag};
use crate::position::{
MoveStage, Position, bitboard::Bitboard, castling_rights::CastlingSide, piece::Piece, square::Square,
};

use super::{MoveVec, square_attackers};
use super::square_attackers;

const COLOR_CASTLE_RANKS: [Bitboard; 2] = [Bitboard::rank_mask(0), Bitboard::rank_mask(7)];
const FINAL_KING_SQUARES: [Square; 4] = [Square::G1, Square::C1, Square::G8, Square::C8];
Expand Down Expand Up @@ -90,7 +91,7 @@ pub fn castle_moves(position: &Position, stage: MoveStage, moves: &mut MoveVec)
mod tests {
use super::castle_moves;
use crate::{
moves::generate::MoveVec,
moves::vec::MoveVec,
position::{MoveStage, Position},
};
use std::str::FromStr;
Expand All @@ -102,7 +103,7 @@ mod tests {

assert_eq!(buf.len(), moves.len());

for m in buf {
for m in buf.into_iter() {
assert!(moves.contains(&m.to_string().as_str()));
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/moves/generate/leapers.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
moves::{Move, MoveFlag},
moves::{Move, MoveFlag, vec::MoveVec},
position::{
Position,
bitboard::Bitboard,
Expand All @@ -9,7 +9,7 @@ use crate::{
},
};

use super::{MoveStage, MoveVec};
use super::MoveStage;

pub type LeaperAttackMap = [Bitboard; 64];

Expand Down
35 changes: 16 additions & 19 deletions src/moves/generate/mod.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
use super::{Move, MoveFlag, make::make_move};
use crate::position::{MoveStage, Position, bitboard::Bitboard, color::Color, piece::Piece, square::Square};
use super::{MoveFlag, make::make_move};
use crate::{
moves::vec::MoveVec,
position::{MoveStage, Position, bitboard::Bitboard, color::Color, piece::Piece, square::Square},
};
use castle::castle_moves;
use leapers::{king_attackers, king_regular_moves, knight_attackers, knight_moves};
use magics::queen_attacks;
use pawns::{pawn_attackers, pawn_moves};
use sliders::{bishop_moves, diagonal_attackers, file_attackers, queen_moves, rook_moves};
use smallvec::SmallVec;

pub mod castle;
pub mod leapers;
pub mod magics;
pub mod pawns;
pub mod sliders;

pub type MoveVec = SmallVec<[Move; 64]>;

pub fn generate_moves(position: &Position, stage: MoveStage) -> MoveVec {
let mut moves = MoveVec::new();
pub fn generate_moves(position: &Position, stage: MoveStage, mut moves: &mut MoveVec) {
moves.clear();

let our_king = position
.pieces_color_bb(Piece::King, position.side_to_move())
Expand Down Expand Up @@ -62,11 +62,9 @@ pub fn generate_moves(position: &Position, stage: MoveStage) -> MoveVec {
_ => {}
};

let new_position = make_move::<false>(position, *mov);
let new_position = make_move::<false>(position, mov);
!new_position.is_check()
});

moves
}

pub fn square_attackers(position: &Position, square: Square, color: Color) -> Bitboard {
Expand All @@ -81,17 +79,16 @@ pub fn square_attackers(position: &Position, square: Square, color: Color) -> Bi
mod tests {
use std::str::FromStr;

use crate::{moves::Move, position::Position};
use crate::position::Position;

use super::{MoveStage, MoveVec};

fn assert_eq_vec_move(moves: &[Move], expected: &[&str]) {
fn assert_eq_vec_move(moves: &mut MoveVec, expected: &[&str]) {
assert_eq!(moves.len(), expected.len());
let mov_strs = moves.iter().map(|m| m.to_string()).collect::<Vec<String>>();
moves
let move_vec = moves.into_iter().map(|m| m.to_string()).collect::<Vec<String>>();
move_vec
.iter()
.map(|m| m.to_string())
.for_each(|m| assert!(expected.contains(&m.as_str()), "got: {:?}, expected: {:?}", mov_strs, expected));
.for_each(|m| assert!(expected.contains(&m.as_str()), "got: {:?}, expected: {:?}", move_vec, expected));
Comment on lines +86 to +91

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Compare the complete move multisets.

The current check accepts duplicates such as actual [a, a] against expected [a, b]. Sort both collections and assert equality.

Proposed fix
 fn assert_eq_vec_move(moves: &mut MoveVec, expected: &[&str]) {
-    assert_eq!(moves.len(), expected.len());
-    let move_vec = moves.into_iter().map(|m| m.to_string()).collect::<Vec<String>>();
-    move_vec
-        .iter()
-        .for_each(|m| assert!(expected.contains(&m.as_str()), "got: {:?}, expected: {:?}", move_vec, expected));
+    let mut actual = moves.into_iter().map(|m| m.to_string()).collect::<Vec<_>>();
+    let mut expected = expected.iter().map(|m| (*m).to_owned()).collect::<Vec<_>>();
+    actual.sort_unstable();
+    expected.sort_unstable();
+    assert_eq!(actual, expected);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fn assert_eq_vec_move(moves: &mut MoveVec, expected: &[&str]) {
assert_eq!(moves.len(), expected.len());
let mov_strs = moves.iter().map(|m| m.to_string()).collect::<Vec<String>>();
moves
let move_vec = moves.into_iter().map(|m| m.to_string()).collect::<Vec<String>>();
move_vec
.iter()
.map(|m| m.to_string())
.for_each(|m| assert!(expected.contains(&m.as_str()), "got: {:?}, expected: {:?}", mov_strs, expected));
.for_each(|m| assert!(expected.contains(&m.as_str()), "got: {:?}, expected: {:?}", move_vec, expected));
fn assert_eq_vec_move(moves: &mut MoveVec, expected: &[&str]) {
let mut actual = moves.into_iter().map(|m| m.to_string()).collect::<Vec<_>>();
let mut expected = expected.iter().map(|m| (*m).to_owned()).collect::<Vec<_>>();
actual.sort_unstable();
expected.sort_unstable();
assert_eq!(actual, expected);
}

}

pub fn assert_staged_moves(
Expand All @@ -103,14 +100,14 @@ mod tests {

let mut moves1 = MoveVec::new();
function(&position, MoveStage::All, &mut moves1);
assert_eq_vec_move(&moves1, &expected[0]);
assert_eq_vec_move(&mut moves1, &expected[0]);

let mut moves2 = MoveVec::new();
function(&position, MoveStage::CapturesAndPromotions, &mut moves2);
assert_eq_vec_move(&moves2, &expected[1]);
assert_eq_vec_move(&mut moves2, &expected[1]);

let mut moves3 = MoveVec::new();
function(&position, MoveStage::Quiet, &mut moves3);
assert_eq_vec_move(&moves3, &expected[2]);
assert_eq_vec_move(&mut moves3, &expected[2]);
}
}
7 changes: 2 additions & 5 deletions src/moves/generate/pawns.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
moves::{Move, MoveFlag},
moves::{Move, MoveFlag, vec::MoveVec},
position::{
MoveStage, Position,
bitboard::Bitboard,
Expand All @@ -9,10 +9,7 @@ use crate::{
},
};

use super::{
MoveVec,
leapers::{LeaperAttackMap, init_leaper_attacks},
};
use super::leapers::{LeaperAttackMap, init_leaper_attacks};

const PAWN_DIRECTIONS: [Direction; 2] = [Square::NORTH, Square::SOUTH];

Expand Down
7 changes: 3 additions & 4 deletions src/moves/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::{fmt::Display, mem};

pub mod generate;
pub mod make;
pub mod vec;

primitive_enum! { MoveFlag u8;
Quiet,
Expand Down Expand Up @@ -205,9 +206,7 @@ mod tests {
#[case("8/8/4k3/8/2p5/8/B2P2K1/8 w - - 0 1")]
fn legal_are_pseudo_legal(#[case] fen: Fen) {
let position = Position::try_from(fen.clone()).unwrap();
position
.moves(MoveStage::All)
.iter()
.for_each(|m| assert!(m.pseudo_legal(&position)));
let mut moves = position.moves(MoveStage::All);
moves.into_iter().for_each(|m| assert!(m.pseudo_legal(&position)));
}
}
Loading
Loading