diff --git a/game/src/board/mod.rs b/game/src/board/mod.rs index 007b877..3815ae0 100644 --- a/game/src/board/mod.rs +++ b/game/src/board/mod.rs @@ -38,7 +38,7 @@ impl Tile { pub struct Board { pub tiles:[Tile; 61], pub columns:[Column; 9], - pub pieces:[Option; 38], + pub pieces:[Option; PIECES_TOTAL], } impl Board { pub fn new() -> Self @@ -46,14 +46,14 @@ impl Board { Self { tiles:[Tile::new(); 61], columns:[Column::new(); 9], - pieces:[None; 38], + pieces:[None; PIECES_TOTAL], } } pub fn init(&mut self) { self.tiles = [Tile::new(); 61]; self.columns = [Column::new(); 9]; - self.pieces = [None; 38]; + self.pieces = [None; PIECES_TOTAL]; let layout = [ (Piece::new(PIECE_MILITIA, PLAYER_DAWN), Hex::from_hex(0, 1)), @@ -78,7 +78,8 @@ impl Board { (Piece::new(PIECE_TOWER, PLAYER_DAWN), Hex::from_hex(3, 0)), (Piece::new(PIECE_TOWER, PLAYER_DAWN), Hex::from_hex(5, 1)), - (Piece::new(PIECE_DRAGON, PLAYER_DAWN), Hex::from_hex(4, 1)), + (Piece::new(PIECE_DRAGON, PLAYER_DAWN), Hex::from_hex(4, 2)), + (Piece::new(PIECE_BEHEMOTH, PLAYER_DAWN), Hex::from_hex(4, 1)), (Piece::new(PIECE_OMEN, PLAYER_DAWN), Hex::from_hex(4, 0)), ]; diff --git a/game/src/consts.rs b/game/src/consts.rs index 1a86014..2829ae5 100644 --- a/game/src/consts.rs +++ b/game/src/consts.rs @@ -1,12 +1,14 @@ pub const PLAYER_DAWN :u8 = 0; pub const PLAYER_DUSK :u8 = 1; -pub const PIECES_COUNT :usize = 7; -pub const PIECE_NONE :u8 = PIECES_COUNT as u8 + 1; -pub const PIECE_MILITIA :u8 = 0; -pub const PIECE_LANCE :u8 = 1; -pub const PIECE_KNIGHT :u8 = 2; -pub const PIECE_TOWER :u8 = 3; -pub const PIECE_CASTLE :u8 = 4; -pub const PIECE_DRAGON :u8 = 5; -pub const PIECE_OMEN :u8 = 6; +pub const PIECES_TOTAL :usize = 40; +pub const PIECES_COUNT :usize = 8; +pub const PIECE_NONE :u8 = PIECES_COUNT as u8 + 1; +pub const PIECE_MILITIA :u8 = 0; +pub const PIECE_LANCE :u8 = 1; +pub const PIECE_KNIGHT :u8 = 2; +pub const PIECE_TOWER :u8 = 3; +pub const PIECE_CASTLE :u8 = 4; +pub const PIECE_DRAGON :u8 = 5; +pub const PIECE_BEHEMOTH :u8 = 6; +pub const PIECE_OMEN :u8 = 7; diff --git a/game/src/game/mod.rs b/game/src/game/mod.rs index edbe16a..0f51396 100644 --- a/game/src/game/mod.rs +++ b/game/src/game/mod.rs @@ -5,6 +5,8 @@ use crate::{ piece::Piece, }; +pub type Pool = [u8; 7]; + #[derive(Clone, Copy, PartialEq)] pub enum GameState { None, @@ -17,7 +19,7 @@ pub struct Game { pub turn:u16, pub state:GameState, pub board:Board, - pub pool:[[u8; 6]; 2], + pub pool:[Pool; 2], pub history:Vec, } @@ -30,7 +32,7 @@ impl Game { turn:0, board:Board::new(), - pool:[[0; 6]; 2], + pool:[Pool::default(); 2], history:Vec::new(), } @@ -74,7 +76,6 @@ impl Game { // Check for piece swap. if piece.player == target.player { - println!("swap"); swap = true; target.tile = play.from; } diff --git a/game/src/piece/mod.rs b/game/src/piece/mod.rs index 3b1b867..eb7959b 100644 --- a/game/src/piece/mod.rs +++ b/game/src/piece/mod.rs @@ -93,7 +93,18 @@ pub const PIECES :[PieceClass; PIECES_COUNT] = [ }, }, PieceClass { - name: "King", + name: "Behemoth", + moves: MoveSet { + direction:0, + stride:0, + }, + pmoves: MoveSet { + direction:0, + stride:0, + }, + }, + PieceClass { + name: "Omen", moves: MoveSet { direction:0, stride:0, diff --git a/server/src/main.rs b/server/src/main.rs index 1d29236..f1a9056 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -149,6 +149,7 @@ async fn main() "promote.svg", "omen_dawn.svg", + "behemoth_dawn.svg", "dragon_dawn.svg", "castle_dawn.svg", "tower_dawn.svg", @@ -157,6 +158,7 @@ async fn main() "militia_dawn.svg", "omen_dusk.svg", + "behemoth_dusk.svg", "dragon_dusk.svg", "castle_dusk.svg", "tower_dusk.svg", diff --git a/server/src/protocol/packet/game_state.rs b/server/src/protocol/packet/game_state.rs index 8b099e9..eb22d56 100644 --- a/server/src/protocol/packet/game_state.rs +++ b/server/src/protocol/packet/game_state.rs @@ -3,6 +3,8 @@ use crate::{ util::pack::pack_u16, }; +use game::game::Pool; + use super::Packet; #[derive(Clone)] @@ -64,9 +66,9 @@ pub struct PacketGameStateResponse { pub turn:u16, pub dawn_handle:String, pub dusk_handle:String, - pub dawn_pool:[u8; 6], - pub dusk_pool:[u8; 6], - pub pieces:[PacketGameStateResponsePiece; 38], + pub dawn_pool:Pool, + pub dusk_pool:Pool, + pub pieces:[PacketGameStateResponsePiece; game::consts::PIECES_TOTAL], } impl PacketGameStateResponse { pub fn new() -> Self @@ -76,9 +78,9 @@ impl PacketGameStateResponse { turn:0, dawn_handle:String::new(), dusk_handle:String::new(), - dawn_pool:[0; 6], - dusk_pool:[0; 6], - pieces:[PacketGameStateResponsePiece::new(); 38], + dawn_pool:Pool::default(), + dusk_pool:Pool::default(), + pieces:[PacketGameStateResponsePiece::new(); game::consts::PIECES_TOTAL], } } } @@ -103,14 +105,16 @@ impl Packet for PacketGameStateResponse { | ((self.dawn_pool[2] as u16) << 7) | ((self.dawn_pool[3] as u16) << 9) | ((self.dawn_pool[4] as u16) << 11) - | ((self.dawn_pool[5] as u16) << 13); + | ((self.dawn_pool[5] as u16) << 13) + | ((self.dawn_pool[6] as u16) << 14); let dusk_pool_bytes :u16 = self.dusk_pool[0] as u16 | ((self.dusk_pool[1] as u16) << 5) | ((self.dusk_pool[2] as u16) << 7) | ((self.dusk_pool[3] as u16) << 9) | ((self.dusk_pool[4] as u16) << 11) - | ((self.dusk_pool[5] as u16) << 13); + | ((self.dusk_pool[5] as u16) << 13) + | ((self.dusk_pool[6] as u16) << 14); [ pack_u16(self.status), diff --git a/www/asset/behemoth_dawn.svg b/www/asset/behemoth_dawn.svg new file mode 100644 index 0000000..9f79372 --- /dev/null +++ b/www/asset/behemoth_dawn.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + diff --git a/www/asset/behemoth_dusk.svg b/www/asset/behemoth_dusk.svg new file mode 100644 index 0000000..c9ec66e --- /dev/null +++ b/www/asset/behemoth_dusk.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + diff --git a/www/asset/knight_dawn.svg b/www/asset/knight_dawn.svg index adca537..7fb3196 100644 --- a/www/asset/knight_dawn.svg +++ b/www/asset/knight_dawn.svg @@ -24,9 +24,9 @@ inkscape:deskcolor="#d1d1d1" inkscape:document-units="px" showgrid="true" - inkscape:zoom="19.683333" - inkscape:cx="67.392042" - inkscape:cy="82.049112" + inkscape:zoom="9.8416665" + inkscape:cx="63.759527" + inkscape:cy="60.355632" inkscape:window-width="2588" inkscape:window-height="1368" inkscape:window-x="1257" @@ -65,7 +65,7 @@ y="105" /> diff --git a/www/asset/knight_dusk.svg b/www/asset/knight_dusk.svg index eaf7d00..d6f2a11 100644 --- a/www/asset/knight_dusk.svg +++ b/www/asset/knight_dusk.svg @@ -24,9 +24,9 @@ inkscape:deskcolor="#d1d1d1" inkscape:document-units="px" showgrid="true" - inkscape:zoom="19.683333" - inkscape:cx="67.392042" - inkscape:cy="81.998308" + inkscape:zoom="9.8416665" + inkscape:cx="63.759527" + inkscape:cy="60.355632" inkscape:window-width="2588" inkscape:window-height="1368" inkscape:window-x="1257" @@ -65,7 +65,7 @@ y="105" /> diff --git a/www/js/game.js b/www/js/game.js index 79d8756..03716b6 100644 --- a/www/js/game.js +++ b/www/js/game.js @@ -4,14 +4,14 @@ let GAME_DATA = null; GAME.Board = class { constructor() { this.tiles = [ ]; for(let i = 0; i < 61; ++i) { this.tiles.push(new GAME.Tile(i)); } - this.pieces = [ ]; for(let i = 0; i < 38; ++i) { this.pieces.push(null); } + this.pieces = [ ]; for(let i = 0; i < GAME.Const.Count.Pieces; ++i) { this.pieces.push(null); } this.columns = [ ]; for(let i = 0; i < 9; ++i) { this.columns.push(new GAME.Column()); } this.init(); } init() { - this.pieces = [ ]; for(let i = 0; i < 38; ++i) { this.pieces.push(null); } + this.pieces = [ ]; for(let i = 0; i < GAME.Const.Count.Pieces; ++i) { this.pieces.push(null); } // Describe Dawn layout let layout = [ @@ -37,7 +37,9 @@ GAME.Board = class { { piece:GAME.Const.PieceId.Tower, hex:new MATH.Vec2(3, 0) }, { piece:GAME.Const.PieceId.Tower, hex:new MATH.Vec2(5, 1) }, - { piece:GAME.Const.PieceId.Dragon, hex:new MATH.Vec2(4, 1) }, + { piece:GAME.Const.PieceId.Dragon, hex:new MATH.Vec2(4, 2) }, + { piece:GAME.Const.PieceId.Behemoth, hex:new MATH.Vec2(4, 1) }, + { piece:GAME.Const.PieceId.Omen, hex:new MATH.Vec2(4, 0) }, ]; @@ -79,7 +81,7 @@ GAME.Board = class { GAME.Pool = class { constructor() { - this.pieces = [ ]; for(let i = 0; i < 6; ++i) { this.pieces.push(1); } + this.pieces = [ ]; for(let i = 0; i < 7; ++i) { this.pieces.push(0); } } }; @@ -224,7 +226,7 @@ GAME.Game = class { else { this.board.columns[hex.x].extent[1] = Math.min(hex.y, this.board.columns[hex.x].extent[1]); } // Get threatened tiles. - for(let movement of this.movement_tiles_ext(piece, piece.tile)) { + for(let movement of this.movement_tiles(piece, piece.tile)) { if(movement.threat) { this.board.tiles[movement.tile].threaten[piece.player] = true; } @@ -244,16 +246,19 @@ GAME.Game = class { // Search for valid board moves. for(let piece of this.board.pieces) { if(piece !== null && piece.player == (this.turn & 1)) { - moves += this.movement_tiles(piece, piece.tile).length; + for(let move of this.movement_tiles(piece, piece.tile)) { + if(move.valid) { moves += 1; } + } } } // Search for valid pool placements. - for(let i = 0; i < 6; ++i) { - moves += this.placement_tiles(i, (this.turn & 1)).length; + for(let i = 0; i < this.pools[0].length; ++i) { + for(let move of this.placement_tiles(i, (this.turn & 1))) { + if(move.valid) { moves += 1; } + } } - console.log("moves " + moves); if(moves == 0) { this.state.checkmate = true; } } } @@ -298,7 +303,6 @@ GAME.Game = class { // Add captured piece to pool and destroy. else { - console.log(piece.player); this.pools[piece.player].pieces[target.piece] += 1; this.board.pieces[target_id] = null; } @@ -321,6 +325,7 @@ GAME.Game = class { player, play.to ); + this.pools[this.turn & 1].pieces[play.from] -= 1; } this.turn++; @@ -332,17 +337,6 @@ GAME.Game = class { } movement_tiles(piece, tile) { - let tiles = this.movement_tiles_ext(piece, tile); - let result = [ ]; - - for(let movement in tiles) { - if(movement.valid) { result.push(movement); } - } - - return result; - } - - movement_tiles_ext(piece, tile) { let tiles = [ ]; let moves = piece.moves(); let hex = this.board.tiles[tile].hex; @@ -382,13 +376,15 @@ GAME.Game = class { let result = valid; - if(piece.player == (this.turn & 1) && this.state.check && !tile_data.checking) { + if(piece.player == (this.turn & 1) + && this.state.check && !tile_data.checking + && piece.piece != GAME.Const.PieceId.Omen) { result = false; } // King may not move onto threatened tile. if(piece.piece == GAME.Const.PieceId.Omen && tile_data.threaten[+(!piece.player)]) { - valid = false; + result = false; } // Handle occupied tile. @@ -449,17 +445,6 @@ GAME.Game = class { } placement_tiles(piece_id, player) { - let tiles = this.placement_tiles_ext(piece_id, player); - let result = [ ]; - - for(let movement in tiles) { - if(movement.valid) { result.push(movement); } - } - - return result; - } - - placement_tiles_ext(piece_id, player) { let tiles = [ ]; let piece = new GAME.Piece(piece_id, player); @@ -491,7 +476,7 @@ GAME.Game = class { // Check if position puts king in check. let checking = false; - let movements = this.movement_tiles_ext(piece, i); + let movements = this.movement_tiles(piece, i); for(let movement of movements) { if(movement.check) { checking = true; @@ -565,7 +550,12 @@ GAME.Const = { Tower: 3, Castle: 4, Dragon: 5, - Omen: 6, + Behemoth: 6, + Omen: 7, + }, + + Count: { + Pieces:40, }, Piece: [ @@ -693,6 +683,29 @@ GAME.Const = { .add_stride(10) .add_stride(11), ), + new GAME.GamePiece( + "Behemoth", + new GAME.PieceMovement() + .add_stride(0) + .add_stride(1) + .add_stride(2) + .add_stride(3) + .add_stride(4) + .add_stride(5), + new GAME.PieceMovement() + .add_stride(0) + .add_stride(1) + .add_stride(2) + .add_stride(3) + .add_stride(4) + .add_stride(5) + .add(6) + .add(7) + .add(8) + .add(9) + .add(10) + .add(11) + ), new GAME.GamePiece( "Omen", new GAME.PieceMovement() diff --git a/www/js/game_asset.js b/www/js/game_asset.js index e163edf..575b8b5 100644 --- a/www/js/game_asset.js +++ b/www/js/game_asset.js @@ -15,6 +15,7 @@ GAME_ASSET.Image = { [ GAME_ASSET.load_image("asset/tower_dawn.svg"), GAME_ASSET.load_image("asset/tower_dusk.svg") ], [ GAME_ASSET.load_image("asset/castle_dawn.svg"), GAME_ASSET.load_image("asset/castle_dusk.svg") ], [ GAME_ASSET.load_image("asset/dragon_dawn.svg"), GAME_ASSET.load_image("asset/dragon_dusk.svg") ], + [ GAME_ASSET.load_image("asset/behemoth_dawn.svg"), GAME_ASSET.load_image("asset/behemoth_dusk.svg") ], [ GAME_ASSET.load_image("asset/omen_dawn.svg"), GAME_ASSET.load_image("asset/omen_dusk.svg") ], ], }; diff --git a/www/js/interface.js b/www/js/interface.js index 3dfb1e0..4bde561 100644 --- a/www/js/interface.js +++ b/www/js/interface.js @@ -63,12 +63,12 @@ const INTERFACE = { if(piece_id !== null) { let piece = GAME_DATA.board.pieces[piece_id]; player = piece.player; - movements = GAME_DATA.movement_tiles_ext(piece, selection.tile); + movements = GAME_DATA.movement_tiles(piece, selection.tile); } } else { - player = Math.floor(selection.tile / 6); + player = Math.floor(selection.tile / 7); player ^= (INTERFACE_DATA.player & 1) ^ INTERFACE_DATA.rotate; - movements = GAME_DATA.placement_tiles_ext(selection.tile % 6, player); + movements = GAME_DATA.placement_tiles(selection.tile % 7, player); } if(movements !== null) { @@ -154,11 +154,11 @@ const INTERFACE = { let rad_slope = 1 - (hex_slope * apo_offset); let hx = kx + (rad_offset > rad_slope); - let hy = Math.floor((ky - hx) / 2.0); + let hy = Math.floor((ky + hx) / 2.0); let hex = new MATH.Vec2(hx, hy); if(INTERFACE.Ui.pool_hex_is_valid(hex)) { - let tile = (hx * 6) + hy; + let tile = (hx * 7) + hy; INTERFACE_DATA.hover = new INTERFACE.Selection(1, tile, hex); } } @@ -173,7 +173,7 @@ const INTERFACE = { if(redraw) { INTERFACE.draw(); } }, - click(event) { + click() { let initial_select = INTERFACE_DATA.select; if(INTERFACE_DATA.hover !== null) { @@ -190,7 +190,6 @@ const INTERFACE = { if(is_valid) { let move_data = INTERFACE_DATA.select.source | (INTERFACE_DATA.select.tile << 1) | (INTERFACE_DATA.hover.tile << 7); - console.log("SEND Play"); MESSAGE_COMPOSE([ PACK.u16(OpCode.GamePlay), PACK.u16(0), @@ -202,13 +201,13 @@ const INTERFACE = { INTERFACE_DATA.select = null; if(INTERFACE_DATA.hover.source == 0) { if(GAME_DATA.board.tiles[INTERFACE_DATA.hover.tile].piece !== null) { - INTERFACE_DATA.select = INTERFACE_DATA.hover; + INTERFACE_DATA.select = INTERFACE_DATA.hover; } } else { - let pool_player = Math.floor(INTERFACE_DATA.hover.tile / 6); + let pool_player = Math.floor(INTERFACE_DATA.hover.tile / 7); pool_player ^= (INTERFACE_DATA.player & 1) ^ INTERFACE_DATA.rotate; - let pool_piece = INTERFACE_DATA.hover.tile % 6; + let pool_piece = INTERFACE_DATA.hover.tile % 7; if(GAME_DATA.pools[pool_player].pieces[pool_piece] > 0) { INTERFACE_DATA.select = INTERFACE_DATA.hover; @@ -384,7 +383,7 @@ const INTERFACE = { } // Draw player pool - for(let i = 0; i < 6; ++i) { + for(let i = 0; i < 7; ++i) { let is_hover = INTERFACE.Ui.tile_is_hover(1, i); let is_select = INTERFACE.Ui.tile_is_select(1, i); @@ -423,12 +422,12 @@ const INTERFACE = { } // Draw opponent pool - for(let i = 0; i < 6; ++i) { - let is_hover = INTERFACE.Ui.tile_is_hover(1, 6 + i); - let is_select = INTERFACE.Ui.tile_is_select(1, 6 + i); + for(let i = 0; i < 7; ++i) { + let is_hover = INTERFACE.Ui.tile_is_hover(1, 7 + i); + let is_select = INTERFACE.Ui.tile_is_select(1, 7 + i); let gui_x = basis_x + (radius * 15.5); - let gui_y = basis_y - (8 - (2 * i)) * gui_scale; + let gui_y = basis_y - (10 - (2 * i)) * gui_scale; ctx.save(); ctx.translate(gui_x, gui_y); @@ -466,12 +465,12 @@ const INTERFACE = { let handle_pos = [ new MATH.Vec2( - basis_x + (radius * 12), - basis_y - (11 * gui_scale) + basis_x + (radius * 10.5), + basis_y - (11.5 * gui_scale) ), new MATH.Vec2( - basis_x + (radius * 12), - basis_y + (3 * gui_scale) + basis_x + (radius * 10.5), + basis_y + (3.5 * gui_scale) ), ]; @@ -505,11 +504,12 @@ const INTERFACE = { text = INTERFACE.Ui.hex_to_alnum(INTERFACE_DATA.hover.hex); let piece_id = GAME_DATA.board.tiles[INTERFACE_DATA.hover.tile].piece; if(piece_id !== null) { - let piece_class = GAME_DATA.board.pieces[piece_id].piece; - text += " " + GAME.Const.Piece[piece_class].name; + let piece = GAME_DATA.board.pieces[piece_id]; + text += " " + GAME.Const.Piece[piece.piece].name; + if(piece.promoted) { text += "+"; } } } else { - text = " " + GAME.Const.Piece[INTERFACE_DATA.hover.tile % 6].name; + text = " " + GAME.Const.Piece[INTERFACE_DATA.hover.tile % 7].name; } ctx.fillStyle = INTERFACE.Color.Text; @@ -637,7 +637,7 @@ const INTERFACE = { }, pool_hex_is_valid(hex) { - return (hex.x >= 0 && hex.x < 2 && hex.y >= 0 && hex.y < 6); + return (hex.x >= 0 && hex.x < 2 && hex.y >= 0 && hex.y < 7); }, hex_to_alnum(hex) { diff --git a/www/js/system.js b/www/js/system.js index 8093361..72b1bcd 100644 --- a/www/js/system.js +++ b/www/js/system.js @@ -243,6 +243,7 @@ function MESSAGE(event) { data.pool_dawn.push((dawn_pool_bits >> 9) & 0x3); data.pool_dawn.push((dawn_pool_bits >> 11) & 0x3); data.pool_dawn.push((dawn_pool_bits >> 13) & 0x1); + data.pool_dawn.push((dawn_pool_bits >> 14) & 0x1); // Dusk pool result = UNPACK.u16(bytes, index); @@ -255,9 +256,10 @@ function MESSAGE(event) { data.pool_dusk.push((dusk_pool_bits >> 9) & 0x3); data.pool_dusk.push((dusk_pool_bits >> 11) & 0x3); data.pool_dusk.push((dusk_pool_bits >> 13) & 0x1); + data.pool_dusk.push((dusk_pool_bits >> 14) & 0x1); // Pieces - for(let i = 0; i < 38; ++i) { + for(let i = 0; i < GAME.Const.Count.Pieces; ++i) { result = UNPACK.u16(bytes, index); index = result.index; let piece_data = result.data;