diff --git a/battlesnake/src/main.rs b/battlesnake/src/main.rs index 4636a65..a346bca 100644 --- a/battlesnake/src/main.rs +++ b/battlesnake/src/main.rs @@ -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::>(); + 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"); diff --git a/battlesnake/src/types/simulation/mod.rs b/battlesnake/src/types/simulation/mod.rs index 1c4b6d8..b5ab1ce 100644 --- a/battlesnake/src/types/simulation/mod.rs +++ b/battlesnake/src/types/simulation/mod.rs @@ -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::>() + .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::>() + .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 { + 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 + 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 { self.snakes.binary_search_by_key(&id, |snake| snake.id).ok() } diff --git a/battlesnake/src/types/simulation/rules/solo.rs b/battlesnake/src/types/simulation/rules/solo.rs index 91f20f5..7a45a12 100644 --- a/battlesnake/src/types/simulation/rules/solo.rs +++ b/battlesnake/src/types/simulation/rules/solo.rs @@ -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 } diff --git a/battlesnake/src/types/simulation/rules/standard.rs b/battlesnake/src/types/simulation/rules/standard.rs index 0d035c9..9b15926 100644 --- a/battlesnake/src/types/simulation/rules/standard.rs +++ b/battlesnake/src/types/simulation/rules/standard.rs @@ -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 }