From c9272f5580b00180738eb6dde623ea0abb37f7af Mon Sep 17 00:00:00 2001 From: stale Date: Sat, 30 Apr 2022 17:32:53 -0300 Subject: lazy sync --- src/main.rs | 74 ++++++++++++++++++++++++++++++++++++------------------ src/minesweeper.rs | 19 +++++++------- 2 files changed, 58 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/main.rs b/src/main.rs index 28a10ed..8f556c3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,12 +26,16 @@ use tokio::fs; use tokio_tungstenite::tungstenite::protocol::Message; type Tx = UnboundedSender; -type MovReqTx = mpsc::UnboundedSender; +type MovReqTx = mpsc::UnboundedSender; type PeerMap = Arc>>; type PeerInfo = (PeerMap, Arc::); -// Which will either perform a move, or simply request the current board -type BoardRequest = Option; +#[derive(Debug)] +enum MetaMove { + Move(Move), + Dump, + Reset, +} const PAGE_RELPATH: &str = "./page.html"; const FONT_FILE_FUCKIT: &[u8] = include_bytes!("./VT323-Regular.ttf"); @@ -71,18 +75,30 @@ async fn main() { } // If a move is made, broadcast new board, else just send current board -async fn gameloop(mut move_rx: mpsc::UnboundedReceiver, peers: PeerMap) { - let mut game = Game::new(Board::new(30,10), (30*10)/8); +async fn gameloop(mut move_rx: mpsc::UnboundedReceiver, peers: PeerMap) { + let mut game = Game::new(Board::new(75,35), (75*35)/8); while let Some(req) = move_rx.recv().await { - let m = req; - if let Some(m) = m { - game = game.act(m); - } - let reply = Message::binary(game.board.render(None)); - { - let peers = peers.read().await; - for (_, (tx, _, _, _)) in peers.iter() { - tx.unbounded_send(reply.clone()).unwrap(); + let mut done = game.phase == Phase::Die || game.phase == Phase::Win; + match req { + MetaMove::Move(m) => if !done { game = game.act(m)}, + MetaMove::Dump => (), + MetaMove::Reset => { game = Game::new(Board::new(75,35), (75*35)/8); done = false;}, + } + if !done { + let mut reply = vec![]; + match game.phase { + Phase::Win => { reply.push(Message::text("win")); game.board = game.board.grade(); }, + Phase::Die => { reply.push(Message::text("lose")); game.board = game.board.grade(); }, + _ => (), + } + reply.push(Message::binary(game.board.render())); + { + let peers = peers.read().await; + for (_, (tx, _, _, _)) in peers.iter() { + for r in reply.iter() { + tx.unbounded_send(r.clone()).unwrap(); + } + } } } } @@ -112,25 +128,15 @@ async fn peer_connection(peer_info: PeerInfo, cmd_tx: MovReqTx, raw_stream: TcpS // Insert the write part of this peer to the peer map. let (tx, rx) = unbounded(); - peer_map.write().await.insert(addr, (tx.clone(), peer_seqid, "Dummy".to_string(), (0,0))); let (outgoing, mut incoming) = ws_stream.split(); - { // 1 - Inform the new player its id - tx.unbounded_send(Message::text(format!("id {}", peer_seqid))).unwrap(); - } - - { // 2 - Queue up a current board broadcast - cmd_tx.send(None).unwrap(); - } - let process_incoming = async { while let Some(cmd) = incoming.try_next().await.unwrap() { let cmd = cmd.to_text().unwrap(); - println!("Received a message from {}: {}", addr, cmd); + let mut fields = cmd.split(" ").skip(1); if cmd.starts_with("pos") { - let mut fields = cmd.split(" ").skip(1); let pos = (fields.next().unwrap().parse::().unwrap(), fields.next().unwrap().parse::().unwrap()); let (name, id) = { let mut peers = peer_map.write().await; @@ -144,6 +150,24 @@ async fn peer_connection(peer_info: PeerInfo, cmd_tx: MovReqTx, raw_stream: TcpS peer_tx.unbounded_send(Message::text(format!("pos {} {} {} {}", id, name, pos.0, pos.1))).unwrap(); } } + } else if cmd.starts_with("reveal") { + println!("got {} from {}", cmd, addr); + let pos = (fields.next().unwrap().parse::().unwrap(), fields.next().unwrap().parse::().unwrap()); + cmd_tx.send(MetaMove::Move(Move { t: MoveType::Reveal, pos })).unwrap(); + } else if cmd.starts_with("flag") { + println!("got {} from {}", cmd, addr); + let pos = (fields.next().unwrap().parse::().unwrap(), fields.next().unwrap().parse::().unwrap()); + cmd_tx.send(MetaMove::Move(Move { t: MoveType::ToggleFlag, pos })).unwrap(); + } else if cmd.starts_with("reset") { + println!("got {} from {}", cmd, addr); + cmd_tx.send(MetaMove::Reset).unwrap(); + } else if cmd.starts_with("register") { + let name = fields.next().unwrap(); + { // new scope cuz paranoid bout deadlocks + peer_map.write().await.insert(addr, (tx.clone(), peer_seqid, name.to_string(), (0,0))); + } + tx.unbounded_send(Message::text(format!("id {}", peer_seqid))).unwrap(); + cmd_tx.send(MetaMove::Dump).unwrap(); } } }; diff --git a/src/minesweeper.rs b/src/minesweeper.rs index 8c0dc77..a56758b 100644 --- a/src/minesweeper.rs +++ b/src/minesweeper.rs @@ -148,11 +148,14 @@ impl Board { } } pub fn reveal(mut self, pos: (usize, usize)) -> MoveResult { - if pos.0 > self.width - 1 || pos.1 > self.height - 1 { panic!("OOB reveal"); } + if pos.0 > self.width - 1 || pos.1 > self.height - 1 { + println!("attempted OOB reveal @ {:?}", pos); + return MoveResult { 0: self, 1: false }; + } let off = self.pos_to_off(pos); self.flood_reveal(pos); let c = self.data[off]; - MoveResult { 0: self, 1: (c & !(FLAGGED_BIT | CORRECT_BIT)) == MINE_VAL } // Kaboom + MoveResult { 0: self, 1: (c & !(FLAGGED_BIT | CORRECT_BIT)) == MINE_VAL } } pub fn grade(mut self) -> Board { for i in &mut self.data { @@ -168,25 +171,20 @@ impl Board { MoveResult { 0: self, 1: false } } - pub fn render(&self, cursor: Option<(usize,usize)>) -> Vec { + pub fn render(&self) -> Vec { const CYAN: &[u8] = &[27,b'[',b'3',b'6',b'm']; const YELLOW: &[u8] = &[27,b'[',b'3',b'3',b'm']; const GREEN: &[u8] = &[27,b'[',b'3',b'2',b'm']; const RED: &[u8] = &[27,b'[',b'3',b'1',b'm']; const FG: &[u8] = &[27,b'[',b'3',b'9',b'm']; - const ULINE: &[u8] = &[27,b'[',b'4',b'm']; - const REGULAR: &[u8] = &[27,b'[',b'0',b'm']; let mut ret = vec![27]; let mut cur_clr = FG; for y in 0..self.height { - ret.extend_from_slice(b"
"); for x in 0..self.width { let c = &self.data[self.pos_to_off((x,y))]; - let is_cursor = if let Some(cursor) = cursor { cursor.0 == x && cursor.1 == y } else { false }; - if is_cursor { ret.extend_from_slice(ULINE); } match *c { - 0 => ret.push(b' '), + 0 => ret.extend_from_slice(b" "), _ if *c <= 8 => { if cur_clr != FG { ret.extend_from_slice(FG); cur_clr = FG; } ret.push(b'0' + c); }, _ if (*c & CORRECT_BIT) > 0 => { if cur_clr != GREEN { ret.extend_from_slice(GREEN); cur_clr = GREEN; } ret.push(b'F') }, _ if (*c & FLAGGED_BIT) > 0 => { if cur_clr != YELLOW { ret.extend_from_slice(YELLOW); cur_clr = YELLOW; } ret.push(b'F'); }, @@ -194,8 +192,9 @@ impl Board { _ if *c == MINE_VAL => { if cur_clr != RED { ret.extend_from_slice(RED); cur_clr = RED; } ret.push(b'O'); }, _ => ret.push(b'?'), } - if is_cursor { ret.extend_from_slice(REGULAR); ret.extend_from_slice(cur_clr); } } + ret.extend_from_slice(FG); cur_clr = FG; + ret.extend_from_slice(b"
"); } ret } -- cgit v1.2.3