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 core::{ops::Not, sync::atomic::Ordering};
|
||||||
|
use embassy_time::{Duration, Instant};
|
||||||
use heapless::Vec;
|
use heapless::Vec;
|
||||||
use pico_website::unwrap;
|
use pico_website::unwrap;
|
||||||
use portable_atomic::{AtomicBool, AtomicU32};
|
use portable_atomic::{AtomicBool, AtomicU32};
|
||||||
@ -14,14 +15,52 @@ pub struct GameClient {
|
|||||||
res_buf: Vec<u8, 4096>,
|
res_buf: Vec<u8, 4096>,
|
||||||
/// State of the board last time it has been sent
|
/// State of the board last time it has been sent
|
||||||
last_board: u32,
|
last_board: u32,
|
||||||
team: Team
|
team: Team,
|
||||||
|
end: Option<(Instant, Option<Team>)>
|
||||||
}
|
}
|
||||||
impl GameClient {
|
impl GameClient {
|
||||||
pub fn new(team: Team) -> Self {
|
pub fn new(team: Team) -> Self {
|
||||||
Self {
|
Self {
|
||||||
res_buf: Vec::new(),
|
res_buf: Vec::new(),
|
||||||
last_board: 0,
|
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
|
/// Generate board html
|
||||||
@ -40,11 +79,24 @@ impl GameClient {
|
|||||||
}
|
}
|
||||||
unwrap(write!(
|
unwrap(write!(
|
||||||
self.res_buf,
|
self.res_buf,
|
||||||
"<h3>Team : <span style=\"color:{}\">{}</span></h3>\
|
"<h3>Team : <span style=\"color:{}\">{}</span></h3>",
|
||||||
<div id=\"grid\">",
|
|
||||||
self.team.color(),
|
self.team.color(),
|
||||||
self.team.name()
|
self.team.name()
|
||||||
)).await;
|
)).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 {
|
for c in 0..=8 {
|
||||||
let picked_by = if board & 2_u32.pow(c) != 0 {
|
let picked_by = if board & 2_u32.pow(c) != 0 {
|
||||||
Some(Team::Zero)
|
Some(Team::Zero)
|
||||||
@ -61,7 +113,7 @@ impl GameClient {
|
|||||||
t.color()
|
t.color()
|
||||||
)).await;
|
)).await;
|
||||||
}
|
}
|
||||||
None => if self.team == turn.into() {
|
None => if self.team == turn.into() && self.end.is_none() {
|
||||||
unwrap(write!(
|
unwrap(write!(
|
||||||
self.res_buf,
|
self.res_buf,
|
||||||
"<button class=\"cell\" hx-post=\"/ttt/cell{}\" hx-trigger=\"click\" hx-target=\"#game\" hx-swap=\"innerHTML\"></button>",
|
"<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);
|
BOARD.store(board, Ordering::Release);
|
||||||
TURN.store(turn, Ordering::Release);
|
TURN.store(turn, Ordering::Release);
|
||||||
}
|
}
|
||||||
|
self.update_end_state(&mut board);
|
||||||
if self.last_board != board {
|
if self.last_board != board {
|
||||||
self.last_board = board;
|
self.last_board = board;
|
||||||
(HttpResCode::Ok, "html", self.generate_board_res(board, turn.into(), false).await)
|
(HttpResCode::Ok, "html", self.generate_board_res(board, turn.into(), false).await)
|
||||||
|
Loading…
Reference in New Issue
Block a user