[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>
|
// Eryn Wells <eryn@erynwells.me>
|
||||||
|
|
||||||
|
use crate::neighbor::Direction;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ParseSquareError;
|
pub struct ParseSquareError;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SquareIndexOutOfBoundsError;
|
pub struct SquareOutOfBoundsError;
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct Square {
|
pub struct Square {
|
||||||
|
@ -16,15 +17,31 @@ pub struct Square {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Square {
|
impl Square {
|
||||||
pub fn from_index(index: u8) -> Result<Square, SquareIndexOutOfBoundsError> {
|
pub fn from_index(index: u8) -> Result<Square, SquareOutOfBoundsError> {
|
||||||
if index >= 64 {
|
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,
|
rank: index / 8,
|
||||||
file: index % 8,
|
file: index % 8,
|
||||||
index: index,
|
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()
|
s.parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rank_index(&self) -> usize {
|
pub fn neighbor(&self, direction: Direction) -> Option<Square> {
|
||||||
self.rank.into()
|
match direction {
|
||||||
}
|
Direction::North => Square::from_index(self.index + 8),
|
||||||
|
Direction::NorthWest => {
|
||||||
pub fn file_index(&self) -> usize {
|
if self.rank < 7 {
|
||||||
self.file.into()
|
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);
|
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