From 943887fd7bcb031828b989a3e49876658fa0faff Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Sun, 19 Apr 2020 14:47:10 +0200 Subject: Coloured analysis output --- src/state.rs | 2 +- vroomba-analysis/Cargo.lock | 12 ++++ vroomba-analysis/Cargo.toml | 3 +- vroomba-analysis/src/main.rs | 127 ++++++++++++++++++++++++++++++++++--------- 4 files changed, 116 insertions(+), 28 deletions(-) diff --git a/src/state.rs b/src/state.rs index 0a9c2f2..47a2168 100644 --- a/src/state.rs +++ b/src/state.rs @@ -160,7 +160,7 @@ impl GameState { if player.boosts > 0 { result.push(Command::UseBoost); } - if false && player.oils > 0 { + if player.oils > 0 { result.push(Command::UseOil); } result diff --git a/vroomba-analysis/Cargo.lock b/vroomba-analysis/Cargo.lock index 48826bb..9ac35c7 100644 --- a/vroomba-analysis/Cargo.lock +++ b/vroomba-analysis/Cargo.lock @@ -53,6 +53,17 @@ dependencies = [ "vec_map", ] +[[package]] +name = "colored" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59" +dependencies = [ + "atty", + "lazy_static", + "winapi", +] + [[package]] name = "either" version = "1.5.3" @@ -338,6 +349,7 @@ name = "vroomba_analysis" version = "0.1.0" dependencies = [ "anyhow", + "colored", "pathfinding", "structopt", "vroomba", diff --git a/vroomba-analysis/Cargo.toml b/vroomba-analysis/Cargo.toml index fa5d203..b39c01e 100644 --- a/vroomba-analysis/Cargo.toml +++ b/vroomba-analysis/Cargo.toml @@ -7,4 +7,5 @@ edition = "2018" anyhow = "1.0.27" vroomba = { path = "../" } pathfinding = "2.0.4" -structopt = "0.3" \ No newline at end of file +structopt = "0.3" +colored = "1.9" diff --git a/vroomba-analysis/src/main.rs b/vroomba-analysis/src/main.rs index a1145b7..931832f 100644 --- a/vroomba-analysis/src/main.rs +++ b/vroomba-analysis/src/main.rs @@ -1,10 +1,11 @@ +use colored::*; use pathfinding::prelude::*; use std::path::PathBuf; use structopt::StructOpt; use vroomba::command::Command; use vroomba::consts::*; use vroomba::global_json; -use vroomba::state::{GameState, GameStatus}; +use vroomba::state::*; #[derive(StructOpt, Debug)] #[structopt(name = "vroomba-analysis")] @@ -15,36 +16,116 @@ struct Opt { fn main() { let opt = Opt::from_args(); - let initial_node = Node { - state: global_json::read_initial_state_from_global_json_file(opt.path.to_str().unwrap()) - .unwrap(), - //last_command: Command::Nothing, - }; + let initial_state = + global_json::read_initial_state_from_global_json_file(opt.path.to_str().unwrap()).unwrap(); let shortest_path = astar( - &initial_node, - |node| { - let player_moves = node.state.valid_moves(0); + &initial_state, + |state| { + let player_moves = state.valid_moves(0); player_moves .into_iter() + .filter(|player_move| *player_move != Command::UseOil) .map(|player_move| { - let mut state = node.state.clone(); + let mut state = state.clone(); state.update([player_move, Command::Decelerate]); - ( - Node { - state, - //last_command: player_move, - }, - 1, - ) + (state, 1) }) .collect::>() }, - |node| (WIDTH - node.state.players[0].position.x) / SPEED_BOOST, - |node| node.state.status != GameStatus::Continue, + |state| (WIDTH - state.players[0].position.x) / SPEED_BOOST, + |state| state.status != GameStatus::Continue, ) .unwrap(); + let shortest_path_actions = shortest_path + .0 + .iter() + .zip(shortest_path.0.iter().skip(1)) + .map(|(state, next)| { + let player = &state.players[0]; + let player_move = state + .valid_moves(0) + .into_iter() + .find(|player_move| { + let mut state = state.clone(); + state.update([*player_move, Command::Decelerate]); + state == *next + }) + .unwrap(); + ( + player.position, + next.players[0].position, + state, + next, + player_move, + ) + }) + .collect::>(); + + let chunk_size = 100; + for chunk in 0..(WIDTH / chunk_size) { + let start_x = chunk * chunk_size; + for i in 0..chunk_size / 10 { + print!("{:<10}", start_x + i * 10); + } + println!(); + for y in MIN_Y..MAX_Y { + for x in start_x..start_x + chunk_size { + let pos = Position { y, x }; + + let c = if initial_state.obstacles.contains(&pos) { + "O" + } else if initial_state.powerup_boosts.contains(&pos) { + ">" + } else if initial_state.finish_lines.contains(&pos) { + "|" + } else { + "-" + }; + + let player_on_block = shortest_path_actions + .iter() + .find(|(position, _, _, _, _)| *position == pos); + let c_with_background = match player_on_block { + None => c.black(), + Some((_, _, _, _, Command::Accelerate)) => c.on_red(), + Some((_, _, _, _, Command::Decelerate)) => c.on_green(), + Some((_, _, _, _, Command::UseBoost)) => c.on_blue(), + Some(_) => c.on_yellow(), + }; + + let speed = shortest_path_actions + .iter() + .find(|(position, next_position, _, _, _)| { + position.x < x && x < next_position.x && y == next_position.y + }) + .map(|(_, _, _, next_state, _)| next_state.players[0].speed); + + let c_with_foreground = match speed { + None => c_with_background.white(), + Some(SPEED_0) | Some(SPEED_1) => c_with_background.green(), + Some(SPEED_2) => c_with_background.yellow(), + Some(SPEED_3) => c_with_background.red(), + Some(SPEED_4) => c_with_background.bright_red(), + Some(SPEED_BOOST) => c_with_background.blue(), + Some(_) => c_with_background.yellow(), + }; + + print!("{}", c_with_foreground); + } + println!(); + } + } + + for (i, (position, _, state, _, player_move)) in shortest_path_actions.iter().enumerate() { + let player = &state.players[0]; + println!( + "{:3}: x: {:4}, y: {:1}, speed: {:2}: {}", + i, position.x, position.y, player.speed, player_move + ); + } + // println!( // "{:?}", // shortest_path @@ -53,11 +134,5 @@ fn main() { // .map(|node| node.last_command) // .collect::>() // ); - println!("{}", shortest_path.1); -} - -#[derive(Debug, Clone, Hash, PartialEq, Eq)] -struct Node { - state: GameState, - //last_command: Command, + println!("{} moves", shortest_path.1); } -- cgit v1.2.3