mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-22 21:55:22 +00:00
1b672420b3
This is the first move in the effort to combine the redundant logic that exists between BotExecution and FakeHumonExecution. This commit: 1. Combines the alliance request handler, moving bots to use the same logic as nations for acceptance. 2. Combines the sendAttack() functions, which may later be reworked. 3. Introduces selectEnemy() function to wrap enemy selection logic that nations use. 4. Blocks nations from nuking bots. 5. Alters enemy selection to prefer neighboring bots if there are any. ## Description: Fixes #467 ## Please complete the following: - [x] I have added screenshots for all UI updates - [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 ## Please put your Discord username so you can be contacted if a bug or regression is found: fake.neo --------- Co-authored-by: Scott Anderson <662325+scottanderson@users.noreply.github.com>
81 lines
1.9 KiB
TypeScript
81 lines
1.9 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 attackRate: number;
|
|
private mg: Game;
|
|
private neighborsTerraNullius = true;
|
|
|
|
private behavior: BotBehavior | null = null;
|
|
|
|
constructor(private bot: Player) {
|
|
this.random = new PseudoRandom(simpleHash(bot.id()));
|
|
this.attackRate = this.random.nextInt(10, 50);
|
|
}
|
|
|
|
activeDuringSpawnPhase(): boolean {
|
|
return false;
|
|
}
|
|
|
|
init(mg: Game) {
|
|
this.mg = mg;
|
|
this.bot.setTargetTroopRatio(0.7);
|
|
}
|
|
|
|
tick(ticks: number) {
|
|
if (!this.bot.isAlive()) {
|
|
this.active = false;
|
|
return;
|
|
}
|
|
|
|
if (ticks % this.attackRate != 0) {
|
|
return;
|
|
}
|
|
|
|
if (this.behavior === null) {
|
|
this.behavior = new BotBehavior(this.random, this.mg, this.bot, 1 / 20);
|
|
}
|
|
|
|
this.behavior.handleAllianceRequests();
|
|
this.maybeAttack();
|
|
}
|
|
|
|
private maybeAttack() {
|
|
const traitors = this.bot
|
|
.neighbors()
|
|
.filter((n) => n.isPlayer() && n.isTraitor()) as Player[];
|
|
if (traitors.length > 0) {
|
|
const toAttack = this.random.randElement(traitors);
|
|
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;
|
|
}
|
|
|
|
const enemy = this.behavior.selectRandomEnemy();
|
|
if (!enemy) return;
|
|
this.behavior.sendAttack(enemy);
|
|
}
|
|
|
|
owner(): Player {
|
|
return this.bot;
|
|
}
|
|
|
|
isActive(): boolean {
|
|
return this.active;
|
|
}
|
|
}
|