[board] Re-do the Square implementation

- Rank and file are 0-indexed values
- Add an index property, a 1D index into an array
- Add from_index() and from_algebraic_string()
This commit is contained in:
Eryn Wells 2023-12-21 08:15:51 -08:00
parent d776bd18e2
commit 0a42adf1fa

View file

@ -3,19 +3,20 @@
use std::str::FromStr; use std::str::FromStr;
#[derive(Debug)] #[derive(Debug)]
struct ParseSquareError; pub struct ParseSquareError;
#[derive(Debug)] #[derive(Debug)]
struct SquareIndexOutOfBoundsError; pub struct SquareIndexOutOfBoundsError;
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
struct Square { pub struct Square {
rank: u8, pub rank: u8,
file: u8, pub file: u8,
pub index: u8,
} }
impl Square { impl Square {
fn from_index(index: u8) -> Result<Square, SquareIndexOutOfBoundsError> { pub fn from_index(index: u8) -> Result<Square, SquareIndexOutOfBoundsError> {
if index >= 64 { if index >= 64 {
return Err(SquareIndexOutOfBoundsError); return Err(SquareIndexOutOfBoundsError);
} }
@ -23,18 +24,19 @@ impl Square {
Ok(Square { Ok(Square {
rank: index / 8, rank: index / 8,
file: index % 8, file: index % 8,
index: index,
}) })
} }
fn from_algebraic_string(s: &str) -> Result<Square, ParseSquareError> { pub fn from_algebraic_string(s: &str) -> Result<Square, ParseSquareError> {
s.parse() s.parse()
} }
fn rank_index(&self) -> usize { pub fn rank_index(&self) -> usize {
self.rank.into() self.rank.into()
} }
fn file_index(&self) -> usize { pub fn file_index(&self) -> usize {
self.file.into() self.file.into()
} }
} }
@ -53,17 +55,21 @@ impl FromStr for Square {
return Err(ParseSquareError); return Err(ParseSquareError);
} }
let rank = (rank_char as u8) - ('a' as u8) + 1; let rank = (rank_char as u8) - ('a' as u8);
if rank < 1 || rank > 8 { if rank >= 8 {
return Err(ParseSquareError); return Err(ParseSquareError);
} }
let file = u8::try_from(chars[1].to_digit(10).ok_or(ParseSquareError)?) let converted_file_digit = chars[1]
.map_err(|_| ParseSquareError)?; .to_digit(10)
.and_then(|x| if x != 0 { Some(x) } else { None })
.ok_or(ParseSquareError)?;
let file = u8::try_from(converted_file_digit).map_err(|_| ParseSquareError)? - 1;
Ok(Square { Ok(Square {
rank: rank - 1, rank: rank,
file: file - 1, file: file,
index: rank * 8 + file,
}) })
} }
} }
@ -84,7 +90,7 @@ mod tests {
} }
#[test] #[test]
fn parse_good_input() { fn good_algebraic_input() {
let sq1 = Square::from_algebraic_string("a4").expect("Failed to parse 'a4' square"); let sq1 = Square::from_algebraic_string("a4").expect("Failed to parse 'a4' square");
assert_eq!(sq1.rank, 0); assert_eq!(sq1.rank, 0);
assert_eq!(sq1.file, 3); assert_eq!(sq1.file, 3);
@ -94,6 +100,16 @@ mod tests {
assert_eq!(sq2.file, 7); assert_eq!(sq2.file, 7);
} }
#[test]
fn bad_algebraic_input() {
Square::from_algebraic_string("a0").expect_err("Got valid Square for 'a0'");
Square::from_algebraic_string("j3").expect_err("Got valid Square for 'j3'");
Square::from_algebraic_string("a11").expect_err("Got valid Square for 'a11'");
Square::from_algebraic_string("b-1").expect_err("Got valid Square for 'b-1'");
Square::from_algebraic_string("a 1").expect_err("Got valid Square for 'a 1'");
Square::from_algebraic_string("").expect_err("Got valid Square for ''");
}
#[test] #[test]
fn from_index() { fn from_index() {
let sq1 = Square::from_index(4).expect("Unable to get Square from index"); let sq1 = Square::from_index(4).expect("Unable to get Square from index");