Compare commits

...

2 Commits

Author SHA1 Message Date
701cb1f5a4 I don't fucking know any more
All checks were successful
Build / build (push) Successful in 5m37s
2025-08-14 12:22:18 +02:00
a198352aa9 upgrade rust version 2025-08-14 12:22:07 +02:00
6 changed files with 50 additions and 34 deletions

View File

@@ -1,4 +1,4 @@
FROM rust:1.86-bullseye AS build
FROM rust:1.88-bullseye AS build
COPY battlesnake/ /usr/app
WORKDIR /usr/app

View File

@@ -3,7 +3,7 @@ authors = ["Max Känner"]
name = "battlesnake"
version = "2.0.0"
edition = "2024"
rust-version = "1.86"
rust-version = "1.88"
readme = "README.md"
repository = "https://git.mkaenner.de/max/battlesnake"

View File

@@ -179,7 +179,28 @@ async fn get_move(
{
warn!("Unable to observe request: {e}");
}
let board = Game::from(&request);
let mut board = Game::from(&request);
board.agent = |snake, direction, board| {
let food = board.food().collect::<Vec<_>>();
if food.is_empty() {
return 1.0;
}
let head = board.head(snake);
let next_head = head.wrapping_apply(direction);
let dist = food
.iter()
.map(|food| u16::from(food.x.abs_diff(head.x)) + u16::from(food.y.abs_diff(head.y)))
.min()
.unwrap_or(1);
let next_dist = food
.iter()
.map(|food| {
u16::from(food.x.abs_diff(next_head.x)) + u16::from(food.y.abs_diff(next_head.y))
})
.min()
.unwrap_or(100);
f32::from(next_dist) / f32::from(dist)
};
let timeout = Duration::from_millis(u64::from(request.game.timeout));
let id = board.board.get_id(&request.you.id).unwrap_or_else(|| {
error!("My id is not in the simulation board");

View File

@@ -69,6 +69,7 @@ pub struct Game {
pub board: Board,
map: Maps,
ruleset: Rulesets,
pub agent: fn(snake: u8, direction: Direction, board: &Board) -> f32,
}
impl From<&Request> for Game {
@@ -80,6 +81,7 @@ impl From<&Request> for Game {
board,
map,
ruleset,
agent: |_, _, _| 1.0,
}
}
}
@@ -91,8 +93,12 @@ impl Game {
.filter_map(|i| {
self.board
.valid_actions_index(i)
.choose(rng)
.map(|direction| (i.saturating_as(), direction))
.collect::<Vec<_>>()
.choose_weighted(rng, |&direction| {
(self.agent)(i.saturating_as(), direction, &self.board)
})
.ok()
.map(|&direction| (i.saturating_as(), direction))
})
.collect();
if self.next_turn(&random_actions, rng) {
@@ -111,8 +117,12 @@ impl Game {
.or_else(|| {
self.board
.valid_actions_index(i)
.choose(rng)
.map(|direction| (i.saturating_as(), direction))
.collect::<Vec<_>>()
.choose_weighted(rng, |&direction| {
(self.agent)(i.saturating_as(), direction, &self.board)
})
.ok()
.map(|&direction| (i.saturating_as(), direction))
})
})
.collect();
@@ -254,10 +264,15 @@ impl Board {
}
#[must_use]
pub fn num_snakes(&self) -> usize {
pub const fn num_snakes(&self) -> usize {
self.snakes.len()
}
#[must_use]
pub fn head(&self, id: u8) -> Coord {
self.snakes[usize::from(id)].head()
}
#[must_use]
pub fn alive(&self, id: u8) -> bool {
self.id_to_index(id).is_some()
@@ -286,6 +301,10 @@ impl Board {
self.food[index]
}
pub fn food(&self) -> impl Iterator<Item = Coord> {
self.food.iter_ones().map(|i| self.linear_to_coord(i))
}
#[must_use]
pub fn is_hazard(&self, tile: Coord) -> bool {
let index = self.coord_to_linear(tile);
@@ -308,30 +327,6 @@ impl Board {
.flat_map(|index| self.valid_actions_index(index))
}
#[must_use]
pub fn random_action(&self, id: u8, rng: &mut impl RngCore) -> Direction {
let Some(index) = self.id_to_index(id) else {
return Direction::Up;
};
self.valid_actions_index(index)
.choose(rng)
.unwrap_or(Direction::Up)
}
pub fn random_actions<'a, R: RngCore>(
&self,
rng: &'a mut R,
) -> impl Iterator<Item = (u8, Direction)> + use<'_, 'a, R> {
(0..self.snakes.len()).map(|index| {
(
self.snakes[index].id,
self.valid_actions_index(index)
.choose(rng)
.unwrap_or(Direction::Up),
)
})
}
fn id_to_index(&self, id: u8) -> Option<usize> {
self.snakes.binary_search_by_key(&id, |snake| snake.id).ok()
}

View File

@@ -31,6 +31,6 @@ impl Ruleset for Solo {
}
}
pub fn game_over(board: &Board) -> bool {
pub const fn game_over(board: &Board) -> bool {
board.num_snakes() == 0
}

View File

@@ -175,6 +175,6 @@ pub fn feed_snakes(board: &mut Board) {
}
}
pub fn game_over(board: &Board) -> bool {
pub const fn game_over(board: &Board) -> bool {
board.num_snakes() <= 1
}