[board] Implement finding a neighbor of a square
Use the Direction enum to calculate the neighbor of a square with bounds checking. Remove the unused rank_index() and file_index methods. Add Square::from_rank_file and Square::from_index_unsafe to support tests. Unify the Square*OutOfBounds error types
This commit is contained in:
parent
341d8211ad
commit
153e21b693
1 changed files with 135 additions and 10 deletions
|
@ -1,12 +1,13 @@
|
|||
// Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
use crate::neighbor::Direction;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ParseSquareError;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SquareIndexOutOfBoundsError;
|
||||
pub struct SquareOutOfBoundsError;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Square {
|
||||
|
@ -16,15 +17,31 @@ pub struct Square {
|
|||
}
|
||||
|
||||
impl Square {
|
||||
pub fn from_index(index: u8) -> Result<Square, SquareIndexOutOfBoundsError> {
|
||||
pub fn from_index(index: u8) -> Result<Square, SquareOutOfBoundsError> {
|
||||
if index >= 64 {
|
||||
return Err(SquareIndexOutOfBoundsError);
|
||||
return Err(SquareOutOfBoundsError);
|
||||
}
|
||||
|
||||
Ok(Square {
|
||||
Ok(Square::from_index_unsafe(index))
|
||||
}
|
||||
|
||||
fn from_index_unsafe(index: u8) -> Square {
|
||||
Square {
|
||||
rank: index / 8,
|
||||
file: index % 8,
|
||||
index: index,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_rank_file(rank: u8, file: u8) -> Result<Square, SquareOutOfBoundsError> {
|
||||
if rank >= 8 || file >= 8 {
|
||||
return Err(SquareOutOfBoundsError);
|
||||
}
|
||||
|
||||
Ok(Square {
|
||||
rank,
|
||||
file,
|
||||
index: rank * 8 + file,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -32,12 +49,54 @@ impl Square {
|
|||
s.parse()
|
||||
}
|
||||
|
||||
pub fn rank_index(&self) -> usize {
|
||||
self.rank.into()
|
||||
}
|
||||
|
||||
pub fn file_index(&self) -> usize {
|
||||
self.file.into()
|
||||
pub fn neighbor(&self, direction: Direction) -> Option<Square> {
|
||||
match direction {
|
||||
Direction::North => Square::from_index(self.index + 8),
|
||||
Direction::NorthWest => {
|
||||
if self.rank < 7 {
|
||||
Square::from_index(self.index + 7)
|
||||
} else {
|
||||
Err(SquareOutOfBoundsError)
|
||||
}
|
||||
}
|
||||
Direction::West => {
|
||||
if self.file > 0 {
|
||||
Square::from_index(self.index - 1)
|
||||
} else {
|
||||
Err(SquareOutOfBoundsError)
|
||||
}
|
||||
}
|
||||
Direction::SouthWest => {
|
||||
if self.rank > 0 {
|
||||
Square::from_index(self.index - 9)
|
||||
} else {
|
||||
Err(SquareOutOfBoundsError)
|
||||
}
|
||||
}
|
||||
Direction::South => {
|
||||
if self.rank > 0 {
|
||||
Square::from_index(self.index - 8)
|
||||
} else {
|
||||
Err(SquareOutOfBoundsError)
|
||||
}
|
||||
}
|
||||
Direction::SouthEast => {
|
||||
if self.rank > 0 {
|
||||
Square::from_index(self.index - 7)
|
||||
} else {
|
||||
Err(SquareOutOfBoundsError)
|
||||
}
|
||||
}
|
||||
Direction::East => {
|
||||
if self.file < 7 {
|
||||
Square::from_index(self.index + 1)
|
||||
} else {
|
||||
Err(SquareOutOfBoundsError)
|
||||
}
|
||||
}
|
||||
Direction::NorthEast => Square::from_index(self.index + 9),
|
||||
}
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,5 +176,71 @@ mod tests {
|
|||
assert_eq!(sq1.file, 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn valid_neighbors() {
|
||||
let sq = Square::from_index_unsafe(28);
|
||||
|
||||
assert_eq!(
|
||||
sq.neighbor(Direction::North),
|
||||
Some(Square::from_index_unsafe(36))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
sq.neighbor(Direction::NorthEast),
|
||||
Some(Square::from_index_unsafe(37))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
sq.neighbor(Direction::East),
|
||||
Some(Square::from_index_unsafe(29))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
sq.neighbor(Direction::SouthEast),
|
||||
Some(Square::from_index_unsafe(21))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
sq.neighbor(Direction::South),
|
||||
Some(Square::from_index_unsafe(20))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
sq.neighbor(Direction::SouthWest),
|
||||
Some(Square::from_index_unsafe(19))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
sq.neighbor(Direction::West),
|
||||
Some(Square::from_index_unsafe(27))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
sq.neighbor(Direction::NorthWest),
|
||||
Some(Square::from_index_unsafe(35))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_neighbors() {
|
||||
let square0 = Square::from_index_unsafe(0);
|
||||
assert!(square0.neighbor(Direction::West).is_none());
|
||||
assert!(square0.neighbor(Direction::SouthWest).is_none());
|
||||
assert!(square0.neighbor(Direction::South).is_none());
|
||||
|
||||
let square7 = Square::from_index_unsafe(7);
|
||||
assert!(square7.neighbor(Direction::East).is_none());
|
||||
assert!(square7.neighbor(Direction::SouthEast).is_none());
|
||||
assert!(square7.neighbor(Direction::South).is_none());
|
||||
|
||||
let square56 = Square::from_index_unsafe(56);
|
||||
assert!(square56.neighbor(Direction::North).is_none());
|
||||
assert!(square56.neighbor(Direction::NorthWest).is_none());
|
||||
assert!(square56.neighbor(Direction::West).is_none());
|
||||
|
||||
let square63 = Square::from_index_unsafe(63);
|
||||
assert!(square63.neighbor(Direction::North).is_none());
|
||||
assert!(square63.neighbor(Direction::NorthEast).is_none());
|
||||
assert!(square63.neighbor(Direction::East).is_none());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue