diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index 33f7ef61a..c4d1fd49b 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -348,7 +348,6 @@ export class DefaultConfig implements Config { return { cost: () => 0n, territoryBound: false, - playerBuildable: false, }; case UnitType.Warship: return { @@ -357,21 +356,18 @@ export class DefaultConfig implements Config { UnitType.Warship, ), territoryBound: false, - playerBuildable: true, maxHealth: 1000, }; case UnitType.Shell: return { cost: () => 0n, territoryBound: false, - playerBuildable: false, damage: 250, }; case UnitType.SAMMissile: return { cost: () => 0n, territoryBound: false, - playerBuildable: false, }; case UnitType.Port: return { @@ -382,7 +378,6 @@ export class DefaultConfig implements Config { UnitType.Factory, ), territoryBound: true, - playerBuildable: true, constructionDuration: this.instantBuild() ? 0 : 2 * 10, upgradable: true, }; @@ -390,13 +385,11 @@ export class DefaultConfig implements Config { return { cost: this.costWrapper(() => 750_000, UnitType.AtomBomb), territoryBound: false, - playerBuildable: true, }; case UnitType.HydrogenBomb: return { cost: this.costWrapper(() => 5_000_000, UnitType.HydrogenBomb), territoryBound: false, - playerBuildable: true, }; case UnitType.MIRV: return { @@ -407,25 +400,21 @@ export class DefaultConfig implements Config { return 25_000_000n + game.stats().numMirvsLaunched() * 15_000_000n; }, territoryBound: false, - playerBuildable: true, }; case UnitType.MIRVWarhead: return { cost: () => 0n, territoryBound: false, - playerBuildable: false, }; case UnitType.TradeShip: return { cost: () => 0n, territoryBound: false, - playerBuildable: true, }; case UnitType.MissileSilo: return { cost: this.costWrapper(() => 1_000_000, UnitType.MissileSilo), territoryBound: true, - playerBuildable: true, constructionDuration: this.instantBuild() ? 0 : 10 * 10, upgradable: true, }; @@ -436,7 +425,6 @@ export class DefaultConfig implements Config { UnitType.DefensePost, ), territoryBound: true, - playerBuildable: true, constructionDuration: this.instantBuild() ? 0 : 5 * 10, }; case UnitType.SAMLauncher: @@ -447,7 +435,6 @@ export class DefaultConfig implements Config { UnitType.SAMLauncher, ), territoryBound: true, - playerBuildable: true, constructionDuration: this.instantBuild() ? 0 : 30 * 10, upgradable: true, }; @@ -459,7 +446,6 @@ export class DefaultConfig implements Config { UnitType.City, ), territoryBound: true, - playerBuildable: true, constructionDuration: this.instantBuild() ? 0 : 2 * 10, upgradable: true, }; @@ -472,7 +458,6 @@ export class DefaultConfig implements Config { UnitType.Port, ), territoryBound: true, - playerBuildable: true, constructionDuration: this.instantBuild() ? 0 : 2 * 10, upgradable: true, }; @@ -480,7 +465,6 @@ export class DefaultConfig implements Config { return { cost: () => 0n, territoryBound: false, - playerBuildable: false, }; default: assertNever(type); diff --git a/src/core/execution/BotExecution.ts b/src/core/execution/BotExecution.ts index 8db725ee2..491bf1b21 100644 --- a/src/core/execution/BotExecution.ts +++ b/src/core/execution/BotExecution.ts @@ -1,4 +1,4 @@ -import { Execution, Game, Player } from "../game/Game"; +import { Execution, Game, isStructureType, Player } from "../game/Game"; import { PseudoRandom } from "../PseudoRandom"; import { simpleHash } from "../Util"; import { AllianceExtensionExecution } from "./alliance/AllianceExtensionExecution"; @@ -85,7 +85,7 @@ export class BotExecution implements Execution { private deleteAllStructures() { for (const unit of this.bot.units()) { - if (this.mg.isStructureType(unit.type()) && this.bot.canDeleteUnit()) { + if (isStructureType(unit.type()) && this.bot.canDeleteUnit()) { this.mg.addExecution(new DeleteUnitExecution(this.bot, unit.id())); } } diff --git a/src/core/execution/NukeExecution.ts b/src/core/execution/NukeExecution.ts index 448b8ec06..d35be7a39 100644 --- a/src/core/execution/NukeExecution.ts +++ b/src/core/execution/NukeExecution.ts @@ -1,6 +1,7 @@ import { Execution, Game, + isStructureType, MessageType, Player, TerraNullius, @@ -332,7 +333,7 @@ export class NukeExecution implements Execution { private redrawBuildings(range: number) { const rangeSquared = range * range; for (const unit of this.mg.units()) { - if (this.mg.isStructureType(unit.type())) { + if (isStructureType(unit.type())) { if ( this.mg.euclideanDistSquared(this.dst, unit.tile()) < rangeSquared ) { diff --git a/src/core/execution/Util.ts b/src/core/execution/Util.ts index e21af88a5..ed33836f5 100644 --- a/src/core/execution/Util.ts +++ b/src/core/execution/Util.ts @@ -1,5 +1,5 @@ import { NukeMagnitude } from "../configuration/Config"; -import { Game, Player } from "../game/Game"; +import { Game, Player, StructureTypes } from "../game/Game"; import { euclDistFN, GameMap, TileRef } from "../game/GameMap"; import { GameView } from "../game/GameView"; @@ -60,7 +60,7 @@ export function wouldNukeBreakAlliance( const wouldDestroyAlliedStructure = game.anyUnitNearby( targetTile, magnitude.outer, - game.getStructureTypes(), + StructureTypes, (unit) => unit.owner().isPlayer() && allySmallIds.has(unit.owner().smallID()), ); @@ -119,7 +119,7 @@ export function listNukeBreakAlliance( // Also check if any allied structures would be destroyed game - .nearbyUnits(targetTile, magnitude.outer, [...game.getStructureTypes()]) + .nearbyUnits(targetTile, magnitude.outer, StructureTypes) .forEach(({ unit }) => playersToBreakAllianceWith.add(unit.owner().smallID()), ); diff --git a/src/core/execution/nation/NationStructureBehavior.ts b/src/core/execution/nation/NationStructureBehavior.ts index 29ed93cd7..a0afa186b 100644 --- a/src/core/execution/nation/NationStructureBehavior.ts +++ b/src/core/execution/nation/NationStructureBehavior.ts @@ -5,6 +5,7 @@ import { Player, PlayerType, Relation, + StructureTypes, Unit, UnitType, } from "../../game/Game"; @@ -344,7 +345,7 @@ export class NationStructureBehavior { private getTotalStructureDensity(): number { const tilesOwned = this.player.numTilesOwned(); return tilesOwned > 0 - ? this.player.units(...this.game.getStructureTypes()).length / tilesOwned + ? this.player.units(...StructureTypes).length / tilesOwned : 0; //ignoring levels for structures } diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts index 4933c2619..11bee0562 100644 --- a/src/core/game/Game.ts +++ b/src/core/game/Game.ts @@ -225,7 +225,6 @@ export interface UnitInfo { cost: (game: Game, player: Player) => Gold; // Determines if its owner changes when its tile is conquered. territoryBound: boolean; - playerBuildable: boolean; maxHealth?: number; damage?: number; constructionDuration?: number; @@ -257,6 +256,39 @@ export enum TrainType { Carriage = "Carriage", } +const _structureTypes: ReadonlySet = new Set([ + UnitType.City, + UnitType.DefensePost, + UnitType.SAMLauncher, + UnitType.MissileSilo, + UnitType.Port, + UnitType.Factory, +]); + +export const StructureTypes: readonly UnitType[] = [..._structureTypes]; + +export function isStructureType(type: UnitType): boolean { + return _structureTypes.has(type); +} + +const _playerBuildableTypes: ReadonlySet = new Set([ + UnitType.City, + UnitType.DefensePost, + UnitType.SAMLauncher, + UnitType.MissileSilo, + UnitType.Port, + UnitType.Factory, + UnitType.TransportShip, + UnitType.Warship, + UnitType.AtomBomb, + UnitType.HydrogenBomb, + UnitType.MIRV, +]); + +export const PlayerBuildableTypes: readonly UnitType[] = [ + ..._playerBuildableTypes, +]; + export interface OwnerComp { owner: Player; } @@ -774,13 +806,10 @@ export interface Game extends GameMap { nearbyUnits( tile: TileRef, searchRange: number, - types: UnitType | UnitType[], + types: UnitType | readonly UnitType[], predicate?: UnitPredicate, includeUnderConstruction?: boolean, ): Array<{ unit: Unit; distSquared: number }>; - getStructureTypes(): readonly UnitType[]; - isStructureType(type: UnitType): boolean; - getPlayerBuildableUnitTypes(): readonly UnitType[]; addExecution(...exec: Execution[]): void; displayMessage( diff --git a/src/core/game/GameImpl.ts b/src/core/game/GameImpl.ts index 9d48cc5e1..417128f57 100644 --- a/src/core/game/GameImpl.ts +++ b/src/core/game/GameImpl.ts @@ -97,10 +97,6 @@ export class GameImpl implements Game { private _miniWaterGraph: AbstractGraph | null = null; private _miniWaterHPA: AStarWaterHierarchical | null = null; - private _structureTypes: UnitType[] = []; - private _structureTypesSet: Set; - private _buildableUnitTypes: UnitType[] = []; - constructor( private _humans: PlayerInfo[], private _nations: Nation[], @@ -132,17 +128,6 @@ export class GameImpl implements Game { ); } - this._structureTypes = - Object.values(UnitType).filter( - (t) => this._config.unitInfo(t).territoryBound, - ) ?? []; - this._structureTypesSet = new Set(this._structureTypes); - - this._buildableUnitTypes = - Object.values(UnitType).filter( - (t) => this._config.unitInfo(t).playerBuildable, - ) ?? []; - console.log( `[GameImpl] Constructor total: ${(performance.now() - constructorStart).toFixed(0)}ms`, ); @@ -908,7 +893,7 @@ export class GameImpl implements Game { nearbyUnits( tile: TileRef, searchRange: number, - types: UnitType | UnitType[], + types: UnitType | readonly UnitType[], predicate?: UnitPredicate, includeUnderConstruction?: boolean, ): Array<{ unit: Unit; distSquared: number }> { @@ -924,18 +909,6 @@ export class GameImpl implements Game { }>; } - getStructureTypes(): UnitType[] { - return this._structureTypes; - } - - isStructureType(type: UnitType): boolean { - return this._structureTypesSet.has(type); - } - - getPlayerBuildableUnitTypes(): UnitType[] { - return this._buildableUnitTypes; - } - ref(x: number, y: number): TileRef { return this._map.ref(x, y); } diff --git a/src/core/game/GameView.ts b/src/core/game/GameView.ts index 5495b2229..69f0608eb 100644 --- a/src/core/game/GameView.ts +++ b/src/core/game/GameView.ts @@ -598,9 +598,6 @@ export class GameView implements GameMap { private _map: GameMap; - private _structureTypes: UnitType[]; - private _structureTypesSet: Set; - constructor( public worker: WorkerClient, private _config: Config, @@ -629,12 +626,6 @@ export class GameView implements GameMap { flag: nation.flag, } satisfies PlayerCosmetics); } - - this._structureTypes = - Object.values(UnitType).filter( - (t) => this._config.unitInfo(t).territoryBound, - ) ?? []; - this._structureTypesSet = new Set(this._structureTypes); } isOnEdgeOfMap(ref: TileRef): boolean { @@ -715,7 +706,7 @@ export class GameView implements GameMap { nearbyUnits( tile: TileRef, searchRange: number, - types: UnitType | UnitType[], + types: UnitType | readonly UnitType[], predicate?: UnitPredicate, ): Array<{ unit: UnitView; distSquared: number }> { return this.unitGrid.nearbyUnits( @@ -763,14 +754,6 @@ export class GameView implements GameMap { ); } - getStructureTypes(): UnitType[] { - return this._structureTypes; - } - - isStructureType(type: UnitType): boolean { - return this._structureTypesSet.has(type); - } - myClientID(): ClientID { return this._myClientID; } diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts index 97b7653d0..7dba7439a 100644 --- a/src/core/game/PlayerImpl.ts +++ b/src/core/game/PlayerImpl.ts @@ -25,11 +25,13 @@ import { MessageType, MutableAlliance, Player, + PlayerBuildableTypes, PlayerID, PlayerInfo, PlayerProfile, PlayerType, Relation, + StructureTypes, Team, TerraNullius, Tick, @@ -966,7 +968,7 @@ export class PlayerImpl implements Player { public buildableUnits(tile: TileRef | null): BuildableUnit[] { const validTiles = tile !== null ? this.validStructureSpawnTiles(tile) : []; - return this.mg.getPlayerBuildableUnitTypes().map((u) => { + return PlayerBuildableTypes.map((u) => { const cost = this.mg.config().unitInfo(u).cost(this.mg, this); let canUpgrade: number | false = false; let canBuild: TileRef | false = false; @@ -1062,7 +1064,7 @@ export class PlayerImpl implements Player { const wouldHitTeammate = this.mg.anyUnitNearby( tile, magnitude.outer, - this.mg.getStructureTypes(), + StructureTypes, (unit) => unit.owner().isPlayer() && this.isOnSameTeam(unit.owner()), ); if (wouldHitTeammate) { @@ -1145,7 +1147,7 @@ export class PlayerImpl implements Player { const nearbyUnits = this.mg.nearbyUnits( tile, searchRadius * 2, - this.mg.getStructureTypes(), + StructureTypes, undefined, true, );