diff --git a/src/bin/client.rs b/src/bin/client.rs index 98f1deb..b4ba395 100644 --- a/src/bin/client.rs +++ b/src/bin/client.rs @@ -97,26 +97,12 @@ fn main() { .unwrap(); } - client.display_sender.send(DisplayMessage::Help).unwrap(); - let current_position = game_loop(&mut client, &mut stream); - let end_message = match current_position.outcome() { - None => "", - Some(Outcome::Draw) => "Draw game.", - Some(Outcome::Decisive { winner }) => { - if winner == Color::White { - "White has won the game." - } else { - "Black has won the game." - } + loop { + client.display_sender.send(DisplayMessage::Help).unwrap(); + if !game_loop(&mut client, &mut stream) { + break; } - } - .to_string(); - if !end_message.is_empty() { - client - .display_sender - .send(DisplayMessage::Message(end_message)) - .unwrap(); - thread::sleep(time::Duration::from_secs(5)); + client.display_sender.send(DisplayMessage::Clear).unwrap(); } client.display_sender.send(DisplayMessage::Clear).unwrap(); send_request(&client, &mut stream, ClientRequest::Exit); @@ -152,7 +138,8 @@ fn login(client: &mut Client, stream: &mut UnixStream) -> LoginResult { LoginResult::Success } -fn game_loop(client: &mut Client, stream: &mut UnixStream) -> Chess { +fn game_loop(client: &mut Client, stream: &mut UnixStream) -> bool { + let mut replay = false; let mut current_position = fetch_initial_chess_position(client, stream); loop { @@ -223,7 +210,55 @@ fn game_loop(client: &mut Client, stream: &mut UnixStream) -> Chess { }; } } - current_position + let end_message = match current_position.outcome() { + None => "", + Some(Outcome::Draw) => "Draw game.", + Some(Outcome::Decisive { winner }) => { + if winner == Color::White { + "White has won the game." + } else { + "Black has won the game." + } + } + } + .to_string(); + if !end_message.is_empty() { + //accept input + if client.player.role != UserRole::Spectator { + client + .display_sender + .send(DisplayMessage::Message(format!( + "{}\n\rPress enter to rematch.", + end_message + ))) + .unwrap(); + let mut is_player_turn = client.is_player_turn.lock().unwrap(); + *is_player_turn = true; + } else { + client + .display_sender + .send(DisplayMessage::Message(format!("{}", end_message))) + .unwrap(); + thread::sleep(time::Duration::from_secs(5)); + return false; + } + let buffer = client.keyboard_input_recv.recv().unwrap(); + + if buffer == EXIT_MSG { + client.waiting_server_msg_receiver.recv().unwrap(); + } else { + replay = true; + client + .display_sender + .send(DisplayMessage::Message(format!( + "{}\n\rWaiting for your opponent to restart...", + end_message + ))) + .unwrap(); + send_request(client, stream, ClientRequest::Reset); + } + } + replay } fn send_request(client: &Client, stream: &mut UnixStream, request: ClientRequest) -> String { diff --git a/src/bin/server.rs b/src/bin/server.rs index bd8c574..81260b9 100644 --- a/src/bin/server.rs +++ b/src/bin/server.rs @@ -19,6 +19,7 @@ struct Server { cvar: Arc<(Mutex, Condvar)>, opponent_name: Arc>>, last_move: Arc>>, + confirm_reset: Arc<(Mutex, Condvar)>, } fn main() { @@ -31,6 +32,9 @@ fn main() { let listener = UnixListener::bind("/tmp/clichess.socket").unwrap(); + //boolean shared amongst all server instances + let confirm_reset = Arc::new((Mutex::new(false), Condvar::new())); + // accept connections and process them, spawning a new thread for each one for stream in listener.incoming() { match stream { @@ -48,6 +52,7 @@ fn main() { cvar: condvar_pair, opponent_name: Arc::new(Mutex::new(Option::None)), last_move: Arc::new(Mutex::new(Option::None)), + confirm_reset: confirm_reset.clone(), }; /* connection succeeded */ thread::spawn(move || handle_player(stream, &mut server, others_serv_msg_sender)); @@ -94,6 +99,7 @@ fn handle_player( } } Ok(ClientRequest::Play(movestr)) => play(&mut stream, server, movestr), + Ok(ClientRequest::Reset) => reset(&mut stream, server), Ok(ClientRequest::Exit) => { send_ok(&mut stream); break; @@ -291,6 +297,30 @@ fn play(stream: &mut UnixStream, server: &Server, movestr: String) { .unwrap(); } +fn reset(stream: &mut UnixStream, server: &Server) { + //wait for the other server. + println!("client {} wants to restart game.", server.id); + let (lock, cvar) = &*server.confirm_reset; + let mut reset_confirmed = lock.lock().unwrap(); + if *reset_confirmed { + println!("restarting game."); + { + let mut chess = server.chess_position.lock().unwrap(); + *chess = Chess::default(); + } + *reset_confirmed = false; + cvar.notify_one(); + } else { + //wait for other server + println!("client {} is waiting.", server.id); + *reset_confirmed = true; + while *reset_confirmed { + reset_confirmed = cvar.wait(reset_confirmed).unwrap(); + } + } + send_ok(stream); +} + fn send_ok(stream: &mut UnixStream) { clichess::write_to_stream(stream, String::from("OK")).unwrap(); } diff --git a/src/lib.rs b/src/lib.rs index c19c64c..86feb14 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,6 +47,7 @@ pub enum ClientRequest { GetGameInfo, WaitForNextMove, Play(String), + Reset, Exit, }