import { consolex } from "../Consolex"; import { Cell, Game, PlayerType } from "../game/Game"; import { TileRef } from "../game/GameMap"; import { PseudoRandom } from "../PseudoRandom"; import { GameID, SpawnIntent } from "../Schemas"; import { simpleHash } from "../Util"; import { BOT_NAME_PREFIXES, BOT_NAME_SUFFIXES } from "./utils/BotNames"; export class BotSpawner { private random: PseudoRandom private bots: SpawnIntent[] = []; constructor(private gs: Game, gameID: GameID) { this.random = new PseudoRandom(simpleHash(gameID)) } spawnBots(numBots: number): SpawnIntent[] { let tries = 0 while (this.bots.length < numBots) { if (tries > 10000) { consolex.log('too many retries while spawning bots, giving up') return this.bots } const botName = this.randomBotName(); const spawn = this.spawnBot(botName); if (spawn != null) { this.bots.push(spawn); } else { tries++ } } return this.bots; } spawnBot(botName: string): SpawnIntent | null { const tile = this.randTile() if (!this.gs.isLand(tile)) { return null } for (const spawn of this.bots) { if (this.gs.manhattanDist(this.gs.ref(spawn.x, spawn.y), tile) < 30) { return null } } return { type: 'spawn', playerID: this.random.nextID(), name: botName, playerType: PlayerType.Bot, x: this.gs.x(tile), y: this.gs.y(tile) }; } 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]}`; } private randTile(): TileRef { return this.gs.ref( this.random.nextInt(0, this.gs.width()), this.random.nextInt(0, this.gs.height()) ) } }