From c6fcb6bd785bd48f0efe34a16a90db5edeed88d2 Mon Sep 17 00:00:00 2001 From: yukirij Date: Tue, 20 Aug 2024 13:03:21 -0700 Subject: [PATCH] Fix checking move handling. --- www/js/game.js | 94 +++++++++++++++++++++++++-------------------- www/js/interface.js | 6 +-- 2 files changed, 55 insertions(+), 45 deletions(-) diff --git a/www/js/game.js b/www/js/game.js index 3865e23..ee249d1 100644 --- a/www/js/game.js +++ b/www/js/game.js @@ -122,7 +122,7 @@ GAME.Tile = class { this.piece = null; this.threaten = [0, 0]; - this.checking = false; + this.checking = 0; this.hex = HEX.tile_to_hex(index); } @@ -136,7 +136,7 @@ GAME.Tile = class { reset() { this.threaten = [0, 0]; - this.checking = false; + this.checking = 0; } }; @@ -260,13 +260,15 @@ GAME.Game = class { // Reset tiles this.board.reset(); - this.state.check = false; + this.state.check = 0; this.state.checkmate = false; // Determine threaten, check, and blocking for each piece + let checking_pieces = 0; for(let piece of this.board.pieces) { if(piece !== null) { let hex = this.board.tiles[piece.tile].hex; + let is_checking = false; // Check if column has militia. if(piece.piece == GAME.Const.PieceId.Militia && !piece.promoted) { @@ -282,20 +284,26 @@ GAME.Game = class { if(movement.threat) { this.board.tiles[movement.tile].threaten[piece.player] += 1; } - if(movement.check) { - this.board.tiles[piece.tile].checking = true; - this.board.tiles[movement.tile].checking = true; - this.state.check = true; + if(movement.valid && movement.check != 0) { + is_checking = true; + this.board.tiles[movement.tile].checking |= movement.check; + this.state.check |= movement.check; } if(movement.block != 0) { this.board.pieces[this.board.tiles[movement.tile].piece].blocking = movement.block; } } + + if(is_checking) { + this.board.tiles[piece.tile].checking = 1; + checking_pieces++; + } } } + this.state.check += checking_pieces; // Count moves available to next turn player to determine checkmate. - if(this.state.check) { + if(this.state.check != 0) { let moves = 0; // Search for valid board moves. @@ -396,8 +404,6 @@ GAME.Game = class { // Recalculate new board state. this.update_board(); - - // If check, detect checkmate. } movement_tiles(piece, tile) { @@ -410,9 +416,6 @@ GAME.Game = class { let block_directions = piece.blocking; if(block_directions != 0) { block_directions |= BITWISE.rotate_blocks(piece.blocking); - //if(piece.piece != GAME.Const.PieceId.Omen) { - // permitted_moves &= piece.blocking; - //} } // Check directions of movement. @@ -433,7 +436,7 @@ GAME.Game = class { move_hex.add(direction); let threat = valid; - let check = false; + let check = 0; let block = 0; let swap = false; let tile_occupied = false; @@ -441,14 +444,27 @@ GAME.Game = class { if(HEX.is_valid(move_hex)) { let tile_id = HEX.hex_to_tile(move_hex); let tile_data = this.board.tiles[tile_id]; + let target_id = tile_data.piece; let result = valid; - // Prevent moves that do not uncheck the King. - if(piece.player == (this.turn & 1) - && this.state.check && !tile_data.checking - && piece.piece != GAME.Const.PieceId.Omen) { - result = false; + // Prevent moves that do not uncheck King. + let check_direct = (this.state.check & 0x040) != 0; + let check_count = this.state.check & 0x3F; + if(piece.player == (this.turn & 1) && this.state.check != 0) { + if(piece.piece != GAME.Const.PieceId.Omen) { + if(tile_data.checking != 0) { + if(target_id !== null) { + if(check_count > 1) { + result = false; + } + } else if(check_direct != 0 || check_count > 1) { + result = false; + } + } else { + result = false; + } + } } // King may not move onto threatened tile. @@ -457,8 +473,8 @@ GAME.Game = class { } // Handle occupied tile. - if(tile_data.piece !== null) { - let target = this.board.pieces[tile_data.piece]; + if(target_id !== null) { + let target = this.board.pieces[target_id]; tile_occupied = true; // Target piece is ally. @@ -479,13 +495,14 @@ GAME.Game = class { // Check if target piece is opposing king. if(target.piece == GAME.Const.PieceId.Omen) { if(valid) { - check = true; + if(dist == 1) { check = GAME.Const.Check.Direct; } + else { check = GAME.Const.Check.Stride; } if(stride) { block = mask; } // Apply check to previous moves. for(let idist = 1; idist < dist; idist++) { - tiles[tiles.length - idist].check = true; + tiles[tiles.length - idist].check = GAME.Const.Check.Stride; } } @@ -555,8 +572,15 @@ GAME.Game = class { if(tile.piece === null) { let position_valid = true; - if(player == (this.turn & 1) && this.state.check && !tile.checking) { - position_valid = false; + // Prevent placement that does not uncheck King. + let check_direct = (this.state.check & GAME.Const.Check.Direct) != 0; + let check_count = this.state.check & 0x3F; + if(player == (this.turn & 1) && this.state.check != 0) { + if(check_direct == 0 && check_count == 1) { + position_valid = tile.checking != 0; + } else { + position_valid = false; + } } // Check off-sides. @@ -625,25 +649,11 @@ GAME.Const = { new MATH.Vec2(-1, -2), new MATH.Vec2(-2, -1), new MATH.Vec2(-1, 1), - - /*new MATH.Vec2(1, 3), - new MATH.Vec2(2, 3), - new MATH.Vec2(3, 2), - new MATH.Vec2(3, 1), - new MATH.Vec2(2, -1), - new MATH.Vec2(1, -2), - new MATH.Vec2(-1, -3), - new MATH.Vec2(-2, -3), - new MATH.Vec2(-3, -2), - new MATH.Vec2(-3, -1), - new MATH.Vec2(-2, 1), - new MATH.Vec2(-1, 2),*/ ], - MoveStatus: { - Valid: 0, - Invalid: 1, - Check: 2, + Check: { + Direct: 0x0040, + Stride: 0x0080, }, PieceId: { diff --git a/www/js/interface.js b/www/js/interface.js index 952ceb9..69e3648 100644 --- a/www/js/interface.js +++ b/www/js/interface.js @@ -371,7 +371,7 @@ const INTERFACE = { } if(GAME_DATA.turn > 0 && INTERFACE_DATA.play.source < 2 && (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)) { + } else if(GAME_DATA.state.check != 0 && piece !== null && piece.piece == GAME.Const.PieceId.Omen && piece.player == (GAME_DATA.turn & 1)) { ctx.fillStyle = INTERFACE.Color.HintCheck; } switch(hover_state) { @@ -579,7 +579,7 @@ const INTERFACE = { if(GAME_DATA.state.code == GAME.Const.State.Retire) { ctx.fillStyle = INTERFACE.Color.HintCheck; message = "Retire"; - } else if(GAME_DATA.state.check) { + } else if(GAME_DATA.state.check != 0) { ctx.fillStyle = INTERFACE.Color.HintCheck; if(GAME_DATA.state.checkmate) { message = "Checkmate"; @@ -1003,7 +1003,7 @@ const INTERFACE = { } } - if(state.state.check) { + if(state.state.check != 0) { if(turn == player) { score -= 20; } else { score += 1; } }