mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-08-16 13:14:56 +00:00
Combine Bot and Nation behaviors in to a shared class (#434)
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>
This commit is contained in:
co-authored by
Scott Anderson
parent
ccadd7f6a8
commit
1b672420b3
@@ -1,13 +1,7 @@
|
||||
import {
|
||||
Execution,
|
||||
Game,
|
||||
Player,
|
||||
PlayerType,
|
||||
TerraNullius,
|
||||
} from "../game/Game";
|
||||
import { Execution, Game, Player } from "../game/Game";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { simpleHash } from "../Util";
|
||||
import { AttackExecution } from "./AttackExecution";
|
||||
import { BotBehavior } from "./utils/BotBehavior";
|
||||
|
||||
export class BotExecution implements Execution {
|
||||
private active = true;
|
||||
@@ -16,18 +10,20 @@ export class BotExecution implements Execution {
|
||||
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, ticks: number) {
|
||||
init(mg: Game) {
|
||||
this.mg = mg;
|
||||
this.bot.setTargetTroopRatio(0.7);
|
||||
// this.neighborsTerra = this.bot.neighbors().filter(n => n == this.gs.terraNullius()).length > 0
|
||||
}
|
||||
|
||||
tick(ticks: number) {
|
||||
@@ -40,14 +36,15 @@ export class BotExecution implements Execution {
|
||||
return;
|
||||
}
|
||||
|
||||
this.bot.incomingAllianceRequests().forEach((ar) => {
|
||||
if (ar.requestor().isTraitor()) {
|
||||
ar.reject();
|
||||
} else {
|
||||
ar.accept();
|
||||
}
|
||||
});
|
||||
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[];
|
||||
@@ -55,56 +52,22 @@ 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);
|
||||
this.behavior.sendAttack(toAttack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.neighborsTerraNullius) {
|
||||
for (const b of this.bot.borderTiles()) {
|
||||
for (const n of this.mg.neighbors(b)) {
|
||||
if (!this.mg.hasOwner(n) && this.mg.isLand(n)) {
|
||||
this.sendAttack(this.mg.terraNullius());
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.bot.sharesBorderWith(this.mg.terraNullius())) {
|
||||
this.behavior.sendAttack(this.mg.terraNullius());
|
||||
return;
|
||||
}
|
||||
this.neighborsTerraNullius = false;
|
||||
}
|
||||
|
||||
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()) {
|
||||
if (this.bot.isFriendly(owner)) {
|
||||
return;
|
||||
}
|
||||
if (owner.type() == PlayerType.FakeHuman) {
|
||||
if (!this.random.chance(2)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.sendAttack(owner);
|
||||
}
|
||||
|
||||
sendAttack(toAttack: Player | TerraNullius) {
|
||||
if (toAttack.isPlayer() && this.bot.isOnSameTeam(toAttack)) return;
|
||||
this.mg.addExecution(
|
||||
new AttackExecution(
|
||||
this.bot.troops() / 20,
|
||||
this.bot.id(),
|
||||
toAttack.isPlayer() ? toAttack.id() : null,
|
||||
),
|
||||
);
|
||||
const enemy = this.behavior.selectRandomEnemy();
|
||||
if (!enemy) return;
|
||||
this.behavior.sendAttack(enemy);
|
||||
}
|
||||
|
||||
owner(): Player {
|
||||
|
||||
Reference in New Issue
Block a user