Compare commits
No commits in common. "879f99e23fe85f0deba408525e2f65cbcf5609cb" and "d715aa47b35ef9577152697e65dc64fb470930f9" have entirely different histories.
879f99e23f
...
d715aa47b3
@ -65,7 +65,6 @@ async fn start(request: Json<Request>) {
|
|||||||
info!("got start request: {board}");
|
info!("got start request: {board}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_lines)]
|
|
||||||
async fn get_move(request: Json<Request>) -> response::Json<Response> {
|
async fn get_move(request: Json<Request>) -> response::Json<Response> {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let board = Board::from(&*request);
|
let board = Board::from(&*request);
|
||||||
@ -89,68 +88,43 @@ async fn get_move(request: Json<Request>) -> response::Json<Response> {
|
|||||||
|
|
||||||
tokio::task::spawn_blocking(move || {
|
tokio::task::spawn_blocking(move || {
|
||||||
let base_turns = board.turn();
|
let base_turns = board.turn();
|
||||||
let end_condition: &dyn Fn(&Board) -> Option<_> = match &*request.game.ruleset.name {
|
let end_condition: &dyn Fn(&Board) -> Option<u32> = match &*request.game.ruleset.name {
|
||||||
"solo" => &|board| {
|
"solo" => &|board: &Board| {
|
||||||
if board.num_snakes() == 0
|
if board.num_snakes() == 0
|
||||||
|| board.turn() > base_turns + (u32::from(request.you.length) * 3).min(32)
|
|| board.turn() > base_turns + (u32::from(request.you.length) * 3).min(32)
|
||||||
{
|
{
|
||||||
Some(())
|
Some(board.turn())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => &|board| {
|
_ => &|board: &Board| {
|
||||||
if board.num_snakes() <= 1
|
if board.num_snakes() <= 1
|
||||||
|| board.turn() > base_turns + (u32::from(request.you.length) * 3).min(32)
|
|| board.turn() > base_turns + (u32::from(request.you.length) * 3).min(32)
|
||||||
{
|
{
|
||||||
Some(())
|
Some(u32::from(board.alive(id)))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let start_snakes = u32::try_from(board.num_snakes()).unwrap_or(0);
|
|
||||||
let score_fn: &dyn Fn(&Board, u8) -> u32 = match &*request.game.ruleset.name {
|
|
||||||
"solo" => &|board, _| board.turn(),
|
|
||||||
_ => &|board, id| {
|
|
||||||
if board.alive(id) {
|
|
||||||
1 + start_snakes - u32::try_from(board.num_snakes()).unwrap_or(start_snakes)
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut mcts_managers: Vec<_> = (0..request.board.snakes.len())
|
let mut mcts_manager = MctsManager::new(id);
|
||||||
.map(|id| MctsManager::new(u8::try_from(id).unwrap()))
|
|
||||||
.collect();
|
|
||||||
let c = f32::sqrt(2.0);
|
let c = f32::sqrt(2.0);
|
||||||
while start.elapsed() < Duration::from_millis(250) {
|
'outer: while start.elapsed() < Duration::from_millis(250) {
|
||||||
let mut board = board.clone();
|
let mut board = board.clone();
|
||||||
while end_condition(&board).is_none() {
|
while let Some(action) = mcts_manager.next_action(&board, c) {
|
||||||
let actions: Vec<_> = mcts_managers
|
board.next_turn(&[(id, action)]);
|
||||||
.iter_mut()
|
if let Some(score) = end_condition(&board) {
|
||||||
.filter_map(|mcts_manager| {
|
mcts_manager.apply_score(score);
|
||||||
mcts_manager
|
continue 'outer;
|
||||||
.next_action(&board, c)
|
|
||||||
.map(|action| (mcts_manager.snake, action))
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
board.next_turn(&actions);
|
|
||||||
if actions.is_empty() {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
board.simulate_random(end_condition);
|
let score = board.simulate_random(end_condition);
|
||||||
for mcts_manager in &mut mcts_managers {
|
|
||||||
let id = mcts_manager.snake;
|
|
||||||
let score = score_fn(&board, id);
|
|
||||||
mcts_manager.apply_score(score);
|
mcts_manager.apply_score(score);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let my_mcts_manager = &mcts_managers[usize::from(id)];
|
|
||||||
for action in actions {
|
for action in actions {
|
||||||
let score = my_mcts_manager.base.next[usize::from(action)]
|
let score = mcts_manager.base.next[usize::from(action)]
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|info| info.score as f32 / info.played as f32);
|
.map(|info| info.score as f32 / info.played as f32);
|
||||||
if let Some(score) = score {
|
if let Some(score) = score {
|
||||||
@ -160,7 +134,7 @@ async fn get_move(request: Json<Request>) -> response::Json<Response> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let action = my_mcts_manager
|
let action = mcts_manager
|
||||||
.base
|
.base
|
||||||
.next
|
.next
|
||||||
.iter()
|
.iter()
|
||||||
@ -185,7 +159,7 @@ async fn get_move(request: Json<Request>) -> response::Json<Response> {
|
|||||||
if let Some(action) = action {
|
if let Some(action) = action {
|
||||||
info!(
|
info!(
|
||||||
"found action {action:?} after {} simulations.",
|
"found action {action:?} after {} simulations.",
|
||||||
my_mcts_manager.base.played
|
mcts_manager.base.played
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
warn!("unable to find a valid action");
|
warn!("unable to find a valid action");
|
||||||
|
@ -233,6 +233,9 @@ impl Board {
|
|||||||
|
|
||||||
pub fn valid_actions(&self, id: u8) -> impl Iterator<Item = Direction> + use<'_> {
|
pub fn valid_actions(&self, id: u8) -> impl Iterator<Item = Direction> + use<'_> {
|
||||||
let index = self.id_to_index(id);
|
let index = self.id_to_index(id);
|
||||||
|
if index.is_none() {
|
||||||
|
warn!("Asked for a snake that doesn't exist");
|
||||||
|
}
|
||||||
index
|
index
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|index| self.valid_actions_index(index))
|
.flat_map(|index| self.valid_actions_index(index))
|
||||||
|
@ -366,7 +366,7 @@ fn run_local_docker(port: u16) -> Result<Child, DynError> {
|
|||||||
"--env",
|
"--env",
|
||||||
"RUST_LOG=error",
|
"RUST_LOG=error",
|
||||||
"--env",
|
"--env",
|
||||||
format!("PORT={}", port).as_str(),
|
format!("ROCKET_PORT={}", port).as_str(),
|
||||||
"--network=host",
|
"--network=host",
|
||||||
"--rm",
|
"--rm",
|
||||||
"local_snake",
|
"local_snake",
|
||||||
@ -396,7 +396,7 @@ fn run_production(port: u16) -> Result<Child, DynError> {
|
|||||||
"--env",
|
"--env",
|
||||||
"RUST_LOG=error",
|
"RUST_LOG=error",
|
||||||
"--env",
|
"--env",
|
||||||
format!("PORT={}", port).as_str(),
|
format!("ROCKET_PORT={}", port).as_str(),
|
||||||
"--network=host",
|
"--network=host",
|
||||||
"--rm",
|
"--rm",
|
||||||
"docker.mkaenner.de/snake:latest",
|
"docker.mkaenner.de/snake:latest",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user