From c39c05969e7229ab61a86b621d62dbe96b9cbf4a Mon Sep 17 00:00:00 2001 From: yukirij Date: Sun, 8 Sep 2024 00:58:50 -0700 Subject: [PATCH] Fix handling of alt move plays. --- game/src/board/mod.rs | 8 +- game/src/consts.rs | 2 +- game/src/game/mod.rs | 138 +++++++++++++----------- game/src/piece/mod.rs | 2 +- game/src/util/hex.rs | 1 + server/src/main.rs | 6 +- server/src/protocol/packet/game_play.rs | 6 +- www/js/game.js | 8 +- www/js/interface.js | 61 ++++++----- www/js/scene.js | 11 ++ www/js/ui.js | 2 +- www/{ => pages}/about/main.md | 11 ++ www/{ => pages}/guide/game.md | 0 www/{ => pages}/guide/interface.md | 0 www/{ => pages}/guide/pieces.md | 0 15 files changed, 154 insertions(+), 102 deletions(-) rename www/{ => pages}/about/main.md (71%) rename www/{ => pages}/guide/game.md (100%) rename www/{ => pages}/guide/interface.md (100%) rename www/{ => pages}/guide/pieces.md (100%) diff --git a/game/src/board/mod.rs b/game/src/board/mod.rs index 8ff655e..769318f 100644 --- a/game/src/board/mod.rs +++ b/game/src/board/mod.rs @@ -23,6 +23,9 @@ impl Column { pub struct Tile { pub piece:Option, pub threat:[bool; 2], + pub check:bool, + + pub hex:Hex, } impl Tile { pub fn new() -> Self @@ -30,6 +33,9 @@ impl Tile { Self { piece:None, threat:[false; 2], + check:false, + + hex:Hex::new(), } } } @@ -81,7 +87,7 @@ impl Board { (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)), + (Piece::new(PIECE_SOURCE, PLAYER_DAWN), Hex::from_hex(4, 0)), ]; for (piece, hex) in &layout { diff --git a/game/src/consts.rs b/game/src/consts.rs index 2829ae5..fa3d059 100644 --- a/game/src/consts.rs +++ b/game/src/consts.rs @@ -11,4 +11,4 @@ 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; +pub const PIECE_SOURCE :u8 = 7; diff --git a/game/src/game/mod.rs b/game/src/game/mod.rs index e244f6c..6236fe1 100644 --- a/game/src/game/mod.rs +++ b/game/src/game/mod.rs @@ -50,6 +50,8 @@ impl Game { if self.complete { return Err(()); } + let valid = true; + // // TODO: // - Check for piece promotion. @@ -58,85 +60,93 @@ impl Game { // - // Move piece on board. - if match play.source { - 0 => { - if let Some(pid) = self.board.tiles[play.from as usize].piece { - if let Some(mut piece) = self.board.pieces[pid as usize] { - let mut swap = false; + if valid { - if let Some(tid) = self.board.tiles[play.to as usize].piece { - if let Some(target) = &mut self.board.pieces[tid as usize] { + // Move piece on board. + if match play.source { + 0 | 3 => { + if let Some(pid) = self.board.tiles[play.from as usize].piece { + if let Some(mut piece) = self.board.pieces[pid as usize] { + let mut swap = false; - // Check for piece swap. - if piece.player == target.player { - swap = true; - target.tile = play.from; + if let Some(tid) = self.board.tiles[play.to as usize].piece { + if let Some(target) = &mut self.board.pieces[tid as usize] { - // Check for target promotion. - let hex = Hex::from_tile(play.from); - if !target.promoted && target.has_promotion() && Hex::is_back(hex.x, hex.y, target.player) { - target.promoted = true; + // Check for piece swap. + if piece.player == target.player { + swap = true; + target.tile = play.from; + + // Check for target promotion. + let hex = Hex::from_tile(play.from); + if !target.promoted && target.has_promotion() && Hex::is_back(hex.x, hex.y, target.player) { + target.promoted = true; + } + } + + // Add captured piece to pool. + else { + self.pool[piece.player as usize][target.class as usize] += 1; } } - - // Add captured piece to pool. - else { - self.pool[piece.player as usize][target.class as usize] += 1; + + // Destroy piece if captured. + if !swap { self.board.pieces[tid as usize] = None; } + } + + // Set tile/piece associations. + if swap { + self.board.tiles[play.from as usize].piece = self.board.tiles[play.to as usize].piece; + } else { + self.board.tiles[play.from as usize].piece = None; + } + self.board.tiles[play.to as usize].piece = Some(pid); + piece.tile = play.to; + + self.board.pieces[pid as usize] = Some(piece); + + // Check for piece promotion. + let hex = Hex::from_tile(play.to); + if !piece.promoted && piece.has_promotion() && Hex::is_back(hex.x, hex.y, piece.player) { + if let Some(piece) = &mut self.board.pieces[pid as usize] { + piece.promoted = true; } } - // Destroy piece if captured. - if !swap { self.board.pieces[tid as usize] = None; } - } - - // Set tile/piece associations. - if swap { - self.board.tiles[play.from as usize].piece = self.board.tiles[play.to as usize].piece; - } else { - self.board.tiles[play.from as usize].piece = None; - } - self.board.tiles[play.to as usize].piece = Some(pid); - piece.tile = play.to; - - self.board.pieces[pid as usize] = Some(piece); - - // Check for piece promotion. - let hex = Hex::from_tile(play.to); - if !piece.promoted && piece.has_promotion() && Hex::is_back(hex.x, hex.y, piece.player) { - if let Some(piece) = &mut self.board.pieces[pid as usize] { - piece.promoted = true; - } - } + self.turn += 1; + true + } else { false } + } else { false } + } + + // Place piece from pool. + 1 => { + if self.pool[player as usize][play.from as usize] > 0 && self.board.tiles[play.to as usize].piece.is_none() { + self.pool[player as usize][play.from as usize] -= 1; + let piece = Piece::new(play.from, player); + self.board.set_piece(piece, play.to); self.turn += 1; true } else { false } - } else { false } - } - - // Place piece from pool. - 1 => { - if self.pool[player as usize][play.from as usize] > 0 && self.board.tiles[play.to as usize].piece.is_none() { - self.pool[player as usize][play.from as usize] -= 1; - let piece = Piece::new(play.from, player); - self.board.set_piece(piece, play.to); + } - self.turn += 1; + // Player retired. + 2 => { + self.complete = true; true - } else { false } - } + } - // Player retired. - 2 => { - self.complete = true; - true - } - - _ => false, - } { - self.history.push(*play); - Ok(()) + _ => false, + } { + self.history.push(*play); + Ok(()) + } else { Err(()) } } else { Err(()) } } + + fn get_moves(_piece:&Piece) -> Vec + { + Vec::new() + } } diff --git a/game/src/piece/mod.rs b/game/src/piece/mod.rs index 4b8481a..65c1349 100644 --- a/game/src/piece/mod.rs +++ b/game/src/piece/mod.rs @@ -104,7 +104,7 @@ pub const PIECES :[PieceClass; PIECES_COUNT] = [ }, }, PieceClass { - name: "Omen", + name: "Source", moves: MoveSet { direction:0, stride:0, diff --git a/game/src/util/hex.rs b/game/src/util/hex.rs index 4330225..ca1683f 100644 --- a/game/src/util/hex.rs +++ b/game/src/util/hex.rs @@ -1,5 +1,6 @@ const ROWS :[u8; 10] = [ 0, 5, 11, 18, 26, 35, 43, 50, 56, 61 ]; +#[derive(Clone, Copy)] pub struct Hex { pub x:u8, pub y:u8, diff --git a/server/src/main.rs b/server/src/main.rs index d43d4ee..d7b6035 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -211,7 +211,7 @@ async fn main() } } - let about_path = std::path::Path::new("www/about"); + let about_path = std::path::Path::new("www/pages/about"); for doc in [ "main", ] { @@ -220,7 +220,7 @@ async fn main() } } - let guide_path = std::path::Path::new("www/guide"); + let guide_path = std::path::Path::new("www/pages/guide"); for doc in [ "game", "pieces", @@ -230,7 +230,7 @@ async fn main() println!("error: failed to load: {}", doc); } } - + let mut tcp_server = TcpServer::new(); match tcp_server.bind("127.0.0.1:38611").await { Ok(_) => { diff --git a/server/src/protocol/packet/game_play.rs b/server/src/protocol/packet/game_play.rs index a771219..13a0f83 100644 --- a/server/src/protocol/packet/game_play.rs +++ b/server/src/protocol/packet/game_play.rs @@ -36,9 +36,9 @@ impl Packet for PacketGamePlay { result.turn = unpack_u16(data, index); let play = unpack_u16(data, index) as u32; - result.play.source = (play & mask(1, 0)) as u8; - result.play.from = ((play & mask(6, 1)) >> 1) as u8; - result.play.to = ((play & mask(6, 7)) >> 7) as u8; + result.play.source = (play & mask(4, 0)) as u8; + result.play.from = ((play & mask(6, 4)) >> 4) as u8; + result.play.to = ((play & mask(6, 10)) >> 10) as u8; Ok(result) } diff --git a/www/js/game.js b/www/js/game.js index 7fa51dc..564e458 100644 --- a/www/js/game.js +++ b/www/js/game.js @@ -151,11 +151,10 @@ GAME.MovementTile = class { }; GAME.Play = class { - constructor(source, from, to, alt=false) { + constructor(source, from, to) { this.source = source; this.from = from; this.to = to; - this.alt = alt; } }; @@ -347,7 +346,8 @@ GAME.Game = class { // Move piece on board. switch(play.source) { - case 0: { + case 0: + case 3: { let piece_id = this.board.tiles[play.from].piece; let piece = this.board.pieces[piece_id]; piece.tile = play.to; @@ -387,7 +387,7 @@ GAME.Game = class { } // Handle alt moves. - if(play.alt) { + if(play.source == 3) { switch(piece.piece) { case GAME.Const.PieceId.Knight: { piece.promoted = false; diff --git a/www/js/interface.js b/www/js/interface.js index 4b188e6..0e9aae1 100644 --- a/www/js/interface.js +++ b/www/js/interface.js @@ -241,8 +241,13 @@ const INTERFACE = { // Handle player action. switch(result) { case 1: { + let source = INTERFACE_DATA.select.source; + if(source == 0 && INTERFACE_DATA.alt_mode) { + source = 3; + } + let play = new GAME.Play( - INTERFACE_DATA.select.source, + source, INTERFACE_DATA.select.tile, INTERFACE_DATA.hover.tile, INTERFACE_DATA.alt_mode @@ -386,7 +391,7 @@ const INTERFACE = { let draw_piece = true; if(INTERFACE_DATA.Animate.play !== null) { let play = INTERFACE_DATA.Animate.play; - draw_piece = draw_piece && !(play.source == 0 && (play.from == i || play.to == i)); + draw_piece = draw_piece && !((play.source == 0 || play.source == 3) && (play.from == i || play.to == i)); draw_piece = draw_piece && !(play.source == 1 && play.to == i); } @@ -425,7 +430,7 @@ const INTERFACE = { case 1: ctx.fillStyle = INTERFACE.Color.TileLight; break; case 2: ctx.fillStyle = INTERFACE.Color.TileDark; break; } - if(GAME_DATA.turn > 0 && play.source < 2 && (play.to == i || (play.source == 0 && play.from == i))) { + if(GAME_DATA.turn > 0 && (play.source < 2 || play.source == 3) && (play.to == i || ((play.source == 0 || play.source == 3) && play.from == i))) { ctx.fillStyle = INTERFACE.Color.HintPlay; } else if(GAME_DATA.state.check != 0 && piece !== null && piece.piece == GAME.Const.PieceId.Source && piece.player == (GAME_DATA.turn & 1)) { ctx.fillStyle = INTERFACE.Color.HintCheck; @@ -655,7 +660,8 @@ const INTERFACE = { let from_y = 0; switch(play.source) { // Lerp between board positions. - case 0: { + case 0: + case 3: { let coord_from = HEX.tile_to_hex(play.from); if((INTERFACE_DATA.player & 1) ^ INTERFACE_DATA.rotate == 1) { coord_from.x = 8 - coord_from.x; @@ -1100,7 +1106,8 @@ const INTERFACE = { let valid = true; switch(play.source) { - case 0: { + case 0: + case 3: { let piece_id = GAME_DATA.board.tiles[play.from].piece; let piece = GAME_DATA.board.pieces[piece_id]; valid = piece.player == (GAME_DATA.turn & 1); @@ -1134,7 +1141,7 @@ const INTERFACE = { // Send action to server for validation. case INTERFACE.Mode.Player: { - let move_data = play.source | (play.from << 1) | (play.to << 7); + let move_data = play.source | (play.from << 4) | (play.to << 10); MESSAGE_COMPOSE([ PACK.u16(OpCode.GamePlay), PACK.u16(0), @@ -1211,26 +1218,32 @@ const INTERFACE = { let target = null; while(INTERFACE_DATA.replay_turn < turn) { play = INTERFACE_DATA.history[INTERFACE_DATA.replay_turn]; - if(play.source < 2) { - if(play.source == 0) { - let piece_id = GAME_DATA.board.tiles[play.from].piece; - if(piece_id !== null) { piece = GAME_DATA.board.pieces[piece_id].clone(); } + switch(play.source) { + case 0: + case 1: + case 3: { + if(play.source == 0 || play.source == 3) { + let piece_id = GAME_DATA.board.tiles[play.from].piece; + if(piece_id !== null) { piece = GAME_DATA.board.pieces[piece_id].clone(); } - piece_id = GAME_DATA.board.tiles[play.to].piece; - if(piece_id !== null) { target = GAME_DATA.board.pieces[piece_id].clone(); } - else { target = null; } + piece_id = GAME_DATA.board.tiles[play.to].piece; + if(piece_id !== null) { target = GAME_DATA.board.pieces[piece_id].clone(); } + else { target = null; } + } + + GAME_DATA.process(play); + + if(play.source == 1) { + let piece_id = GAME_DATA.board.tiles[play.to].piece; + if(piece_id !== null) { piece = GAME_DATA.board.pieces[piece_id].clone(); } + target = null; + } + } break; + + default: { + GAME_DATA.process(play); + play = null; } - - GAME_DATA.process(play); - - if(play.source == 1) { - let piece_id = GAME_DATA.board.tiles[play.to].piece; - if(piece_id !== null) { piece = GAME_DATA.board.pieces[piece_id].clone(); } - target = null; - } - } else { - GAME_DATA.process(play); - play = null; } INTERFACE_DATA.replay_turn++; } diff --git a/www/js/scene.js b/www/js/scene.js index 043992d..50ac8ee 100644 --- a/www/js/scene.js +++ b/www/js/scene.js @@ -557,6 +557,17 @@ const SCENES = { } }, + Extras:class{ + constructor() { } + load() { + UI.mainmenu("extras"); + UI.mainnav([], []); + + history.pushState(null, "Dzura - About", "/extras/"); + return true; + } + }, + Game:class{ constructor() { this.game = null; diff --git a/www/js/ui.js b/www/js/ui.js index 3540e81..641f5c3 100644 --- a/www/js/ui.js +++ b/www/js/ui.js @@ -165,7 +165,7 @@ const UI = { top.push(UI.button(LANG("guide"), () => { LOAD(SCENES.Guide); }, page == "guide")); top.push(UI.button(LANG("about"), () => { LOAD(SCENES.About); }, page == "about")); - bottom.push(UI.button(LANG("extras"), () => { })); + bottom.push(UI.button(LANG("extras"), () => { LOAD(SCENES.Extras) }, page == "extras")); if(sessionStorage.getItem("auth") !== null) { bottom.push(UI.button(LANG("account"), () => { })); diff --git a/www/about/main.md b/www/pages/about/main.md similarity index 71% rename from www/about/main.md rename to www/pages/about/main.md index 06b1899..200f5f7 100644 --- a/www/about/main.md +++ b/www/pages/about/main.md @@ -11,6 +11,17 @@ Dzura is a work of [Project Kirisame](https://kirisame.com). © 2024 Yukiri Corporation +## Guidelines + +1. Be polite, respectful, and honorable. + +### Bots + +1. Bots are generally permitted, provided they abide by these rules. +2. While not manidatory, we prefer that bots be labeled as such (e.g. in their handles). +3. Bots should not initiate games or send challenges. + + ## User Privacy This website does not collect any information beyond that used to implement user accounts and gameplay. diff --git a/www/guide/game.md b/www/pages/guide/game.md similarity index 100% rename from www/guide/game.md rename to www/pages/guide/game.md diff --git a/www/guide/interface.md b/www/pages/guide/interface.md similarity index 100% rename from www/guide/interface.md rename to www/pages/guide/interface.md diff --git a/www/guide/pieces.md b/www/pages/guide/pieces.md similarity index 100% rename from www/guide/pieces.md rename to www/pages/guide/pieces.md