summaryrefslogtreecommitdiff
path: root/2020-overdrive/tests/live_comparison.rs
blob: 3e290692f0bd1a663d77fb2a1e3cdd767ec6a158 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
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
        );
    }
}