diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index 9b7880224..5c0d170c6 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -488,7 +488,7 @@ export class DefaultConfig implements Config { (defender.isTraitor() ? this.traitorDefenseDebuff() : 1), defenderTroopLoss: defenderdensity, tilesPerTickUsed: - 9 * + 8 * within(defenderdensity, 3, 100) ** 0.5 * (10_000 / attackTroops) ** 0.1 * speed * @@ -498,7 +498,7 @@ export class DefaultConfig implements Config { return { attackerTroopLoss: attackerType == PlayerType.Bot ? mag * 10 : mag * 10, defenderTroopLoss: 0, - tilesPerTickUsed: 30 * speed * (10_000 / attackTroops) ** 0.5, + tilesPerTickUsed: 30 * speed, // * (10_000 / attackTroops) ** 0.5, }; } } diff --git a/src/core/execution/FakeHumanExecution.ts b/src/core/execution/FakeHumanExecution.ts index ab9414544..3e960d789 100644 --- a/src/core/execution/FakeHumanExecution.ts +++ b/src/core/execution/FakeHumanExecution.ts @@ -879,14 +879,15 @@ export class FakeHumanExecution implements Execution { this.dogpileTarget = null; return; } - const CHECK_INTERVAL = 50; // only check every 50 ticks - if (this.mg.ticks() - this.dogpileLastChecked < CHECK_INTERVAL) return; + const CHECK_INTERVAL = 50; + if (this.mg.ticks() - this.dogpileLastChecked < CHECK_INTERVAL) return; this.dogpileLastChecked = this.mg.ticks(); const alivePlayers = this.mg .players() .filter((p) => p.isAlive() && p.isPlayer()); + if (alivePlayers.length < 2) { this.dogpileTarget = null; return; @@ -898,10 +899,18 @@ export class FakeHumanExecution implements Execution { const top = sorted[0]; const second = sorted[1]; + // Dominant player condition if (top.numTilesOwned() > second.numTilesOwned() * 2) { - this.dogpileTarget = top; - } else if (this.dogpileTarget != null && this.dogpileTarget != top) { - // if top player changes, reset + // Enter dogpile with probability (e.g. 30%) + if (this.dogpileTarget !== top && this.random.chance(5)) { + this.dogpileTarget = top; + } + } else { + this.dogpileTarget = null; + } + + // Reset if the dominant player changed + if (this.dogpileTarget && this.dogpileTarget !== top) { this.dogpileTarget = null; } } diff --git a/src/core/execution/utils/BotBehavior.ts b/src/core/execution/utils/BotBehavior.ts index 88407016e..d4f1dbff2 100644 --- a/src/core/execution/utils/BotBehavior.ts +++ b/src/core/execution/utils/BotBehavior.ts @@ -94,15 +94,13 @@ export class BotBehavior { } // Prefer neighboring bots - if (this.enemy === null) { - const bots = this.player - .neighbors() - .filter((n) => n.isPlayer() && n.type() === PlayerType.Bot) as Player[]; - if (bots.length > 0) { - const density = (p: Player) => p.troops() / p.numTilesOwned(); - this.enemy = bots.sort((a, b) => density(a) - density(b))[0]; - this.enemyUpdated = this.game.ticks(); - } + const bots = this.player + .neighbors() + .filter((n) => n.isPlayer() && n.type() === PlayerType.Bot) as Player[]; + if (bots.length > 0) { + const density = (p: Player) => p.troops() / p.numTilesOwned(); + this.enemy = bots.sort((a, b) => density(a) - density(b))[0]; + this.enemyUpdated = this.game.ticks(); } // Select the most hated player