This commit is contained in:
Scott Anderson
2025-04-04 00:06:41 -04:00
parent 1c0b4905e2
commit 0a3397b8c6
2 changed files with 52 additions and 28 deletions
+38 -26
View File
@@ -5,6 +5,7 @@ import {
PlayerType,
Relation,
TerraNullius,
Tick,
} from "../game/Game";
import { PseudoRandom } from "../PseudoRandom";
import { simpleHash } from "../Util";
@@ -17,6 +18,7 @@ export class BotExecution implements Execution {
private neighborsTerraNullius = true;
private enemy: Player;
private lastEnemyUpdateTick: Tick;
private attackRate: number;
private attackTick: number;
private triggerRatio: number;
@@ -77,13 +79,42 @@ export class BotExecution implements Execution {
this.neighborsTerraNullius = false;
}
if (this.mg.ticks() - this.lastEnemyUpdateTick > 100) {
this.enemy = null;
}
// Switch enemies if we're under attack
const incomingAttacks = this.bot.incomingAttacks();
if (incomingAttacks.length > 0) {
this.enemy = incomingAttacks
.sort((a, b) => b.troops() - a.troops())[0]
.attacker();
this.lastEnemyUpdateTick = this.mg.ticks();
}
if (this.enemy === null) {
// Save up troops until we reach the trigger ratio
const ratio =
this.bot.population() / this.mg.config().maxPopulation(this.bot);
if (ratio * 100 < this.triggerRatio) return;
// Select a new enemy
// Choose a new enemy randomly
const border = Array.from(this.bot.borderTiles())
.flatMap((t) => this.mg.neighbors(t))
.filter((t) => this.mg.hasOwner(t) && this.mg.owner(t) != this.bot);
if (border.length > 0) {
const toAttack = this.random.randElement(border);
const owner = this.mg.owner(toAttack);
if (!owner.isPlayer()) {
this.sendAttack(this.mg.terraNullius());
this.neighborsTerraNullius = true;
return;
}
this.enemy = owner;
this.lastEnemyUpdateTick = this.mg.ticks();
}
// Select an allied traitor as an enemy
const traitors = this.bot
.neighbors()
.filter((n) => n.isPlayer() && n.isTraitor()) as Player[];
@@ -91,26 +122,10 @@ export class BotExecution implements Execution {
const toAttack = this.random.randElement(traitors);
const odds = this.bot.isFriendly(toAttack) ? 6 : 3;
if (this.random.chance(odds)) {
this.sendAttack(toAttack);
return;
this.enemy = toAttack;
this.lastEnemyUpdateTick = this.mg.ticks();
}
}
const border = Array.from(this.bot.borderTiles())
.flatMap((t) => this.mg.neighbors(t))
.filter((t) => this.mg.hasOwner(t) && this.mg.owner(t) != this.bot);
if (border.length == 0) {
return;
}
const toAttack = border[this.random.nextInt(0, border.length)];
const owner = this.mg.owner(toAttack);
if (!owner.isPlayer()) {
this.neighborsTerraNullius = true;
return;
}
this.enemy = owner;
}
if (this.enemy) {
@@ -127,11 +142,12 @@ export class BotExecution implements Execution {
}
}
sendAttack(toAttack: Player | TerraNullius) {
private sendAttack(toAttack: Player | TerraNullius) {
if (toAttack.isPlayer() && this.bot.isOnSameTeam(toAttack)) return;
const max = this.mg.config().maxPopulation(this.bot);
const max =
this.mg.config().maxPopulation(this.bot) * this.bot.targetTroopRatio();
const target = (max * this.reserveRatio) / 100;
const troops = this.bot.population() - target;
const troops = this.bot.troops() - target;
if (troops < 1) return;
this.mg.addExecution(
new AttackExecution(
@@ -142,10 +158,6 @@ export class BotExecution implements Execution {
);
}
owner(): Player {
return this.bot;
}
isActive(): boolean {
return this.active;
}
+14 -2
View File
@@ -238,6 +238,16 @@ export class FakeHumanExecution implements Execution {
this.enemy = null;
}
// Switch enemies if we're under attack
const incomingAttacks = this.player.incomingAttacks();
if (incomingAttacks.length > 0) {
this.enemy = incomingAttacks
.sort((a, b) => b.troops() - a.troops())[0]
.attacker();
this.lastEnemyUpdateTick = this.mg.ticks();
}
// Attack allies' targets
outer: for (const ally of this.player.allies()) {
if (this.player.relation(ally) < Relation.Friendly) continue;
for (const target of ally.targets()) {
@@ -659,9 +669,11 @@ export class FakeHumanExecution implements Execution {
sendAttack(toAttack: Player | TerraNullius) {
if (toAttack.isPlayer() && this.player.isOnSameTeam(toAttack)) return;
const max = this.mg.config().maxPopulation(this.player);
const max =
this.mg.config().maxPopulation(this.player) *
this.player.targetTroopRatio();
const target = (max * this.reserveRatio) / 100;
const troops = this.player.population() - target;
const troops = this.player.troops() - target;
if (troops < 1) return;
this.mg.addExecution(
new AttackExecution(