This commit is contained in:
@ -202,14 +202,20 @@ struct PreparedGame {
|
|||||||
corners: [Option<u8>; 4],
|
corners: [Option<u8>; 4],
|
||||||
cardinals: [Option<u8>; 4],
|
cardinals: [Option<u8>; 4],
|
||||||
corner_first: bool,
|
corner_first: bool,
|
||||||
food_spawns: Vec<Option<FoodSpawn>>,
|
food_spawns: Vec<FoodSpawn>,
|
||||||
food_chance: u8,
|
food_chance: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
enum FoodSpawn {
|
enum FoodSpawn {
|
||||||
|
/// No food was spawned
|
||||||
|
None,
|
||||||
|
/// Some food was spawned because it would go under `min_food` otherwise
|
||||||
Forced { selected: u16, free_spots: u16 },
|
Forced { selected: u16, free_spots: u16 },
|
||||||
|
/// Some food was spawned by chance
|
||||||
Random { selected: u16, free_spots: u16 },
|
Random { selected: u16, free_spots: u16 },
|
||||||
|
/// No food was spawned because there is no space on the board
|
||||||
|
Blocked,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PreparedGame {
|
impl PreparedGame {
|
||||||
@ -269,9 +275,14 @@ impl PreparedGame {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.map(|(previous, next)| {
|
.map(|(previous, next)| {
|
||||||
// no new food, no food eaten
|
let mut tmp = next.clone();
|
||||||
if previous.board.food == next.board.food {
|
tmp.board.food.clone_from(&previous.board.food);
|
||||||
return None;
|
let heads: Vec<_> = tmp.board.snakes.iter().map(|snake| snake.head).collect();
|
||||||
|
tmp.board.food.retain(|coord| !heads.contains(coord));
|
||||||
|
let free_spots = get_unoccupied_points(&tmp);
|
||||||
|
|
||||||
|
if free_spots.is_empty() {
|
||||||
|
return FoodSpawn::Blocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
let diff: Vec<_> = next
|
let diff: Vec<_> = next
|
||||||
@ -282,15 +293,9 @@ impl PreparedGame {
|
|||||||
.collect();
|
.collect();
|
||||||
if diff.is_empty() {
|
if diff.is_empty() {
|
||||||
// We didn't spawn any food. It was only eaten
|
// We didn't spawn any food. It was only eaten
|
||||||
return None;
|
return FoodSpawn::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut tmp = next.clone();
|
|
||||||
tmp.board.food.clone_from(&previous.board.food);
|
|
||||||
let heads: Vec<_> = tmp.board.snakes.iter().map(|snake| snake.head).collect();
|
|
||||||
tmp.board.food.retain(|coord| !heads.contains(coord));
|
|
||||||
let free_spots = get_unoccupied_points(&tmp);
|
|
||||||
|
|
||||||
let selected = free_spots
|
let selected = free_spots
|
||||||
.iter()
|
.iter()
|
||||||
.position(|spot| spot == diff[0])
|
.position(|spot| spot == diff[0])
|
||||||
@ -299,15 +304,15 @@ impl PreparedGame {
|
|||||||
let free_spots = free_spots.len().az();
|
let free_spots = free_spots.len().az();
|
||||||
|
|
||||||
if next.board.food.len() == usize::from(food_min) {
|
if next.board.food.len() == usize::from(food_min) {
|
||||||
Some(FoodSpawn::Forced {
|
FoodSpawn::Forced {
|
||||||
selected,
|
selected,
|
||||||
free_spots,
|
free_spots,
|
||||||
})
|
}
|
||||||
} else {
|
} else {
|
||||||
Some(FoodSpawn::Random {
|
FoodSpawn::Random {
|
||||||
selected,
|
selected,
|
||||||
free_spots,
|
free_spots,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@ -360,16 +365,14 @@ impl PreparedGame {
|
|||||||
let rand = get_rand(input_rand, seed, (turn).az());
|
let rand = get_rand(input_rand, seed, (turn).az());
|
||||||
|
|
||||||
match spawn {
|
match spawn {
|
||||||
Some(
|
spawn @ (FoodSpawn::Forced {
|
||||||
spawn @ (FoodSpawn::Forced {
|
selected,
|
||||||
selected,
|
free_spots,
|
||||||
free_spots,
|
}
|
||||||
}
|
| FoodSpawn::Random {
|
||||||
| FoodSpawn::Random {
|
selected,
|
||||||
selected,
|
free_spots,
|
||||||
free_spots,
|
}) => {
|
||||||
}),
|
|
||||||
) => {
|
|
||||||
if matches!(spawn, FoodSpawn::Random { .. })
|
if matches!(spawn, FoodSpawn::Random { .. })
|
||||||
&& 100 - rand.int_n(100) >= usize::from(self.food_chance)
|
&& 100 - rand.int_n(100) >= usize::from(self.food_chance)
|
||||||
{
|
{
|
||||||
@ -387,13 +390,17 @@ impl PreparedGame {
|
|||||||
}
|
}
|
||||||
correct
|
correct
|
||||||
}
|
}
|
||||||
None => {
|
FoodSpawn::None => {
|
||||||
let correct = 100 - rand.int_n(100) >= usize::from(self.food_chance);
|
let correct = 100 - rand.int_n(100) >= usize::from(self.food_chance);
|
||||||
if log && !correct {
|
if log && !correct {
|
||||||
error!("Food spawned, when none should have been spawned");
|
error!("Food spawned, when none should have been spawned");
|
||||||
}
|
}
|
||||||
correct
|
correct
|
||||||
}
|
}
|
||||||
|
FoodSpawn::Blocked => {
|
||||||
|
// We can't get any info if there isn't even a chance for food
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user