diff --git a/resources/lang/en.json b/resources/lang/en.json index 9b21f97828..3594794494 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -242,7 +242,6 @@ "atom_bomb": "Atom Bomb", "hydrogen_bomb": "Hydrogen Bomb", "mirv": "MIRV", - "train": "Train", "factory": "Factory" }, "user_setting": { @@ -446,7 +445,6 @@ "cooldown": "Cooldown", "type": "Type", "upgrade": "Upgrade", - "create_station": "Create Station", "level": "Level" }, "relation": { diff --git a/src/client/HostLobbyModal.ts b/src/client/HostLobbyModal.ts index b0dbc6ae8b..0270e169bb 100644 --- a/src/client/HostLobbyModal.ts +++ b/src/client/HostLobbyModal.ts @@ -39,10 +39,7 @@ export class HostLobbyModal extends LitElement { @state() private copySuccess = false; @state() private players: string[] = []; @state() private useRandomMap: boolean = false; - @state() private disabledUnits: UnitType[] = [ - UnitType.Factory, - UnitType.Train, - ]; + @state() private disabledUnits: UnitType[] = [UnitType.Factory]; private playersInterval: NodeJS.Timeout | null = null; // Add a new timer for debouncing bot changes diff --git a/src/client/SinglePlayerModal.ts b/src/client/SinglePlayerModal.ts index ec7059c983..6419c488dd 100644 --- a/src/client/SinglePlayerModal.ts +++ b/src/client/SinglePlayerModal.ts @@ -40,10 +40,7 @@ export class SinglePlayerModal extends LitElement { @state() private gameMode: GameMode = GameMode.FFA; @state() private teamCount: number | typeof Duos = 2; - @state() private disabledUnits: UnitType[] = [ - UnitType.Factory, - UnitType.Train, - ]; + @state() private disabledUnits: UnitType[] = [UnitType.Factory]; private userSettings: UserSettings = new UserSettings(); diff --git a/src/client/Transport.ts b/src/client/Transport.ts index 6ae2c7c4b7..b5cb44c303 100644 --- a/src/client/Transport.ts +++ b/src/client/Transport.ts @@ -54,10 +54,6 @@ export class SendUpgradeStructureIntentEvent implements GameEvent { ) {} } -export class SendCreateTrainStationIntentEvent implements GameEvent { - constructor(public readonly unitId: number) {} -} - export class SendAllianceReplyIntentEvent implements GameEvent { constructor( // The original alliance requestor @@ -211,9 +207,6 @@ export class Transport { this.eventBus.on(SendUpgradeStructureIntentEvent, (e) => this.onSendUpgradeStructureIntent(e), ); - this.eventBus.on(SendCreateTrainStationIntentEvent, (e) => - this.onSendCreateTrainStationIntent(e), - ); this.eventBus.on(SendBoatAttackIntentEvent, (e) => this.onSendBoatAttackIntent(e), ); @@ -478,16 +471,6 @@ export class Transport { }); } - private onSendCreateTrainStationIntent( - event: SendCreateTrainStationIntentEvent, - ) { - this.sendIntent({ - type: "create_station", - clientID: this.lobbyConfig.clientID, - unitId: event.unitId, - }); - } - private onSendTargetPlayerIntent(event: SendTargetPlayerIntentEvent) { this.sendIntent({ type: "targetPlayer", diff --git a/src/client/graphics/layers/UILayer.ts b/src/client/graphics/layers/UILayer.ts index f3ba9711f7..1fc2d5257e 100644 --- a/src/client/graphics/layers/UILayer.ts +++ b/src/client/graphics/layers/UILayer.ts @@ -10,8 +10,6 @@ import { ProgressBar } from "../ProgressBar"; import { TransformHandler } from "../TransformHandler"; import { Layer } from "./Layer"; -import trainStationBadge from "../../../../resources/images/buildings/badges/trainStationBadge.png"; - const COLOR_PROGRESSION = [ "rgb(232, 25, 25)", "rgb(240, 122, 25)", @@ -49,7 +47,6 @@ export class UILayer implements Layer { // Visual settings for selection private readonly SELECTION_BOX_SIZE = 6; // Size of the selection box (should be larger than the warship) - private badges: Map = new Map(); constructor( private game: GameView, @@ -57,23 +54,6 @@ export class UILayer implements Layer { private transformHandler: TransformHandler, ) { this.theme = game.config().theme(); - this.loadBadges(); - } - - private loadBadge(badge: string): Promise { - return new Promise((resolve, reject) => { - const img = new Image(); - img.src = badge; - img.onload = () => { - this.badges.set(badge, img); - resolve(img); - }; - img.onerror = reject; - }); - } - - private async loadBadges() { - await Promise.all([this.loadBadge(trainStationBadge)]); } shouldTransform(): boolean { @@ -165,35 +145,12 @@ export class UILayer implements Layer { const endTick = this.game.config().SAMCooldown(); this.drawLoadingBar(unit, endTick); } - this.drawBadges(unit); - break; - case UnitType.City: - case UnitType.Port: - case UnitType.Factory: - this.drawBadges(unit); break; default: return; } } - private drawBadges(unit: UnitView) { - if (unit.hasTrainStation()) { - const icon = this.badges.get(trainStationBadge); - if (icon === undefined) { - return; - } - const startX = this.game.x(unit.tile()) - Math.floor(icon.width / 2) + 6; - const startY = this.game.y(unit.tile()) - Math.floor(icon.height / 2) - 6; - - if (unit.isActive()) { - this.drawIcon(icon, unit, startX, startY); - } else { - this.clearIcon(icon, startX, startY); - } - } - } - private clearIcon(icon: HTMLImageElement, startX: number, startY: number) { if (this.context !== null) { this.context.clearRect(startX, startY, icon.width, icon.height); diff --git a/src/client/utilities/RenderUnitTypeOptions.ts b/src/client/utilities/RenderUnitTypeOptions.ts index 028f196fae..0392935d6f 100644 --- a/src/client/utilities/RenderUnitTypeOptions.ts +++ b/src/client/utilities/RenderUnitTypeOptions.ts @@ -18,7 +18,6 @@ const unitOptions: { type: UnitType; translationKey: string }[] = [ { type: UnitType.AtomBomb, translationKey: "unit_type.atom_bomb" }, { type: UnitType.HydrogenBomb, translationKey: "unit_type.hydrogen_bomb" }, { type: UnitType.MIRV, translationKey: "unit_type.mirv" }, - { type: UnitType.Train, translationKey: "unit_type.train" }, { type: UnitType.Factory, translationKey: "unit_type.factory" }, ]; diff --git a/src/core/Schemas.ts b/src/core/Schemas.ts index 2697fe5600..0faadbe187 100644 --- a/src/core/Schemas.ts +++ b/src/core/Schemas.ts @@ -38,9 +38,7 @@ export type Intent = | QuickChatIntent | MoveWarshipIntent | MarkDisconnectedIntent - | UpgradeStructureIntent - | CreateStationIntent; - + | UpgradeStructureIntent; export type AttackIntent = z.infer; export type CancelAttackIntent = z.infer; export type SpawnIntent = z.infer; @@ -63,7 +61,6 @@ export type BuildUnitIntent = z.infer; export type UpgradeStructureIntent = z.infer< typeof UpgradeStructureIntentSchema >; -export type CreateStationIntent = z.infer; export type MoveWarshipIntent = z.infer; export type QuickChatIntent = z.infer; export type MarkDisconnectedIntent = z.infer< @@ -310,11 +307,6 @@ export const UpgradeStructureIntentSchema = BaseIntentSchema.extend({ unitId: z.number(), }); -export const CreateStationIntentSchema = BaseIntentSchema.extend({ - type: z.literal("create_station"), - unitId: z.number(), -}); - export const CancelAttackIntentSchema = BaseIntentSchema.extend({ type: z.literal("cancel_attack"), attackID: z.string(), @@ -360,7 +352,6 @@ const IntentSchema = z.discriminatedUnion("type", [ TargetTroopRatioIntentSchema, BuildUnitIntentSchema, UpgradeStructureIntentSchema, - CreateStationIntentSchema, EmbargoIntentSchema, MoveWarshipIntentSchema, QuickChatIntentSchema, diff --git a/src/core/StatsSchemas.ts b/src/core/StatsSchemas.ts index 03d151ad27..0974c6237d 100644 --- a/src/core/StatsSchemas.ts +++ b/src/core/StatsSchemas.ts @@ -37,6 +37,7 @@ export const OtherUnitSchema = z.union([ z.literal("wshp"), z.literal("silo"), z.literal("saml"), + z.literal("fact"), ]); export type OtherUnit = z.infer; export type OtherUnitType = @@ -45,7 +46,8 @@ export type OtherUnitType = | UnitType.MissileSilo | UnitType.Port | UnitType.SAMLauncher - | UnitType.Warship; + | UnitType.Warship + | UnitType.Factory; export const unitTypeToOtherUnit = { [UnitType.City]: "city", @@ -54,6 +56,7 @@ export const unitTypeToOtherUnit = { [UnitType.Port]: "port", [UnitType.SAMLauncher]: "saml", [UnitType.Warship]: "wshp", + [UnitType.Factory]: "fact", } as const satisfies Record; // Attacks diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index 69fb22df06..42464f2824 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -310,7 +310,7 @@ export class DefaultConfig implements Config { return Math.min(50, Math.round(10 * Math.pow(numberOfPorts, 0.6))); } trainSpawnRate(numberOfStations: number): number { - return Math.min(1400, Math.round(60 * Math.pow(numberOfStations, 0.8))); + return Math.min(1400, Math.round(70 * Math.pow(numberOfStations, 0.8))); } trainGold(): Gold { return BigInt(10_000); diff --git a/src/core/execution/CityExecution.ts b/src/core/execution/CityExecution.ts index 880755573e..c037c12c25 100644 --- a/src/core/execution/CityExecution.ts +++ b/src/core/execution/CityExecution.ts @@ -1,5 +1,6 @@ import { Execution, Game, Player, Unit, UnitType } from "../game/Game"; import { TileRef } from "../game/GameMap"; +import { TrainStationExecution } from "./TrainStationExecution"; export class CityExecution implements Execution { private mg: Game; @@ -24,6 +25,7 @@ export class CityExecution implements Execution { return; } this.city = this.player.buildUnit(UnitType.City, spawnTile, {}); + this.createStation(); } if (!this.city.isActive()) { this.active = false; @@ -42,4 +44,18 @@ export class CityExecution implements Execution { activeDuringSpawnPhase(): boolean { return false; } + + createStation(): void { + if (this.city !== null) { + const nearbyFactory = this.mg.hasUnitNearby( + this.city.tile()!, + this.mg.config().trainStationMaxRange(), + UnitType.Factory, + this.player.id(), + ); + if (nearbyFactory) { + this.mg.addExecution(new TrainStationExecution(this.city)); + } + } + } } diff --git a/src/core/execution/ExecutionManager.ts b/src/core/execution/ExecutionManager.ts index 72e552cb9d..2b7a479e0a 100644 --- a/src/core/execution/ExecutionManager.ts +++ b/src/core/execution/ExecutionManager.ts @@ -23,7 +23,6 @@ import { RetreatExecution } from "./RetreatExecution"; import { SetTargetTroopRatioExecution } from "./SetTargetTroopRatioExecution"; import { SpawnExecution } from "./SpawnExecution"; import { TargetPlayerExecution } from "./TargetPlayerExecution"; -import { TrainStationExecution } from "./TrainStationExecution"; import { TransportShipExecution } from "./TransportShipExecution"; import { UpgradeStructureExecution } from "./UpgradeStructureExecution"; @@ -118,8 +117,6 @@ export class Executor { case "upgrade_structure": return new UpgradeStructureExecution(player, intent.unitId); - case "create_station": - return new TrainStationExecution(player, intent.unitId); case "quick_chat": return new QuickChatExecution( player, diff --git a/src/core/execution/FactoryExecution.ts b/src/core/execution/FactoryExecution.ts index c51ed58b51..cbd1d16672 100644 --- a/src/core/execution/FactoryExecution.ts +++ b/src/core/execution/FactoryExecution.ts @@ -1,28 +1,30 @@ import { Execution, Game, Player, Unit, UnitType } from "../game/Game"; import { TileRef } from "../game/GameMap"; +import { TrainStationExecution } from "./TrainStationExecution"; export class FactoryExecution implements Execution { private factory: Unit | null = null; private active: boolean = true; - + private game: Game; constructor( private player: Player, private tile: TileRef, ) {} init(mg: Game, ticks: number): void { - const spawnTile = this.player.canBuild(UnitType.Factory, this.tile); - if (spawnTile === false) { - console.warn("cannot build factory"); - this.active = false; - return; - } - this.factory = this.player.buildUnit(UnitType.Factory, spawnTile, {}); + this.game = mg; } tick(ticks: number): void { - if (this.factory === null) { - throw new Error("Not initialized"); + if (!this.factory) { + const spawnTile = this.player.canBuild(UnitType.Factory, this.tile); + if (spawnTile === false) { + console.warn("cannot build factory"); + this.active = false; + return; + } + this.factory = this.player.buildUnit(UnitType.Factory, spawnTile, {}); + this.createStation(); } if (!this.factory.isActive()) { this.active = false; @@ -41,4 +43,21 @@ export class FactoryExecution implements Execution { activeDuringSpawnPhase(): boolean { return false; } + + createStation(): void { + if (this.factory !== null) { + const structures = this.game.nearbyUnits( + this.factory.tile()!, + this.game.config().trainStationMaxRange(), + [UnitType.City, UnitType.Port, UnitType.Factory], + ); + // Use different seeds or trains will spawn simultaneously + let seed = 0; + for (const { unit } of structures) { + if (!unit.hasTrainStation()) { + this.game.addExecution(new TrainStationExecution(unit, ++seed)); + } + } + } + } } diff --git a/src/core/execution/FakeHumanExecution.ts b/src/core/execution/FakeHumanExecution.ts index eb9467c8da..622c433830 100644 --- a/src/core/execution/FakeHumanExecution.ts +++ b/src/core/execution/FakeHumanExecution.ts @@ -22,7 +22,6 @@ import { ConstructionExecution } from "./ConstructionExecution"; import { EmojiExecution } from "./EmojiExecution"; import { NukeExecution } from "./NukeExecution"; import { SpawnExecution } from "./SpawnExecution"; -import { TrainStationExecution } from "./TrainStationExecution"; import { TransportShipExecution } from "./TransportShipExecution"; import { closestTwoTiles } from "./Util"; import { BotBehavior } from "./utils/BotBehavior"; @@ -438,35 +437,11 @@ export class FakeHumanExecution implements Execution { this.maybeSpawnStructure(UnitType.Port, 1) || this.maybeSpawnStructure(UnitType.City, 2) || this.maybeSpawnWarship() || - this.maybeSpawnTrainStation() || + this.maybeSpawnStructure(UnitType.Factory, 1) || this.maybeSpawnStructure(UnitType.MissileSilo, 1) ); } - private maybeSpawnTrainStation(): boolean { - if (this.mg.config().isUnitDisabled(UnitType.Train)) { - return false; - } - if (this.player === null) throw new Error("not initialized"); - const citiesWithoutStations = this.player.units().filter((unit) => { - switch (unit.type()) { - case UnitType.City: - case UnitType.Port: - case UnitType.Factory: - return !unit.hasTrainStation(); - default: - return false; - } - }); - if (citiesWithoutStations.length === 0) { - return false; - } - this.mg.addExecution( - new TrainStationExecution(this.player, citiesWithoutStations[0].id()), - ); - return true; - } - private maybeSpawnStructure(type: UnitType, maxNum: number): boolean { if (this.player === null) throw new Error("not initialized"); if (this.player.unitsOwned(type) >= maxNum) { diff --git a/src/core/execution/TrainExecution.ts b/src/core/execution/TrainExecution.ts index 77517788e8..30e9df7b6b 100644 --- a/src/core/execution/TrainExecution.ts +++ b/src/core/execution/TrainExecution.ts @@ -22,7 +22,7 @@ export class TrainExecution implements Execution { private usedTiles: TileRef[] = []; // used for cars behind private stations: TrainStation[] = []; private currentRailroad: OrientedRailroad | null = null; - private speed: number = 3; + private speed: number = 2; constructor( private railNetwork: RailNetwork, @@ -30,9 +30,7 @@ export class TrainExecution implements Execution { private source: TrainStation, private destination: TrainStation, private numCars: number, - ) { - this.hasCargo = source.unit.type() === UnitType.Factory; - } + ) {} init(mg: Game, ticks: number): void { this.mg = mg; diff --git a/src/core/execution/TrainStationExecution.ts b/src/core/execution/TrainStationExecution.ts index 358899ca70..fc8563da12 100644 --- a/src/core/execution/TrainStationExecution.ts +++ b/src/core/execution/TrainStationExecution.ts @@ -1,4 +1,4 @@ -import { Execution, Game, Player, Unit, UnitType } from "../game/Game"; +import { Execution, Game, Unit } from "../game/Game"; import { TrainStation } from "../game/TrainStation"; import { PseudoRandom } from "../PseudoRandom"; import { TrainExecution } from "./TrainExecution"; @@ -8,11 +8,10 @@ export class TrainStationExecution implements Execution { private active: boolean = true; private random: PseudoRandom | null = null; private station: TrainStation | null = null; - private unit: Unit | undefined = undefined; private numCars: number = 5; constructor( - private player: Player, - private unitId: number, + private unit: Unit, + private randomSeed?: number, ) {} isActive(): boolean { @@ -21,21 +20,7 @@ export class TrainStationExecution implements Execution { init(mg: Game, ticks: number): void { this.mg = mg; - - if (this.mg.config().isUnitDisabled(UnitType.Train)) { - this.active = false; - console.warn(`train station is disabled`); - return; - } - - this.random = new PseudoRandom(mg.ticks()); - - this.unit = this.player.units().find((unit) => unit.id() === this.unitId); - if (this.unit === undefined) { - console.warn(`station unit is undefined`); - this.active = false; - return; - } + this.random = new PseudoRandom(mg.ticks() + (this.randomSeed ?? 0)); this.unit.setTrainStation(true); } diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts index 3301790006..48ae1822ca 100644 --- a/src/core/game/Game.ts +++ b/src/core/game/Game.ts @@ -633,6 +633,12 @@ export interface Game extends GameMap { // Units units(...types: UnitType[]): Unit[]; unitInfo(type: UnitType): UnitInfo; + hasUnitNearby( + tile: TileRef, + searchRange: number, + type: UnitType, + playerId: PlayerID, + ); nearbyUnits( tile: TileRef, searchRange: number, diff --git a/src/core/game/GameImpl.ts b/src/core/game/GameImpl.ts index 151ea84a7f..99341a99c5 100644 --- a/src/core/game/GameImpl.ts +++ b/src/core/game/GameImpl.ts @@ -715,6 +715,15 @@ export class GameImpl implements Game { } } + hasUnitNearby( + tile: TileRef, + searchRange: number, + type: UnitType, + playerId: PlayerID, + ) { + return this.unitGrid.hasUnitNearby(tile, searchRange, type, playerId); + } + nearbyUnits( tile: TileRef, searchRange: number, diff --git a/src/core/game/RailNetworkImpl.ts b/src/core/game/RailNetworkImpl.ts index 5d220e6f57..ca1a3319ed 100644 --- a/src/core/game/RailNetworkImpl.ts +++ b/src/core/game/RailNetworkImpl.ts @@ -120,6 +120,7 @@ export class RailNetworkImpl implements RailNetwork { newCluster.addStations(stations); } } + station.unit.setTrainStation(false); } /** diff --git a/src/core/game/TrainStation.ts b/src/core/game/TrainStation.ts index a86f819fcf..027ddd2763 100644 --- a/src/core/game/TrainStation.ts +++ b/src/core/game/TrainStation.ts @@ -1,4 +1,3 @@ -import { TradeShipExecution } from "../execution/TradeShipExecution"; import { TrainExecution } from "../execution/TrainExecution"; import { GraphAdapter } from "../pathfinding/SerialAStar"; import { PseudoRandom } from "../PseudoRandom"; @@ -14,30 +13,34 @@ interface TrainStopHandler { onStop(mg: Game, station: TrainStation, trainExecution: TrainExecution): void; } +/** + * All stop handlers share the same logic for the time being + * Behavior to be defined + */ class CityStopHandler implements TrainStopHandler { + private factor: bigint = BigInt(2); onStop( mg: Game, station: TrainStation, trainExecution: TrainExecution, ): void { - const goldBonus = mg.config().trainGold(); + const level = BigInt(station.unit.level() + 1); + const goldBonus = (mg.config().trainGold() * level) / this.factor; station.unit.owner().addGold(goldBonus, station.tile()); } } class PortStopHandler implements TrainStopHandler { + private factor: bigint = BigInt(2); constructor(private random: PseudoRandom) {} onStop( mg: Game, station: TrainStation, trainExecution: TrainExecution, ): void { - const unit = station.unit; - const ports = unit.owner().tradingPorts(unit); - if (ports.length === 0) return; - - const port = this.random.randElement(ports); - mg.addExecution(new TradeShipExecution(unit.owner(), unit, port)); + const level = BigInt(station.unit.level() + 1); + const goldBonus = (mg.config().trainGold() * level) / this.factor; + station.unit.owner().addGold(goldBonus, station.tile()); } } @@ -47,7 +50,15 @@ class FactoryStopHandler implements TrainStopHandler { station: TrainStation, trainExecution: TrainExecution, ): void { - trainExecution.loadCargo(); + const goldBonus = mg.config().trainGold(); + station.unit.owner().addGold(goldBonus); + mg.addUpdate({ + type: GameUpdateType.BonusEvent, + tile: station.tile(), + gold: Number(goldBonus), + workers: 0, + troops: 0, + }); } } diff --git a/src/core/game/UnitImpl.ts b/src/core/game/UnitImpl.ts index 5dbe57968b..80527e53bf 100644 --- a/src/core/game/UnitImpl.ts +++ b/src/core/game/UnitImpl.ts @@ -249,6 +249,7 @@ export class UnitImpl implements Unit { case UnitType.Port: case UnitType.SAMLauncher: case UnitType.Warship: + case UnitType.Factory: this.mg.stats().unitDestroy(destroyer, this._type); this.mg.stats().unitLose(this.owner(), this._type); break; diff --git a/src/server/GameServer.ts b/src/server/GameServer.ts index c971688e09..eda377740e 100644 --- a/src/server/GameServer.ts +++ b/src/server/GameServer.ts @@ -21,7 +21,7 @@ import { } from "../core/Schemas"; import { createGameRecord } from "../core/Util"; import { GameEnv, ServerConfig } from "../core/configuration/Config"; -import { GameType, UnitType } from "../core/game/Game"; +import { GameType } from "../core/game/Game"; import { archive } from "./Archive"; import { Client } from "./Client"; import { gatekeeper } from "./Gatekeeper"; @@ -222,15 +222,6 @@ export class GameServer { ); return; } - if ( - clientMsg.intent.type === "create_station" && - this.gameConfig.disabledUnits?.includes(UnitType.Train) - ) { - this.log.warn( - `create_station is disabled, client: ${client.clientID}`, - ); - return; - } this.addIntent(clientMsg.intent); } if (clientMsg.type === "ping") { diff --git a/tests/core/game/RailNetwork.test.ts b/tests/core/game/RailNetwork.test.ts index 563d5f83c7..1ebe382354 100644 --- a/tests/core/game/RailNetwork.test.ts +++ b/tests/core/game/RailNetwork.test.ts @@ -11,7 +11,10 @@ const createMockStation = (unitId: number): any => { const cluster = new Cluster(); const railroads = new Set(); return { - unit: { id: unitId }, + unit: { + id: unitId, + setTrainStation: jest.fn(), + }, tile: jest.fn(), neighbors: jest.fn(() => []), getCluster: jest.fn(() => cluster), diff --git a/tests/core/game/TrainStation.test.ts b/tests/core/game/TrainStation.test.ts index 316556f1f8..e67458964c 100644 --- a/tests/core/game/TrainStation.test.ts +++ b/tests/core/game/TrainStation.test.ts @@ -15,7 +15,7 @@ describe("TrainStation", () => { game = { ticks: jest.fn().mockReturnValue(123), config: jest.fn().mockReturnValue({ - trainGold: () => 10, + trainGold: () => BigInt(10), }), addUpdate: jest.fn(), addExecution: jest.fn(), @@ -28,6 +28,7 @@ describe("TrainStation", () => { canTrade: jest.fn().mockReturnValue(true), tradingPorts: jest.fn().mockReturnValue([{ name: "Port1" }]), }), + level: jest.fn().mockReturnValue(1), tile: jest.fn().mockReturnValue({ x: 0, y: 0 }), type: jest.fn(), isActive: jest.fn().mockReturnValue(true), @@ -44,25 +45,7 @@ describe("TrainStation", () => { station.onTrainStop(trainExecution); - expect(unit.owner().addGold).toHaveBeenCalledWith(10, unit.tile()); - }); - - it("handles Port stop", () => { - unit.type.mockReturnValue(UnitType.Port); - - const station = new TrainStation(game, unit); - station.onTrainStop(trainExecution); - - expect(game.addExecution).toHaveBeenCalled(); - }); - - it("handles Factory stop", () => { - unit.type.mockReturnValue(UnitType.Factory); - - const station = new TrainStation(game, unit); - station.onTrainStop(trainExecution); - - expect(trainExecution.loadCargo).toHaveBeenCalled(); + expect(unit.owner().addGold).toHaveBeenCalledWith(10n, unit.tile()); }); it("checks trade availability (same owner)", () => {