Created
January 7, 2018 16:22
-
-
Save mackwic/08b7b8bb1b88058401f4b1bb0cc69f14 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate nalgebra; | |
#[cfg(test)] | |
extern crate rspec; | |
#[cfg(test)] | |
#[macro_use] | |
extern crate expectest; | |
use nalgebra::{Vector2, Point2}; | |
#[derive(Clone, Debug)] | |
pub struct Map { | |
tiles: Vec<Option<()>>, | |
size: Vector2<i32>, | |
player_spawn: Point2<f32>, | |
} | |
impl Map { | |
pub fn new(size: Vector2<i32>) -> Self { | |
Map { | |
tiles: vec![None; (size.x * size.y) as usize], | |
size, | |
player_spawn: Point2::new(0.0, 0.0), | |
} | |
} | |
pub fn size(&self) -> Vector2<i32> { | |
self.size | |
} | |
pub fn player_spawn(&self) -> Point2<f32> { | |
self.player_spawn | |
} | |
pub fn set_player_spawn(&mut self, position: Point2<f32>) { | |
self.player_spawn = position | |
} | |
pub fn add_enemy_spawn(&mut self, _position: Point2<f32>) { | |
} | |
pub fn get_at(&self, position: Point2<i32>) -> Result<Option<()>, MapError> { | |
if self.in_bounds(position) { | |
Ok(self.tiles[self.index_at(position)]) | |
} else { | |
Err(MapError::OutOfBounds { position }) | |
} | |
} | |
pub fn set_at(&mut self, position: Point2<i32>, value: Option<()>) -> Result<(), MapError> { | |
if self.in_bounds(position) { | |
let index = self.index_at(position); | |
self.tiles[index] = value; | |
Ok(()) | |
} else { | |
Err(MapError::OutOfBounds { position }) | |
} | |
} | |
fn in_bounds(&self, position: Point2<i32>) -> bool { | |
if position.x >= 0 && position.y >= 0 && | |
position.x < self.size.x && position.y < self.size.y { | |
true | |
} else { | |
false | |
} | |
} | |
fn index_at(&self, position: Point2<i32>) -> usize { | |
(position.x + position.y * self.size.x) as usize | |
} | |
} | |
#[derive(Debug, PartialEq)] | |
pub enum MapError { | |
OutOfBounds { position: Point2<i32> }, | |
} | |
#[cfg(test)] | |
mod tests { | |
use nalgebra::{Vector2, Point2}; | |
use super::{Map, MapError}; | |
use expectest::prelude::*; | |
use rspec; | |
use rspec::*; | |
#[test] | |
fn error_handling_spec() { | |
let base_x = 1; | |
let base_y = 1; | |
let base_map = Map::new(Vector2::new(base_x, base_y)); | |
rspec::run(&describe("error handling", base_map, |ctx| { | |
ctx.specify("MapError::OutOfBounds", |ctx| { | |
ctx.it("errs when position X is over", move |map| { | |
// arrange | |
let out_position = Point2::new(base_x + 1, base_y); | |
// act | |
let result = map.get_at(out_position); | |
// assert | |
// XXX: note the absence of the semi colon at the end. This is an alternative | |
// to assert_eq! | |
result == Err(MapError::OutOfBounds { position: out_position }) | |
}); | |
ctx.it("errs when position Y is over", move |map| { | |
// arrange | |
let out_position = Point2::new(base_x, base_y + 1); | |
// act | |
let result = map.get_at(out_position); | |
// assert | |
result == Err(MapError::OutOfBounds { position: out_position }) | |
}); | |
ctx.it("errs when position X is under", move |map| { | |
// arrange | |
let out_position = Point2::new(base_x - 1, base_y); | |
// act | |
let result = map.get_at(out_position); | |
// assert | |
result == Err(MapError::OutOfBounds { position: out_position }) | |
}); | |
ctx.it("errs when position Y is under (with bools)", move |map| { | |
// arrange | |
let out_position = Point2::new(base_x, base_y - 1); | |
// act | |
let result = map.get_at(out_position); | |
// assert | |
// XXX reversed condition with assert_eq! | |
result != Err(MapError::OutOfBounds { position: out_position }) | |
}); | |
ctx.it("errs when position Y is under (with assert)", move |map| { | |
// arrange | |
let out_position = Point2::new(base_x, base_y - 1); | |
// act | |
let result = map.get_at(out_position); | |
// assert | |
// XXX reversed condition with assert_eq! | |
assert_ne!(result, Err(MapError::OutOfBounds { position: out_position })) | |
}); | |
ctx.it("errs when position Y is under (with expectest)", move |map| { | |
// arrange | |
let out_position = Point2::new(base_x, base_y - 1); | |
// act | |
let result = map.get_at(out_position); | |
// assert | |
// XXX reversed condition with assert_eq! | |
expect!(result).not_to(be_equal_to(Err(MapError::OutOfBounds { position: out_position }))); | |
}); | |
}); | |
})); | |
} | |
// #[test] | |
// fn set_at_spec() { | |
// let base_x = 5; | |
// let base_y = 5; | |
// let something = Some(()); | |
// let nothing = None; | |
// let empty_position = Point2::new(1, 1); | |
// | |
// rspec::run(&describe("Map::set_at", (), |ctx| { | |
// ctx.context("set at empty position is OK", |ctx| { | |
// ctx.it("set Some(())", move |_| { | |
// // arrange | |
// let mut map = Map::new(Vector2::new(base_x, base_y)); | |
// // act | |
// let result = map.set_at(empty_position, something); | |
// // assert | |
// result.is_ok() | |
// }); | |
// | |
// ctx.it("set None", move |_| { | |
// // arrange | |
// let mut map = Map::new(Vector2::new(base_x, base_y)); | |
// // act | |
// let result = map.set_at(empty_position, nothing); | |
// // assert | |
// result.is_ok() | |
// }); | |
// }); | |
// | |
// ctx.context("set at a non-empty position", |ctx| { | |
// ctx.it("set Some(())", move |_| { | |
// // arrange | |
// let mut map = Map::new(Vector2::new(base_x, base_y)); | |
// map.set_at(empty_position, something).unwrap(); | |
// // act | |
// let result = map.set_at(empty_position, something); | |
// // assert | |
// result.is_err() | |
// }); | |
// | |
// ctx.it("set None", move |_| { | |
// // arrange | |
// let something = None; | |
// let mut map = Map::new(Vector2::new(base_x, base_y)); | |
// map.set_at(empty_position, something).unwrap(); | |
// // act | |
// let result = map.set_at(empty_position, something); | |
// // assert | |
// result.is_ok() | |
// }); | |
// }); | |
// | |
// })); | |
// } | |
#[test] | |
fn it_gets_value_after_set() { | |
let mut map = Map::new(Vector2::new(5, 5)); | |
let position1 = Point2::new(3, 3); | |
let position2 = Point2::new(1, 3); | |
map.set_at(position1, Some(())).unwrap(); | |
map.set_at(position2, None).unwrap(); | |
assert_eq!(map.get_at(position1), Ok(Some(()))); | |
assert_eq!(map.get_at(position2), Ok(None)); | |
} | |
#[test] | |
fn it_returns_error_for_out_of_bounds_set() { | |
let mut map = Map::new(Vector2::new(5, 5)); | |
let result = map.set_at(Point2::new(10, 10), Some(())); | |
assert!(result.is_err()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment