make simulation faster
All checks were successful
Build / build (push) Successful in 2m43s

This commit is contained in:
Max Känner 2025-04-21 21:48:11 +02:00
parent c5097ec417
commit 1d527a89cd

View File

@ -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);
}
}