This commit is contained in:
		| @@ -224,7 +224,7 @@ impl Board { | ||||
|  | ||||
|     #[must_use] | ||||
|     pub fn is_free(&self, tile: Coord) -> bool { | ||||
|         if !(tile.x < self.width && tile.y < self.height) { | ||||
|         if !self.is_in_bounds(tile) { | ||||
|             return false; | ||||
|         } | ||||
|         let index = self.coord_to_linear(tile); | ||||
| @@ -286,10 +286,7 @@ impl Board { | ||||
|     fn valid_actions_index(&self, index: usize) -> impl Iterator<Item = Direction> + use<'_> { | ||||
|         let head = self.snakes[index].head(); | ||||
|         enum_iterator::all::<Direction>() | ||||
|             .map(move |direction| (direction, head.wrapping_apply(direction))) | ||||
|             .filter(|(_, tile)| self.is_in_bounds(*tile)) | ||||
|             .filter(|(_, tile)| self.is_free(*tile)) | ||||
|             .map(|(direction, _)| direction) | ||||
|             .filter(move |direction| self.is_free(head.wrapping_apply(*direction))) | ||||
|     } | ||||
|  | ||||
|     fn move_standard(&mut self, actions: &[(u8, Direction)]) { | ||||
| @@ -432,44 +429,57 @@ impl Board { | ||||
|     } | ||||
|  | ||||
|     fn spawn_food(&mut self) { | ||||
|         let num_food = self.food.count_ones(); | ||||
|         let needed_food = if num_food < usize::from(self.min_food) { | ||||
|             usize::from(self.min_food) - num_food | ||||
|         } else { | ||||
|             usize::from( | ||||
|                 self.food_spawn_chance > 0 && rng().random_range(0..100) < self.food_spawn_chance, | ||||
|             ) | ||||
|         }; | ||||
|         let food_needed = self.check_food_needing_placement(); | ||||
|  | ||||
|         if needed_food == 0 { | ||||
|             return; | ||||
|         if food_needed > 0 { | ||||
|             self.place_food_randomly(food_needed); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn check_food_needing_placement(&self) -> u16 { | ||||
|         let min_food = self.min_food; | ||||
|         let food_spawn_chance = self.food_spawn_chance; | ||||
|         let num_current_food = u16::try_from(self.food.count_ones()).unwrap_or(u16::MAX); | ||||
|  | ||||
|         if num_current_food < min_food { | ||||
|             return min_food - num_current_food; | ||||
|         } | ||||
|         if food_spawn_chance > 0 && (100 - rng().random_range(0..100)) < food_spawn_chance { | ||||
|             return 1; | ||||
|         } | ||||
|  | ||||
|         let food_spots = self | ||||
|         0 | ||||
|     } | ||||
|  | ||||
|     fn place_food_randomly(&mut self, amount: u16) { | ||||
|         let tails: Vec<_> = self | ||||
|             .snakes | ||||
|             .iter() | ||||
|             .map(|snake| self.coord_to_linear(snake.tail())) | ||||
|             .collect(); | ||||
|         let possible_moves: Vec<_> = self | ||||
|             .snakes | ||||
|             .iter() | ||||
|             .flat_map(|snake| { | ||||
|                 let head = snake.head(); | ||||
|                 enum_iterator::all::<Direction>() | ||||
|                     .map(move |direction| head.wrapping_apply(direction)) | ||||
|                     .filter(|tile| self.is_in_bounds(*tile)) | ||||
|                     .map(|tile| self.coord_to_linear(tile)) | ||||
|             }) | ||||
|             .collect(); | ||||
|         let unoccupied_points = self | ||||
|             .free | ||||
|             .iter() | ||||
|             .by_vals() | ||||
|             .enumerate() | ||||
|             .filter_map(|(i, free)| free.then_some(i)) | ||||
|             .filter(|i| { | ||||
|                 self.snakes | ||||
|                     .iter() | ||||
|                     .all(|snake| self.coord_to_linear(snake.tail()) != *i) | ||||
|             }) | ||||
|             .filter(|i| { | ||||
|                 self.snakes | ||||
|                     .iter() | ||||
|                     .flat_map(|snake| { | ||||
|                         let head = snake.head(); | ||||
|                         enum_iterator::all::<Direction>() | ||||
|                             .map(move |direction| head.wrapping_apply(direction)) | ||||
|                             .filter(|tile| self.is_in_bounds(*tile)) | ||||
|                     }) | ||||
|                     .all(|action| *i != self.coord_to_linear(action)) | ||||
|             }) | ||||
|             .filter(|i| !self.food[*i]) | ||||
|             .choose_multiple(&mut rng(), needed_food); | ||||
|         for index in food_spots { | ||||
|             self.food.set(index, true); | ||||
|             .zip(self.hazard.iter().by_vals()) | ||||
|             .filter_map(|((i, free), hazard)| (!hazard && free).then_some(i)) | ||||
|             .filter(|i| !tails.contains(i)) | ||||
|             .filter(|i| !possible_moves.contains(i)); | ||||
|  | ||||
|         for food_spot in unoccupied_points.choose_multiple(&mut rng(), usize::from(amount)) { | ||||
|             self.food.set(food_spot, true); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user