First commit
This commit is contained in:
commit
fcc5d5727a
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/target
|
||||
**/*.rs.bk
|
113
Cargo.lock
generated
Normal file
113
Cargo.lock
generated
Normal 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
11
Cargo.toml
Normal 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
4
README.md
Normal file
@ -0,0 +1,4 @@
|
||||
Clichess
|
||||
========
|
||||
|
||||
Chess playable with a command line interface.
|
222
src/chessboard.rs
Normal file
222
src/chessboard.rs
Normal 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
17
src/lib.rs
Normal 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
5
src/main.rs
Normal file
@ -0,0 +1,5 @@
|
||||
use clichess;
|
||||
|
||||
fn main() {
|
||||
clichess::play();
|
||||
}
|
Loading…
Reference in New Issue
Block a user