diff --git a/src/core/Util.ts b/src/core/Util.ts index 330359021..a79dda1a8 100644 --- a/src/core/Util.ts +++ b/src/core/Util.ts @@ -80,13 +80,14 @@ export function calculateBoundingBox( maxX = -Infinity, maxY = -Infinity; - borderTiles.forEach((tile: TileRef) => { - const cell = gm.cell(tile); - minX = Math.min(minX, cell.x); - minY = Math.min(minY, cell.y); - maxX = Math.max(maxX, cell.x); - maxY = Math.max(maxY, cell.y); - }); + for (const tile of borderTiles) { + const x = gm.x(tile); + const y = gm.y(tile); + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } return { min: new Cell(minX, minY), max: new Cell(maxX, maxY) }; } diff --git a/src/core/execution/PlayerExecution.ts b/src/core/execution/PlayerExecution.ts index c7e452e5d..e1d80d0b4 100644 --- a/src/core/execution/PlayerExecution.ts +++ b/src/core/execution/PlayerExecution.ts @@ -1,5 +1,5 @@ import { Config } from "../configuration/Config"; -import { Execution, Game, Player, UnitType } from "../game/Game"; +import { Cell, Execution, Game, Player, UnitType } from "../game/Game"; import { TileRef } from "../game/GameMap"; import { calculateBoundingBox, getMode, inscribed, simpleHash } from "../Util"; @@ -139,11 +139,12 @@ export class PlayerExecution implements Execution { const largestCluster = clusters[largestIndex]; if (largestCluster === undefined) throw new Error("No clusters"); - this.player.largestClusterBoundingBox = calculateBoundingBox( - this.mg, + const largestClusterBox = calculateBoundingBox(this.mg, largestCluster); + this.player.largestClusterBoundingBox = largestClusterBox; + const surroundedBy = this.surroundedBySamePlayer( largestCluster, + largestClusterBox, ); - const surroundedBy = this.surroundedBySamePlayer(largestCluster); if (surroundedBy && !surroundedBy.isFriendly(this.player)) { this.removeCluster(largestCluster); } @@ -158,7 +159,10 @@ export class PlayerExecution implements Execution { } } - private surroundedBySamePlayer(cluster: Set): false | Player { + private surroundedBySamePlayer( + cluster: Set, + clusterBox: { min: Cell; max: Cell }, + ): false | Player { const enemies = new Set(); for (const tile of cluster) { let hasUnownedNeighbor = false; @@ -187,7 +191,6 @@ export class PlayerExecution implements Execution { } const enemy = this.mg.playerBySmallID(Array.from(enemies)[0]) as Player; const enemyBox = calculateBoundingBox(this.mg, enemy.borderTiles()); - const clusterBox = calculateBoundingBox(this.mg, cluster); if (inscribed(enemyBox, clusterBox)) { return enemy; } @@ -195,7 +198,11 @@ export class PlayerExecution implements Execution { } private isSurrounded(cluster: Set): boolean { - const enemyTiles = new Set(); + let hasEnemy = false; + let minX = Infinity, + minY = Infinity, + maxX = -Infinity, + maxY = -Infinity; for (const tr of cluster) { if (this.mg.isShore(tr) || this.mg.isOnEdgeOfMap(tr)) { return false; @@ -203,27 +210,31 @@ export class PlayerExecution implements Execution { this.mg.forEachNeighbor(tr, (n) => { const owner = this.mg.owner(n); if (owner.isPlayer() && this.mg.ownerID(n) !== this.player.smallID()) { - enemyTiles.add(n); + hasEnemy = true; + const x = this.mg.x(n); + const y = this.mg.y(n); + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); } }); } - if (enemyTiles.size === 0) { + if (!hasEnemy) { return false; } - const enemyBox = calculateBoundingBox(this.mg, enemyTiles); const clusterBox = calculateBoundingBox(this.mg, cluster); + const enemyBox = { min: new Cell(minX, minY), max: new Cell(maxX, maxY) }; return inscribed(enemyBox, clusterBox); } private removeCluster(cluster: Set) { - if ( - Array.from(cluster).some( - (t) => this.mg?.ownerID(t) !== this.player?.smallID(), - ) - ) { - // Other removeCluster operations could change tile owners, - // so double check. - return; + for (const t of cluster) { + if (this.mg?.ownerID(t) !== this.player?.smallID()) { + // Other removeCluster operations could change tile owners, + // so double check. + return; + } } const capturing = this.getCapturingPlayer(cluster);