diff --git a/src/core/execution/FakeHumanExecution.ts b/src/core/execution/FakeHumanExecution.ts index 86654e6e1..a70893937 100644 --- a/src/core/execution/FakeHumanExecution.ts +++ b/src/core/execution/FakeHumanExecution.ts @@ -173,7 +173,6 @@ export class FakeHumanExecution implements Execution { ); if (enemyborder.length === 0) { - // No more land to expand in to if (this.random.chance(10)) { this.sendBoatRandomly(); } @@ -201,12 +200,22 @@ export class FakeHumanExecution implements Execution { const toAlly = this.random.randElement(enemies); if (this.player.canSendAllianceRequest(toAlly)) { this.player.createAllianceRequest(toAlly); + return; } } + // 50-50 attack weakest player vs random player + const toAttack = this.random.chance(2) + ? enemies[0] + : this.random.randElement(enemies); + if (this.shouldAttack(toAttack)) { + this.behavior.sendAttack(toAttack); + return; + } + this.behavior.forgetOldEnemies(); this.behavior.assistAllies(); - const enemy = this.behavior.selectEnemy(enemies); + const enemy = this.behavior.selectEnemy(); if (!enemy) return; this.maybeSendEmoji(enemy); this.maybeSendNuke(enemy); @@ -217,6 +226,42 @@ export class FakeHumanExecution implements Execution { } } + private shouldAttack(other: Player): boolean { + if (this.player === null) throw new Error("not initialized"); + if (this.player.isOnSameTeam(other)) { + return false; + } + if (this.player.isFriendly(other)) { + if (this.shouldDiscourageAttack(other)) { + return this.random.chance(200); + } + return this.random.chance(50); + } else { + if (this.shouldDiscourageAttack(other)) { + return this.random.chance(4); + } + return true; + } + } + + private shouldDiscourageAttack(other: Player) { + if (other.isTraitor()) { + return false; + } + const difficulty = this.mg.config().gameConfig().difficulty; + if ( + difficulty === Difficulty.Hard || + difficulty === Difficulty.Impossible + ) { + return false; + } + if (other.type() !== PlayerType.Human) { + return false; + } + // Only discourage attacks on Humans who are not traitors on easy or medium difficulty. + return true; + } + private maybeSendEmoji(enemy: Player) { if (this.player === null) throw new Error("not initialized"); if (enemy.type() !== PlayerType.Human) return; diff --git a/src/core/execution/utils/BotBehavior.ts b/src/core/execution/utils/BotBehavior.ts index bf5c92a4e..3e4f4245e 100644 --- a/src/core/execution/utils/BotBehavior.ts +++ b/src/core/execution/utils/BotBehavior.ts @@ -1,6 +1,5 @@ import { AllianceRequest, - Difficulty, Game, Player, PlayerType, @@ -66,48 +65,11 @@ export class BotBehavior { this.game.addExecution(new EmojiExecution(this.player, player.id(), emoji)); } - private setNewEnemy(newEnemy: Player | null, force = false) { - if (newEnemy !== null && !force && !this.shouldAttack(newEnemy)) return; + private setNewEnemy(newEnemy: Player | null) { this.enemy = newEnemy; this.enemyUpdated = this.game.ticks(); } - private shouldAttack(other: Player): boolean { - if (this.player === null) throw new Error("not initialized"); - if (this.player.isOnSameTeam(other)) { - return false; - } - if (this.player.isFriendly(other)) { - if (this.shouldDiscourageAttack(other)) { - return this.random.chance(200); - } - return this.random.chance(50); - } else { - if (this.shouldDiscourageAttack(other)) { - return this.random.chance(4); - } - return true; - } - } - - private shouldDiscourageAttack(other: Player) { - if (other.isTraitor()) { - return false; - } - const difficulty = this.game.config().gameConfig().difficulty; - if ( - difficulty === Difficulty.Hard || - difficulty === Difficulty.Impossible - ) { - return false; - } - if (other.type() !== PlayerType.Human) { - return false; - } - // Only discourage attacks on Humans who are not traitors on easy or medium difficulty. - return true; - } - private clearEnemy() { this.enemy = null; } @@ -136,7 +98,7 @@ export class BotBehavior { largestAttacker = attack.attacker(); } if (largestAttacker !== undefined) { - this.setNewEnemy(largestAttacker, true); + this.setNewEnemy(largestAttacker); } } @@ -172,8 +134,7 @@ export class BotBehavior { } } - /** Nation enemy selection logic */ - selectEnemy(enemies: Player[]): Player | null { + selectEnemy(): Player | null { if (this.enemy === null) { // Save up troops until we reach the trigger ratio if (!this.hasSufficientTroops()) return null; @@ -204,13 +165,11 @@ export class BotBehavior { // Retaliate against incoming attacks if (this.enemy === null) { - // Only after clearing bots this.checkIncomingAttacks(); } // Select the most hated player - if (this.enemy === null && this.random.chance(2)) { - // 50% chance + if (this.enemy === null) { const mostHated = this.player.allRelationsSorted()[0]; if ( mostHated !== undefined && @@ -219,23 +178,12 @@ export class BotBehavior { this.setNewEnemy(mostHated.player); } } - - // Select the weakest player - if (this.enemy === null && enemies.length > 0) { - this.setNewEnemy(enemies[0]); - } - - // Select a random player - if (this.enemy === null) { - this.setNewEnemy(this.random.randElement(enemies)); - } } // Sanity check, don't attack our allies or teammates return this.enemySanityCheck(); } - /** Bot enemy selection logic */ selectRandomEnemy(): Player | TerraNullius | null { if (this.enemy === null) { // Save up troops until we reach the trigger ratio