mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 15:20:43 +00:00
refactor: rename Bot to Tribe in internal execution code (#3372)
## Description Follows up on #3290 which renamed the user-facing "Bots" to "Tribes". This renames the internal implementation to match: - `BotExecution` → `TribeExecution` - `BotSpawner` → `TribeSpawner` - `BotNames` → `TribeNames` (`BOT_NAME_*` → `TRIBE_NAME_*`) All callers updated accordingly. `PlayerType.Bot` and `ColoredTeams.Bot` are intentionally left unchanged as they are serialised wire-format values. Closes #3335 ## Please complete the following: - [x] My changes do not break existing functionality - [x] I have tested my changes ## Please put your Discord username so you can be contacted if a bug or regression is found: Just reply here --------- Co-authored-by: PGray <PGrayCS@users.noreply.github.com>
This commit is contained in:
@@ -99,7 +99,7 @@ export class GameRunner {
|
||||
}
|
||||
if (this.game.config().bots() > 0) {
|
||||
this.game.addExecution(
|
||||
...this.execManager.spawnBots(this.game.config().numBots()),
|
||||
...this.execManager.spawnTribes(this.game.config().bots()),
|
||||
);
|
||||
}
|
||||
if (this.game.config().spawnNations()) {
|
||||
|
||||
+7
-6
@@ -13,9 +13,9 @@ import {
|
||||
} from "./Schemas";
|
||||
|
||||
import {
|
||||
BOT_NAME_PREFIXES,
|
||||
BOT_NAME_SUFFIXES,
|
||||
} from "./execution/utils/BotNames";
|
||||
TRIBE_NAME_PREFIXES,
|
||||
TRIBE_NAME_SUFFIXES,
|
||||
} from "./execution/utils/TribeNames";
|
||||
|
||||
export function manhattanDistWrapped(
|
||||
c1: Cell,
|
||||
@@ -296,11 +296,12 @@ export function createRandomName(
|
||||
let randomName: string | null = null;
|
||||
if (playerType === PlayerType.Human) {
|
||||
const hash = simpleHash(name);
|
||||
const prefixIndex = hash % BOT_NAME_PREFIXES.length;
|
||||
const prefixIndex = hash % TRIBE_NAME_PREFIXES.length;
|
||||
const suffixIndex =
|
||||
Math.floor(hash / BOT_NAME_PREFIXES.length) % BOT_NAME_SUFFIXES.length;
|
||||
Math.floor(hash / TRIBE_NAME_PREFIXES.length) %
|
||||
TRIBE_NAME_SUFFIXES.length;
|
||||
|
||||
randomName = `👤 ${BOT_NAME_PREFIXES[prefixIndex]} ${BOT_NAME_SUFFIXES[suffixIndex]}`;
|
||||
randomName = `👤 ${TRIBE_NAME_PREFIXES[prefixIndex]} ${TRIBE_NAME_SUFFIXES[suffixIndex]}`;
|
||||
}
|
||||
return randomName;
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
import { Game, PlayerInfo, PlayerType } from "../game/Game";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { GameID } from "../Schemas";
|
||||
import { simpleHash } from "../Util";
|
||||
import { SpawnExecution } from "./SpawnExecution";
|
||||
import { BOT_NAME_PREFIXES, BOT_NAME_SUFFIXES } from "./utils/BotNames";
|
||||
|
||||
export class BotSpawner {
|
||||
private random: PseudoRandom;
|
||||
private bots: SpawnExecution[] = [];
|
||||
|
||||
constructor(
|
||||
private gs: Game,
|
||||
private gameID: GameID,
|
||||
) {
|
||||
// Use a different seed than createGameRunner (which uses simpleHash(gameID))
|
||||
// to avoid bot IDs colliding with nation/human IDs from the same PRNG sequence.
|
||||
this.random = new PseudoRandom(simpleHash(gameID) + 2);
|
||||
}
|
||||
|
||||
spawnBots(numBots: number): SpawnExecution[] {
|
||||
for (let i = 0; i < numBots; i++) {
|
||||
const name = this.randomBotName();
|
||||
const spawn = this.spawnBot(name);
|
||||
this.bots.push(spawn);
|
||||
}
|
||||
|
||||
return this.bots;
|
||||
}
|
||||
|
||||
spawnBot(botName: string): SpawnExecution {
|
||||
return new SpawnExecution(
|
||||
this.gameID,
|
||||
new PlayerInfo(botName, PlayerType.Bot, null, this.random.nextID()),
|
||||
);
|
||||
}
|
||||
|
||||
private randomBotName(): string {
|
||||
const prefixIndex = this.random.nextInt(0, BOT_NAME_PREFIXES.length);
|
||||
const suffixIndex = this.random.nextInt(0, BOT_NAME_SUFFIXES.length);
|
||||
return `${BOT_NAME_PREFIXES[prefixIndex]} ${BOT_NAME_SUFFIXES[suffixIndex]}`;
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ import { AllianceRequestExecution } from "./alliance/AllianceRequestExecution";
|
||||
import { BreakAllianceExecution } from "./alliance/BreakAllianceExecution";
|
||||
import { AttackExecution } from "./AttackExecution";
|
||||
import { BoatRetreatExecution } from "./BoatRetreatExecution";
|
||||
import { BotSpawner } from "./BotSpawner";
|
||||
import { ConstructionExecution } from "./ConstructionExecution";
|
||||
import { DeleteUnitExecution } from "./DeleteUnitExecution";
|
||||
import { DonateGoldExecution } from "./DonateGoldExecution";
|
||||
@@ -26,6 +25,7 @@ import { RetreatExecution } from "./RetreatExecution";
|
||||
import { SpawnExecution } from "./SpawnExecution";
|
||||
import { TargetPlayerExecution } from "./TargetPlayerExecution";
|
||||
import { TransportShipExecution } from "./TransportShipExecution";
|
||||
import { TribeSpawner } from "./TribeSpawner";
|
||||
import { UpgradeStructureExecution } from "./UpgradeStructureExecution";
|
||||
import { PlayerSpawner } from "./utils/PlayerSpawner";
|
||||
|
||||
@@ -38,7 +38,7 @@ export class Executor {
|
||||
private gameID: GameID,
|
||||
private clientID: ClientID | undefined,
|
||||
) {
|
||||
// Add one to avoid id collisions with bots.
|
||||
// Add one to avoid id collisions with tribes.
|
||||
this.random = new PseudoRandom(simpleHash(gameID) + 1);
|
||||
}
|
||||
|
||||
@@ -126,8 +126,8 @@ export class Executor {
|
||||
}
|
||||
}
|
||||
|
||||
spawnBots(numBots: number): SpawnExecution[] {
|
||||
return new BotSpawner(this.mg, this.gameID).spawnBots(numBots);
|
||||
spawnTribes(numTribes: number): SpawnExecution[] {
|
||||
return new TribeSpawner(this.mg, this.gameID).spawnTribes(numTribes);
|
||||
}
|
||||
|
||||
spawnPlayers(): SpawnExecution[] {
|
||||
|
||||
@@ -10,8 +10,8 @@ import { TileRef } from "../game/GameMap";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { GameID } from "../Schemas";
|
||||
import { simpleHash } from "../Util";
|
||||
import { BotExecution } from "./BotExecution";
|
||||
import { PlayerExecution } from "./PlayerExecution";
|
||||
import { TribeExecution } from "./TribeExecution";
|
||||
import { getSpawnTiles } from "./Util";
|
||||
|
||||
type Spawn = { center: TileRef; tiles: TileRef[] };
|
||||
@@ -71,7 +71,7 @@ export class SpawnExecution implements Execution {
|
||||
if (!player.hasSpawned()) {
|
||||
this.mg.addExecution(new PlayerExecution(player));
|
||||
if (player.type() === PlayerType.Bot) {
|
||||
this.mg.addExecution(new BotExecution(player));
|
||||
this.mg.addExecution(new TribeExecution(player));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Execution, Game, Player, Structures } from "../game/Game";
|
||||
import { Execution, Game, Player, Structures } from "../game/Game";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { simpleHash } from "../Util";
|
||||
import { AllianceExtensionExecution } from "./alliance/AllianceExtensionExecution";
|
||||
import { DeleteUnitExecution } from "./DeleteUnitExecution";
|
||||
import { AiAttackBehavior } from "./utils/AiAttackBehavior";
|
||||
|
||||
export class BotExecution implements Execution {
|
||||
export class TribeExecution implements Execution {
|
||||
private active = true;
|
||||
private random: PseudoRandom;
|
||||
private mg: Game;
|
||||
@@ -18,8 +18,8 @@ export class BotExecution implements Execution {
|
||||
private reserveRatio: number;
|
||||
private expandRatio: number;
|
||||
|
||||
constructor(private bot: Player) {
|
||||
this.random = new PseudoRandom(simpleHash(bot.id()));
|
||||
constructor(private tribe: Player) {
|
||||
this.random = new PseudoRandom(simpleHash(tribe.id()));
|
||||
this.attackRate = this.random.nextInt(40, 80);
|
||||
this.attackTick = this.random.nextInt(0, this.attackRate);
|
||||
this.triggerRatio = this.random.nextInt(50, 60) / 100;
|
||||
@@ -38,8 +38,8 @@ export class BotExecution implements Execution {
|
||||
tick(ticks: number) {
|
||||
if (ticks % this.attackRate !== this.attackTick) return;
|
||||
|
||||
if (!this.bot.isAlive()) {
|
||||
//removeOnDeath is called from bot's PlayerExecution
|
||||
if (!this.tribe.isAlive()) {
|
||||
//removeOnDeath is called from tribe's PlayerExecution
|
||||
this.active = false;
|
||||
return;
|
||||
}
|
||||
@@ -48,7 +48,7 @@ export class BotExecution implements Execution {
|
||||
this.attackBehavior = new AiAttackBehavior(
|
||||
this.random,
|
||||
this.mg,
|
||||
this.bot,
|
||||
this.tribe,
|
||||
this.triggerRatio,
|
||||
this.reserveRatio,
|
||||
this.expandRatio,
|
||||
@@ -66,27 +66,27 @@ export class BotExecution implements Execution {
|
||||
|
||||
private acceptAllAllianceRequests() {
|
||||
// Accept all alliance requests
|
||||
for (const req of this.bot.incomingAllianceRequests()) {
|
||||
for (const req of this.tribe.incomingAllianceRequests()) {
|
||||
req.accept();
|
||||
}
|
||||
|
||||
// Accept all alliance extension requests
|
||||
for (const alliance of this.bot.alliances()) {
|
||||
for (const alliance of this.tribe.alliances()) {
|
||||
// Alliance expiration tracked by Events Panel, only human ally can click Request to Renew
|
||||
// Skip if no expiration yet/ ally didn't request extension yet / bot already agreed to extend
|
||||
// Skip if no expiration yet/ ally didn't request extension yet / tribe already agreed to extend
|
||||
if (!alliance.onlyOneAgreedToExtend()) continue;
|
||||
|
||||
const human = alliance.other(this.bot);
|
||||
const human = alliance.other(this.tribe);
|
||||
this.mg.addExecution(
|
||||
new AllianceExtensionExecution(this.bot, human.id()),
|
||||
new AllianceExtensionExecution(this.tribe, human.id()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private deleteAllStructures() {
|
||||
for (const unit of this.bot.units()) {
|
||||
if (Structures.has(unit.type()) && this.bot.canDeleteUnit()) {
|
||||
this.mg.addExecution(new DeleteUnitExecution(this.bot, unit.id()));
|
||||
for (const unit of this.tribe.units()) {
|
||||
if (Structures.has(unit.type()) && this.tribe.canDeleteUnit()) {
|
||||
this.mg.addExecution(new DeleteUnitExecution(this.tribe, unit.id()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,13 +97,13 @@ export class BotExecution implements Execution {
|
||||
}
|
||||
const toAttack = this.attackBehavior.getNeighborTraitorToAttack();
|
||||
if (toAttack !== null) {
|
||||
const odds = this.bot.isFriendly(toAttack) ? 6 : 3;
|
||||
const odds = this.tribe.isFriendly(toAttack) ? 6 : 3;
|
||||
if (this.random.chance(odds)) {
|
||||
// Check and break alliance before attacking if needed
|
||||
const alliance = this.bot.allianceWith(toAttack);
|
||||
const alliance = this.tribe.allianceWith(toAttack);
|
||||
|
||||
if (alliance !== null) {
|
||||
this.bot.breakAlliance(alliance);
|
||||
this.tribe.breakAlliance(alliance);
|
||||
}
|
||||
|
||||
this.attackBehavior.sendAttack(toAttack);
|
||||
@@ -112,7 +112,7 @@ export class BotExecution implements Execution {
|
||||
}
|
||||
|
||||
if (this.neighborsTerraNullius) {
|
||||
if (this.bot.neighbors().some((n) => !n.isPlayer())) {
|
||||
if (this.tribe.neighbors().some((n) => !n.isPlayer())) {
|
||||
this.attackBehavior.sendAttack(this.mg.terraNullius());
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Game, PlayerInfo, PlayerType } from "../game/Game";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { GameID } from "../Schemas";
|
||||
import { simpleHash } from "../Util";
|
||||
import { SpawnExecution } from "./SpawnExecution";
|
||||
import { TRIBE_NAME_PREFIXES, TRIBE_NAME_SUFFIXES } from "./utils/TribeNames";
|
||||
|
||||
export class TribeSpawner {
|
||||
private random: PseudoRandom;
|
||||
|
||||
constructor(
|
||||
private gs: Game,
|
||||
private gameID: GameID,
|
||||
) {
|
||||
// Use a different seed than createGameRunner (which uses simpleHash(gameID))
|
||||
// to avoid tribe IDs colliding with nation/human IDs from the same PRNG sequence.
|
||||
this.random = new PseudoRandom(simpleHash(gameID) + 2);
|
||||
}
|
||||
|
||||
spawnTribes(numTribes: number): SpawnExecution[] {
|
||||
const tribes: SpawnExecution[] = [];
|
||||
for (let i = 0; i < numTribes; i++) {
|
||||
tribes.push(this.spawnTribe(this.randomTribeName()));
|
||||
}
|
||||
return tribes;
|
||||
}
|
||||
|
||||
spawnTribe(tribeName: string): SpawnExecution {
|
||||
return new SpawnExecution(
|
||||
this.gameID,
|
||||
new PlayerInfo(tribeName, PlayerType.Bot, null, this.random.nextID()),
|
||||
);
|
||||
}
|
||||
|
||||
private randomTribeName(): string {
|
||||
const prefixIndex = this.random.nextInt(0, TRIBE_NAME_PREFIXES.length);
|
||||
const suffixIndex = this.random.nextInt(0, TRIBE_NAME_SUFFIXES.length);
|
||||
return `${TRIBE_NAME_PREFIXES[prefixIndex]} ${TRIBE_NAME_SUFFIXES[suffixIndex]}`;
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ export class NationNukeBehavior {
|
||||
const silos = this.player.units(UnitType.MissileSilo);
|
||||
if (
|
||||
silos.length === 0 ||
|
||||
nukeTarget.type() === PlayerType.Bot || // Don't nuke bots (as opposed to nations and humans)
|
||||
nukeTarget.type() === PlayerType.Bot || // Don't nuke tribes (as opposed to nations and humans)
|
||||
this.player.isOnSameTeam(nukeTarget) ||
|
||||
this.attackBehavior.shouldAttack(nukeTarget) === false
|
||||
) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export const BOT_NAME_PREFIXES = [
|
||||
export const TRIBE_NAME_PREFIXES = [
|
||||
"Akkadian",
|
||||
"Babylonian",
|
||||
"Sumerian",
|
||||
@@ -159,8 +159,6 @@ export const BOT_NAME_PREFIXES = [
|
||||
"Armenian",
|
||||
"Circassian",
|
||||
"Georgian",
|
||||
"Phoenician",
|
||||
"Chaldean",
|
||||
"Kurdish",
|
||||
"Turkic",
|
||||
"Kazakh",
|
||||
@@ -171,7 +169,6 @@ export const BOT_NAME_PREFIXES = [
|
||||
"Pashtun",
|
||||
"Baloch",
|
||||
"Afghan",
|
||||
"Persian",
|
||||
"Kenyan",
|
||||
"Ugandan",
|
||||
"Bhutanese",
|
||||
@@ -180,7 +177,7 @@ export const BOT_NAME_PREFIXES = [
|
||||
"Militant",
|
||||
"Spartan",
|
||||
];
|
||||
export const BOT_NAME_SUFFIXES = [
|
||||
export const TRIBE_NAME_SUFFIXES = [
|
||||
"Empire",
|
||||
"Dynasty",
|
||||
"Kingdom",
|
||||
@@ -218,7 +215,6 @@ export const BOT_NAME_SUFFIXES = [
|
||||
"Confederacy",
|
||||
"Order",
|
||||
"Regime",
|
||||
"Dominion",
|
||||
"Syndicate",
|
||||
"Guild",
|
||||
"Corporation",
|
||||
@@ -231,10 +227,7 @@ export const BOT_NAME_SUFFIXES = [
|
||||
"Sisterhood",
|
||||
"Ascendancy",
|
||||
"Supremacy",
|
||||
"Province",
|
||||
"Tribe",
|
||||
"Dominion",
|
||||
"Assembly",
|
||||
"Republics",
|
||||
"Army",
|
||||
"Dictatorship",
|
||||
@@ -508,7 +508,7 @@ export class PlayerInfo {
|
||||
constructor(
|
||||
public readonly name: string,
|
||||
public readonly playerType: PlayerType,
|
||||
// null if bot.
|
||||
// null if tribe.
|
||||
public readonly clientID: ClientID | null,
|
||||
// TODO: make player id the small id
|
||||
public readonly id: PlayerID,
|
||||
|
||||
Reference in New Issue
Block a user