pub struct MoveList { /* private fields */ }Expand description
A fixed-capacity, stack-allocated list of Move values.
This is a drop-in replacement for Vec<Move> in move-generation hot paths.
It avoids heap allocation, eliminates dynamic capacity checks, and improves
cache locality by keeping the entire move list on the stack.
Implementations§
Source§impl MoveList
impl MoveList
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates an empty MoveList.
Examples found in repository?
examples/list_moves.rs (line 17)
7fn main() {
8 atomic_movegen::attacks::init();
9 let args: Vec<String> = env::args().collect();
10 if args.len() < 2 {
11 eprintln!("Usage: list_moves <fen>");
12 return;
13 }
14 let fen = &args[1];
15 let board = Board::from_fen(fen).expect("Invalid FEN");
16
17 let mut moves = MoveList::new();
18 movegen::generate_legal(&board, &mut moves);
19 moves
20 .as_mut_slice()
21 .sort_by_key(|m| (m.from_sq() as u16, m.to_sq() as u16));
22
23 println!("Legal moves ({} total):", moves.len());
24 for &m in moves.as_slice() {
25 println!(" {}{}", sq_str(m.from_sq()), sq_str(m.to_sq()));
26 }
27}More examples
examples/perft_divide.rs (line 20)
8fn main() {
9 atomic_movegen::attacks::init();
10 let args: Vec<String> = env::args().collect();
11 if args.len() < 3 {
12 eprintln!("Usage: perft_divide <fen> <depth>");
13 return;
14 }
15 let fen = &args[1];
16 let depth: u32 = args[2].parse().unwrap_or(1);
17
18 let mut board = Board::from_fen(fen).expect("Invalid FEN");
19
20 let mut moves = MoveList::new();
21 movegen::generate_legal(&board, &mut moves);
22 moves
23 .as_mut_slice()
24 .sort_by_key(|m| (m.from_sq() as u16, m.to_sq() as u16));
25
26 let mut total = 0u64;
27 for &m in moves.as_slice() {
28 let mut state = atomic_movegen::board::StateInfo::new();
29 board.do_move(m, &mut state);
30 let cnt = if depth <= 1 {
31 1
32 } else {
33 perft(&mut board, depth - 1)
34 };
35 board.undo_move(m, &state);
36 total += cnt;
37 println!("{}{}: {}", sq_str(m.from_sq()), sq_str(m.to_sq()), cnt);
38 }
39 println!("\nNodes searched: {}", total);
40}examples/fen_after.rs (line 22)
8fn main() {
9 atomic_movegen::attacks::init();
10 let args: Vec<String> = env::args().collect();
11 if args.len() < 3 {
12 eprintln!("Usage: fen_after <fen> <move>");
13 return;
14 }
15 let fen = &args[1];
16 let movestr = &args[2];
17 let mut board = Board::from_fen(fen).expect("Invalid FEN");
18
19 let from_sq = parse_sq(&movestr[0..2]);
20 let to_sq = parse_sq(&movestr[2..4]);
21
22 let mut moves = MoveList::new();
23 movegen::generate_legal(&board, &mut moves);
24
25 for &m in moves.as_slice() {
26 if m.from_sq() == from_sq && m.to_sq() == to_sq {
27 let mut state = atomic_movegen::board::StateInfo::new();
28 board.do_move(m, &mut state);
29 println!("{}", board.fen());
30
31 let mut moves2 = MoveList::new();
32 movegen::generate_legal(&board, &mut moves2);
33 moves2
34 .as_mut_slice()
35 .sort_by_key(|m| (m.from_sq() as u16, m.to_sq() as u16));
36 println!("Legal moves ({} total):", moves2.len());
37 for &m2 in moves2.as_slice() {
38 println!(" {}{}", sq_str(m2.from_sq()), sq_str(m2.to_sq()));
39 }
40 return;
41 }
42 }
43 println!("Move not found");
44}examples/debug_moves.rs (line 18)
8fn main() {
9 atomic_movegen::attacks::init();
10 let args: Vec<String> = env::args().collect();
11 if args.len() < 2 {
12 eprintln!("Usage: debug_moves <fen>");
13 return;
14 }
15 let fen = &args[1];
16 let board = Board::from_fen(fen).expect("Invalid FEN");
17
18 let mut pseudo = MoveList::new();
19 movegen::generate_pseudo_legal(&board, &mut pseudo);
20
21 let mut pseudo_set = HashSet::new();
22 for &m in pseudo.as_slice() {
23 if !pseudo_set.insert((m.from_sq(), m.to_sq(), m.move_type())) {
24 println!(
25 "DUPLICATE PSEUDO-LEGAL: {}{}",
26 sq_str(m.from_sq()),
27 sq_str(m.to_sq())
28 );
29 }
30 }
31
32 let mut legal = MoveList::new();
33 movegen::generate_legal(&board, &mut legal);
34
35 let mut legal_set = HashSet::new();
36 for &m in legal.as_slice() {
37 if !legal_set.insert((m.from_sq(), m.to_sq(), m.move_type())) {
38 println!(
39 "DUPLICATE LEGAL: {}{}",
40 sq_str(m.from_sq()),
41 sq_str(m.to_sq())
42 );
43 }
44 }
45
46 println!(
47 "Pseudo-legal moves: {} (unique: {})",
48 pseudo.len(),
49 pseudo_set.len()
50 );
51 println!("Legal moves: {} (unique: {})", legal.len(), legal_set.len());
52}examples/pawn_debug.rs (line 39)
7fn main() {
8 atomic_movegen::attacks::init();
9 let args: Vec<String> = env::args().collect();
10 if args.len() < 2 {
11 eprintln!("Usage: pawn_debug <fen>");
12 return;
13 }
14 let fen = &args[1];
15 let board = Board::from_fen(fen).expect("Invalid FEN");
16
17 println!("Board side to move: {:?}", board.side_to_move());
18
19 // Manual check: iterate all pawns
20 let us = board.side_to_move();
21 let _them = us.flip();
22 let _occupied = board.occupied();
23
24 let pawns = board.pieces_color_pt(us, PieceType::Pawn);
25 println!("Pawns ({:?}): {}", us, pawns.count());
26 let mut p = pawns;
27 while !p.is_empty() {
28 let sq = p.pop_lsb();
29 println!(
30 " Pawn at {} (idx={}): file={} rank={}",
31 sq_str(sq),
32 sq as u8,
33 file_of(sq) as u8,
34 rank_of(sq) as u8
35 );
36 }
37
38 // Check what generate_legal produces
39 let mut moves = MoveList::new();
40 movegen::generate_legal(&board, &mut moves);
41
42 // Find all h3g2 moves
43 let h3 = Square::from_index(23);
44 let g2 = Square::from_index(14);
45 println!("\nAll h3g2 moves:");
46 for (i, &m) in moves.as_slice().iter().enumerate() {
47 if m.from_sq() == h3 && m.to_sq() == g2 {
48 println!(
49 " Move #{}: from={} to={} type={:?}",
50 i,
51 sq_str(m.from_sq()),
52 sq_str(m.to_sq()),
53 m.move_type()
54 );
55 }
56 }
57
58 // Also check how many times each move appears
59 use std::collections::HashMap;
60 let mut counts: HashMap<(u16, u16, u16), usize> = HashMap::new();
61 for &m in moves.as_slice() {
62 *counts
63 .entry((m.from_sq() as u16, m.to_sq() as u16, m.move_type() as u16))
64 .or_insert(0) += 1;
65 }
66 for ((from, to, mt), count) in &counts {
67 if *count > 1 {
68 println!(
69 "DUPLICATE: {}{} type={:?} appears {} times",
70 sq_str(Square::from_u8(*from as u8)),
71 sq_str(Square::from_u8(*to as u8)),
72 match mt {
73 0 => "Normal",
74 1 => "Promo",
75 2 => "EP",
76 3 => "Castle",
77 _ => "?",
78 },
79 count
80 );
81 }
82 }
83}Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of moves currently stored.
Examples found in repository?
examples/list_moves.rs (line 23)
7fn main() {
8 atomic_movegen::attacks::init();
9 let args: Vec<String> = env::args().collect();
10 if args.len() < 2 {
11 eprintln!("Usage: list_moves <fen>");
12 return;
13 }
14 let fen = &args[1];
15 let board = Board::from_fen(fen).expect("Invalid FEN");
16
17 let mut moves = MoveList::new();
18 movegen::generate_legal(&board, &mut moves);
19 moves
20 .as_mut_slice()
21 .sort_by_key(|m| (m.from_sq() as u16, m.to_sq() as u16));
22
23 println!("Legal moves ({} total):", moves.len());
24 for &m in moves.as_slice() {
25 println!(" {}{}", sq_str(m.from_sq()), sq_str(m.to_sq()));
26 }
27}More examples
examples/fen_after.rs (line 36)
8fn main() {
9 atomic_movegen::attacks::init();
10 let args: Vec<String> = env::args().collect();
11 if args.len() < 3 {
12 eprintln!("Usage: fen_after <fen> <move>");
13 return;
14 }
15 let fen = &args[1];
16 let movestr = &args[2];
17 let mut board = Board::from_fen(fen).expect("Invalid FEN");
18
19 let from_sq = parse_sq(&movestr[0..2]);
20 let to_sq = parse_sq(&movestr[2..4]);
21
22 let mut moves = MoveList::new();
23 movegen::generate_legal(&board, &mut moves);
24
25 for &m in moves.as_slice() {
26 if m.from_sq() == from_sq && m.to_sq() == to_sq {
27 let mut state = atomic_movegen::board::StateInfo::new();
28 board.do_move(m, &mut state);
29 println!("{}", board.fen());
30
31 let mut moves2 = MoveList::new();
32 movegen::generate_legal(&board, &mut moves2);
33 moves2
34 .as_mut_slice()
35 .sort_by_key(|m| (m.from_sq() as u16, m.to_sq() as u16));
36 println!("Legal moves ({} total):", moves2.len());
37 for &m2 in moves2.as_slice() {
38 println!(" {}{}", sq_str(m2.from_sq()), sq_str(m2.to_sq()));
39 }
40 return;
41 }
42 }
43 println!("Move not found");
44}examples/debug_moves.rs (line 48)
8fn main() {
9 atomic_movegen::attacks::init();
10 let args: Vec<String> = env::args().collect();
11 if args.len() < 2 {
12 eprintln!("Usage: debug_moves <fen>");
13 return;
14 }
15 let fen = &args[1];
16 let board = Board::from_fen(fen).expect("Invalid FEN");
17
18 let mut pseudo = MoveList::new();
19 movegen::generate_pseudo_legal(&board, &mut pseudo);
20
21 let mut pseudo_set = HashSet::new();
22 for &m in pseudo.as_slice() {
23 if !pseudo_set.insert((m.from_sq(), m.to_sq(), m.move_type())) {
24 println!(
25 "DUPLICATE PSEUDO-LEGAL: {}{}",
26 sq_str(m.from_sq()),
27 sq_str(m.to_sq())
28 );
29 }
30 }
31
32 let mut legal = MoveList::new();
33 movegen::generate_legal(&board, &mut legal);
34
35 let mut legal_set = HashSet::new();
36 for &m in legal.as_slice() {
37 if !legal_set.insert((m.from_sq(), m.to_sq(), m.move_type())) {
38 println!(
39 "DUPLICATE LEGAL: {}{}",
40 sq_str(m.from_sq()),
41 sq_str(m.to_sq())
42 );
43 }
44 }
45
46 println!(
47 "Pseudo-legal moves: {} (unique: {})",
48 pseudo.len(),
49 pseudo_set.len()
50 );
51 println!("Legal moves: {} (unique: {})", legal.len(), legal_set.len());
52}Sourcepub fn push(&mut self, m: Move)
pub fn push(&mut self, m: Move)
Appends a move to the end of the list.
§Panics
Panics in debug mode if the list is full (len == MAX_MOVES).
In release mode, exceeding the capacity silently overwrites (unreachable
in practice due to the move-count bound).
Sourcepub fn as_slice(&self) -> &[Move]
pub fn as_slice(&self) -> &[Move]
Returns the stored moves as a slice.
Examples found in repository?
examples/list_moves.rs (line 24)
7fn main() {
8 atomic_movegen::attacks::init();
9 let args: Vec<String> = env::args().collect();
10 if args.len() < 2 {
11 eprintln!("Usage: list_moves <fen>");
12 return;
13 }
14 let fen = &args[1];
15 let board = Board::from_fen(fen).expect("Invalid FEN");
16
17 let mut moves = MoveList::new();
18 movegen::generate_legal(&board, &mut moves);
19 moves
20 .as_mut_slice()
21 .sort_by_key(|m| (m.from_sq() as u16, m.to_sq() as u16));
22
23 println!("Legal moves ({} total):", moves.len());
24 for &m in moves.as_slice() {
25 println!(" {}{}", sq_str(m.from_sq()), sq_str(m.to_sq()));
26 }
27}More examples
examples/perft_divide.rs (line 27)
8fn main() {
9 atomic_movegen::attacks::init();
10 let args: Vec<String> = env::args().collect();
11 if args.len() < 3 {
12 eprintln!("Usage: perft_divide <fen> <depth>");
13 return;
14 }
15 let fen = &args[1];
16 let depth: u32 = args[2].parse().unwrap_or(1);
17
18 let mut board = Board::from_fen(fen).expect("Invalid FEN");
19
20 let mut moves = MoveList::new();
21 movegen::generate_legal(&board, &mut moves);
22 moves
23 .as_mut_slice()
24 .sort_by_key(|m| (m.from_sq() as u16, m.to_sq() as u16));
25
26 let mut total = 0u64;
27 for &m in moves.as_slice() {
28 let mut state = atomic_movegen::board::StateInfo::new();
29 board.do_move(m, &mut state);
30 let cnt = if depth <= 1 {
31 1
32 } else {
33 perft(&mut board, depth - 1)
34 };
35 board.undo_move(m, &state);
36 total += cnt;
37 println!("{}{}: {}", sq_str(m.from_sq()), sq_str(m.to_sq()), cnt);
38 }
39 println!("\nNodes searched: {}", total);
40}examples/fen_after.rs (line 25)
8fn main() {
9 atomic_movegen::attacks::init();
10 let args: Vec<String> = env::args().collect();
11 if args.len() < 3 {
12 eprintln!("Usage: fen_after <fen> <move>");
13 return;
14 }
15 let fen = &args[1];
16 let movestr = &args[2];
17 let mut board = Board::from_fen(fen).expect("Invalid FEN");
18
19 let from_sq = parse_sq(&movestr[0..2]);
20 let to_sq = parse_sq(&movestr[2..4]);
21
22 let mut moves = MoveList::new();
23 movegen::generate_legal(&board, &mut moves);
24
25 for &m in moves.as_slice() {
26 if m.from_sq() == from_sq && m.to_sq() == to_sq {
27 let mut state = atomic_movegen::board::StateInfo::new();
28 board.do_move(m, &mut state);
29 println!("{}", board.fen());
30
31 let mut moves2 = MoveList::new();
32 movegen::generate_legal(&board, &mut moves2);
33 moves2
34 .as_mut_slice()
35 .sort_by_key(|m| (m.from_sq() as u16, m.to_sq() as u16));
36 println!("Legal moves ({} total):", moves2.len());
37 for &m2 in moves2.as_slice() {
38 println!(" {}{}", sq_str(m2.from_sq()), sq_str(m2.to_sq()));
39 }
40 return;
41 }
42 }
43 println!("Move not found");
44}examples/debug_moves.rs (line 22)
8fn main() {
9 atomic_movegen::attacks::init();
10 let args: Vec<String> = env::args().collect();
11 if args.len() < 2 {
12 eprintln!("Usage: debug_moves <fen>");
13 return;
14 }
15 let fen = &args[1];
16 let board = Board::from_fen(fen).expect("Invalid FEN");
17
18 let mut pseudo = MoveList::new();
19 movegen::generate_pseudo_legal(&board, &mut pseudo);
20
21 let mut pseudo_set = HashSet::new();
22 for &m in pseudo.as_slice() {
23 if !pseudo_set.insert((m.from_sq(), m.to_sq(), m.move_type())) {
24 println!(
25 "DUPLICATE PSEUDO-LEGAL: {}{}",
26 sq_str(m.from_sq()),
27 sq_str(m.to_sq())
28 );
29 }
30 }
31
32 let mut legal = MoveList::new();
33 movegen::generate_legal(&board, &mut legal);
34
35 let mut legal_set = HashSet::new();
36 for &m in legal.as_slice() {
37 if !legal_set.insert((m.from_sq(), m.to_sq(), m.move_type())) {
38 println!(
39 "DUPLICATE LEGAL: {}{}",
40 sq_str(m.from_sq()),
41 sq_str(m.to_sq())
42 );
43 }
44 }
45
46 println!(
47 "Pseudo-legal moves: {} (unique: {})",
48 pseudo.len(),
49 pseudo_set.len()
50 );
51 println!("Legal moves: {} (unique: {})", legal.len(), legal_set.len());
52}examples/pawn_debug.rs (line 46)
7fn main() {
8 atomic_movegen::attacks::init();
9 let args: Vec<String> = env::args().collect();
10 if args.len() < 2 {
11 eprintln!("Usage: pawn_debug <fen>");
12 return;
13 }
14 let fen = &args[1];
15 let board = Board::from_fen(fen).expect("Invalid FEN");
16
17 println!("Board side to move: {:?}", board.side_to_move());
18
19 // Manual check: iterate all pawns
20 let us = board.side_to_move();
21 let _them = us.flip();
22 let _occupied = board.occupied();
23
24 let pawns = board.pieces_color_pt(us, PieceType::Pawn);
25 println!("Pawns ({:?}): {}", us, pawns.count());
26 let mut p = pawns;
27 while !p.is_empty() {
28 let sq = p.pop_lsb();
29 println!(
30 " Pawn at {} (idx={}): file={} rank={}",
31 sq_str(sq),
32 sq as u8,
33 file_of(sq) as u8,
34 rank_of(sq) as u8
35 );
36 }
37
38 // Check what generate_legal produces
39 let mut moves = MoveList::new();
40 movegen::generate_legal(&board, &mut moves);
41
42 // Find all h3g2 moves
43 let h3 = Square::from_index(23);
44 let g2 = Square::from_index(14);
45 println!("\nAll h3g2 moves:");
46 for (i, &m) in moves.as_slice().iter().enumerate() {
47 if m.from_sq() == h3 && m.to_sq() == g2 {
48 println!(
49 " Move #{}: from={} to={} type={:?}",
50 i,
51 sq_str(m.from_sq()),
52 sq_str(m.to_sq()),
53 m.move_type()
54 );
55 }
56 }
57
58 // Also check how many times each move appears
59 use std::collections::HashMap;
60 let mut counts: HashMap<(u16, u16, u16), usize> = HashMap::new();
61 for &m in moves.as_slice() {
62 *counts
63 .entry((m.from_sq() as u16, m.to_sq() as u16, m.move_type() as u16))
64 .or_insert(0) += 1;
65 }
66 for ((from, to, mt), count) in &counts {
67 if *count > 1 {
68 println!(
69 "DUPLICATE: {}{} type={:?} appears {} times",
70 sq_str(Square::from_u8(*from as u8)),
71 sq_str(Square::from_u8(*to as u8)),
72 match mt {
73 0 => "Normal",
74 1 => "Promo",
75 2 => "EP",
76 3 => "Castle",
77 _ => "?",
78 },
79 count
80 );
81 }
82 }
83}Sourcepub fn as_mut_slice(&mut self) -> &mut [Move]
pub fn as_mut_slice(&mut self) -> &mut [Move]
Returns the stored moves as a mutable slice (for sorting, etc.).
Examples found in repository?
examples/list_moves.rs (line 20)
7fn main() {
8 atomic_movegen::attacks::init();
9 let args: Vec<String> = env::args().collect();
10 if args.len() < 2 {
11 eprintln!("Usage: list_moves <fen>");
12 return;
13 }
14 let fen = &args[1];
15 let board = Board::from_fen(fen).expect("Invalid FEN");
16
17 let mut moves = MoveList::new();
18 movegen::generate_legal(&board, &mut moves);
19 moves
20 .as_mut_slice()
21 .sort_by_key(|m| (m.from_sq() as u16, m.to_sq() as u16));
22
23 println!("Legal moves ({} total):", moves.len());
24 for &m in moves.as_slice() {
25 println!(" {}{}", sq_str(m.from_sq()), sq_str(m.to_sq()));
26 }
27}More examples
examples/perft_divide.rs (line 23)
8fn main() {
9 atomic_movegen::attacks::init();
10 let args: Vec<String> = env::args().collect();
11 if args.len() < 3 {
12 eprintln!("Usage: perft_divide <fen> <depth>");
13 return;
14 }
15 let fen = &args[1];
16 let depth: u32 = args[2].parse().unwrap_or(1);
17
18 let mut board = Board::from_fen(fen).expect("Invalid FEN");
19
20 let mut moves = MoveList::new();
21 movegen::generate_legal(&board, &mut moves);
22 moves
23 .as_mut_slice()
24 .sort_by_key(|m| (m.from_sq() as u16, m.to_sq() as u16));
25
26 let mut total = 0u64;
27 for &m in moves.as_slice() {
28 let mut state = atomic_movegen::board::StateInfo::new();
29 board.do_move(m, &mut state);
30 let cnt = if depth <= 1 {
31 1
32 } else {
33 perft(&mut board, depth - 1)
34 };
35 board.undo_move(m, &state);
36 total += cnt;
37 println!("{}{}: {}", sq_str(m.from_sq()), sq_str(m.to_sq()), cnt);
38 }
39 println!("\nNodes searched: {}", total);
40}examples/fen_after.rs (line 34)
8fn main() {
9 atomic_movegen::attacks::init();
10 let args: Vec<String> = env::args().collect();
11 if args.len() < 3 {
12 eprintln!("Usage: fen_after <fen> <move>");
13 return;
14 }
15 let fen = &args[1];
16 let movestr = &args[2];
17 let mut board = Board::from_fen(fen).expect("Invalid FEN");
18
19 let from_sq = parse_sq(&movestr[0..2]);
20 let to_sq = parse_sq(&movestr[2..4]);
21
22 let mut moves = MoveList::new();
23 movegen::generate_legal(&board, &mut moves);
24
25 for &m in moves.as_slice() {
26 if m.from_sq() == from_sq && m.to_sq() == to_sq {
27 let mut state = atomic_movegen::board::StateInfo::new();
28 board.do_move(m, &mut state);
29 println!("{}", board.fen());
30
31 let mut moves2 = MoveList::new();
32 movegen::generate_legal(&board, &mut moves2);
33 moves2
34 .as_mut_slice()
35 .sort_by_key(|m| (m.from_sq() as u16, m.to_sq() as u16));
36 println!("Legal moves ({} total):", moves2.len());
37 for &m2 in moves2.as_slice() {
38 println!(" {}{}", sq_str(m2.from_sq()), sq_str(m2.to_sq()));
39 }
40 return;
41 }
42 }
43 println!("Move not found");
44}Trait Implementations§
Source§impl<'a> IntoIterator for &'a MoveList
Iteration over &MoveList yields Move by value (cheap copy).
impl<'a> IntoIterator for &'a MoveList
Iteration over &MoveList yields Move by value (cheap copy).
Auto Trait Implementations§
impl Freeze for MoveList
impl RefUnwindSafe for MoveList
impl Send for MoveList
impl Sync for MoveList
impl Unpin for MoveList
impl UnsafeUnpin for MoveList
impl UnwindSafe for MoveList
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more