From 32883b2a1b04a2ecb992b75836aa46b1d1da3249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20K=C3=A4nner?= Date: Wed, 22 Jan 2025 01:17:11 +0100 Subject: [PATCH] spawn blocking task for simulations --- battlesnake/src/main.rs | 90 ++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/battlesnake/src/main.rs b/battlesnake/src/main.rs index eb3c428..aa60bcc 100644 --- a/battlesnake/src/main.rs +++ b/battlesnake/src/main.rs @@ -82,46 +82,60 @@ async fn get_move(request: Json) -> response::Json { } info!("valid actions: {:?}", actions); - let mut action_data = [(0, 0); 4]; - let mut total_simulations = 0; - let base_turns = board.turn(); - while start.elapsed() < Duration::from_millis(250) { - let mut board = board.clone(); - let action = *actions.choose(&mut thread_rng()).unwrap_or(&Direction::Up); - board.next_turn(&[(id, action)]); - let turns = board.simulate_random(|board| { - if board.num_snakes() == 0 - || board.turn() > base_turns + u32::from(request.you.length) * 3 - { - Some(board.turn()) - } else { - None - } + tokio::task::spawn_blocking(move || { + let base_turns = board.turn(); + let end_condition: &dyn Fn(&Board) -> Option = match &*request.game.ruleset.name { + "solo" => &|board: &Board| { + if board.num_snakes() == 0 + || board.turn() > base_turns + u32::from(request.you.length) * 3 + { + Some(board.turn()) + } else { + None + } + }, + _ => &|board: &Board| { + if !board.alive(id) || board.turn() > base_turns + u32::from(request.you.length) * 3 + { + Some(board.turn()) + } else { + None + } + }, + }; + + let mut action_data = [(0, 0); 4]; + let mut total_simulations = 0; + while start.elapsed() < Duration::from_millis(250) { + let mut board = board.clone(); + let action = *actions.choose(&mut thread_rng()).unwrap_or(&Direction::Up); + board.next_turn(&[(id, action)]); + let turns = board.simulate_random(end_condition); + let action_data = &mut action_data[usize::from(action)]; + action_data.0 += turns - base_turns; + action_data.1 += 1; + total_simulations += 1; + } + debug!("action data: {action_data:?}"); + + let action = actions.into_iter().max_by_key(|action| { + let action_data = action_data[usize::from(*action)]; + (action_data.0 / action_data.1, action_data.0 % action_data.1) }); - let action_data = &mut action_data[usize::from(action)]; - action_data.0 += turns - base_turns; - action_data.1 += 1; - total_simulations += 1; - } - debug!("action data: {action_data:?}"); - let action = actions.into_iter().max_by_key(|action| { - let action_data = action_data[usize::from(*action)]; - (action_data.0 / action_data.1, action_data.0 % action_data.1) - }); - - if let Some(action) = action { - let action_data = action_data[usize::from(action)]; - let avg_turns = action_data.0 / action_data.1; - info!("found action {action:?} after {total_simulations} simulations with an average of {avg_turns} turns."); - } else { - warn!("unable to find a valid action"); - } - info!("chose {action:?}"); - response::Json(Response { - direction: action.unwrap_or(Direction::Up), - shout: None, - }) + if let Some(action) = action { + let action_data = action_data[usize::from(action)]; + let avg_turns = action_data.0 / action_data.1; + info!("found action {action:?} after {total_simulations} simulations with an average of {avg_turns} turns."); + } else { + warn!("unable to find a valid action"); + } + info!("chose {action:?}"); + response::Json(Response { + direction: action.unwrap_or(Direction::Up), + shout: None, + }) + }).await.unwrap() } async fn end(request: Json) {