#[derive(Debug)]
pub struct PieceRecord {
pos : Pos,
- p : Box<dyn Piece>,
+ p : Rc<dyn Piece>,
held : Option<PlayerRef>,
}
#[derive(Debug)]
pub struct GameState {
- pub pieces : Vec<PieceRecord>,
- pub players : Vec<PlayerRecord>,
+ pub pieces : Vec<Rc<PieceRecord>>,
+ pub players : Vec<Rc<PlayerRecord>>,
}
-type MsgPiece = SvgData;
-
pub struct GameRef (InstanceGuard);
impl Deref for GameRef {
type Output = GamState;
fn deref(&self) -> &GameState { self.0.read() }
}
-
-#[derive(Serialize)]
-enum MsgUpdate {
- MsgNoUpdate,
- MsgPieceInsert(usize, MsgPiece),
- MsgPieceDelete(usize),
- MsgPieceUpdate(usize, MsgPiece),
+enum GameUpdate {
+ NoUpdate,
+ PieceInsert(usize, PieceRecord),
+ PieceDelete(usize, PieceRecord),
+ PieceUpdate(usize, PieceRecord, PieceRecord),
}
+struct LogMessage (HtmlString);
+
impl PieceRecord {
fn msg(&self) -> MsgPiece { self.p.svg(self) }
}
impl GameRef {
- fn piece_insert(&mut self, i : usize, p : PieceRecord) {
- self.0.update(|d| {
- d.pieces.insert(i, p);
- MsgPieceInsert(i, p.msg())
+ fn piece_insert(&mut self, i : usize,
+ p : Rc<PieceRecord>, msg : LogMessage) {
+ self.0.action(|g| {
+ g.pieces.insert(i, p);
+ (msg, MsgPieceInsert(i, p))
);
- }
- fn piece_delete(&mut self, i : usize) {
- self.0.update(|d| {
- d.pieces.remove(i, p);
- MsgPieceDelete(i)
+ fn piece_delete(&mut self, i : usize, msg : LogMessage) {
+ self.0.action(|g| {
+ let old = g.pieces.remove(i, p);
+ (msg, MsgPieceDelete(i, old))
}
}
fn piece_update(&mut self, i : usize, p : PieceRecord) {
- self.0.update(|d| {
- d.pieces[i] = p,
- MsgPieceUpdate(i, p.msg()),
+ self.0.action(|g| {
+ let new = p.clone();
+ let old = replace(g.pieces[i], p);
+ (msg, MsgPieceUpdate(i, old, new))
}
}
}
struct Game {
gen : Counter,
gs : GameState,
- recent : VecDeque<MsgUpdate>,
+ log : VecDeque<LogEntry>,
+}
+
+struct LogEntry {
+ game : Vec<GameUpdate>,
+ msgs : Vec<LogMessage>,
+}
+
+impl From<(LogMessage, GameUpdate)> for LogEntry {
+ fn from((msg, gu) : (LogMessage, GameUpdate)) -> LogEntry {
+ LogEntry { game : vec![lm], msgs: vec![msg] }
+ }
}
impl Instance {
fn read(&self) -> &GameState { &self.g.deref().gs }
fn iname(&self) -> &str { self.iname }
- fn<F> update(&mut self, f : F)
- where F : FnOnce(&mut GameState) -> MsgUpdate {
+ fn<F,L> action(&mut self, f : F)
+ where F : FnOnce(&mut GameState) -> L
+ L : Into<LogEntry>
+ {
let msg = f(&mut self.gs.g),
if let MsgNoUpdate = msg { return }
self.gs.gen += 1,
if self.gw.recent.len() >= RECENT_BUFFER { self.pop_front() }
- self.g.recent.push_back(msg);
+ self.g.evenglog.push_back(msg);
self.g_notify.notify_all();
}
}