diff --git a/battlesnake/src/types/simulation.rs b/battlesnake/src/types/simulation.rs index 0756efb..df53c79 100644 --- a/battlesnake/src/types/simulation.rs +++ b/battlesnake/src/types/simulation.rs @@ -204,25 +204,19 @@ impl Board { } pub fn valid_actions(&self, id: u8) -> impl Iterator + use<'_> { - let head = self - .snakes - .binary_search_by_key(&id, |snake| snake.id) - .ok() - .map(|index| self.snakes[index].head()); - if head.is_none() { - warn!( - "Asked for an action for a snake that doesn't exist: {id} not in {:?}", - self.snakes - ); + let index = self.snakes.binary_search_by_key(&id, |snake| snake.id).ok(); + if index.is_none() { + warn!("Asked for a snake that doesn't exist"); } - enum_iterator::all::() - .filter_map(move |direction| { - head.and_then(|head| head.apply(direction)) - .map(|tile| (direction, tile)) - }) - .filter(|(_, tile)| tile.x < self.width && tile.y < self.height) - .filter(|(_, tile)| self.is_free(*tile)) - .map(|(direction, _)| direction) + index + .into_iter() + .flat_map(|index| self.valid_actions_index(index)) + } + + pub fn random_actions( + &self, + ) -> impl Iterator + use<'_>)> { + (0..self.snakes.len()).map(|index| (self.snakes[index].id, self.valid_actions_index(index))) } pub fn simulate_random(&mut self, stop: impl Fn(&Self) -> Option) -> T { @@ -245,12 +239,21 @@ impl Board { self.turn += 1; } + fn valid_actions_index(&self, index: usize) -> impl Iterator + use<'_> { + let head = self.snakes[index].head(); + enum_iterator::all::() + .map(move |direction| (direction, head.wrapping_apply(direction))) + .filter(|(_, tile)| self.is_in_bounds(*tile)) + .filter(|(_, tile)| self.is_free(*tile)) + .map(|(direction, _)| direction) + } + fn move_standard(&mut self, actions: &[(u8, Direction)]) { for i in 0..self.snakes.len() { let snake = &self.snakes[i]; let action = actions.iter().find(|(id, _)| *id == snake.id).map_or_else( || { - self.valid_actions(snake.id) + self.valid_actions_index(i) .choose(&mut thread_rng()) .unwrap_or(Direction::Up) },