use crate::moves::{Move, MoveDirection}; use crate::possible_moves::PossibleMoves; const FORWARD_LEFT_SLIDE_SQUARES: [usize; 33] = [ 1, 3, 3, 4, 6, 6, 7, 8, 9, 12, 12, 12, 13, 14, 15, 16, 17, 19, 19, 20, 21, 22, 23, 24, 27, 27, 27, 28, 29, 30, 32, 32, 32, ]; const FORWARD_RIGHT_SLIDE_SQUARES: [usize; 33] = [ 2, 2, 3, 4, 6, 6, 7, 8, 10, 10, 12, 12, 13, 14, 15, 16, 18, 18, 19, 20, 21, 22, 23, 24, 26, 26, 27, 28, 29, 30, 32, 32, 32, ]; const BACKWARD_LEFT_SLIDE_SQUARES: [usize; 33] = [ 1, 3, 3, 4, 5, 7, 7, 8, 9, 11, 11, 13, 13, 14, 15, 16, 17, 19, 19, 20, 21, 22, 23, 24, 25, 27, 27, 28, 29, 30, 31, 32, 32, ]; const BACKWARD_RIGHT_SLIDE_SQUARES: [usize; 33] = [ 2, 2, 3, 4, 5, 7, 7, 8, 10, 10, 11, 13, 13, 14, 15, 16, 19, 19, 19, 20, 21, 22, 23, 24, 26, 26, 27, 28, 29, 30, 31, 32, 32, ]; const FORWARD_LEFT_JUMP_SQUARES: [usize; 33] = [ 1, 6, 6, 6, 6, 6, 7, 8, 9, 12, 12, 12, 13, 14, 15, 16, 17, 20, 20, 20, 21, 22, 23, 28, 28, 28, 28, 28, 29, 32, 32, 32, 32, ]; const FORWARD_RIGHT_JUMP_SQUARES: [usize; 33] = [ 2, 2, 3, 6, 6, 6, 7, 12, 12, 12, 12, 12, 13, 14, 15, 18, 18, 18, 19, 20, 21, 22, 23, 26, 26, 26, 27, 28, 29, 32, 32, 32, 32, ]; const BACKWARD_LEFT_JUMP_SQUARES: [usize; 33] = [ 4, 4, 4, 4, 5, 8, 8, 8, 9, 14, 14, 14, 14, 14, 15, 16, 17, 20, 20, 20, 21, 22, 23, 24, 25, 28, 28, 28, 29, 30, 31, 32, 32, ]; const BACKWARD_RIGHT_JUMP_SQUARES: [usize; 33] = [ 2, 2, 3, 4, 5, 10, 10, 10, 10, 10, 11, 14, 14, 14, 15, 20, 20, 20, 20, 20, 21, 22, 23, 26, 26, 26, 27, 28, 29, 30, 31, 32, 32, ]; static SLIDE_ARRAYS: [[usize; 33]; 4] = [ FORWARD_LEFT_SLIDE_SQUARES, FORWARD_RIGHT_SLIDE_SQUARES, BACKWARD_LEFT_SLIDE_SQUARES, BACKWARD_RIGHT_SLIDE_SQUARES, ]; static JUMP_ARRAYS: [[usize; 33]; 4] = [ FORWARD_LEFT_JUMP_SQUARES, FORWARD_RIGHT_JUMP_SQUARES, BACKWARD_LEFT_JUMP_SQUARES, BACKWARD_RIGHT_JUMP_SQUARES, ]; pub struct PossibleMovesIter { possible_moves: PossibleMoves, current_square: usize, current_direction: MoveDirection, movers: u32, squares: &'static [usize; 33], } impl From for PossibleMovesIter { fn from(possible_moves: PossibleMoves) -> Self { Self { possible_moves, current_square: 0, current_direction: MoveDirection::ForwardLeft, movers: possible_moves.forward_left_bits(), squares: unsafe { if possible_moves.can_jump() { JUMP_ARRAYS.get_unchecked(0) } else { SLIDE_ARRAYS.get_unchecked(0) } }, } } } impl Iterator for PossibleMovesIter { type Item = Move; fn next(&mut self) -> Option { loop { if self.current_square == 32 { if self.current_direction != MoveDirection::BackwardRight { self.current_square = 0; // safety: only results in undefined variant if equal to backward right // this has already been checked for self.current_direction = unsafe { std::mem::transmute((self.current_direction as u8) + 1) }; self.movers = self .possible_moves .get_direction_bits(self.current_direction); // safety: the max value of the enum is 3 unsafe { self.squares = &*(self.squares as *const [usize; 33]).add(1); } } else { return None; } } if (self.movers >> self.current_square) & 1 != 0 { let next_move = Move::new( self.current_square, self.current_direction, self.possible_moves.can_jump(), ); // safety: self.current_square will never be > 32 // squares does not contain such a value unsafe { self.current_square = *self.squares.get_unchecked(self.current_square); } return Some(next_move); } if self.current_square != 32 { // safety: self.current_square will never be > 32 // squares does not contain such a value unsafe { self.current_square = *self.squares.get_unchecked(self.current_square); } } } } fn size_hint(&self) -> (usize, Option) { ( 0, Some( (32 - self.current_square) + 32 * match self.current_direction { MoveDirection::ForwardLeft => 3, MoveDirection::ForwardRight => 2, MoveDirection::BackwardLeft => 1, MoveDirection::BackwardRight => 0, }, ), ) } }