summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs74
-rw-r--r--src/minesweeper.rs19
2 files changed, 58 insertions, 35 deletions
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<Message>;
-type MovReqTx = mpsc::UnboundedSender<BoardRequest>;
+type MovReqTx = mpsc::UnboundedSender<MetaMove>;
type PeerMap = Arc<RwLock<HashMap<SocketAddr, (Tx, usize, String, (usize, usize))>>>;
type PeerInfo = (PeerMap, Arc::<AtomicUsize>);
-// Which will either perform a move, or simply request the current board
-type BoardRequest = Option<Move>;
+#[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<BoardRequest>, peers: PeerMap) {
- let mut game = Game::new(Board::new(30,10), (30*10)/8);
+async fn gameloop(mut move_rx: mpsc::UnboundedReceiver<MetaMove>, 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::<usize>().unwrap(), fields.next().unwrap().parse::<usize>().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::<usize>().unwrap(), fields.next().unwrap().parse::<usize>().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::<usize>().unwrap(), fields.next().unwrap().parse::<usize>().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<u8> {
+ pub fn render(&self) -> Vec<u8> {
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"<br>");
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"&nbsp"),
_ 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"<br>");
}
ret
}