chess_move_gen/mv_list/
mv_vec.rs

1use crate::bb::{BB, END_ROWS};
2use crate::castle::Castle;
3use crate::mv::Move;
4use crate::mv_list::MoveAdder;
5use crate::piece::*;
6use crate::square::{Square, SquareInternal};
7use std;
8use std::fmt;
9
10/// MoveVec implements MoveAdder and collects moves in a vector.
11/// Use `iter` to access the moves once they have been added.
12#[derive(Clone)]
13pub struct MoveVec {
14    moves: Vec<Move>,
15}
16
17impl fmt::Display for MoveVec {
18    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
19        write!(
20            f,
21            "{}",
22            self.iter()
23                .map(|mv: &Move| mv.to_string())
24                .collect::<Vec<String>>()
25                .join(", ")
26        )
27    }
28}
29
30impl fmt::Debug for MoveVec {
31    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32        write!(
33            f,
34            "{}",
35            self.iter()
36                .map(|mv: &Move| mv.to_string())
37                .collect::<Vec<String>>()
38                .join(", ")
39        )
40    }
41}
42
43impl MoveAdder for MoveVec {
44    fn add_captures(&mut self, from: Square, targets: BB) {
45        self.insert_moves(from, targets, Move::new_capture);
46    }
47
48    fn add_non_captures(&mut self, from: Square, targets: BB) {
49        self.insert_moves(from, targets, Move::new_push);
50    }
51
52    fn add_castle(&mut self, castle: Castle) {
53        self.moves.push(Move::new_castle(castle));
54    }
55
56    fn add_pawn_ep_capture(&mut self, from: Square, to: Square) {
57        self.moves.push(Move::new_ep_capture(from, to));
58    }
59
60    fn add_pawn_pushes(&mut self, shift: usize, targets: BB) {
61        self.insert_promos_by_shift(shift, targets & END_ROWS, Move::new_promotion);
62        self.insert_moves_by_shift(shift, targets & !END_ROWS, Move::new_push);
63    }
64
65    fn add_pawn_captures(&mut self, shift: usize, targets: BB) {
66        self.insert_promos_by_shift(shift, targets & END_ROWS, Move::new_capture_promotion);
67        self.insert_moves_by_shift(shift, targets & !END_ROWS, Move::new_capture);
68    }
69}
70
71impl Default for MoveVec {
72    fn default() -> Self {
73        Self::new()
74    }
75}
76
77impl MoveVec {
78    pub fn new() -> MoveVec {
79        MoveVec {
80            moves: Vec::with_capacity(60),
81        }
82    }
83
84    pub fn iter(&self) -> std::slice::Iter<Move> {
85        self.moves.iter()
86    }
87
88    fn insert_moves<F: Fn(Square, Square) -> Move>(&mut self, from: Square, targets: BB, f: F) {
89        for (to, _) in targets.iter() {
90            self.moves.push(f(from, to));
91        }
92    }
93
94    fn insert_moves_by_shift<F: Fn(Square, Square) -> Move>(
95        &mut self,
96        shift: usize,
97        targets: BB,
98        f: F,
99    ) {
100        for (to, _) in targets.iter() {
101            let from = to.rotate_right(shift as SquareInternal);
102            self.moves.push(f(from, to));
103        }
104    }
105
106    pub fn len(&self) -> usize {
107        self.moves.len()
108    }
109
110    #[allow(dead_code)]
111    pub fn is_empty(&self) -> bool {
112        self.len() == 0
113    }
114
115    fn insert_promos_by_shift<F: Fn(Square, Square, Kind) -> Move>(
116        &mut self,
117        shift: usize,
118        targets: BB,
119        f: F,
120    ) {
121        for (to, _) in targets.iter() {
122            let from = to.rotate_right(shift as SquareInternal);
123            self.moves.push(f(from, to, QUEEN));
124            self.moves.push(f(from, to, KNIGHT));
125            self.moves.push(f(from, to, BISHOP));
126            self.moves.push(f(from, to, ROOK));
127        }
128    }
129}
130
131#[cfg(test)]
132mod test {
133    use super::*;
134    use crate::generation::*;
135    use crate::position::*;
136
137    #[test]
138    fn test_move_vec() {
139        let position = &Position::from_fen(STARTING_POSITION_FEN).unwrap();
140        let mut list = MoveVec::new();
141
142        legal_moves(&position, &mut list);
143
144        assert_eq!(list.len(), 20);
145    }
146}