mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 09:50:43 +00:00
fix encirclement issues (#2191)
## Description: Players with no ongoing attacks were ignored during cluster calculations in https://github.com/openfrontio/OpenFrontIO/commit/3680d9cc1663a22f0e174d2c2de806c0ee78b923 This PR has it fallback to neighbor with largest border if no ongoing attacks ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: evan
This commit is contained in:
@@ -129,6 +129,20 @@ export function boundingBoxTiles(
|
||||
return tiles;
|
||||
}
|
||||
|
||||
export function getMode<T>(counts: Map<T, number>): T | null {
|
||||
let mode: T | null = null;
|
||||
let maxCount = 0;
|
||||
|
||||
for (const [item, count] of counts) {
|
||||
if (count > maxCount) {
|
||||
maxCount = count;
|
||||
mode = item;
|
||||
}
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
export function calculateBoundingBoxCenter(
|
||||
gm: GameMap,
|
||||
borderTiles: ReadonlySet<TileRef>,
|
||||
|
||||
@@ -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, inscribed, simpleHash } from "../Util";
|
||||
import { calculateBoundingBox, getMode, inscribed, simpleHash } from "../Util";
|
||||
|
||||
export class PlayerExecution implements Execution {
|
||||
private readonly ticksPerClusterCalc = 20;
|
||||
@@ -221,28 +221,20 @@ export class PlayerExecution implements Execution {
|
||||
}
|
||||
|
||||
private getCapturingPlayer(cluster: Set<TileRef>): Player | null {
|
||||
// Collect unique neighbor IDs (excluding self) as candidates
|
||||
const candidatesIDs = new Set<number>();
|
||||
const selfID = this.player.smallID();
|
||||
|
||||
const neighbors = new Map<Player, number>();
|
||||
for (const t of cluster) {
|
||||
for (const neighbor of this.mg.neighbors(t)) {
|
||||
if (this.mg.ownerID(neighbor) !== selfID) {
|
||||
candidatesIDs.add(this.mg.ownerID(neighbor));
|
||||
const owner = this.mg.owner(neighbor);
|
||||
if (
|
||||
owner.isPlayer() &&
|
||||
owner !== this.player &&
|
||||
!owner.isFriendly(this.player)
|
||||
) {
|
||||
neighbors.set(owner, (neighbors.get(owner) ?? 0) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Filter out friendly and non-player candidates
|
||||
const neighbors = new Set<Player>();
|
||||
for (const id of candidatesIDs) {
|
||||
const neighbor = this.mg.playerBySmallID(id);
|
||||
if (!neighbor.isPlayer() || neighbor.isFriendly(this.player)) {
|
||||
continue;
|
||||
}
|
||||
neighbors.add(neighbor);
|
||||
}
|
||||
|
||||
// If there are no enemies, return null
|
||||
if (neighbors.size === 0) {
|
||||
return null;
|
||||
@@ -251,7 +243,7 @@ export class PlayerExecution implements Execution {
|
||||
// Get the largest attack from the neighbors
|
||||
let largestNeighborAttack: Player | null = null;
|
||||
let largestTroopCount = 0;
|
||||
for (const neighbor of neighbors) {
|
||||
for (const [neighbor] of neighbors) {
|
||||
for (const attack of neighbor.outgoingAttacks()) {
|
||||
if (attack.target() === this.player) {
|
||||
if (attack.troops() > largestTroopCount) {
|
||||
@@ -262,9 +254,12 @@ export class PlayerExecution implements Execution {
|
||||
}
|
||||
}
|
||||
|
||||
// Return the largest neighbor attack
|
||||
// If there is no largest neighbor attack, this will return null
|
||||
return largestNeighborAttack;
|
||||
if (largestNeighborAttack !== null) {
|
||||
return largestNeighborAttack;
|
||||
}
|
||||
|
||||
// There are no ongoing attacks, so find the enemy with the largest border.
|
||||
return getMode(neighbors);
|
||||
}
|
||||
|
||||
private calculateClusters(): Set<TileRef>[] {
|
||||
|
||||
Reference in New Issue
Block a user