First commit

This commit is contained in:
Artlef 2019-12-14 23:37:46 +01:00
commit fcc5d5727a
7 changed files with 374 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
**/*.rs.bk

113
Cargo.lock generated Normal file
View File

@ -0,0 +1,113 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "arrayvec"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "atty"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "autocfg"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "btoi"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clichess"
version = "0.1.0"
dependencies = [
"colored 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"shakmaty 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "colored"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "num-traits"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "shakmaty"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"btoi 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
"checksum btoi 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e4ced8205e70d9e553d008d53ded735808fa6133597318d48f74fc2bf9861471"
"checksum colored 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "433e7ac7d511768127ed85b0c4947f47a254131e37864b2dc13f52aa32cd37e5"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4"
"checksum shakmaty 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "995611c42b955b8661f1eaf19e83beec36e72ec3ac51ed41a9018a19323c8022"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

11
Cargo.toml Normal file
View File

@ -0,0 +1,11 @@
[package]
name = "clichess"
version = "0.1.0"
authors = ["Artlef <artlef@localhost>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
shakmaty = "0.16.0"
colored = "1.9"

4
README.md Normal file
View File

@ -0,0 +1,4 @@
Clichess
========
Chess playable with a command line interface.

222
src/chessboard.rs Normal file
View File

@ -0,0 +1,222 @@
use colored::Colorize;
use shakmaty::fen;
use shakmaty::fen::Fen;
use shakmaty::fen::ParseFenError;
use shakmaty::san::ParseSanError;
use shakmaty::san::San;
use shakmaty::san::SanError;
use shakmaty::{Chess, Color, IllegalMoveError, Position, PositionError, Setup, Square};
use std::fmt;
use std::fs::File;
use std::io;
use std::io::{ErrorKind, Read, Write};
struct SquareToPrint {
color: String,
background_color: String,
square_representation: String,
}
#[derive(Debug)]
pub enum MoveInputError {
SanSanError(SanError),
SanParseSanError(ParseSanError),
ShakmatyIllegalMoveError(IllegalMoveError),
}
impl From<SanError> for MoveInputError {
fn from(error: SanError) -> Self {
MoveInputError::SanSanError(error)
}
}
impl From<ParseSanError> for MoveInputError {
fn from(error: ParseSanError) -> Self {
MoveInputError::SanParseSanError(error)
}
}
impl From<IllegalMoveError> for MoveInputError {
fn from(error: IllegalMoveError) -> Self {
MoveInputError::ShakmatyIllegalMoveError(error)
}
}
impl fmt::Display for MoveInputError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
MoveInputError::SanSanError(san_error) => san_error.fmt(f),
MoveInputError::SanParseSanError(parse_san_error) => parse_san_error.fmt(f),
MoveInputError::ShakmatyIllegalMoveError(illegal_move_error) => {
illegal_move_error.fmt(f)
}
}
}
}
#[derive(Debug)]
pub enum ReadingFileError {
ReadParseFenError(ParseFenError),
ReadFileError(io::Error),
ReadPositionError(PositionError),
}
impl From<ParseFenError> for ReadingFileError {
fn from(error: ParseFenError) -> Self {
ReadingFileError::ReadParseFenError(error)
}
}
impl From<io::Error> for ReadingFileError {
fn from(error: io::Error) -> Self {
ReadingFileError::ReadFileError(error)
}
}
impl From<PositionError> for ReadingFileError {
fn from(error: PositionError) -> Self {
ReadingFileError::ReadPositionError(error)
}
}
impl fmt::Display for ReadingFileError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ReadingFileError::ReadParseFenError(error) => error.fmt(f),
ReadingFileError::ReadFileError(error) => error.fmt(f),
ReadingFileError::ReadPositionError(error) => error.fmt(f),
}
}
}
pub fn retrieve_chess_from_file_or_create(filename: &str) -> Result<Chess, ReadingFileError> {
match retrieve_chess_from_file(filename) {
Ok(chess) => Ok(chess),
Err(ReadingFileError::ReadFileError(error)) => {
if error.kind() == ErrorKind::NotFound {
create_default_fen_in_file(filename)
} else {
Err(ReadingFileError::ReadFileError(error))
}
}
other_error => other_error,
}
}
pub fn save_chess_position(chess: &Chess, filename: &str) -> std::io::Result<()> {
let mut file = File::create(filename)?;
file.write_all(fen::fen(chess).as_bytes())?;
Ok(())
}
fn retrieve_chess_from_file(filename: &str) -> Result<Chess, ReadingFileError> {
let mut file = File::open(filename)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
let setup: Fen = contents.trim().parse()?;
let position: Chess = setup.position()?;
Ok(position)
}
fn create_default_fen_in_file(filename: &str) -> Result<Chess, ReadingFileError> {
let chess = Chess::default();
save_chess_position(&Chess::default(), filename)?;
Ok(chess)
}
pub fn board_representation(chess: &Chess, side: Color) -> String {
let mut s = String::from("");
let mut rank_numbers;
if side == Color::White {
rank_numbers = 8;
} else {
rank_numbers = 1;
}
for v in board_string_representation(chess, side) {
for square_to_print in v {
s.push_str(&format!(
"{}",
square_to_print
.square_representation
.color(square_to_print.color)
.on_color(square_to_print.background_color)
));
}
s.push_str(&format!("{}\n\r", rank_numbers));
if side == Color::White {
rank_numbers -= 1;
} else {
rank_numbers += 1;
}
}
let mut files = vec!["a", "b", "c", "d", "e", "f", "g", "h"];
if side == Color::Black {
files.reverse();
}
for file in files {
s.push_str(&format!("{} ", file));
}
s
}
fn board_string_representation(chess: &Chess, side: Color) -> Vec<Vec<SquareToPrint>> {
let mut full_board_to_print = Vec::new();
for _ in 0..8 {
full_board_to_print.push(Vec::new())
}
for i in 0..8 {
for j in 0..8 {
let square = Square::new(i + 8 * j);
let square_to_print = SquareToPrint {
color: "black".to_string(),
background_color: if square.is_light() {
"white".to_string()
} else {
"green".to_string()
},
square_representation: get_square_representation(&square, chess),
};
full_board_to_print[j as usize].push(square_to_print);
}
}
if side == Color::White {
full_board_to_print.reverse();
} else {
for j in 0..8 {
full_board_to_print[j as usize].reverse();
}
}
full_board_to_print
}
pub fn try_to_play_move(chess: &Chess, movestr: String) -> Result<Chess, MoveInputError> {
let san: San = movestr.parse()?;
let mv = san.to_move(chess)?;
Ok((*chess).clone().play(&mv)?)
}
fn get_square_representation(square: &Square, chess: &Chess) -> String {
let board = (*chess).board();
match board.piece_at(*square) {
Some(piece) => format!("{} ", piece_char_to_utf8(piece.char())),
None => " ".to_string(),
}
}
fn piece_char_to_utf8(piece: char) -> char {
match piece {
'P' => '♙',
'p' => '♟',
'N' => '♘',
'n' => '♞',
'B' => '♗',
'b' => '♝',
'R' => '♖',
'r' => '♜',
'Q' => '♕',
'q' => '♛',
'K' => '♔',
'k' => '♚',
c => c,
}
}

17
src/lib.rs Normal file
View File

@ -0,0 +1,17 @@
use std::io;
pub mod chessboard;
use shakmaty::{Chess, Color};
pub fn play() {
let mut chess = Chess::default();
loop {
println!("{}", chessboard::board_representation(&chess, Color::White));
let mut input = String::new();
io::stdin().read_line(&mut input).unwrap();
print!("try to play: {}", input);
match chessboard::try_to_play_move(&chess, String::from(input.trim())) {
Ok(played_chess) => chess = played_chess,
Err(e) => println!("Error: {}", e),
};
}
}

5
src/main.rs Normal file
View File

@ -0,0 +1,5 @@
use clichess;
fn main() {
clichess::play();
}