Files
chess/rs/src/main.rs
Pavel Lutskov 458f87fd61 Rename row/column to rank/file
This is how they're "officially" called
2021-12-04 18:54:09 +01:00

230 lines
5.1 KiB
Rust

#[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)]
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(())
} else {
Ok(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)]
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() {}