Skip to content

Instantly share code, notes, and snippets.

@jdiez17
Last active August 5, 2017 11:16
Show Gist options
  • Save jdiez17/52442df6511e40d04d1b8b48817bb654 to your computer and use it in GitHub Desktop.
Save jdiez17/52442df6511e40d04d1b8b48817bb654 to your computer and use it in GitHub Desktop.
use std::fmt;
use std::char;
#[derive(Debug, Clone, Copy)]
enum Piece {
King,
Queen,
Rook,
Bishop,
Knight,
Pawn,
Empty
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum Color {
Black,
White,
None
}
#[derive(Debug, Clone, Copy)]
struct Square {
piece: Piece,
color: Color
}
impl fmt::Display for Square {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let offset = if self.color == Color::Black { '♚' as u32 - '♔' as u32 } else { 0 };
let symbol = char::from_u32(offset + match self.piece {
Piece::King => '♔',
Piece::Queen => '♕',
Piece::Rook => '♖',
Piece::Bishop => '♗',
Piece::Knight => '♘',
Piece::Pawn => '♙',
Piece::Empty => ' '
} as u32).unwrap();
write!(f, "{}", symbol)
}
}
impl Square { // TODO: is there a trait for this?
fn parse(c: char) -> Option<Square> {
if c == ' ' {
return Some(Square { piece: Piece::Empty, color: Color::None });
}
if c < '♔' || c > '♟' {
return None;
}
let color = if c >= '♚' { Color::Black } else { Color::White };
let offset = if color == Color::Black { '♚' as u32 - '♔' as u32 } else { 0 };
let piece = match char::from_u32(c as u32 - offset).unwrap() {
'♔' => Piece::King,
'♕' => Piece::Queen,
'♖' => Piece::Rook,
'♗' => Piece::Bishop,
'♘' => Piece::Knight,
'♙' => Piece::Pawn,
_ => unreachable!()
};
Some(Square { piece: piece, color: color })
}
}
struct Board {
board: [[Square; 8]; 8]
}
impl Board {
fn new() -> Board {
Board::parse(
"♜♞♝♛♚♝♞♜\n\
♟♟x♟♟♟♟♟\n\
        \n\
        \n\
        \n\
        \n\
♙♙♙♙♙♙♙♙\n\
♖♘♗♕♔♗♘♖"
).unwrap()
}
fn parse(s: &str) -> Result<Board, String> {
let lines: Vec<&str> = s.split("\n").collect();
let count = lines.len();
if lines.len() != 8 {
return Err(format!("invalid number of lines, got {}, expecting 8", count));
}
let rows_result: Result<Vec<Vec<Square>>, String> = lines.into_iter().enumerate().map(|(i, line)| {
let chars: Vec<char> = line.chars().collect();
let count = chars.len();
if count != 8 {
return Err(format!("invalid number of chars in line {}, got {}, expecting 8", i, count));
}
// type is Result<Vec<Square>, String>
chars.into_iter().enumerate()
.map(|(ii, c)| match Square::parse(c) {
Some(sq) => Ok(sq),
None => Err(format!("cannot parse char '{}' at position {} in line {}", c, ii, i))
})
.collect()
}).collect();
match rows_result {
Err(msg) => Err(msg),
Ok(rows) => {
// TODO better way of doing this? >_<
let mut board: [[Square; 8]; 8] = [[Square { piece: Piece::Empty, color: Color::None }; 8]; 8];
for i in 0..8 {
for ii in 0..8 {
board[i][ii] = rows[i][ii];
}
}
Ok(Board { board: board })
}
}
}
fn process(&mut self, instr: &str) -> Result<(), String> {
// TODO
}
}
impl fmt::Display for Board {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, " a b c d e f g h\n").unwrap();
for i in 0..8 {
write!(f, "{}", 8 - i).unwrap();
for ii in 0..8 {
write!(f, " {}", self.board[i][ii]).unwrap();
}
write!(f, " {}\n", 8 - i).unwrap();
}
write!(f, " a b c d e f g h").unwrap();
Ok(()) // TODO: this is probably not a good idea
}
}
fn main() {
let mut board = Board::new();
println!("{}", board);
println!("\ne4\n");
board.process("e4").unwrap();
println!("{}", board);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment