diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index beffd9d38..1773fb222 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -479,6 +479,9 @@ export class DefaultConfig implements Config { const defenderTroops = defender.troops(); const defenderTiles = defender.numTilesOwned(); const defenderdensity = defenderTroops / defenderTiles; + const avgDefenseDensity = gm.averageDefenseDensity(); + const relativeDensity = + defenderdensity / Math.max(1e-6, avgDefenseDensity); const adjustedRatio = within(defenderTroops / attackTroops, 0.3, 20); return { attackerTroopLoss: @@ -486,9 +489,9 @@ export class DefaultConfig implements Config { defenderdensity * mag * (defender.isTraitor() ? this.traitorDefenseDebuff() : 1), - defenderTroopLoss: defenderdensity, + defenderTroopLoss: relativeDensity, tilesPerTickUsed: within( - 6.6 * defenderdensity ** 0.2 * adjustedRatio ** 0.4 * speed, + 16 * defenderdensity ** 0.3 * adjustedRatio ** 0.4 * speed, 6, 500, ), diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts index ebf4857bd..02bc8ba55 100644 --- a/src/core/game/Game.ts +++ b/src/core/game/Game.ts @@ -480,6 +480,7 @@ export interface Game extends GameMap { executeNextTick(): GameUpdates; setWinner(winner: Player | Team, allPlayersStats: AllPlayersStats): void; config(): Config; + averageDefenseDensity(): number; // Units units(...types: UnitType[]): Unit[]; diff --git a/src/core/game/GameImpl.ts b/src/core/game/GameImpl.ts index 21b10c21d..b53d1f2e2 100644 --- a/src/core/game/GameImpl.ts +++ b/src/core/game/GameImpl.ts @@ -714,6 +714,19 @@ export class GameImpl implements Game { stats(): Stats { return this._stats; } + averageDefenseDensity(): number { + let totalTroops = 0; + let totalTiles = 0; + for (const player of this.players()) { + if (!player.isAlive()) continue; + totalTroops += player.troops(); + totalTiles += player.numTilesOwned(); + } + if (totalTiles === 0) { + return 1; // safe fallback to prevent division by 0 + } + return totalTroops / totalTiles; + } } // Or a more dynamic approach that will catch new enum values: