Split board-related stuff into board.rs
This commit is contained in:
235
rs/src/board.rs
Normal file
235
rs/src/board.rs
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
#[derive(Clone)]
|
||||||
|
enum Color {
|
||||||
|
Black,
|
||||||
|
White,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Color {
|
||||||
|
fn get_home_rank(&self) -> Rank {
|
||||||
|
match self {
|
||||||
|
Color::Black => Rank::_8,
|
||||||
|
Color::White => Rank::_1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn get_pawn_rank(&self) -> Rank {
|
||||||
|
match self {
|
||||||
|
Color::Black => Rank::_7,
|
||||||
|
Color::White => Rank::_2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn get_direction(&self) -> i8 {
|
||||||
|
match self {
|
||||||
|
Color::Black => -1,
|
||||||
|
Color::White => 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Position {
|
||||||
|
rank: Rank,
|
||||||
|
file: File,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Position {
|
||||||
|
pub fn new(rank: Rank, file: File) -> Position {
|
||||||
|
Position {
|
||||||
|
rank,
|
||||||
|
file,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn delta(&self, delta_rank_file: (i8, i8)) -> Result<Position, ()> {
|
||||||
|
let (delta_rank, delta_file) = delta_rank_file;
|
||||||
|
Ok(Position::new(
|
||||||
|
self.rank.delta(delta_rank)?,
|
||||||
|
self.file.delta(delta_file)?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Clone, Copy)]
|
||||||
|
pub enum Rank {
|
||||||
|
_1,
|
||||||
|
_2,
|
||||||
|
_3,
|
||||||
|
_4,
|
||||||
|
_5,
|
||||||
|
_6,
|
||||||
|
_7,
|
||||||
|
_8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Clone, Copy)]
|
||||||
|
pub enum File {
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
C,
|
||||||
|
D,
|
||||||
|
E,
|
||||||
|
F,
|
||||||
|
G,
|
||||||
|
H,
|
||||||
|
}
|
||||||
|
|
||||||
|
trait GridAxis
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
Self: Clone,
|
||||||
|
{
|
||||||
|
const ALL_VALUES: [Self; 8];
|
||||||
|
fn new(index: u8) -> Result<Self, ()> {
|
||||||
|
return Ok(
|
||||||
|
Self::ALL_VALUES[Self::validate_index(index)? as usize].clone()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
fn validate_index(index: u8) -> Result<u8, ()> {
|
||||||
|
if index as usize >= Self::ALL_VALUES.len() {
|
||||||
|
Err(())
|
||||||
|
} else {
|
||||||
|
Ok(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn get_index(&self) -> u8;
|
||||||
|
fn delta(&self, delta: i8) -> Result<Self, ()> {
|
||||||
|
let highest = Self::ALL_VALUES.len() as i8 - 1;
|
||||||
|
if delta > highest
|
||||||
|
|| delta < -highest
|
||||||
|
|| (delta < 0 && self.get_index() < delta.abs() as u8)
|
||||||
|
|| (delta > 0 && self.get_index() + delta as u8 > highest as u8)
|
||||||
|
{
|
||||||
|
Err(())
|
||||||
|
} else {
|
||||||
|
Self::new(((self.get_index() as i8) + delta) as u8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GridAxis for Rank {
|
||||||
|
const ALL_VALUES: [Rank; 8] = [
|
||||||
|
Rank::_1,
|
||||||
|
Rank::_2,
|
||||||
|
Rank::_3,
|
||||||
|
Rank::_4,
|
||||||
|
Rank::_5,
|
||||||
|
Rank::_6,
|
||||||
|
Rank::_7,
|
||||||
|
Rank::_8,
|
||||||
|
];
|
||||||
|
fn get_index(&self) -> u8 {
|
||||||
|
*self as u8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GridAxis for File {
|
||||||
|
const ALL_VALUES: [File; 8] = [
|
||||||
|
File::A,
|
||||||
|
File::B,
|
||||||
|
File::C,
|
||||||
|
File::D,
|
||||||
|
File::E,
|
||||||
|
File::F,
|
||||||
|
File::G,
|
||||||
|
File::H,
|
||||||
|
];
|
||||||
|
fn get_index(&self) -> u8 {
|
||||||
|
*self as u8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum PieceType {
|
||||||
|
Pawn,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PieceType {
|
||||||
|
fn initial_setup(&self) -> Vec<Piece> {
|
||||||
|
match &self {
|
||||||
|
PieceType::Pawn => [Color::Black, Color::White]
|
||||||
|
.iter()
|
||||||
|
.flat_map(|color| {
|
||||||
|
File::ALL_VALUES.iter().map(|&file| Piece {
|
||||||
|
piece_type: self.clone(),
|
||||||
|
position: Position::new(color.get_pawn_rank(), file),
|
||||||
|
color: color.clone(),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Piece {
|
||||||
|
position: Position,
|
||||||
|
color: Color,
|
||||||
|
piece_type: PieceType,
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Movement {
|
||||||
|
fn get_moves(&self) -> Vec<Position>;
|
||||||
|
fn get_captures(&self) -> Vec<Position>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Piece {
|
||||||
|
fn get_moves(&self) -> Vec<Position> {
|
||||||
|
let deltas = match self.piece_type {
|
||||||
|
PieceType::Pawn => self._pawn_get_move_deltas(),
|
||||||
|
};
|
||||||
|
self.deltas_to_valid_positions(&deltas)
|
||||||
|
}
|
||||||
|
fn get_captures(&self) -> Vec<Position> {
|
||||||
|
let deltas = match self.piece_type {
|
||||||
|
PieceType::Pawn => self._pawn_get_capture_deltas(),
|
||||||
|
};
|
||||||
|
self.deltas_to_valid_positions(&deltas)
|
||||||
|
}
|
||||||
|
fn deltas_to_valid_positions(
|
||||||
|
&self,
|
||||||
|
deltas: &Vec<(i8, i8)>,
|
||||||
|
) -> Vec<Position> {
|
||||||
|
deltas
|
||||||
|
.iter()
|
||||||
|
.filter_map(|&delta_rank_file| {
|
||||||
|
self.position.delta(delta_rank_file).ok()
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
fn _pawn_get_move_deltas(&self) -> Vec<(i8, i8)> {
|
||||||
|
let direction = self.color.get_direction();
|
||||||
|
if self.position.rank == self.color.get_pawn_rank() {
|
||||||
|
vec![(1 * direction, 0), (2 * direction, 0)]
|
||||||
|
} else {
|
||||||
|
vec![(1 * direction, 0)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn _pawn_get_capture_deltas(&self) -> Vec<(i8, i8)> {
|
||||||
|
let direction = self.color.get_direction();
|
||||||
|
vec![(1 * direction, 1), (1 * direction, -1)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Board {
|
||||||
|
state: [[Option<Piece>; File::ALL_VALUES.len()]; Rank::ALL_VALUES.len()],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Board {
|
||||||
|
pub fn get_at(&self, position: &Position) -> &Option<Piece> {
|
||||||
|
&self.state[position.rank.get_index() as usize]
|
||||||
|
[position.file.get_index() as usize]
|
||||||
|
}
|
||||||
|
fn set_at(&mut self, position: &Position, mut piece: Piece) {
|
||||||
|
piece.position = position.clone();
|
||||||
|
self.state[position.rank.get_index() as usize]
|
||||||
|
[position.file.get_index() as usize] = Some(piece);
|
||||||
|
}
|
||||||
|
pub fn new() -> Board {
|
||||||
|
let mut board = Board {
|
||||||
|
state: Default::default(),
|
||||||
|
};
|
||||||
|
for piece_type in &[PieceType::Pawn] {
|
||||||
|
for piece in piece_type.initial_setup() {
|
||||||
|
board.set_at(&piece.position.clone(), piece);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
board
|
||||||
|
}
|
||||||
|
}
|
||||||
238
rs/src/main.rs
238
rs/src/main.rs
@@ -1,229 +1,17 @@
|
|||||||
#[derive(Clone)]
|
mod board;
|
||||||
enum Color {
|
|
||||||
Black,
|
|
||||||
White,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Color {
|
fn main() {
|
||||||
fn get_home_rank(&self) -> Rank {
|
println!(
|
||||||
match self {
|
"{}",
|
||||||
Color::Black => Rank::_8,
|
match board::Board::new()
|
||||||
Color::White => Rank::_1,
|
.get_at(&board::Position::new(board::Rank::_2, board::File::A))
|
||||||
}
|
|
||||||
}
|
|
||||||
fn get_pawn_rank(&self) -> Rank {
|
|
||||||
match self {
|
|
||||||
Color::Black => Rank::_7,
|
|
||||||
Color::White => Rank::_2,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn get_direction(&self) -> i8 {
|
|
||||||
match self {
|
|
||||||
Color::Black => -1,
|
|
||||||
Color::White => 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct Position {
|
|
||||||
rank: Rank,
|
|
||||||
file: File,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Position {
|
|
||||||
fn delta(&self, delta_rank_file: (i8, i8)) -> Result<Position, ()> {
|
|
||||||
let (delta_rank, delta_file) = delta_rank_file;
|
|
||||||
Ok(Position {
|
|
||||||
rank: self.rank.delta(delta_rank)?,
|
|
||||||
file: self.file.delta(delta_file)?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy)]
|
|
||||||
enum Rank {
|
|
||||||
_1,
|
|
||||||
_2,
|
|
||||||
_3,
|
|
||||||
_4,
|
|
||||||
_5,
|
|
||||||
_6,
|
|
||||||
_7,
|
|
||||||
_8,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy)]
|
|
||||||
enum File {
|
|
||||||
A,
|
|
||||||
B,
|
|
||||||
C,
|
|
||||||
D,
|
|
||||||
E,
|
|
||||||
F,
|
|
||||||
G,
|
|
||||||
H,
|
|
||||||
}
|
|
||||||
|
|
||||||
trait GridAxis
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
Self: Clone,
|
|
||||||
{
|
|
||||||
const ALL_VALUES: [Self; 8];
|
|
||||||
fn new(index: u8) -> Result<Self, ()> {
|
|
||||||
return Ok(
|
|
||||||
Self::ALL_VALUES[Self::validate_index(index)? as usize].clone()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
fn validate_index(index: u8) -> Result<u8, ()> {
|
|
||||||
if index as usize >= Self::ALL_VALUES.len() {
|
|
||||||
Err(())
|
|
||||||
} else {
|
|
||||||
Ok(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn get_index(&self) -> u8;
|
|
||||||
fn delta(&self, delta: i8) -> Result<Self, ()> {
|
|
||||||
let highest = Self::ALL_VALUES.len() as i8 - 1;
|
|
||||||
if delta > highest
|
|
||||||
|| delta < -highest
|
|
||||||
|| (delta < 0 && self.get_index() < delta.abs() as u8)
|
|
||||||
|| (delta > 0 && self.get_index() + delta as u8 > highest as u8)
|
|
||||||
{
|
{
|
||||||
Err(())
|
Some(piece) => "Some",
|
||||||
} else {
|
None => "None",
|
||||||
Ok(Self::new(((self.get_index() as i8) + delta) as u8)?)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
// reset -> (ok/fail)
|
||||||
|
// get_state -> (ok/fail),state
|
||||||
|
// get_moves,position,[state] -> (ok/fail),position[]
|
||||||
|
// make_move,[move],[state] -> (ok/fail),state
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GridAxis for Rank {
|
|
||||||
const ALL_VALUES: [Rank; 8] = [
|
|
||||||
Rank::_1,
|
|
||||||
Rank::_2,
|
|
||||||
Rank::_3,
|
|
||||||
Rank::_4,
|
|
||||||
Rank::_5,
|
|
||||||
Rank::_6,
|
|
||||||
Rank::_7,
|
|
||||||
Rank::_8,
|
|
||||||
];
|
|
||||||
fn get_index(&self) -> u8 {
|
|
||||||
*self as u8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GridAxis for File {
|
|
||||||
const ALL_VALUES: [File; 8] = [
|
|
||||||
File::A,
|
|
||||||
File::B,
|
|
||||||
File::C,
|
|
||||||
File::D,
|
|
||||||
File::E,
|
|
||||||
File::F,
|
|
||||||
File::G,
|
|
||||||
File::H,
|
|
||||||
];
|
|
||||||
fn get_index(&self) -> u8 {
|
|
||||||
*self as u8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
enum PieceType {
|
|
||||||
Pawn,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PieceType {
|
|
||||||
fn initial_setup(&self) -> Vec<Piece> {
|
|
||||||
match &self {
|
|
||||||
PieceType::Pawn => [Color::Black, Color::White]
|
|
||||||
.iter()
|
|
||||||
.flat_map(|color| {
|
|
||||||
File::ALL_VALUES.iter().map(|&file| Piece {
|
|
||||||
piece_type: self.clone(),
|
|
||||||
position: Position {
|
|
||||||
rank: color.get_pawn_rank(),
|
|
||||||
file,
|
|
||||||
},
|
|
||||||
color: color.clone(),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Piece {
|
|
||||||
position: Position,
|
|
||||||
color: Color,
|
|
||||||
piece_type: PieceType,
|
|
||||||
}
|
|
||||||
|
|
||||||
trait Movement {
|
|
||||||
fn get_moves(&self) -> Vec<Position>;
|
|
||||||
fn get_captures(&self) -> Vec<Position>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Piece {
|
|
||||||
fn get_moves(&self) -> Vec<Position> {
|
|
||||||
let deltas = match self.piece_type {
|
|
||||||
PieceType::Pawn => self._pawn_get_move_deltas(),
|
|
||||||
};
|
|
||||||
self.deltas_to_valid_positions(&deltas)
|
|
||||||
}
|
|
||||||
fn get_captures(&self) -> Vec<Position> {
|
|
||||||
let deltas = match self.piece_type {
|
|
||||||
PieceType::Pawn => self._pawn_get_capture_deltas(),
|
|
||||||
};
|
|
||||||
self.deltas_to_valid_positions(&deltas)
|
|
||||||
}
|
|
||||||
fn deltas_to_valid_positions(
|
|
||||||
&self,
|
|
||||||
deltas: &Vec<(i8, i8)>,
|
|
||||||
) -> Vec<Position> {
|
|
||||||
deltas
|
|
||||||
.iter()
|
|
||||||
.filter_map(|&delta_rank_file| {
|
|
||||||
self.position.delta(delta_rank_file).ok()
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
fn _pawn_get_move_deltas(&self) -> Vec<(i8, i8)> {
|
|
||||||
let direction = self.color.get_direction();
|
|
||||||
if self.position.rank == self.color.get_pawn_rank() {
|
|
||||||
vec![(1 * direction, 0), (2 * direction, 0)]
|
|
||||||
} else {
|
|
||||||
vec![(1 * direction, 0)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn _pawn_get_capture_deltas(&self) -> Vec<(i8, i8)> {
|
|
||||||
let direction = self.color.get_direction();
|
|
||||||
vec![(1 * direction, 1), (1 * direction, -1)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Board {
|
|
||||||
state: [[Option<Piece>; File::ALL_VALUES.len()]; Rank::ALL_VALUES.len()],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Board {
|
|
||||||
fn set_at(&mut self, position: &Position, piece: Piece) {
|
|
||||||
self.state[position.rank.get_index() as usize]
|
|
||||||
[position.file.get_index() as usize] = Some(piece);
|
|
||||||
}
|
|
||||||
fn new() -> Board {
|
|
||||||
let mut board = Board {
|
|
||||||
state: Default::default(),
|
|
||||||
};
|
|
||||||
for piece_type in &[PieceType::Pawn] {
|
|
||||||
for piece in piece_type.initial_setup() {
|
|
||||||
board.set_at(&piece.position.clone(), piece);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
board
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user