Improve random spawn (#2503)

## Description:

This is a previously approved PR with an additional commit that fixes
case when nations change spawn & jump around, their previous territory
wasn't getting deleted.

## 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

## Please put your Discord username so you can be contacted if a bug or
regression is found:

nikolaj_mykola

---------

Co-authored-by: Evan <evanpelle@gmail.com>
This commit is contained in:
Mykola
2025-12-20 13:35:30 -08:00
committed by GitHub
co-authored by Evan
parent 4ee3319397
commit 6112547273
22 changed files with 320 additions and 254 deletions
+9 -34
View File
@@ -1,5 +1,4 @@
import { Game, PlayerInfo, PlayerType } from "../game/Game";
import { TileRef } from "../game/GameMap";
import { PseudoRandom } from "../PseudoRandom";
import { GameID } from "../Schemas";
import { simpleHash } from "../Util";
@@ -17,46 +16,29 @@ export class BotSpawner {
constructor(
private gs: Game,
gameID: GameID,
private gameID: GameID,
) {
this.random = new PseudoRandom(simpleHash(gameID));
}
spawnBots(numBots: number): SpawnExecution[] {
let tries = 0;
while (this.bots.length < numBots) {
if (tries > 10000) {
console.log("too many retries while spawning bots, giving up");
return this.bots;
}
for (let i = 0; i < numBots; i++) {
const candidate = this.nextCandidateName();
const spawn = this.spawnBot(candidate.name);
if (spawn !== null) {
// Only use candidate name once bot successfully spawned
if (candidate.source === "list") {
this.nameIndex++;
}
this.bots.push(spawn);
} else {
tries++;
if (candidate.source === "list") {
this.nameIndex++;
}
this.bots.push(spawn);
}
return this.bots;
}
spawnBot(botName: string): SpawnExecution | null {
const tile = this.randTile();
if (!this.gs.isLand(tile)) {
return null;
}
for (const spawn of this.bots) {
if (this.gs.manhattanDist(spawn.tile, tile) < 30) {
return null;
}
}
spawnBot(botName: string): SpawnExecution {
return new SpawnExecution(
this.gameID,
new PlayerInfo(botName, PlayerType.Bot, null, this.random.nextID()),
tile,
);
}
@@ -97,11 +79,4 @@ export class BotSpawner {
const suffixNumber = this.random.nextInt(1, 10001);
return `Elf ${suffixNumber}`;
}
private randTile(): TileRef {
return this.gs.ref(
this.random.nextInt(0, this.gs.width()),
this.random.nextInt(0, this.gs.height()),
);
}
}