From 254287c124f9dee750b5ad2c9de50353e0d31dea Mon Sep 17 00:00:00 2001 From: sokol Date: Sat, 21 Feb 2026 17:59:41 +0300 Subject: [PATCH] Implement solid territory supply system --- public/game.js | 8 +++++--- public/map.js | 48 ++++++++++++++++++++++++++++++++++++++++++------ src/map.js | 48 ++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 89 insertions(+), 15 deletions(-) diff --git a/public/game.js b/public/game.js index 42d9c42..c9697a4 100644 --- a/public/game.js +++ b/public/game.js @@ -513,14 +513,16 @@ class GameUI { instruction.textContent = 'Select a cell with dice to move'; } - // Update selected cell info + // Update selected cell info - always show with placeholder if nothing selected const cellInfo = document.getElementById('selected-cell-info'); + cellInfo.style.display = 'block'; + if (this.selectedCell) { - cellInfo.style.display = 'block'; document.getElementById('cell-strength').textContent = this.selectedCell.getStrength(); document.getElementById('cell-dice').textContent = this.selectedCell.dice.length; } else { - cellInfo.style.display = 'none'; + document.getElementById('cell-strength').textContent = '-'; + document.getElementById('cell-dice').textContent = '-'; } // Update buttons diff --git a/public/map.js b/public/map.js index 2704f91..d096f8e 100644 --- a/public/map.js +++ b/public/map.js @@ -187,17 +187,53 @@ class HexMap { } /** - * Calculate supply for a player: S = sum of all owned cells + * Calculate supply for a player: S = size of largest solid (connected) territory + * A solid territory is a connected region of player's cells */ calculateSupply(playerId) { const playerCells = this.getPlayerCells(playerId); - let supply = 0; - + if (playerCells.length === 0) return 0; + + // Build adjacency map for player cells + const cellMap = new Map(); for (const cell of playerCells) { - supply += 1; // Each owned cell gives +1 supply + cellMap.set(this.getKey(cell.q, cell.r), cell); } - - return supply; + + // Find connected components using BFS + const visited = new Set(); + let maxTerritory = 0; + + for (const cell of playerCells) { + const key = this.getKey(cell.q, cell.r); + if (visited.has(key)) continue; + + // BFS to find size of this territory + let territorySize = 0; + const queue = [cell]; + visited.add(key); + + while (queue.length > 0) { + const current = queue.shift(); + territorySize++; + + // Get all neighbors that are also player cells + const neighbors = this.getNeighbors(current.q, current.r); + for (const neighbor of neighbors) { + if (neighbor.getOwner() === playerId) { + const nKey = this.getKey(neighbor.q, neighbor.r); + if (!visited.has(nKey)) { + visited.add(nKey); + queue.push(neighbor); + } + } + } + } + + maxTerritory = Math.max(maxTerritory, territorySize); + } + + return maxTerritory; } /** diff --git a/src/map.js b/src/map.js index 2704f91..d096f8e 100644 --- a/src/map.js +++ b/src/map.js @@ -187,17 +187,53 @@ class HexMap { } /** - * Calculate supply for a player: S = sum of all owned cells + * Calculate supply for a player: S = size of largest solid (connected) territory + * A solid territory is a connected region of player's cells */ calculateSupply(playerId) { const playerCells = this.getPlayerCells(playerId); - let supply = 0; - + if (playerCells.length === 0) return 0; + + // Build adjacency map for player cells + const cellMap = new Map(); for (const cell of playerCells) { - supply += 1; // Each owned cell gives +1 supply + cellMap.set(this.getKey(cell.q, cell.r), cell); } - - return supply; + + // Find connected components using BFS + const visited = new Set(); + let maxTerritory = 0; + + for (const cell of playerCells) { + const key = this.getKey(cell.q, cell.r); + if (visited.has(key)) continue; + + // BFS to find size of this territory + let territorySize = 0; + const queue = [cell]; + visited.add(key); + + while (queue.length > 0) { + const current = queue.shift(); + territorySize++; + + // Get all neighbors that are also player cells + const neighbors = this.getNeighbors(current.q, current.r); + for (const neighbor of neighbors) { + if (neighbor.getOwner() === playerId) { + const nKey = this.getKey(neighbor.q, neighbor.r); + if (!visited.has(nKey)) { + visited.add(nKey); + queue.push(neighbor); + } + } + } + } + + maxTerritory = Math.max(maxTerritory, territorySize); + } + + return maxTerritory; } /**