Restore nation AI (#1440)

## Description:

Restore the nation AI that scaled with difficulty, while only allowing
one of the attack routines to attack.

## 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
- [x] I understand that submitting code with bugs that could have been
caught through manual testing blocks releases and new features for all
contributors
This commit is contained in:
Scott Anderson
2025-07-15 01:20:05 -04:00
committed by GitHub
parent be01b90b25
commit 729cc6a500
+60 -13
View File
@@ -1,5 +1,6 @@
import {
Cell,
Difficulty,
Execution,
Game,
Gold,
@@ -196,22 +197,32 @@ export class FakeHumanExecution implements Execution {
return;
}
const enemies = borderPlayers
.filter((o) => o.isPlayer())
.sort((a, b) => a.troops() - b.troops());
// 5% chance to send a random alliance request
if (this.random.chance(20)) {
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();
if (!enemy) {
// 5% chance to send a random alliance request
if (this.random.chance(20)) {
const enemies = borderPlayers
.filter((o) => o.isPlayer())
.sort((a, b) => a.troops() - b.troops());
const toAlly = this.random.randElement(enemies);
if (this.player.canSendAllianceRequest(toAlly)) {
this.player.createAllianceRequest(toAlly);
}
}
return;
}
if (!enemy) return;
this.maybeSendEmoji(enemy);
this.maybeSendNuke(enemy);
if (this.player.sharesBorderWith(enemy)) {
@@ -221,6 +232,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;