diff --git a/src/game.rs b/src/game.rs index b975b13..8edf851 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,4 +1,5 @@ use core::{ops::Not, sync::atomic::Ordering}; +use embassy_time::{Duration, Instant}; use heapless::Vec; use pico_website::unwrap; use portable_atomic::{AtomicBool, AtomicU32}; @@ -14,14 +15,52 @@ pub struct GameClient { res_buf: Vec, /// State of the board last time it has been sent last_board: u32, - team: Team + team: Team, + end: Option<(Instant, Option)> } impl GameClient { pub fn new(team: Team) -> Self { Self { res_buf: Vec::new(), last_board: 0, - team + team, + end: None + } + } + pub fn is_ended(&self, board: u32) -> (bool, Option) { + if let Some((_, t)) = self.end { + return (true, t); + } + for (t, m) in [(Team::Zero, 1), (Team::One, 2_u32.pow(9))] { + for w in [ + 0b111000000, + 0b000111000, + 0b000000111, + 0b100100100, + 0b010010010, + 0b001001001, + 0b100010001, + 0b001010100 + ] { + if board & (w*m) == (w*m) { + return (true, Some(t)) + } + } + } + // TODO: check for draw + (false, None) + } + pub fn update_end_state(&mut self, board: &mut u32) { + if let Some((i, _)) = self.end { + if i+Duration::from_secs(7) < Instant::now() { + self.end = None; + BOARD.store(0, Ordering::Release); + *board = 0; + } + } else { + if let (true, t) = self.is_ended(*board) { + self.end = Some((Instant::now(), t)); + } } } /// Generate board html @@ -40,11 +79,24 @@ impl GameClient { } unwrap(write!( self.res_buf, - "

Team : {}

\ -
", + "

Team : {}

", self.team.color(), self.team.name() )).await; + match self.end { + Some((_, Some(t))) => unwrap(write!( + self.res_buf, + "

Team {} has won!


", + t.color(), + t.name() + )).await, + Some((_, None)) => unwrap(write!( + self.res_buf, + "

Draw!


", + )).await, + None => {} + } + unwrap(self.res_buf.extend_from_slice(b"
")).await; for c in 0..=8 { let picked_by = if board & 2_u32.pow(c) != 0 { Some(Team::Zero) @@ -61,7 +113,7 @@ impl GameClient { t.color() )).await; } - None => if self.team == turn.into() { + None => if self.team == turn.into() && self.end.is_none() { unwrap(write!( self.res_buf, "", @@ -105,6 +157,7 @@ impl GameClient { BOARD.store(board, Ordering::Release); TURN.store(turn, Ordering::Release); } + self.update_end_state(&mut board); if self.last_board != board { self.last_board = board; (HttpResCode::Ok, "html", self.generate_board_res(board, turn.into(), false).await)