diff --git a/src/core/Util.ts b/src/core/Util.ts index d74d27b11..fc5e6c58d 100644 --- a/src/core/Util.ts +++ b/src/core/Util.ts @@ -114,27 +114,6 @@ export function inscribed( ); } -export function getMode(list: Set): number { - // Count occurrences - const counts = new Map(); - for (const item of list) { - counts.set(item, (counts.get(item) ?? 0) + 1); - } - - // Find the item with the highest count - let mode = 0; - let maxCount = 0; - - for (const [item, count] of counts) { - if (count > maxCount) { - maxCount = count; - mode = item; - } - } - - return mode; -} - export function sanitize(name: string): string { return Array.from(name) .join("") diff --git a/src/core/execution/PlayerExecution.ts b/src/core/execution/PlayerExecution.ts index 66f5c6a57..32935eabb 100644 --- a/src/core/execution/PlayerExecution.ts +++ b/src/core/execution/PlayerExecution.ts @@ -2,7 +2,7 @@ import { Config } from "../configuration/Config"; import { Execution, Game, Player, UnitType } from "../game/Game"; import { GameImpl } from "../game/GameImpl"; import { GameMap, TileRef } from "../game/GameMap"; -import { calculateBoundingBox, getMode, inscribed, simpleHash } from "../Util"; +import { calculateBoundingBox, inscribed, simpleHash } from "../Util"; export class PlayerExecution implements Execution { private readonly ticksPerClusterCalc = 20; @@ -214,22 +214,37 @@ export class PlayerExecution implements Execution { } private getCapturingPlayer(cluster: Set): Player | null { - const neighborsIDs = new Set(); + // Collect unique neighbor IDs (excluding self) as candidates + const candidatesIDs = new Set(); + const selfID = this.player.smallID(); + for (const t of cluster) { for (const neighbor of this.mg.neighbors(t)) { - if (this.mg.ownerID(neighbor) !== this.player.smallID()) { - neighborsIDs.add(this.mg.ownerID(neighbor)); + if (this.mg.ownerID(neighbor) !== selfID) { + candidatesIDs.add(this.mg.ownerID(neighbor)); } } } - let largestNeighborAttack: Player | null = null; - let largestTroopCount: number = 0; - for (const id of neighborsIDs) { + // Filter out friendly and non-player candidates + const neighbors = new Set(); + for (const id of candidatesIDs) { const neighbor = this.mg.playerBySmallID(id); - if (!neighbor.isPlayer() || this.player.isFriendly(neighbor)) { + if (!neighbor.isPlayer() || neighbor.isFriendly(this.player)) { continue; } + neighbors.add(neighbor); + } + + // If there are no enemies, return null + if (neighbors.size === 0) { + return null; + } + + // Get the largest attack from the neighbors + let largestNeighborAttack: Player | null = null; + let largestTroopCount = 0; + for (const neighbor of neighbors) { for (const attack of neighbor.outgoingAttacks()) { if (attack.target() === this.player) { if (attack.troops() > largestTroopCount) { @@ -239,20 +254,10 @@ export class PlayerExecution implements Execution { } } } - if (largestNeighborAttack !== null) { - return largestNeighborAttack; - } - // fall back to getting mode if no attacks - const mode = getMode(neighborsIDs); - if (!this.mg.playerBySmallID(mode).isPlayer()) { - return null; - } - const capturing = this.mg.playerBySmallID(mode); - if (!capturing.isPlayer()) { - return null; - } - return capturing; + // Return the largest neighbor attack + // If there is no largest neighbor attack, this will return null + return largestNeighborAttack; } private calculateClusters(): Set[] {