use grovewright_core::codec::{DecodeError, Reader, Writer}; use grovewright_core::map::{Map, Pos, Terrain, Tile}; #[test] fn a_filled_map_has_the_requested_size_and_terrain() { let map = Map::filled(4, 3, Terrain::SoftRock); assert_eq!(map.width(), 4); assert_eq!(map.height(), 3); assert_eq!(map.tiles().len(), 12); assert_eq!(map.get(Pos::new(3, 2)), Some(Tile::new(Terrain::SoftRock))); } #[test] fn positions_outside_the_map_are_rejected() { let mut map = Map::filled(4, 3, Terrain::Ground); for pos in [ Pos::new(-1, 0), Pos::new(0, -1), Pos::new(4, 0), Pos::new(0, 3), ] { assert!(!map.in_bounds(pos), "{pos:?}"); assert_eq!(map.get(pos), None, "{pos:?}"); assert!(!map.set(pos, Tile::new(Terrain::Bedrock)), "{pos:?}"); } assert!(map.in_bounds(Pos::new(3, 2))); } #[test] fn set_changes_exactly_one_tile() { let mut map = Map::filled(4, 3, Terrain::Ground); assert!(map.set(Pos::new(1, 2), Tile::new(Terrain::HardRock))); let hard_rock = map .tiles() .iter() .filter(|tile| tile.terrain == Terrain::HardRock) .count(); assert_eq!(hard_rock, 1); assert_eq!(map.tiles()[2 * 4 + 1].terrain, Terrain::HardRock); } #[test] fn only_rock_can_be_dug() { assert_eq!(Terrain::Ground.hits_to_break(), None); assert_eq!(Terrain::Bedrock.hits_to_break(), None); assert_eq!(Terrain::SoftRock.hits_to_break(), Some(3)); assert_eq!(Terrain::HardRock.hits_to_break(), Some(6)); assert_eq!(Terrain::Ground.required_tool_tier(), None); assert_eq!(Terrain::Bedrock.required_tool_tier(), None); assert_eq!(Terrain::SoftRock.required_tool_tier(), Some(1)); assert_eq!(Terrain::HardRock.required_tool_tier(), Some(2)); } #[test] fn only_ground_can_be_walked_on() { assert!(Terrain::Ground.is_walkable()); assert!(!Terrain::SoftRock.is_walkable()); assert!(!Terrain::HardRock.is_walkable()); assert!(!Terrain::Bedrock.is_walkable()); } #[test] fn terrain_numbers_are_stable() { for terrain in [ Terrain::Ground, Terrain::SoftRock, Terrain::HardRock, Terrain::Bedrock, ] { assert_eq!(Terrain::from_u8(terrain as u8), Some(terrain)); } assert_eq!(Terrain::from_u8(4), None); } #[test] fn a_map_survives_encoding() { let mut map = Map::filled(5, 4, Terrain::Ground); map.set( Pos::new(2, 1), Tile { terrain: Terrain::SoftRock, damage: 2, }, ); let mut w = Writer::new(); map.encode(&mut w); let bytes = w.into_bytes(); let mut r = Reader::new(&bytes); assert_eq!(Map::decode(&mut r), Ok(map)); assert_eq!(r.finish(), Ok(())); } fn encoded_map(width: u32, height: u32, tiles: &[(u8, u8)]) -> Vec { let mut w = Writer::new(); w.u32(width); w.u32(height); for (terrain, damage) in tiles { w.u8(*terrain); w.u8(*damage); } w.into_bytes() } #[test] fn decoding_rejects_impossible_maps() { let cases: [(Vec, DecodeError); 6] = [ ( encoded_map(0, 4, &[]), DecodeError::InvalidValue("map size"), ), ( encoded_map(2_000, 4, &[]), DecodeError::InvalidValue("map size"), ), ( encoded_map(1, 1, &[(9, 0)]), DecodeError::InvalidValue("terrain"), ), ( encoded_map(1, 1, &[(0, 1)]), DecodeError::InvalidValue("tile damage"), ), ( encoded_map(1, 1, &[(1, 3)]), DecodeError::InvalidValue("tile damage"), ), (encoded_map(2, 2, &[(0, 0)]), DecodeError::UnexpectedEnd), ]; for (bytes, expected) in cases { assert_eq!(Map::decode(&mut Reader::new(&bytes)), Err(expected)); } }