use std::cmp::Ordering; use std::io::prelude::*; use std::io::stdin; mod command; mod consts; mod json; mod state; use command::*; use state::*; fn main() { for line in stdin().lock().lines() { let round_number = line.expect("Failed to read line from stdin: {}"); let command = match json::read_state_from_json_file(&format!("./rounds/{}/state.json", round_number)) { Ok(state) => choose_command(&state), Err(e) => { eprintln!("WARN: State file could not be parsed: {}", e); Command::Nothing } }; println!("C;{};{}", round_number, command); } } fn choose_command(state: &GameState) -> Command { /* TODO: * - Simulate both player and opponent moves */ let player_moves = state.valid_moves(0); let naive_result = player_moves .into_iter() .map(|player_move| { let mut state = state.clone(); state.update([player_move, Command::Accelerate]); (player_move, state) }) .flat_map(|(player_move, state)| { state.valid_moves(0).into_iter().map(move |second_move| { let mut second_move_state = state.clone(); second_move_state.update([second_move, Command::Accelerate]); (player_move, second_move_state) }) }) .max_by(|(_, a), (_, b)| compare_states(a, b)) .unwrap() .0; naive_result } fn compare_states(a: &GameState, b: &GameState) -> Ordering { if a.status == GameStatus::PlayerOneWon && b.status == GameStatus::PlayerOneWon { a.players[0].speed.cmp(&b.players[0].speed) } else if a.status == GameStatus::PlayerOneWon { Ordering::Greater } else if b.status == GameStatus::PlayerOneWon { Ordering::Less } else { let weighted_position_a = a.players[0].position.x + a.players[0].boosts * 2; let weighted_position_b = b.players[0].position.x + b.players[0].boosts * 2; weighted_position_a .cmp(&weighted_position_b) .then(a.players[0].speed.cmp(&b.players[0].speed)) .then(a.players[0].position.x.cmp(&b.players[0].position.x)) .then(a.players[0].boosts.cmp(&b.players[0].boosts)) } }