mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 15:00:43 +00:00
2e442c9c29
## Description: - Create a new expand ratio that allows AI players to expand with a much lower reserve ratio than the normal attack reserve ratio. - Unify the implementation of the first attack between bots and nations. - Bugfix: Multiple attacks per tick could cause nations to full-send. - Improve the chance of finding a place to boat to by allowing nations to target non-shore land tiles. ## 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
96 lines
2.5 KiB
TypeScript
96 lines
2.5 KiB
TypeScript
import { Execution, Game, Player } from "../game/Game";
|
|
import { PseudoRandom } from "../PseudoRandom";
|
|
import { simpleHash } from "../Util";
|
|
import { BotBehavior } from "./utils/BotBehavior";
|
|
|
|
export class BotExecution implements Execution {
|
|
private active = true;
|
|
private random: PseudoRandom;
|
|
private mg: Game;
|
|
private neighborsTerraNullius = true;
|
|
|
|
private behavior: BotBehavior | null = null;
|
|
private attackRate: number;
|
|
private attackTick: number;
|
|
private triggerRatio: number;
|
|
private reserveRatio: number;
|
|
private expandRatio: number;
|
|
|
|
constructor(private bot: Player) {
|
|
this.random = new PseudoRandom(simpleHash(bot.id()));
|
|
this.attackRate = this.random.nextInt(40, 80);
|
|
this.attackTick = this.random.nextInt(0, this.attackRate);
|
|
this.triggerRatio = this.random.nextInt(60, 90) / 100;
|
|
this.reserveRatio = this.random.nextInt(20, 30) / 100;
|
|
this.expandRatio = this.random.nextInt(10, 20) / 100;
|
|
}
|
|
|
|
activeDuringSpawnPhase(): boolean {
|
|
return false;
|
|
}
|
|
|
|
init(mg: Game) {
|
|
this.mg = mg;
|
|
this.bot.setTargetTroopRatio(0.7);
|
|
}
|
|
|
|
tick(ticks: number) {
|
|
if (ticks % this.attackRate !== this.attackTick) return;
|
|
|
|
if (!this.bot.isAlive()) {
|
|
this.active = false;
|
|
return;
|
|
}
|
|
|
|
if (this.behavior === null) {
|
|
this.behavior = new BotBehavior(
|
|
this.random,
|
|
this.mg,
|
|
this.bot,
|
|
this.triggerRatio,
|
|
this.reserveRatio,
|
|
this.expandRatio,
|
|
);
|
|
|
|
// Send an attack on the first tick
|
|
this.behavior.sendAttack(this.mg.terraNullius());
|
|
return;
|
|
}
|
|
|
|
this.behavior.handleAllianceRequests();
|
|
this.maybeAttack();
|
|
}
|
|
|
|
private maybeAttack() {
|
|
if (this.behavior === null) {
|
|
throw new Error("not initialized");
|
|
}
|
|
const toAttack = this.behavior.getNeighborTraitorToAttack();
|
|
if (toAttack !== null) {
|
|
const odds = this.bot.isFriendly(toAttack) ? 6 : 3;
|
|
if (this.random.chance(odds)) {
|
|
this.behavior.sendAttack(toAttack);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (this.neighborsTerraNullius) {
|
|
if (this.bot.sharesBorderWith(this.mg.terraNullius())) {
|
|
this.behavior.sendAttack(this.mg.terraNullius());
|
|
return;
|
|
}
|
|
this.neighborsTerraNullius = false;
|
|
}
|
|
|
|
this.behavior.forgetOldEnemies();
|
|
const enemy = this.behavior.selectRandomEnemy();
|
|
if (!enemy) return;
|
|
if (!this.bot.sharesBorderWith(enemy)) return;
|
|
this.behavior.sendAttack(enemy);
|
|
}
|
|
|
|
isActive(): boolean {
|
|
return this.active;
|
|
}
|
|
}
|