2 clients can play and see each other moves.
This commit is contained in:
parent
ae632df144
commit
0cff0e13da
80
Cargo.lock
generated
80
Cargo.lock
generated
@ -37,6 +37,8 @@ name = "clichess"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"colored 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"colored 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"shakmaty 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"shakmaty 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -50,6 +52,11 @@ dependencies = [
|
|||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@ -68,6 +75,55 @@ dependencies = [
|
|||||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.104"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.104"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shakmaty"
|
name = "shakmaty"
|
||||||
version = "0.16.0"
|
version = "0.16.0"
|
||||||
@ -78,6 +134,21 @@ dependencies = [
|
|||||||
"btoi 0.4.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 = "syn"
|
||||||
|
version = "1.0.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.8"
|
version = "0.3.8"
|
||||||
@ -104,10 +175,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
"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 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 colored 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "433e7ac7d511768127ed85b0c4947f47a254131e37864b2dc13f52aa32cd37e5"
|
||||||
|
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
|
||||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
"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 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 num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4"
|
||||||
|
"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27"
|
||||||
|
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
|
||||||
|
"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
|
||||||
|
"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
|
||||||
|
"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
|
||||||
|
"checksum serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)" = "48c575e0cc52bdd09b47f330f646cf59afc586e9c4e3ccd6fc1f625b8ea1dad7"
|
||||||
"checksum shakmaty 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "995611c42b955b8661f1eaf19e83beec36e72ec3ac51ed41a9018a19323c8022"
|
"checksum shakmaty 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "995611c42b955b8661f1eaf19e83beec36e72ec3ac51ed41a9018a19323c8022"
|
||||||
|
"checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238"
|
||||||
|
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||||
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
"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-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"
|
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
@ -9,3 +9,5 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
shakmaty = "0.16.0"
|
shakmaty = "0.16.0"
|
||||||
colored = "1.9"
|
colored = "1.9"
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = "1.0"
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
|
use clichess::UserRole;
|
||||||
|
use shakmaty::fen::Fen;
|
||||||
|
use shakmaty::{Chess, Color, Setup};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::io::{BufRead, BufReader};
|
||||||
use std::os::unix::net::UnixStream;
|
use std::os::unix::net::UnixStream;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@ -10,10 +14,58 @@ fn main() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
let input = clichess::read_from_stream(&stream);
|
let (client, chess) = get_connection_info_from_stream(&stream);
|
||||||
println!("{}", input);
|
//First prompt when connecting to the server
|
||||||
|
println!(
|
||||||
|
"Hello, anonymous !\n\r You're playing with the {} pieces",
|
||||||
|
client.role.to_string()
|
||||||
|
);
|
||||||
|
//then we get the initial role of the connected client.
|
||||||
|
let mut current_position = chess;
|
||||||
|
loop {
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
clichess::board_representation(¤t_position, clichess::to_color(client.side))
|
||||||
|
);
|
||||||
|
if clichess::is_player_turn(client, current_position.turn()) {
|
||||||
|
//it's the user turn, taking user input
|
||||||
io::stdin().read_line(&mut buffer).unwrap();
|
io::stdin().read_line(&mut buffer).unwrap();
|
||||||
|
println!("trying to play {}", buffer);
|
||||||
clichess::write_to_stream(&mut stream, String::from(buffer.trim()));
|
clichess::write_to_stream(&mut stream, String::from(buffer.trim()));
|
||||||
let response = clichess::read_from_stream(&stream);
|
buffer.clear();
|
||||||
println!("{}", response);
|
}
|
||||||
|
//update position after playing.
|
||||||
|
current_position = get_current_position(&stream);
|
||||||
|
|
||||||
|
//come back at the beginning of the loop to wait for incoming moves.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//wait for next position from server, then return the current board.
|
||||||
|
fn get_current_position(stream: &UnixStream) -> Chess {
|
||||||
|
let response = clichess::read_line_from_stream(&stream);
|
||||||
|
parse_position(&response)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_position(string: &str) -> Chess {
|
||||||
|
let setup: Fen = string.trim().parse().expect("Invalid message from server.");
|
||||||
|
let position: Chess = setup.position().expect("Invalid message from server.");
|
||||||
|
position
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_connection_info_from_stream(stream: &UnixStream) -> (clichess::Client, Chess) {
|
||||||
|
println!("Read lines from stream...");
|
||||||
|
let mut buf = String::new();
|
||||||
|
let mut reader = BufReader::new(stream);
|
||||||
|
//first, client as json.
|
||||||
|
reader
|
||||||
|
.read_line(&mut buf)
|
||||||
|
.expect("Server closed connection.");
|
||||||
|
let client = serde_json::from_str(&(buf.trim())).unwrap();
|
||||||
|
buf.clear();
|
||||||
|
reader
|
||||||
|
.read_line(&mut buf)
|
||||||
|
.expect("Server closed connection.");
|
||||||
|
let chess = parse_position(buf.trim());
|
||||||
|
(client, chess)
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,25 @@
|
|||||||
use clichess;
|
use clichess;
|
||||||
use shakmaty::{Chess, Color};
|
use clichess::Client;
|
||||||
|
use clichess::UserRole;
|
||||||
|
use shakmaty::{fen, Chess, Color, Setup};
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::prelude::*;
|
|
||||||
use std::os::unix::net::{UnixListener, UnixStream};
|
use std::os::unix::net::{UnixListener, UnixStream};
|
||||||
use std::str;
|
use std::sync::{Arc, Condvar, Mutex};
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
struct Server {
|
struct Server {
|
||||||
id: usize,
|
id: usize,
|
||||||
chess_position: Arc<Mutex<Chess>>,
|
chess_position: Arc<Mutex<Chess>>,
|
||||||
|
clients: Arc<Mutex<HashMap<usize, (Client, Arc<(Mutex<String>, Condvar)>)>>>,
|
||||||
|
receiving_buffer: Arc<(Mutex<String>, Condvar)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let chess = Arc::new(Mutex::new(Chess::default()));
|
let chess = Arc::new(Mutex::new(Chess::default()));
|
||||||
|
let clients = Arc::new(Mutex::new(HashMap::new()));
|
||||||
let mut counter = 0;
|
let mut counter = 0;
|
||||||
fs::remove_file("/tmp/clichess.socket");
|
fs::remove_file("/tmp/clichess.socket");
|
||||||
|
|
||||||
@ -23,12 +29,13 @@ fn main() {
|
|||||||
for stream in listener.incoming() {
|
for stream in listener.incoming() {
|
||||||
match stream {
|
match stream {
|
||||||
Ok(stream) => {
|
Ok(stream) => {
|
||||||
let chess = Arc::clone(&chess);
|
|
||||||
/* connection succeeded */
|
|
||||||
let server = Server {
|
let server = Server {
|
||||||
id: counter,
|
id: counter,
|
||||||
chess_position: chess,
|
chess_position: chess.clone(),
|
||||||
|
clients: clients.clone(),
|
||||||
|
receiving_buffer: Arc::new((Mutex::new(String::new()), Condvar::new())),
|
||||||
};
|
};
|
||||||
|
/* connection succeeded */
|
||||||
thread::spawn(|| handle_client(stream, server));
|
thread::spawn(|| handle_client(stream, server));
|
||||||
counter += 1;
|
counter += 1;
|
||||||
}
|
}
|
||||||
@ -41,24 +48,81 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_client(mut stream: UnixStream, server: Server) {
|
fn handle_client(mut stream: UnixStream, server: Server) {
|
||||||
|
//create client
|
||||||
|
let client = create_client(&server);
|
||||||
|
//send its information to the client
|
||||||
|
println!(
|
||||||
|
"server {}, send first information to the client...",
|
||||||
|
server.id
|
||||||
|
);
|
||||||
|
clichess::write_to_stream(&mut stream, serde_json::to_string(&client).unwrap());
|
||||||
|
println!("server {}, information to the client sent", server.id);
|
||||||
|
let mut player_turn: Color;
|
||||||
|
//send current position to the client
|
||||||
|
println!(
|
||||||
|
"server {}, send current position to the client...",
|
||||||
|
server.id
|
||||||
|
);
|
||||||
{
|
{
|
||||||
let chess = server.chess_position.lock().unwrap();
|
let chess = server.chess_position.lock().unwrap();
|
||||||
clichess::write_to_stream(
|
player_turn = chess.turn();
|
||||||
&mut stream,
|
clichess::write_to_stream(&mut stream, fen::fen(&*chess));
|
||||||
clichess::board_representation(&chess, Color::White),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
println!("server {}, current position to the client sent", server.id);
|
||||||
|
loop {
|
||||||
|
if clichess::is_player_turn(client, player_turn) {
|
||||||
//let go of the lock while waiting for user input.
|
//let go of the lock while waiting for user input.
|
||||||
let input = clichess::read_from_stream(&stream);
|
println!("server {}, waiting for client move..", server.id);
|
||||||
|
let input = clichess::read_line_from_stream(&stream);
|
||||||
{
|
{
|
||||||
let mut chess = server.chess_position.lock().unwrap();
|
let mut chess = server.chess_position.lock().unwrap();
|
||||||
|
let clients = server.clients.lock().unwrap();
|
||||||
|
println!("User tried to play {}", input);
|
||||||
match clichess::try_to_play_move(&chess, input) {
|
match clichess::try_to_play_move(&chess, input) {
|
||||||
Ok(played_chess) => *chess = played_chess,
|
Ok(played_chess) => *chess = played_chess,
|
||||||
Err(e) => println!("Error: {}", e),
|
Err(e) => println!("Error: {}", e),
|
||||||
};
|
};
|
||||||
clichess::write_to_stream(
|
let chessfen = fen::fen(&*chess);
|
||||||
&mut stream,
|
for (id, (_, cvar_buffer)) in clients.iter() {
|
||||||
clichess::board_representation(&chess, Color::White),
|
if server.id != *id {
|
||||||
);
|
cvar_buffer.0.lock().unwrap().push_str(&chessfen);
|
||||||
|
cvar_buffer.1.notify_one();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
clichess::write_to_stream(&mut stream, chessfen);
|
||||||
|
player_turn = chess.turn();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
{
|
||||||
|
let (buffer_mutex, cvar) = &*server.receiving_buffer;
|
||||||
|
let mut buffer = buffer_mutex.lock().unwrap();
|
||||||
|
println!("server id: {}, waiting for move to send...", server.id);
|
||||||
|
while buffer.is_empty() {
|
||||||
|
buffer = cvar.wait(buffer).unwrap();
|
||||||
|
}
|
||||||
|
println!("server id: {}, sending {}", server.id, buffer);
|
||||||
|
clichess::write_to_stream(&mut stream, buffer.clone());
|
||||||
|
buffer.clear();
|
||||||
|
let chess = server.chess_position.lock().unwrap();
|
||||||
|
player_turn = chess.turn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_client(server: &Server) -> Client {
|
||||||
|
println!("Creating client {}...", server.id);
|
||||||
|
let role = match server.id {
|
||||||
|
0 => UserRole::White,
|
||||||
|
1 => UserRole::Black,
|
||||||
|
_ => UserRole::Spectator,
|
||||||
|
};
|
||||||
|
let mut clients = server.clients.lock().unwrap();
|
||||||
|
let client = Client {
|
||||||
|
role,
|
||||||
|
side: clichess::from_color(clichess::get_default_side(role)),
|
||||||
|
};
|
||||||
|
clients.insert(server.id, (client, server.receiving_buffer.clone()));
|
||||||
|
println!("Created client {}", server.id);
|
||||||
|
client
|
||||||
|
}
|
||||||
|
160
src/lib.rs
160
src/lib.rs
@ -1,18 +1,48 @@
|
|||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use shakmaty::fen;
|
use serde::{Deserialize, Serialize};
|
||||||
use shakmaty::fen::Fen;
|
|
||||||
use shakmaty::fen::ParseFenError;
|
|
||||||
use shakmaty::san::ParseSanError;
|
use shakmaty::san::ParseSanError;
|
||||||
use shakmaty::san::San;
|
use shakmaty::san::San;
|
||||||
use shakmaty::san::SanError;
|
use shakmaty::san::SanError;
|
||||||
use shakmaty::{Chess, Color, IllegalMoveError, Position, PositionError, Setup, Square};
|
use shakmaty::{Chess, Color, IllegalMoveError, Position, Setup, Square};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fs::File;
|
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::io::{self, BufReader, ErrorKind, Read, Write};
|
use std::io::{BufReader, Write};
|
||||||
use std::os::unix::net::UnixStream;
|
use std::os::unix::net::UnixStream;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Client {
|
||||||
|
pub role: UserRole,
|
||||||
|
pub side: BoardSide,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Copy, Clone, Serialize, Deserialize)]
|
||||||
|
pub enum BoardSide {
|
||||||
|
White,
|
||||||
|
Black,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Copy, Clone, Serialize, Deserialize)]
|
||||||
|
pub enum UserRole {
|
||||||
|
White,
|
||||||
|
Black,
|
||||||
|
Spectator,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for UserRole {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
match self {
|
||||||
|
UserRole::White => "white",
|
||||||
|
UserRole::Black => "black",
|
||||||
|
UserRole::Spectator => "spectator",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct SquareToPrint {
|
struct SquareToPrint {
|
||||||
color: String,
|
color: String,
|
||||||
background_color: String,
|
background_color: String,
|
||||||
@ -56,76 +86,6 @@ impl fmt::Display for MoveInputError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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 {
|
pub fn board_representation(chess: &Chess, side: Color) -> String {
|
||||||
let mut s = String::from("");
|
let mut s = String::from("");
|
||||||
let mut rank_numbers;
|
let mut rank_numbers;
|
||||||
@ -224,23 +184,43 @@ fn piece_char_to_utf8(piece: char) -> char {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const DELIMITER_CHAR: u8 = 4;
|
pub fn read_line_from_stream(stream: &UnixStream) -> String {
|
||||||
|
let mut result = String::new();
|
||||||
pub fn read_from_stream(stream: &UnixStream) -> String {
|
|
||||||
let mut result = Vec::new();
|
|
||||||
let mut reader = BufReader::new(stream);
|
let mut reader = BufReader::new(stream);
|
||||||
|
|
||||||
reader.read_until(DELIMITER_CHAR, &mut result).unwrap();
|
reader.read_line(&mut result).unwrap();
|
||||||
if let Some((_, msg)) = result.split_last() {
|
String::from(result.trim_end())
|
||||||
String::from(str::from_utf8(msg).unwrap())
|
|
||||||
} else {
|
|
||||||
String::new()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_to_stream(stream: &mut UnixStream, msg: String) {
|
pub fn write_to_stream(stream: &mut UnixStream, msg: String) {
|
||||||
let mut to_send = Vec::new();
|
stream.write_all(&(msg + "\n").as_bytes()).unwrap();
|
||||||
to_send.append(&mut msg.into_bytes());
|
}
|
||||||
to_send.push(DELIMITER_CHAR);
|
|
||||||
stream.write_all(&to_send).unwrap();
|
pub fn get_default_side(role: UserRole) -> Color {
|
||||||
|
if role == UserRole::Black {
|
||||||
|
Color::Black
|
||||||
|
} else {
|
||||||
|
Color::White
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_color(board_side: BoardSide) -> Color {
|
||||||
|
if board_side == BoardSide::White {
|
||||||
|
Color::White
|
||||||
|
} else {
|
||||||
|
Color::Black
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_color(color: Color) -> BoardSide {
|
||||||
|
if color == Color::White {
|
||||||
|
BoardSide::White
|
||||||
|
} else {
|
||||||
|
BoardSide::Black
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_player_turn(client: Client, playing_side: Color) -> bool {
|
||||||
|
(playing_side == Color::White && client.role == UserRole::White)
|
||||||
|
|| (playing_side == Color::Black && client.role == UserRole::Black)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user