From 4c5331b9b5633fd500c79ada42fc08b3cb986631 Mon Sep 17 00:00:00 2001 From: Justin Worthe Date: Fri, 28 Jun 2019 22:46:39 +0200 Subject: Fixed issues identified through comparison with the official engine --- tests/official-runner-matching.rs | 172 ++++++++++++++++++++++++++++---------- 1 file changed, 130 insertions(+), 42 deletions(-) (limited to 'tests/official-runner-matching.rs') diff --git a/tests/official-runner-matching.rs b/tests/official-runner-matching.rs index 8a0320f..fcc648f 100644 --- a/tests/official-runner-matching.rs +++ b/tests/official-runner-matching.rs @@ -1,11 +1,11 @@ -use steam_powered_wyrm::json; +use steam_powered_wyrm::command::{Action, Command}; use steam_powered_wyrm::game::*; -use steam_powered_wyrm::command::{Command, Action}; use steam_powered_wyrm::geometry::*; +use steam_powered_wyrm::json; -use std::path::Path; use std::fs::File; use std::io::prelude::*; +use std::path::Path; #[test] fn simulates_the_same_match() { @@ -14,50 +14,97 @@ fn simulates_the_same_match() { let replay = replay.expect("error on replay").path(); let mut game_board = GameBoard::new( - json::read_state_from_json_file(&replay.join(Path::new("A-init.json"))).expect("Failed to read initial state") + json::read_state_from_json_file(&replay.join(Path::new("A-init.json"))) + .expect("Failed to read initial state"), ); let player_csv = read_file_lines(&replay.join(Path::new("A-log.csv")), 1); let opponent_csv = read_file_lines(&replay.join(Path::new("B-log.csv")), 1); for round in 0..player_csv.len() { println!("Testing round {}", round); - + let player = split_csv(&player_csv[round]); let opponent = split_csv(&opponent_csv[round]); - assert_eq!(round + 1, player[0].parse::().expect(&format!("Invalid player input on round {}", round))); - assert_eq!(round + 1, opponent[0].parse::().expect(&format!("Invalid opponent input on round {}", round))); + assert_eq!( + round + 1, + player[0] + .parse::() + .expect(&format!("Invalid player input on round {}", round)) + ); + assert_eq!( + round + 1, + opponent[0] + .parse::() + .expect(&format!("Invalid opponent input on round {}", round)) + ); - // active worm id field in CSV refers to the worm of the - // move. The rest of the state refers to after the move - // has happened. - assert_eq!(player[3].parse::().unwrap(), game_board.players[0].worms[game_board.players[0].active_worm].id, "Active worm is incorrect for player 0"); - assert_eq!(opponent[3].parse::().unwrap(), game_board.players[1].worms[game_board.players[1].active_worm].id, "Active worm is incorrect for player 1"); - if round != 0 { - let player_move = read_move(&player); - let opponent_move = read_move(&opponent); + let player_move = read_move( + &player, + game_board.players[0].worms[game_board.players[0].active_worm].id, + ); + let opponent_move = read_move( + &opponent, + game_board.players[1].worms[game_board.players[1].active_worm].id, + ); let _ = game_board.simulate([player_move, opponent_move]); + if player[1] == "invalid" { + game_board.players[0].moves_score -= 4; + } + if opponent[1] == "invalid" { + game_board.players[1].moves_score -= 4; + } } for player_index in 0..2 { let csv_row = match player_index { 0 => &player, - _ => &opponent + _ => &opponent, }; - assert_eq!(csv_row[4].parse::().unwrap(), game_board.players[player_index].score(), "Score is incorrect for player {}, Row: {:?}", player_index, csv_row); + assert_eq!( + csv_row[4].parse::().unwrap(), + game_board.players[player_index].score(), + "Score is incorrect for player {}, Row: {:?}", + player_index, + csv_row + ); for worm_index in 0..3 { let worm_id = worm_index as i32 + 1; match game_board.players[player_index].find_worm(worm_id) { Some(worm) => { - assert_eq!(csv_row[6 + worm_index * 3].parse::().unwrap(), worm.health, "Worm health is incorrect for worm {} on player {}, Row: {:?}", worm_id, player_index, csv_row); - assert_eq!(csv_row[7 + worm_index * 3].parse::().unwrap(), worm.position.x, "Worm x is incorrect for worm {} on player {}, Row: {:?}", worm_id, player_index, csv_row); - assert_eq!(csv_row[8 + worm_index * 3].parse::().unwrap(), worm.position.y, "Worm y is incorrect for worm {} on player {}, Row: {:?}", worm_id, player_index, csv_row); - }, + assert_eq!( + csv_row[6 + worm_index * 3].parse::().unwrap(), + worm.health, + "Worm health is incorrect for worm {} on player {}, Row: {:?}", + worm_id, + player_index, + csv_row + ); + assert_eq!( + csv_row[7 + worm_index * 3].parse::().unwrap(), + worm.position.x, + "Worm x is incorrect for worm {} on player {}, Row: {:?}", + worm_id, + player_index, + csv_row + ); + assert_eq!( + csv_row[8 + worm_index * 3].parse::().unwrap(), + worm.position.y, + "Worm y is incorrect for worm {} on player {}, Row: {:?}", + worm_id, + player_index, + csv_row + ); + } None => { // If the worms don't appear in my state, they should be dead - assert!(csv_row[6 + worm_index * 3].parse::().unwrap() <= 0, "Worm is not actually dead"); + assert!( + csv_row[6 + worm_index * 3].parse::().unwrap() <= 0, + "Worm is not actually dead" + ); } } } @@ -66,28 +113,32 @@ fn simulates_the_same_match() { } } - fn read_file_lines(path: &Path, skip: usize) -> Vec { let mut file = File::open(path).unwrap(); let mut contents = String::new(); file.read_to_string(&mut contents).unwrap(); - contents.split("\n").skip(skip).map(String::from).filter(|s| !s.is_empty()).collect() + contents + .split("\n") + .skip(skip) + .map(String::from) + .filter(|s| !s.is_empty()) + .collect() } fn split_csv(input: &str) -> Vec { let mut result = Vec::new(); let mut next = Vec::new(); let mut quoted = false; - + for c in input.chars() { match c { '"' => { quoted = !quoted; - }, + } ',' if !quoted => { result.push(next.iter().collect()); next = Vec::new(); - }, + } c => { next.push(c); } @@ -97,22 +148,42 @@ fn split_csv(input: &str) -> Vec { result } -fn read_move(csv_line: &[String]) -> Command { +fn read_move(csv_line: &[String], expected_worm_id: i32) -> Command { + let worm_id = csv_line[3].parse::().unwrap(); + let select = if worm_id == expected_worm_id { + None + } else { + Some(worm_id) + }; match csv_line[1].as_ref() { "move" => { let (x, y) = read_xy_pair(&csv_line[2]); - Command::new(Action::Move(Point2d::new(x, y))) - }, + Command { + worm: select, + action: Action::Move(Point2d::new(x, y)), + } + } "dig" => { let (x, y) = read_xy_pair(&csv_line[2]); - Command::new(Action::Dig(Point2d::new(x, y))) - }, - "nothing" => { - Command::new(Action::DoNothing) + Command { + worm: select, + action: Action::Dig(Point2d::new(x, y)), + } + } + "banana" => { + let (x, y) = read_xy_pair(&csv_line[2]); + Command { + worm: select, + action: Action::Bomb(Point2d::new(x, y)), + } + } + "nothing" | "invalid" => Command { + worm: select, + action: Action::DoNothing, }, "shoot" => { use steam_powered_wyrm::geometry::Direction::*; - + let dir = match csv_line[2].as_ref() { "shoot N" => North, "shoot NE" => NorthEast, @@ -122,11 +193,13 @@ fn read_move(csv_line: &[String]) -> Command { "shoot SW" => SouthWest, "shoot W" => West, "shoot NW" => NorthWest, - _ => panic!("Unknown shoot direction: {}", csv_line[2]) + _ => panic!("Unknown shoot direction: {}", csv_line[2]), }; - Command::new(Action::Shoot(dir)) - }, - // TODO: Parsing of new commands + Command { + worm: select, + action: Action::Shoot(dir), + } + } x => { panic!("Unknown command {}", x); } @@ -135,8 +208,23 @@ fn read_move(csv_line: &[String]) -> Command { fn read_xy_pair(input: &str) -> (i8, i8) { let mut char_iter = input.chars(); - let _ = char_iter.by_ref().take_while(|c| *c != '(').collect::(); - let x = char_iter.by_ref().take_while(|c| *c != ',').collect::().trim().parse::().unwrap(); - let y = char_iter.by_ref().take_while(|c| *c != ')').collect::().trim().parse::().unwrap(); + let _ = char_iter + .by_ref() + .take_while(|c| *c != '(') + .collect::(); + let x = char_iter + .by_ref() + .take_while(|c| *c != ',') + .collect::() + .trim() + .parse::() + .unwrap(); + let y = char_iter + .by_ref() + .take_while(|c| *c != ')') + .collect::() + .trim() + .parse::() + .unwrap(); (x, y) } -- cgit v1.2.3