end of game
This commit is contained in:
parent
d949fd80c3
commit
2aabfa52d1
63
src/game.rs
63
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<u8, 4096>,
|
||||
/// State of the board last time it has been sent
|
||||
last_board: u32,
|
||||
team: Team
|
||||
team: Team,
|
||||
end: Option<(Instant, Option<Team>)>
|
||||
}
|
||||
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<Team>) {
|
||||
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,
|
||||
"<h3>Team : <span style=\"color:{}\">{}</span></h3>\
|
||||
<div id=\"grid\">",
|
||||
"<h3>Team : <span style=\"color:{}\">{}</span></h3>",
|
||||
self.team.color(),
|
||||
self.team.name()
|
||||
)).await;
|
||||
match self.end {
|
||||
Some((_, Some(t))) => unwrap(write!(
|
||||
self.res_buf,
|
||||
"<br><h3>Team <span style=\"color:{}\">{}</span> has won!</h3><br>",
|
||||
t.color(),
|
||||
t.name()
|
||||
)).await,
|
||||
Some((_, None)) => unwrap(write!(
|
||||
self.res_buf,
|
||||
"<br><h3>Draw!</h3><br>",
|
||||
)).await,
|
||||
None => {}
|
||||
}
|
||||
unwrap(self.res_buf.extend_from_slice(b"<div id=\"grid\">")).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,
|
||||
"<button class=\"cell\" hx-post=\"/ttt/cell{}\" hx-trigger=\"click\" hx-target=\"#game\" hx-swap=\"innerHTML\"></button>",
|
||||
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user