Mad Pod Racing solution in rust
By NicknamedTwiceunknown
rust
a year ago
9.7 kB
10
Indexable
use std::{cmp, io};
macro_rules! parse_input {
($x:expr, $t:ident) => ($x.trim().parse::<$t>().unwrap())
}
struct GameInput {
player_position: Position,
speed: Speed,
next_checkpoint_id: i32,
next_checkpoint_dist: i32,
next_checkpoint_angle: i32,
}
struct Pod {
thrust: i32,
correction_angle: i32,
min_correction_speed: i32,
max_correction_speed: i32,
multiplier_correction_speed: f32,
boost_angle: i32,
min_boost_distance: i32,
checkpoint_close_proximity_range: i32,
checkpoint_close_proximity_correction_angle: i32,
checkpoint_close_proximity_correction_speed: i32,
checkpoint_target_offset_multiplier: i32,
}
struct Speed(i32, i32);
#[derive(Clone, Copy, Debug)]
struct Position(i32, i32);
#[derive(Clone, Copy, Debug)]
struct Checkpoint {
checkpoint_id: i32,
position: Position,
distance_prev_checkpoint: Option<i32>,
}
impl GameInput {
/// determines the target to aim for with regard to the current pods speed
fn get_target_coordinates(
&self,
pod_parameters: &Pod,
pod_speed: &Speed,
next_checkpoint: &Checkpoint
) -> (i32, i32) {
(
(
next_checkpoint.position.0 +
(-pod_parameters.checkpoint_target_offset_multiplier
* pod_speed.0)
),
(
next_checkpoint.position.1 +
(-pod_parameters.checkpoint_target_offset_multiplier
* pod_speed.1)
),
)
}
/// checking if were on the longest straight to the next checkpoint
fn should_boost(
&self,
pod_parameters: &Pod,
next_checkpoint: &Checkpoint
) -> bool {
if self.next_checkpoint_dist > pod_parameters.min_boost_distance
&& self.next_checkpoint_angle < pod_parameters.boost_angle
&& self.next_checkpoint_angle > -pod_parameters.boost_angle
&& next_checkpoint.distance_prev_checkpoint.unwrap() != 0
&& next_checkpoint.checkpoint_id == self.next_checkpoint_id {
return true;
}
false
}
/// function that determines the speed used while adjusting rotation
fn get_target_speed(
&self,
pod_parameters: &Pod,
) -> i32 {
let mut speed =
(((1 - self.next_checkpoint_angle / 90) as f32)
* 100_f32)
.round() as i32;
if speed == 200 {
speed = 100;
}
cmp::max(
cmp::min(
(speed as f32 * pod_parameters.multiplier_correction_speed) as i32,
pod_parameters.min_correction_speed,
),
pod_parameters.max_correction_speed,
)
}
}
/// calculates the pythagorean theorem
/// c^2 = a^2 + b^2 => c = sqrt(a^2 + b^2)
fn pythagorean_theorem(a: i32, b: i32) -> i32 {
((a.pow(2) + b.pow(2)) as f32).sqrt() as i32
}
/// determines the checkpoint with the highest distance to the previous one
fn get_max_distance_checkpoint(checkpoints: &Vec<Checkpoint>) -> Option<&Checkpoint> {
if checkpoints.len() < 2 || checkpoints[0].distance_prev_checkpoint.unwrap() == 0 { return None; }
let highest_distance = checkpoints.iter().max_by_key(|p| p.distance_prev_checkpoint);
highest_distance
}
/// determines the speed of the pod in the current epoch.
fn get_pod_speed(game_parameters: &GameInput, last_pod_position: (i32, i32)) -> (i32, i32) {
let delta_x = game_parameters.player_position.0 - last_pod_position.0;
let delta_y = game_parameters.player_position.1 - last_pod_position.1;
eprintln!("Speed: {:?}", (delta_x, delta_y));
(delta_x, delta_y)
}
/**
* Auto-generated code below aims at helping you parse
* the standard input according to the problem statement.
**/
fn main() {
let mut input_line = String::new();
io::stdin().read_line(&mut input_line).unwrap();
let laps = parse_input!(input_line, i32);
let mut input_line = String::new();
io::stdin().read_line(&mut input_line).unwrap();
let checkpoint_count = parse_input!(input_line, i32);
let mut checkpoints: Vec<Checkpoint> = vec![];
for i in 0..checkpoint_count as usize {
let mut input_line = String::new();
io::stdin().read_line(&mut input_line).unwrap();
let inputs = input_line.split(" ").collect::<Vec<_>>();
let checkpoint_x = parse_input!(inputs[0], i32);
let checkpoint_y = parse_input!(inputs[1], i32);
if i == 0 {
checkpoints.extend([Checkpoint {
checkpoint_id: i as i32,
position: Position(checkpoint_x, checkpoint_y),
distance_prev_checkpoint: None,
}]);
} else {
checkpoints.extend([Checkpoint {
checkpoint_id: i as i32,
position: Position(checkpoint_x, checkpoint_y),
distance_prev_checkpoint: Option::from(pythagorean_theorem(checkpoints[i - 1].position.0, checkpoints[i - 1].position.1)),
}]);
}
}
checkpoints[0].distance_prev_checkpoint = Option::from(pythagorean_theorem(
(checkpoints[0].position.0 - checkpoints[checkpoints.len() - 1].position.0).abs(),
(checkpoints[0].position.1 - checkpoints[checkpoints.len() - 1].position.1)).abs()
);
// game loop
loop {
let mut pod_inputs: Vec<GameInput> = vec![];
let mut enemy_pod_inputs: Vec<GameInput> = vec![];
for i in 0..2 as usize {
let mut input_line = String::new();
io::stdin().read_line(&mut input_line).unwrap();
let inputs = input_line.split(" ").collect::<Vec<_>>();
let x = parse_input!(inputs[0], i32); // x position of your pod
let y = parse_input!(inputs[1], i32); // y position of your pod
let vx = parse_input!(inputs[2], i32); // x speed of your pod
let vy = parse_input!(inputs[3], i32); // y speed of your pod
let angle = parse_input!(inputs[4], i32); // angle of your pod
let next_check_point_id = parse_input!(inputs[5], i32); // next check point id of your pod
eprintln!("input {} {:?}", i, inputs);
let target_checkpoint = checkpoints.get(next_check_point_id as usize);
let pod_input = GameInput {
player_position: Position(x, y),
speed: Speed(vx, vy),
next_checkpoint_id: next_check_point_id,
next_checkpoint_dist: target_checkpoint.unwrap().distance_prev_checkpoint.unwrap(),
next_checkpoint_angle: angle,
};
pod_inputs.extend([pod_input]);
}
for i in 0..2 as usize {
let mut input_line = String::new();
io::stdin().read_line(&mut input_line).unwrap();
let inputs = input_line.split(" ").collect::<Vec<_>>();
let x_2 = parse_input!(inputs[0], i32); // x position of the opponent's pod
let y_2 = parse_input!(inputs[1], i32); // y position of the opponent's pod
let vx_2 = parse_input!(inputs[2], i32); // x speed of the opponent's pod
let vy_2 = parse_input!(inputs[3], i32); // y speed of the opponent's pod
let angle_2 = parse_input!(inputs[4], i32); // angle of the opponent's pod
let next_check_point_id_2 = parse_input!(inputs[5], i32); // next check point id of the opponent's pod
eprintln!("input enemy {} {:?}", i, inputs);
let target_checkpoint = checkpoints.get(next_check_point_id_2 as usize);
let pod_input = GameInput {
player_position: Position(x_2, y_2),
speed: Speed(vx_2, vy_2),
next_checkpoint_id: next_check_point_id_2,
next_checkpoint_dist: target_checkpoint.unwrap().distance_prev_checkpoint.unwrap(),
next_checkpoint_angle: angle_2,
};
enemy_pod_inputs.extend([pod_input]);
}
// Write an action using println!("message...");
// To debug: eprintln!("Debug message...");
for pod in pod_inputs.iter() {
let pod_parameters = Pod {
thrust: 100,
correction_angle: 45,
min_correction_speed: 20,
max_correction_speed: 100,
multiplier_correction_speed: 0.5,
boost_angle: 20,
min_boost_distance: 0,
checkpoint_close_proximity_range: 2000,
checkpoint_close_proximity_correction_angle: 25,
checkpoint_close_proximity_correction_speed: 15,
checkpoint_target_offset_multiplier: 3,
};
let next_checkpoint = checkpoints.get(pod.next_checkpoint_id as usize);
let (target_x, target_y) = pod.get_target_coordinates(
&pod_parameters,
&pod.speed,
next_checkpoint.unwrap()
);
let thrust = pod.get_target_speed(&pod_parameters);
// boost
if pod.should_boost(&pod_parameters, next_checkpoint.unwrap()) {
println!("{} {} BOOST", target_x, target_y);
continue;
}
println!(
"{} {} {}",
target_x,
target_y,
thrust
);
}
}
}
Editor is loading...
Leave a Comment