diff --git a/server/src/manager/data.rs b/server/src/manager/data.rs
index a2a8487..3435fd1 100644
--- a/server/src/manager/data.rs
+++ b/server/src/manager/data.rs
@@ -597,6 +597,9 @@ fn generate_gamestate(app:&App, session:&Session) -> protocol::PacketGameStateRe
response.player = 2;
response.turn = session.game.turn;
+ if session.game.history.len() > 0 {
+ response.play = session.game.history[session.game.history.len() - 1];
+ }
// Get Dawn handle
if let Some(id) = session.p_dawn.user {
diff --git a/server/src/protocol/packet/game_state.rs b/server/src/protocol/packet/game_state.rs
index b4ae755..3cf1c0a 100644
--- a/server/src/protocol/packet/game_state.rs
+++ b/server/src/protocol/packet/game_state.rs
@@ -3,7 +3,7 @@ use crate::{
util::pack::pack_u16,
};
-use game::game::Pool;
+use game::{game::Pool, history::Play};
use super::Packet;
@@ -65,6 +65,7 @@ pub struct PacketGameStateResponse {
pub status:u16,
pub turn:u16,
pub player:u8,
+ pub play:Play,
pub dawn_handle:String,
pub dusk_handle:String,
pub dawn_pool:Pool,
@@ -78,6 +79,7 @@ impl PacketGameStateResponse {
status:0,
turn:0,
player:0,
+ play:Play::new(),
dawn_handle:String::new(),
dusk_handle:String::new(),
dawn_pool:Pool::default(),
@@ -94,6 +96,11 @@ impl Packet for PacketGameStateResponse {
let mut flags = 0u16;
flags |= self.player as u16;
+ let mut play = 0;
+ play |= self.play.source as u16;
+ play |= (self.play.from as u16) << 1;
+ play |= (self.play.to as u16) << 7;
+
let mut piece_bytes = Vec::new();
for piece in &self.pieces {
let piece_data: u16 = piece.valid as u16
@@ -124,6 +131,7 @@ impl Packet for PacketGameStateResponse {
[
pack_u16(self.status),
pack_u16(flags),
+ pack_u16(play),
pack_u16(self.turn),
pack_u16(self.dawn_handle.len() as u16),
self.dawn_handle.as_bytes().to_vec(),
diff --git a/server/src/system/filesystem/mod.rs b/server/src/system/filesystem/mod.rs
index c73f0dd..5f13fc9 100644
--- a/server/src/system/filesystem/mod.rs
+++ b/server/src/system/filesystem/mod.rs
@@ -271,9 +271,7 @@ impl FileSystem {
to:((data >> 7) & 0x3F) as u8,
});
}
-
- println!("len {}", result.len());
-
+
Ok(result)
} else { Err(()) }
}
diff --git a/www/.html b/www/.html
index 88845bf..a52b463 100644
--- a/www/.html
+++ b/www/.html
@@ -5,7 +5,7 @@
-
+
diff --git a/www/js/interface.js b/www/js/interface.js
index 3ee09db..abd268f 100644
--- a/www/js/interface.js
+++ b/www/js/interface.js
@@ -189,13 +189,24 @@ const INTERFACE = {
}
if(is_valid) {
- let move_data = INTERFACE_DATA.select.source | (INTERFACE_DATA.select.tile << 1) | (INTERFACE_DATA.hover.tile << 7);
- MESSAGE_COMPOSE([
- PACK.u16(OpCode.GamePlay),
- PACK.u16(0),
- PACK.u16(GAME_DATA.turn),
- PACK.u16(move_data),
- ]);
+ if(INTERFACE_DATA.online) {
+ let move_data = INTERFACE_DATA.select.source | (INTERFACE_DATA.select.tile << 1) | (INTERFACE_DATA.hover.tile << 7);
+ MESSAGE_COMPOSE([
+ PACK.u16(OpCode.GamePlay),
+ PACK.u16(0),
+ PACK.u16(GAME_DATA.turn),
+ PACK.u16(move_data),
+ ]);
+ } else {
+ let play = new GAME.Play(INTERFACE_DATA.select.source, INTERFACE_DATA.select.tile, INTERFACE_DATA.hover.tile);
+ INTERFACE_DATA.play = play;
+ GAME_DATA.process(play);
+
+ INTERFACE_DATA.player = +(!INTERFACE_DATA.player);
+ INTERFACE_DATA.rotate = +(!INTERFACE_DATA.rotate);
+
+ INTERFACE.draw();
+ }
INTERFACE_DATA.select = null;
} else {
INTERFACE_DATA.select = null;
@@ -339,7 +350,9 @@ const INTERFACE = {
case 1: ctx.fillStyle = INTERFACE.Color.TileLight; break;
case 2: ctx.fillStyle = INTERFACE.Color.TileDark; break;
}
- if(GAME_DATA.state.check && piece !== null && piece.piece == GAME.Const.PieceId.Omen && piece.player == (GAME_DATA.turn & 1)) {
+ if(GAME_DATA.turn > 0 && (INTERFACE_DATA.play.to == i || (INTERFACE_DATA.play.source == 0 && INTERFACE_DATA.play.from == i))) {
+ ctx.fillStyle = INTERFACE.Color.HintPlay;
+ } else if(GAME_DATA.state.check && piece !== null && piece.piece == GAME.Const.PieceId.Omen && piece.player == (GAME_DATA.turn & 1)) {
ctx.fillStyle = INTERFACE.Color.HintCheck;
}
switch(tile_state) {
@@ -657,16 +670,25 @@ const INTERFACE = {
},
},
- init(data) {
+ init(data, online) {
GAME.init();
+ let token = null;
+ let player = 0;
+ if(data !== null) {
+ token = data.token;
+ player = data.mode;
+ }
+
INTERFACE_DATA = {
- token:data.token,
+ online: online,
+
+ token: token,
canvas: document.getElementById("game"),
context: null,
- player: data.mode,
+ player: player,
rotate: 0,
hover: null,
@@ -674,6 +696,7 @@ const INTERFACE = {
handles: [null, null],
board_state: [ ],
+ play: null,
Ui: {
scale: 0,
@@ -696,17 +719,23 @@ const INTERFACE = {
canvas.addEventListener("mousedown", INTERFACE.click);
window.addEventListener("resize", INTERFACE.draw);
- MESSAGE_COMPOSE([
- PACK.u16(OpCode.GameState),
- INTERFACE_DATA.token,
- ]);
+ if(INTERFACE_DATA.online) {
+ MESSAGE_COMPOSE([
+ PACK.u16(OpCode.GameState),
+ INTERFACE_DATA.token,
+ ]);
+ } else {
+ INTERFACE.draw();
+ }
}
},
uninit() {
- MESSAGE_COMPOSE([
- PACK.u16(OpCode.SessionLeave),
- ]);
+ if(INTERFACE_DATA.online) {
+ MESSAGE_COMPOSE([
+ PACK.u16(OpCode.SessionLeave),
+ ]);
+ }
if(INTERFACE_DATA !== null) {
MAIN.removeChild(INTERFACE_DATA.canvas);
@@ -717,9 +746,9 @@ const INTERFACE = {
message(code, data) {
switch(code) {
case OpCode.GameState: {
- console.log(data.player);
INTERFACE_DATA.player = data.player;
GAME_DATA.turn = data.turn;
+ INTERFACE_DATA.play = data.play;
if(data.dawn.length > 0) { INTERFACE_DATA.handles[0] = data.dawn; }
if(data.dusk.length > 0) { INTERFACE_DATA.handles[1] = data.dusk; }
@@ -747,7 +776,8 @@ const INTERFACE = {
case OpCode.GamePlay: {
if(data.status == Status.Ok && data.turn == GAME_DATA.turn) {
- GAME_DATA.process(data.move);
+ INTERFACE_DATA.play = data.play;
+ GAME_DATA.process(data.play);
INTERFACE.draw();
}
} break;
diff --git a/www/js/scene.js b/www/js/scene.js
index c527828..9141f1d 100644
--- a/www/js/scene.js
+++ b/www/js/scene.js
@@ -488,7 +488,7 @@ const SCENES = {
canvas.setAttribute("id", "game");
MAIN.appendChild(canvas);
- INTERFACE.init(data);
+ INTERFACE.init(data, true);
return true;
},
@@ -510,6 +510,28 @@ const SCENES = {
}
},
},
+
+ GamePractice:{
+ load(data) {
+ let buttons_bottom = [ ];
+ buttons_bottom.push(UI.button("Back", () => { LOAD(SCENES.Browse) }));
+
+ UI.nav([
+ UI.button("Rotate", () => { INTERFACE.rotate(); }),
+ ], buttons_bottom);
+
+ let canvas = document.createElement("canvas");
+ canvas.setAttribute("id", "game");
+ MAIN.appendChild(canvas);
+
+ INTERFACE.init(data, false);
+
+ return true;
+ },
+ unload() {
+ INTERFACE.uninit();
+ },
+ },
};
function LOAD(scene, data=null) {
diff --git a/www/js/system.js b/www/js/system.js
index 3590e07..45b8d85 100644
--- a/www/js/system.js
+++ b/www/js/system.js
@@ -207,6 +207,7 @@ function MESSAGE(event) {
status:0,
player:2,
turn:0,
+ play:new GAME.Play(),
dawn:"",
dusk:"",
pool_dawn:[ ],
@@ -226,6 +227,13 @@ function MESSAGE(event) {
data.player = flags & 0x3;
+ // Last Play
+ result = UNPACK.u16(bytes, index);
+ index = result.index;
+ data.play.source = result.data & 1;
+ data.play.from = (result.data >> 1) & 0x3F;
+ data.play.to = (result.data >> 7) & 0x3F;
+
// Turn
result = UNPACK.u16(bytes, index);
index = result.index;
@@ -290,7 +298,7 @@ function MESSAGE(event) {
data = {
status:0,
- move:new GAME.Play(0, 0, 0),
+ play:new GAME.Play(0, 0, 0),
};
// Status
@@ -306,9 +314,9 @@ function MESSAGE(event) {
// Play description
result = UNPACK.u16(bytes, index);
index = result.index;
- data.move.source = result.data & 1;
- data.move.from = (result.data >> 1) & 0x3F;
- data.move.to = (result.data >> 7) & 0x3F;
+ data.play.source = result.data & 1;
+ data.play.from = (result.data >> 1) & 0x3F;
+ data.play.to = (result.data >> 7) & 0x3F;
} break;
default:
diff --git a/www/js/ui.js b/www/js/ui.js
index 6d3f9f2..793d1e9 100644
--- a/www/js/ui.js
+++ b/www/js/ui.js
@@ -121,6 +121,7 @@ const UI = {
}
top.push(UI.button("Live", () => { LOAD(SCENES.Live); }));
top.push(UI.button("History", () => { LOAD(SCENES.History); }));
+ top.push(UI.button("Practice", () => { LOAD(SCENES.GamePractice); }));
top.push(UI.button("Guide", () => { LOAD(SCENES.Guide); }));
top.push(UI.button("About", () => { LOAD(SCENES.About); }));