This commit is contained in:
		| @@ -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"); | ||||
|   | ||||
| @@ -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() | ||||
|     } | ||||
|   | ||||
| @@ -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 | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user