Skip to content
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/core/configuration/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ export interface Config {
defensePostRange(): number;
SAMCooldown(): number;
SiloCooldown(): number;
minDistanceBetweenPlayers(): number;
defensePostDefenseBonus(): number;
defensePostSpeedBonus(): number;
falloutDefenseModifier(percentOfFallout: number): number;
Expand Down
3 changes: 3 additions & 0 deletions src/core/configuration/DefaultConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,9 @@ export class DefaultConfig implements Config {
temporaryEmbargoDuration(): Tick {
return 300 * 10; // 5 minutes.
}
minDistanceBetweenPlayers(): number {
return 30;
}

percentageTilesOwnedToWin(): number {
if (this._gameConfig.gameMode === GameMode.Team) {
Expand Down
30 changes: 24 additions & 6 deletions src/core/execution/BotSpawner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,33 @@ export class BotSpawner {
if (!this.gs.isLand(tile)) {
return null;
}
for (const spawn of this.bots) {
if (this.gs.manhattanDist(spawn.tile, tile) < 30) {
return null;

const isOtherPlayerSpawnedNearby = this.gs.allPlayers().some((player) => {
const spawnTile = player.spawnTile();

if (spawnTile === undefined) {
return false;
}

return (
this.gs.manhattanDist(spawnTile, tile) <
this.gs.config().minDistanceBetweenPlayers()
);
});

if (isOtherPlayerSpawnedNearby) {
return null;
}
return new SpawnExecution(
new PlayerInfo(botName, PlayerType.Bot, null, this.random.nextID()),
tile,

const playerInfo = new PlayerInfo(
botName,
PlayerType.Bot,
null,
this.random.nextID(),
);
this.gs.addPlayer(playerInfo).setSpawnTile(tile);
Comment on lines +60 to +67
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't the SpawnExecution handle this?


return new SpawnExecution(playerInfo, tile);
}

private randomBotName(): string {
Expand Down
4 changes: 2 additions & 2 deletions src/core/execution/ExecutionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,11 @@ export class Executor {
}
}

spawnBots(numBots: number): Execution[] {
spawnBots(numBots: number): SpawnExecution[] {
return new BotSpawner(this.mg, this.gameID).spawnBots(numBots);
}

spawnPlayers(): Execution[] {
spawnPlayers(): SpawnExecution[] {
return new PlayerSpawner(this.mg, this.gameID).spawnPlayers();
}

Expand Down
38 changes: 29 additions & 9 deletions src/core/execution/FakeHumanExecution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ export class FakeHumanExecution implements Execution {
if (this.random.chance(10)) {
// this.isTraitor = true
}

if (!this.mg.hasPlayer(this.nation.playerInfo.id)) {
this.player = this.mg.addPlayer(this.nation.playerInfo);
} else {
this.player = this.mg.player(this.nation.playerInfo.id);
}
}

private updateRelationsFromEmbargos() {
Expand Down Expand Up @@ -153,25 +159,21 @@ export class FakeHumanExecution implements Execution {
return;
}

if (this.player === null) {
return;
}

if (this.mg.inSpawnPhase()) {
const rl = this.randomSpawnLand();
if (rl === null) {
console.warn(`cannot spawn ${this.nation.playerInfo.name}`);
return;
}
this.player.setSpawnTile(rl);
this.mg.addExecution(new SpawnExecution(this.nation.playerInfo, rl));
return;
}

if (this.player === null) {
this.player =
this.mg.players().find((p) => p.id() === this.nation.playerInfo.id) ??
null;
if (this.player === null) {
return;
}
}

if (!this.player.isAlive()) {
this.active = false;
return;
Expand Down Expand Up @@ -643,6 +645,24 @@ export class FakeHumanExecution implements Execution {
continue;
}
const tile = this.mg.ref(x, y);

const isOtherPlayerSpawnedNearby = this.mg.allPlayers().some((player) => {
const spawnTile = player.spawnTile();

if (spawnTile === undefined) {
return false;
}

return (
this.mg.manhattanDist(spawnTile, tile) <
this.mg.config().minDistanceBetweenPlayers()
);
});

if (isOtherPlayerSpawnedNearby) {
continue;
}

if (this.mg.isLand(tile) && !this.mg.hasOwner(tile)) {
if (
this.mg.terrainType(tile) === TerrainType.Mountain &&
Expand Down
5 changes: 5 additions & 0 deletions src/core/execution/SpawnExecution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ export class SpawnExecution implements Execution {
this.mg.addExecution(new BotExecution(player));
}
}

if (player.spawnTile() === undefined) {
player.setSpawnTile(this.tile);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we want to update the spawn tile every time it changes?

like what if you have multiple spawn executions for the same player?

}

player.setHasSpawned(true);
}

Expand Down
17 changes: 6 additions & 11 deletions src/core/execution/utils/PlayerSpawner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ export class PlayerSpawner {
private random: PseudoRandom;
private players: SpawnExecution[] = [];
private static readonly MAX_SPAWN_TRIES = 10_000;
private static readonly MIN_SPAWN_DISTANCE = 30;

constructor(
private gm: Game,
Expand Down Expand Up @@ -41,18 +40,13 @@ export class PlayerSpawner {
continue;
}

let tooCloseToOtherPlayer = false;
for (const spawn of this.players) {
if (
const isOtherPlayerSpawnedNearby = this.players.some(
(spawn) =>
this.gm.manhattanDist(spawn.tile, tile) <
PlayerSpawner.MIN_SPAWN_DISTANCE
) {
tooCloseToOtherPlayer = true;
break;
}
}
this.gm.config().minDistanceBetweenPlayers(),
);

if (tooCloseToOtherPlayer) {
if (isOtherPlayerSpawnedNearby) {
continue;
}

Expand All @@ -75,6 +69,7 @@ export class PlayerSpawner {
continue;
}

player.setSpawnTile(spawnLand);
this.players.push(new SpawnExecution(player.info(), spawnLand));
}

Expand Down
2 changes: 2 additions & 0 deletions src/core/game/Game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,8 @@ export interface Player {

hasSpawned(): boolean;
setHasSpawned(hasSpawned: boolean): void;
setSpawnTile(spawnTile: TileRef): void;
spawnTile(): TileRef | undefined;

// Territory
tiles(): ReadonlySet<TileRef>;
Expand Down
9 changes: 9 additions & 0 deletions src/core/game/PlayerImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export class PlayerImpl implements Player {
public _outgoingLandAttacks: Attack[] = [];

private _hasSpawned = false;
private _spawnTile: TileRef | undefined;
private _isDisconnected = false;

constructor(
Expand Down Expand Up @@ -351,6 +352,14 @@ export class PlayerImpl implements Player {
this._hasSpawned = hasSpawned;
}

setSpawnTile(spawnTile: TileRef): void {
this._spawnTile = spawnTile;
}

spawnTile(): TileRef | undefined {
return this._spawnTile;
}

incomingAllianceRequests(): AllianceRequest[] {
return this.mg.allianceRequests.filter((ar) => ar.recipient() === this);
}
Expand Down
Loading