summaryrefslogtreecommitdiff
path: root/2020-overdrive/tests/live_comparison.rs
diff options
context:
space:
mode:
Diffstat (limited to '2020-overdrive/tests/live_comparison.rs')
-rw-r--r--2020-overdrive/tests/live_comparison.rs134
1 files changed, 134 insertions, 0 deletions
diff --git a/2020-overdrive/tests/live_comparison.rs b/2020-overdrive/tests/live_comparison.rs
new file mode 100644
index 0000000..3e29069
--- /dev/null
+++ b/2020-overdrive/tests/live_comparison.rs
@@ -0,0 +1,134 @@
+extern crate vroomba;
+
+use vroomba::command::Command;
+use vroomba::json;
+use vroomba::state::{GameState, GameStateUpdateEvents};
+
+use std::fs::File;
+use std::io::prelude::*;
+use std::path::Path;
+
+#[test]
+fn it_successfully_simulates_replay() {
+ test_from_replay(&Path::new("tests/v1-normal-match/"));
+}
+
+fn test_from_replay(replay_folder: &Path) {
+ let length = replay_folder.read_dir().unwrap().count() - 1;
+
+ let mut state = json::read_state_from_json_file(&format!(
+ "{}/Round 001/JsonMap.json",
+ replay_folder.display()
+ ))
+ .unwrap();
+
+ println!("State 1: {:?}", state);
+
+ for i in 1..=length {
+ let player = read_player_command(&format!(
+ "{}/Round {:03}/PlayerCommand.txt",
+ replay_folder.display(),
+ i
+ ));
+ let opponent = read_player_command(&format!(
+ "{}/Round {:03}/OpponentCommand.txt",
+ replay_folder.display(),
+ i
+ ));
+ let expected_state = json::read_state_from_json_file(&format!(
+ "{}/Round {:03}/JsonMap.json",
+ replay_folder.display(),
+ i + 1
+ ))
+ .unwrap();
+
+ // We don't know how many they actually have from the state
+ // files.
+ state.players[1].boosts = 1;
+ state.players[1].oils = 1;
+
+ println!("Player 1: {}, Player 2: {}", player, opponent);
+ state.update([player, opponent], &mut GameStateUpdateEvents::default());
+
+ println!("State {}: {:?}", i + 1, state);
+ assert_eq!(
+ state.status,
+ expected_state.status,
+ "\nFailed on state {}\n",
+ i + 1
+ );
+ player_assertions(&state, &expected_state, 0, true, i + 1);
+
+ // TODO: We're only reading the state for player 1, so we can't say what obstacles player 2 may be hitting. Maybe read the full map of obstacles + powerups into the game state at the beginning? There's also the case of boost_remaining ofr player 2.
+ // player_assertions(&state, &expected_state, 1, false, i + 1);
+
+ // We can do great simulations into the future, but we need to
+ // be told where the future mud is.
+ state = expected_state;
+ }
+}
+
+fn read_player_command(filename: &str) -> Command {
+ let mut file = File::open(filename).unwrap();
+ let mut content = String::new();
+ file.read_to_string(&mut content).unwrap();
+ match content.trim() {
+ "Command: ACCELERATE" => Command::Accelerate,
+ "Command: NOTHING" => Command::Nothing,
+ "Command: DECELERATE" => Command::Decelerate,
+ "Command: TURN_LEFT" => Command::TurnLeft,
+ "Command: TURN_RIGHT" => Command::TurnRight,
+ "Command: USE_BOOST" => Command::UseBoost,
+ "Command: USE_OIL" => Command::UseOil,
+ other => panic!("Unexpected command: {}", other),
+ }
+}
+
+fn player_assertions(
+ actual: &GameState,
+ expected: &GameState,
+ player_index: usize,
+ compare_powerups: bool,
+ round: usize,
+) {
+ let actual = &actual.players[player_index];
+ let expected = &expected.players[player_index];
+
+ assert_eq!(
+ actual.position,
+ expected.position,
+ "\nFailed on state {}, player {} position\n",
+ round,
+ player_index + 1
+ );
+ assert_eq!(
+ actual.speed,
+ expected.speed,
+ "\nFailed on state {}, player {} speed\n",
+ round,
+ player_index + 1
+ );
+ if compare_powerups {
+ assert_eq!(
+ actual.boost_remaining,
+ expected.boost_remaining,
+ "\nFailed on state {}, player {} position,\n",
+ round,
+ player_index + 1
+ );
+ assert_eq!(
+ actual.oils,
+ expected.oils,
+ "\nFailed on state {}, player {} oils,\n",
+ round,
+ player_index + 1
+ );
+ assert_eq!(
+ actual.boosts,
+ expected.boosts,
+ "\nFailed on state {}, player {} boosts,\n",
+ round,
+ player_index + 1
+ );
+ }
+}