From 60d5e8679de4e1e8c2e1a4c0a4575e9e93772ae5 Mon Sep 17 00:00:00 2001 From: Scott Anderson <662325+scottanderson@users.noreply.github.com> Date: Tue, 13 May 2025 03:29:33 -0400 Subject: [PATCH] fix --- src/core/ApiSchemas.ts | 4 +- src/core/GameRunner.ts | 2 +- src/core/Util.ts | 2 +- src/core/game/AllianceImpl.ts | 12 ++- src/core/game/Game.ts | 5 +- src/core/game/GameImpl.ts | 13 ++-- src/core/game/GameView.ts | 39 +++++----- src/core/game/PlayerImpl.ts | 113 +++++++++++++--------------- src/core/game/TerrainMapLoader.ts | 2 +- src/core/game/TransportShipUtils.ts | 38 +++++----- src/core/pathfinding/PathFinding.ts | 18 +++-- src/core/pathfinding/SerialAStar.ts | 2 +- src/core/utilities/Line.ts | 2 +- 13 files changed, 123 insertions(+), 129 deletions(-) diff --git a/src/core/ApiSchemas.ts b/src/core/ApiSchemas.ts index 61952d3d5..81637e8cd 100644 --- a/src/core/ApiSchemas.ts +++ b/src/core/ApiSchemas.ts @@ -13,7 +13,7 @@ export const TokenPayloadSchema = z.object({ .refine( (val) => { const uuid = base64urlToUuid(val); - return uuid != null; + return !!uuid; }, { message: "Invalid base64-encoded UUID", @@ -31,7 +31,7 @@ export const TokenPayloadSchema = z.object({ rol: z .string() .optional() - .transform((val) => val.split(",")), + .transform((val) => (val ?? "").split(",")), }); export type TokenPayload = z.infer; diff --git a/src/core/GameRunner.ts b/src/core/GameRunner.ts index 97999289d..e64909307 100644 --- a/src/core/GameRunner.ts +++ b/src/core/GameRunner.ts @@ -43,7 +43,7 @@ export async function createGameRunner( (p) => new PlayerInfo( p.flag, - p.clientID == clientID + p.clientID === clientID ? sanitize(p.username) : fixProfaneUsername(sanitize(p.username)), PlayerType.Human, diff --git a/src/core/Util.ts b/src/core/Util.ts index b3ebe93bd..fadbd68ea 100644 --- a/src/core/Util.ts +++ b/src/core/Util.ts @@ -319,4 +319,4 @@ export const emojiTable: string[][] = [ ["💰", "⚓", "⛵", "🏡", "🛡️"], ]; // 2d to 1d array -export const flattenedEmojiTable: string[] = [].concat(...emojiTable); +export const flattenedEmojiTable: string[] = emojiTable.flat(); diff --git a/src/core/game/AllianceImpl.ts b/src/core/game/AllianceImpl.ts index d701dbd06..b5c2c5836 100644 --- a/src/core/game/AllianceImpl.ts +++ b/src/core/game/AllianceImpl.ts @@ -1,16 +1,14 @@ -import { MutableAlliance, Player, Tick } from "./Game"; -import { GameImpl } from "./GameImpl"; -import { PlayerImpl } from "./PlayerImpl"; +import { Game, MutableAlliance, Player, Tick } from "./Game"; export class AllianceImpl implements MutableAlliance { constructor( - private readonly mg: GameImpl, - readonly requestor_: PlayerImpl, - readonly recipient_: PlayerImpl, + private readonly mg: Game, + readonly requestor_: Player, + readonly recipient_: Player, readonly createdAtTick_: Tick, ) {} - other(player: Player): PlayerImpl { + other(player: Player): Player { if (this.requestor_ === player) { return this.recipient_; } diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts index 8679fa735..18000734d 100644 --- a/src/core/game/Game.ts +++ b/src/core/game/Game.ts @@ -348,10 +348,10 @@ export interface Unit { ticksLeftInCooldown(cooldownDuration: number): Tick; isCooldown(): boolean; setDstPort(dstPort: Unit): void; - dstPort(): Unit; // Only for trade ships + dstPort(): Unit | null; // Only for trade ships setSafeFromPirates(): void; // Only for trade ships isSafeFromPirates(): boolean; // Only for trade ships - detonationDst(): TileRef; // Only for nukes + detonationDst(): TileRef | null; // Only for nukes setMoveTarget(cell: TileRef | null): void; moveTarget(): TileRef | null; @@ -501,6 +501,7 @@ export interface Player { } export interface Game extends GameMap { + expireAlliance(alliance: Alliance); // Map & Dimensions isOnMap(cell: Cell): boolean; width(): number; diff --git a/src/core/game/GameImpl.ts b/src/core/game/GameImpl.ts index 9503b8169..e9ad538ae 100644 --- a/src/core/game/GameImpl.ts +++ b/src/core/game/GameImpl.ts @@ -36,7 +36,6 @@ import { StatsImpl } from "./StatsImpl"; import { assignTeams } from "./TeamAssignment"; import { TerraNulliusImpl } from "./TerraNulliusImpl"; import { UnitGrid } from "./UnitGrid"; -import { UnitImpl } from "./UnitImpl"; export function createGame( humans: PlayerInfo[], @@ -119,7 +118,7 @@ export class GameImpl implements Game { } private addPlayers() { - if (this.config().gameConfig().gameMode != GameMode.Team) { + if (this.config().gameConfig().gameMode !== GameMode.Team) { this._humans.forEach((p) => this.addPlayer(p)); this._nations.forEach((n) => this.addPlayer(n.playerInfo)); return; @@ -182,7 +181,7 @@ export class GameImpl implements Game { }); } - units(...types: UnitType[]): UnitImpl[] { + units(...types: UnitType[]): Unit[] { return Array.from(this._players.values()).flatMap((p) => p.units(...types)); } unitInfo(type: UnitType): UnitInfo { @@ -619,11 +618,11 @@ export class GameImpl implements Game { category: string, variables: Record = {}, playerID: PlayerID | null, - isFrom: boolean | null = null, + isFrom: boolean, recipient: string, ): void { - let id = null; - if (playerID != null) { + let id: number | null = null; + if (playerID !== null) { id = this.player(playerID).smallID(); } this.addUpdate({ @@ -632,7 +631,7 @@ export class GameImpl implements Game { category: category, variables: variables, playerID: id, - isFrom: isFrom, + isFrom, recipient: recipient, }); } diff --git a/src/core/game/GameView.ts b/src/core/game/GameView.ts index d4f25918b..2b1fbbc72 100644 --- a/src/core/game/GameView.ts +++ b/src/core/game/GameView.ts @@ -57,7 +57,7 @@ export class UnitView { } lastTile(): TileRef { - if (this.lastPos.length == 0) { + if (this.lastPos.length === 0) { return this.data.pos; } return this.lastPos[0]; @@ -89,7 +89,7 @@ export class UnitView { return this.data.isActive; } hasHealth(): boolean { - return this.data.health != undefined; + return this.data.health !== undefined; } health(): number { return this.data.health ?? 0; @@ -98,7 +98,7 @@ export class UnitView { return this.data.constructionType; } dstPortId(): number | undefined { - if (this.type() != UnitType.TradeShip) { + if (this.type() !== UnitType.TradeShip) { throw Error("Must be a trade ship"); } return this.data.dstPortId; @@ -110,7 +110,7 @@ export class UnitView { return this.data.detonationDst; } warshipTargetId(): number | undefined { - if (this.type() != UnitType.Warship) { + if (this.type() !== UnitType.Warship) { throw Error("Must be a warship"); } return this.data.warshipTargetId; @@ -132,13 +132,11 @@ export class PlayerView { public data: PlayerUpdate, public nameData: NameViewData, ) { - if (data.clientID == game.myClientID()) { + if (data.clientID === game.myClientID()) { this.anonymousName = this.data.name; } else { - this.anonymousName = createRandomName( - this.data.name, - this.data.playerType, - ); + this.anonymousName = + createRandomName(this.data.name, this.data.playerType) ?? ""; } } @@ -165,7 +163,7 @@ export class PlayerView { units(...types: UnitType[]): UnitView[] { return this.game .units(...types) - .filter((u) => u.owner().smallID() == this.smallID()); + .filter((u) => u.owner().smallID() === this.smallID()); } nameLocation(): NameViewData { @@ -189,7 +187,7 @@ export class PlayerView { : this.data.name; } - clientID(): ClientID { + clientID(): ClientID | null { return this.data.clientID; } id(): PlayerID { @@ -237,11 +235,11 @@ export class PlayerView { } isAlliedWith(other: PlayerView): boolean { - return this.data.allies.some((n) => other.smallID() == n); + return this.data.allies.some((n) => other.smallID() === n); } isOnSameTeam(other: PlayerView): boolean { - return this.data.team != null && this.data.team == other.data.team; + return this.data.team !== undefined && this.data.team === other.data.team; } isFriendly(other: PlayerView): boolean { @@ -249,7 +247,7 @@ export class PlayerView { } isRequestingAllianceWith(other: PlayerView) { - return this.data.outgoingAllianceRequests.some((id) => other.id() == id); + return this.data.outgoingAllianceRequests.some((id) => other.id() === id); } hasEmbargoAgainst(other: PlayerView): boolean { @@ -400,7 +398,7 @@ export class GameView implements GameMap { } myPlayer(): PlayerView | null { - if (this._myPlayer == null) { + if (this._myPlayer === null) { this._myPlayer = this.playerByClientID(this._myClientID); } return this._myPlayer; @@ -419,7 +417,7 @@ export class GameView implements GameMap { } playerBySmallID(id: number): PlayerView | TerraNullius { - if (id == 0) { + if (id === 0) { return new TerraNulliusImpl(); } const playerId = this.smallIDToID.get(id); @@ -431,9 +429,10 @@ export class GameView implements GameMap { playerByClientID(id: ClientID): PlayerView | null { const player = - Array.from(this._players.values()).filter((p) => p.clientID() == id)[0] ?? - null; - if (player == null) { + Array.from(this._players.values()).filter( + (p) => p.clientID() === id, + )[0] ?? null; + if (player === null) { return null; } return player; @@ -459,7 +458,7 @@ export class GameView implements GameMap { return this._config; } units(...types: UnitType[]): UnitView[] { - if (types.length == 0) { + if (types.length === 0) { return Array.from(this._units.values()).filter((u) => u.isActive()); } return Array.from(this._units.values()).filter( diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts index ca2969d02..af134975c 100644 --- a/src/core/game/PlayerImpl.ts +++ b/src/core/game/PlayerImpl.ts @@ -41,7 +41,6 @@ import { import { GameImpl } from "./GameImpl"; import { andFN, manhattanDistFN, TileRef } from "./GameMap"; import { AttackUpdate, GameUpdateType, PlayerUpdate } from "./GameUpdates"; -import { TerraNulliusImpl } from "./TerraNulliusImpl"; import { bestShoreDeploymentSource, canBuildTransportShip, @@ -77,7 +76,7 @@ export class PlayerImpl implements Player { public _borderTiles: Set = new Set(); - public _units: UnitImpl[] = []; + public _units: Unit[] = []; public _tiles: Set = new Set(); private _flag: string | undefined; @@ -203,8 +202,8 @@ export class PlayerImpl implements Player { return this.playerInfo.clan; } - units(...types: UnitType[]): UnitImpl[] { - if (types.length == 0) { + units(...types: UnitType[]): Unit[] { + if (types.length === 0) { return this._units; } const ts = new Set(types); @@ -215,7 +214,7 @@ export class PlayerImpl implements Player { const units = this.units(type); units.push( ...this.units(UnitType.Construction).filter( - (u) => u.constructionType() == type, + (u) => u.constructionType() === type, ), ); return units; @@ -224,7 +223,7 @@ export class PlayerImpl implements Player { sharesBorderWith(other: Player | TerraNullius): boolean { for (const border of this._borderTiles) { for (const neighbor of this.mg.map().neighbors(border)) { - if (this.mg.map().ownerID(neighbor) == other.smallID()) { + if (this.mg.map().ownerID(neighbor) === other.smallID()) { return true; } } @@ -249,10 +248,8 @@ export class PlayerImpl implements Player { for (const neighbor of this.mg.map().neighbors(border)) { if (this.mg.map().isLand(neighbor)) { const owner = this.mg.map().ownerID(neighbor); - if (owner != this.smallID()) { - ns.add( - this.mg.playerBySmallID(owner) as PlayerImpl | TerraNulliusImpl, - ); + if (owner !== this.smallID()) { + ns.add(this.mg.playerBySmallID(owner) as Player | TerraNullius); } } } @@ -270,7 +267,7 @@ export class PlayerImpl implements Player { this.mg.conquer(this, tile); } orderRetreat(id: string) { - const attack = this._outgoingAttacks.filter((attack) => attack.id() == id); + const attack = this._outgoingAttacks.filter((attack) => attack.id() === id); if (!attack || !attack[0]) { consolex.warn(`Didn't find outgoing attack with id ${id}`); return; @@ -278,7 +275,7 @@ export class PlayerImpl implements Player { attack[0].orderRetreat(); } executeRetreat(id: string): void { - const attack = this._outgoingAttacks.filter((attack) => attack.id() == id); + const attack = this._outgoingAttacks.filter((attack) => attack.id() === id); // Execution is delayed so it's not an error that the attack does not exist. if (!attack || !attack[0]) { return; @@ -286,7 +283,7 @@ export class PlayerImpl implements Player { attack[0].executeRetreat(); } relinquish(tile: TileRef) { - if (this.mg.owner(tile) != this) { + if (this.mg.owner(tile) !== this) { throw new Error(`Cannot relinquish tile not owned by this player`); } this.mg.relinquish(tile); @@ -307,16 +304,16 @@ export class PlayerImpl implements Player { } incomingAllianceRequests(): AllianceRequest[] { - return this.mg.allianceRequests.filter((ar) => ar.recipient() == this); + return this.mg.allianceRequests.filter((ar) => ar.recipient() === this); } outgoingAllianceRequests(): AllianceRequest[] { - return this.mg.allianceRequests.filter((ar) => ar.requestor() == this); + return this.mg.allianceRequests.filter((ar) => ar.requestor() === this); } alliances(): MutableAlliance[] { return this.mg.alliances_.filter( - (a) => a.requestor() == this || a.recipient() == this, + (a) => a.requestor() === this || a.recipient() === this, ); } @@ -325,25 +322,25 @@ export class PlayerImpl implements Player { } isAlliedWith(other: Player): boolean { - if (other == this) { + if (other === this) { return false; } - return this.allianceWith(other) != null; + return this.allianceWith(other) !== null; } allianceWith(other: Player): MutableAlliance | null { - if (other == this) { + if (other === this) { return null; } return ( this.alliances().find( - (a) => a.recipient() == other || a.requestor() == other, + (a) => a.recipient() === other || a.requestor() === other, ) ?? null ); } canSendAllianceRequest(other: Player): boolean { - if (other == this) { + if (other === this) { return false; } if (this.isFriendly(other)) { @@ -351,20 +348,18 @@ export class PlayerImpl implements Player { } const hasPending = - this.incomingAllianceRequests().find((ar) => ar.requestor() == other) != - null || - this.outgoingAllianceRequests().find((ar) => ar.recipient() == other) != - null; + this.incomingAllianceRequests().some((ar) => ar.requestor() === other) || + this.outgoingAllianceRequests().some((ar) => ar.recipient() === other); if (hasPending) { return false; } const recent = this.pastOutgoingAllianceRequests - .filter((ar) => ar.recipient() == other) + .filter((ar) => ar.recipient() === other) .sort((a, b) => b.createdAt() - a.createdAt()); - if (recent.length == 0) { + if (recent.length === 0) { return true; } @@ -396,7 +391,7 @@ export class PlayerImpl implements Player { } relation(other: Player): Relation { - if (other == this) { + if (other === this) { throw new Error(`cannot get relation with self: ${this}`); } const relation = this.relations.get(other) ?? 0; @@ -426,7 +421,7 @@ export class PlayerImpl implements Player { } updateRelation(other: Player, delta: number): void { - if (other == this) { + if (other === this) { throw new Error(`cannot update relation with self: ${this}`); } const relation = this.relations.get(other) ?? 0; @@ -447,7 +442,7 @@ export class PlayerImpl implements Player { } canTarget(other: Player): boolean { - if (this == other) { + if (this === other) { return false; } if (this.isFriendly(other)) { @@ -483,13 +478,13 @@ export class PlayerImpl implements Player { } sendEmoji(recipient: Player | typeof AllPlayers, emoji: string): void { - if (recipient == this) { + if (recipient === this) { throw Error(`Cannot send emoji to oneself: ${this}`); } const msg: EmojiMessage = { message: emoji, senderID: this.smallID(), - recipientID: recipient == AllPlayers ? recipient : recipient.smallID(), + recipientID: recipient === AllPlayers ? recipient : recipient.smallID(), createdAt: this.mg.ticks(), }; this.outgoingEmojis_.push(msg); @@ -508,9 +503,9 @@ export class PlayerImpl implements Player { canSendEmoji(recipient: Player | typeof AllPlayers): boolean { const recipientID = - recipient == AllPlayers ? AllPlayers : recipient.smallID(); + recipient === AllPlayers ? AllPlayers : recipient.smallID(); const prevMsgs = this.outgoingEmojis_.filter( - (msg) => msg.recipientID == recipientID, + (msg) => msg.recipientID === recipientID, ); for (const msg of prevMsgs) { if ( @@ -528,7 +523,7 @@ export class PlayerImpl implements Player { return false; } for (const donation of this.sentDonations) { - if (donation.recipient == recipient) { + if (donation.recipient === recipient) { if ( this.mg.ticks() - donation.tick < this.mg.config().donateCooldown() @@ -576,7 +571,7 @@ export class PlayerImpl implements Player { canTrade(other: Player): boolean { const embargo = other.hasEmbargoAgainst(this) || this.hasEmbargoAgainst(other); - return !embargo && other.id() != this.id(); + return !embargo && other.id() !== this.id(); } addEmbargo(other: PlayerID): void { @@ -590,7 +585,7 @@ export class PlayerImpl implements Player { tradingPartners(): Player[] { return this.mg .players() - .filter((other) => other != this && this.canTrade(other)); + .filter((other) => other !== this && this.canTrade(other)); } team(): Team | null { @@ -598,16 +593,16 @@ export class PlayerImpl implements Player { } isOnSameTeam(other: Player): boolean { - if (other == this) { + if (other === this) { return false; } - if (this.team() == null || other.team() == null) { + if (this.team() === null || other.team() === null) { return false; } - if (this.team() == ColoredTeams.Bot || other.team() == ColoredTeams.Bot) { + if (this.team() === ColoredTeams.Bot || other.team() === ColoredTeams.Bot) { return false; } - return this._team == other.team(); + return this._team === other.team(); } isFriendly(other: Player): boolean { @@ -678,15 +673,15 @@ export class PlayerImpl implements Player { } captureUnit(unit: Unit): void { - if (unit.owner() == this) { + if (unit.owner() === this) { throw new Error(`Cannot capture unit, ${this} already owns ${unit}`); } const prev = unit.owner(); (prev as PlayerImpl)._units = (prev as PlayerImpl)._units.filter( - (u) => u != unit, + (u) => u !== unit, ); (unit as UnitImpl)._owner = this; - this._units.push(unit as UnitImpl); + this._units.push(unit); this.mg.addUpdate(unit.toUpdate()); this.mg.displayMessage( `${unit.type()} captured by ${this.displayName()}`, @@ -704,7 +699,7 @@ export class PlayerImpl implements Player { type: T, spawnTile: TileRef, params: UnitParams, - ): UnitImpl { + ): Unit { if (this.mg.config().isUnitDisabled(type)) { throw new Error( `Attempted to build disabled unit ${type} at tile ${spawnTile} by player ${this.name()}`, @@ -722,7 +717,7 @@ export class PlayerImpl implements Player { ); this._units.push(b); this.removeGold(cost); - this.removeTroops("troops" in params ? params.troops : 0); + this.removeTroops("troops" in params ? (params.troops ?? 0) : 0); this.mg.addUpdate(b.toUpdate()); this.mg.addUnit(b); @@ -801,7 +796,7 @@ export class PlayerImpl implements Player { return !silo.isCooldown(); }) .sort(distSortUnit(this.mg, tile)); - if (spawns.length == 0) { + if (spawns.length === 0) { return false; } return spawns[0].tile(); @@ -814,7 +809,7 @@ export class PlayerImpl implements Player { manhattanDistFN(tile, this.mg.config().radiusPortSpawn()), ), ) - .filter((t) => this.mg.owner(t) == this && this.mg.isOceanShore(t)) + .filter((t) => this.mg.owner(t) === this && this.mg.isOceanShore(t)) .sort( (a, b) => this.mg.manhattanDist(a, tile) - this.mg.manhattanDist(b, tile), @@ -839,7 +834,7 @@ export class PlayerImpl implements Player { this.mg.manhattanDist(a.tile(), tile) - this.mg.manhattanDist(b.tile(), tile), ); - if (spawns.length == 0) { + if (spawns.length === 0) { return false; } return spawns[0].tile(); @@ -850,14 +845,14 @@ export class PlayerImpl implements Player { validTiles: TileRef[] | null = null, ): TileRef | false { const tiles = validTiles ?? this.validStructureSpawnTiles(tile); - if (tiles.length == 0) { + if (tiles.length === 0) { return false; } return tiles[0]; } private validStructureSpawnTiles(tile: TileRef): TileRef[] { - if (this.mg.owner(tile) != this) { + if (this.mg.owner(tile) !== this) { return []; } const searchRadius = 15; @@ -872,7 +867,7 @@ export class PlayerImpl implements Player { const nearbyTiles = this.mg.bfs(tile, (gm, t) => { return ( this.mg.euclideanDistSquared(tile, t) < searchRadiusSquared && - gm.ownerID(t) == this.smallID() + gm.ownerID(t) === this.smallID() ); }); const validSet: Set = new Set(nearbyTiles); @@ -897,9 +892,9 @@ export class PlayerImpl implements Player { tradeShipSpawn(targetTile: TileRef): TileRef | false { const spawns = this.units(UnitType.Port).filter( - (u) => u.tile() == targetTile, + (u) => u.tile() === targetTile, ); - if (spawns.length == 0) { + if (spawns.length === 0) { return false; } return spawns[0].tile(); @@ -911,7 +906,7 @@ export class PlayerImpl implements Player { hash(): number { return ( simpleHash(this.id()) * (this.population() + this.numTilesOwned()) + - this._units.reduce((acc, unit) => acc + unit.hash(), 0) + this._units.reduce((acc, unit) => acc + (unit as UnitImpl).hash(), 0) ); } toString(): string { @@ -970,7 +965,7 @@ export class PlayerImpl implements Player { return false; } - if (this.mg.owner(tile) == this) { + if (this.mg.owner(tile) === this) { return false; } if (this.mg.hasOwner(tile)) { @@ -994,7 +989,7 @@ export class PlayerImpl implements Player { ), )) { for (const n of this.mg.neighbors(t)) { - if (this.mg.owner(n) == this) { + if (this.mg.owner(n) === this) { return true; } } @@ -1012,7 +1007,7 @@ export class PlayerImpl implements Player { tradingPorts(port: Unit): Unit[] { const ports = this.mg .players() - .filter((p) => p != port.owner() && p.canTrade(port.owner())) + .filter((p) => p !== port.owner() && p.canTrade(port.owner())) .flatMap((p) => p.units(UnitType.Port)) .sort((p1, p2) => { return ( @@ -1033,7 +1028,7 @@ export class PlayerImpl implements Player { // Make ally ports twice more likely by putting them again this.mg .players() - .filter((p) => p != port.owner() && p.canTrade(port.owner())) + .filter((p) => p !== port.owner() && p.canTrade(port.owner())) .filter((p) => p.isAlliedWith(port.owner())) .flatMap((p) => p.units(UnitType.Port)) .forEach((p) => ports.push(p)); diff --git a/src/core/game/TerrainMapLoader.ts b/src/core/game/TerrainMapLoader.ts index 2c3ee0c22..adf2399fb 100644 --- a/src/core/game/TerrainMapLoader.ts +++ b/src/core/game/TerrainMapLoader.ts @@ -44,7 +44,7 @@ export async function genTerrainFromBin(data: string): Promise { const width = (data.charCodeAt(1) << 8) | data.charCodeAt(0); const height = (data.charCodeAt(3) << 8) | data.charCodeAt(2); - if (data.length != width * height + 4) { + if (data.length !== width * height + 4) { throw new Error( `Invalid data: buffer size ${data.length} incorrect for ${width}x${height} terrain plus 4 bytes for dimensions.`, ); diff --git a/src/core/game/TransportShipUtils.ts b/src/core/game/TransportShipUtils.ts index a5d5bf7df..5d3f6963c 100644 --- a/src/core/game/TransportShipUtils.ts +++ b/src/core/game/TransportShipUtils.ts @@ -15,12 +15,12 @@ export function canBuildTransportShip( } const dst = targetTransportTile(game, tile); - if (dst == null) { + if (dst === null) { return false; } const other = game.owner(tile); - if (other == player) { + if (other === player) { return false; } if (other.isPlayer() && player.isFriendly(other)) { @@ -71,7 +71,7 @@ export function canBuildTransportShip( ); for (const t of sorted) { - if (game.owner(t) == player) { + if (game.owner(t) === player) { return transportShipSpawn(game, player, t); } } @@ -87,7 +87,7 @@ function transportShipSpawn( return false; } const spawn = closestShoreFromPlayer(game, player, targetTile); - if (spawn == null) { + if (spawn === null) { return false; } return spawn; @@ -128,7 +128,7 @@ export function closestShoreFromPlayer( const shoreTiles = Array.from(player.borderTiles()).filter((t) => gm.isShore(t), ); - if (shoreTiles.length == 0) { + if (shoreTiles.length === 0) { return null; } @@ -144,20 +144,18 @@ export function bestShoreDeploymentSource( player: Player, target: TileRef, ): TileRef | false { - target = targetTransportTile(gm, target); - if (target == null) { - return false; - } + const t = targetTransportTile(gm, target); + if (t === null) return false; - const candidates = candidateShoreTiles(gm, player, target); - const aStar = new MiniAStar(gm, gm.miniMap(), candidates, target, 500_000, 1); + const candidates = candidateShoreTiles(gm, player, t); + const aStar = new MiniAStar(gm, gm.miniMap(), candidates, t, 500_000, 1); const result = aStar.compute(); - if (result != PathFindResultType.Completed) { + if (result !== PathFindResultType.Completed) { console.warn(`bestShoreDeploymentSource: path not found: ${result}`); return false; } const path = aStar.reconstructPath(); - if (path.length == 0) { + if (path.length === 0) { return false; } const potential = path[0]; @@ -165,8 +163,8 @@ export function bestShoreDeploymentSource( // of the potential tile to find a valid deployment point const neighbors = gm .neighbors(potential) - .filter((n) => gm.isShore(n) && gm.owner(n) == player); - if (neighbors.length == 0) { + .filter((n) => gm.isShore(n) && gm.owner(n) === player); + if (neighbors.length === 0) { return false; } return neighbors[0]; @@ -183,8 +181,8 @@ export function candidateShoreTiles( maxX = -Infinity, maxY = -Infinity; - let bestByManhattan: TileRef = null; - const extremumTiles: Record = { + let bestByManhattan: TileRef | null = null; + const extremumTiles: Record = { minX: null, minY: null, maxX: null, @@ -237,7 +235,7 @@ export function candidateShoreTiles( extremumTiles.maxX, extremumTiles.maxY, ...sampledTiles, - ].filter(Boolean); + ].filter(Boolean) as number[]; return candidates; } @@ -246,7 +244,7 @@ function closestShoreTN( gm: GameMap, tile: TileRef, searchDist: number, -): TileRef { +): TileRef | null { const tn = Array.from( gm.bfs( tile, @@ -255,7 +253,7 @@ function closestShoreTN( ) .filter((t) => gm.isShore(t)) .sort((a, b) => gm.manhattanDist(tile, a) - gm.manhattanDist(tile, b)); - if (tn.length == 0) { + if (tn.length === 0) { return null; } return tn[0]; diff --git a/src/core/pathfinding/PathFinding.ts b/src/core/pathfinding/PathFinding.ts index 9fb0ced93..9d26439e0 100644 --- a/src/core/pathfinding/PathFinding.ts +++ b/src/core/pathfinding/PathFinding.ts @@ -40,7 +40,7 @@ export class ParabolaPathFinder { nextTile(speed: number): TileRef | true { if (!this.curve) { - return; + throw new Error("ParabolaPathFinder not initialized"); } const nextPoint = this.curve.increment(speed); if (!nextPoint) { @@ -72,14 +72,14 @@ export class AirPathFinder { const ratio = Math.floor(1 + Math.abs(dstY - y) / (Math.abs(dstX - x) + 1)); - if (this.random.chance(ratio) && x != dstX) { + if (this.random.chance(ratio) && x !== dstX) { if (x < dstX) nextX++; else if (x > dstX) nextX--; } else { if (y < dstY) nextY++; else if (y > dstY) nextY--; } - if (nextX == x && nextY == y) { + if (nextX === x && nextY === y) { return true; } return this.mg.ref(nextX, nextY); @@ -111,12 +111,16 @@ export class PathFinder { }); } - nextTile(curr: TileRef, dst: TileRef, dist: number = 1): TileResult { - if (curr == null) { + nextTile( + curr: TileRef | null, + dst: TileRef | null, + dist: number = 1, + ): TileResult { + if (curr === null) { consolex.error("curr is null"); return { type: PathFindResultType.PathNotFound }; } - if (dst == null) { + if (dst === null) { consolex.error("dst is null"); return { type: PathFindResultType.PathNotFound }; } @@ -160,7 +164,7 @@ export class PathFinder { } private shouldRecompute(curr: TileRef, dst: TileRef) { - if (this.path == null || this.curr == null || this.dst == null) { + if (this.path === null || this.curr === null || this.dst === null) { return true; } const dist = this.game.manhattanDist(curr, dst); diff --git a/src/core/pathfinding/SerialAStar.ts b/src/core/pathfinding/SerialAStar.ts index 8f047ccfa..7655a75ba 100644 --- a/src/core/pathfinding/SerialAStar.ts +++ b/src/core/pathfinding/SerialAStar.ts @@ -123,7 +123,7 @@ export class SerialAStar implements AStar { private expandTileRef(current: TileRef, isForward: boolean) { for (const neighbor of this.gameMap.neighbors(current)) { if ( - neighbor != (isForward ? this.dst : this.closestSource) && + neighbor !== (isForward ? this.dst : this.closestSource) && !this.gameMap.isWater(neighbor) ) continue; diff --git a/src/core/utilities/Line.ts b/src/core/utilities/Line.ts index 521c66d92..2e1fea97b 100644 --- a/src/core/utilities/Line.ts +++ b/src/core/utilities/Line.ts @@ -81,7 +81,7 @@ export class DistanceBasedBezierCurve extends CubicBezierCurve { private distanceLUT: Array<{ t: number; distance: number }> = []; private lastFoundIndex: number = 0; // To keep track of the last found index - increment(distance: number): Point { + increment(distance: number): Point | null { this.totalDistance += distance; const targetDistance = Math.min( this.totalDistance,