From 8443095d89befe957f57fe647c959163cf984082 Mon Sep 17 00:00:00 2001 From: Evan Date: Thu, 2 Jan 2025 13:25:36 -0800 Subject: [PATCH] create game runner --- .../{GameRunner.ts => ClientGameRunner.ts} | 10 ++-- src/client/LocalServer.ts | 2 +- src/client/Main.ts | 2 +- src/client/Transport.ts | 2 +- src/core/GameRunner.ts | 50 +++++++++++++++++++ src/core/GameView.ts | 26 ++++++++++ src/core/execution/ExecutionManager.ts | 5 +- src/core/execution/FakeHumanExecution.ts | 4 +- src/core/execution/PortExecution.ts | 19 ++++--- src/core/pathfinding/PathFinding.ts | 12 ----- 10 files changed, 100 insertions(+), 32 deletions(-) rename src/client/{GameRunner.ts => ClientGameRunner.ts} (97%) create mode 100644 src/core/GameRunner.ts create mode 100644 src/core/GameView.ts diff --git a/src/client/GameRunner.ts b/src/client/ClientGameRunner.ts similarity index 97% rename from src/client/GameRunner.ts rename to src/client/ClientGameRunner.ts index 444f39e1f..bb6d0357f 100644 --- a/src/client/GameRunner.ts +++ b/src/client/ClientGameRunner.ts @@ -69,16 +69,14 @@ export function joinLobby(lobbyConfig: LobbyConfig, onjoin: () => void): () => v } -export async function createClientGame(lobbyConfig: LobbyConfig, gameConfig: GameConfig, eventBus: EventBus, transport: Transport): Promise { +export async function createClientGame(lobbyConfig: LobbyConfig, gameConfig: GameConfig, eventBus: EventBus, transport: Transport): Promise { const config = getConfig(gameConfig) const terrainMap = await loadTerrainMap(gameConfig.gameMap); let game = createGame(terrainMap.map, terrainMap.miniMap, eventBus, config) - const worker = new WorkerClient(game, gameConfig.gameMap) consolex.log('going to init path finder') - await worker.initialize() consolex.log('inited path finder') const canvas = createCanvas() let gameRenderer = createRenderer(canvas, game, eventBus, lobbyConfig.clientID) @@ -86,18 +84,18 @@ export async function createClientGame(lobbyConfig: LobbyConfig, gameConfig: Gam consolex.log(`creating private game got difficulty: ${gameConfig.difficulty}`) - return new GameRunner( + return new ClientGameRunner( lobbyConfig.clientID, eventBus, game, gameRenderer, new InputHandler(canvas, eventBus), - new Executor(game, lobbyConfig.gameID, worker), + new Executor(game, lobbyConfig.gameID), transport, ) } -export class GameRunner { +export class ClientGameRunner { private myPlayer: Player private turns: Turn[] = [] private isActive = false diff --git a/src/client/LocalServer.ts b/src/client/LocalServer.ts index cb5527088..8538d71ac 100644 --- a/src/client/LocalServer.ts +++ b/src/client/LocalServer.ts @@ -3,7 +3,7 @@ import { consolex } from "../core/Consolex"; import { GameEvent } from "../core/EventBus"; import { ClientID, ClientMessage, ClientMessageSchema, GameConfig, GameID, GameRecordSchema, Intent, PlayerRecord, ServerMessage, ServerStartGameMessageSchema, ServerTurnMessageSchema, Turn } from "../core/Schemas"; import { CreateGameRecord, generateID } from "../core/Util"; -import { LobbyConfig } from "./GameRunner"; +import { LobbyConfig } from "./ClientGameRunner"; import { getPersistentIDFromCookie } from "./Main"; diff --git a/src/client/Main.ts b/src/client/Main.ts index 1f11f5811..653efda80 100644 --- a/src/client/Main.ts +++ b/src/client/Main.ts @@ -1,4 +1,4 @@ -import { GameRunner, joinLobby } from "./GameRunner"; +import { ClientGameRunner, joinLobby } from "./ClientGameRunner"; import backgroundImage from '../../resources/images/TerrainMapFrontPage.png'; import favicon from '../../resources/images/Favicon.svg'; diff --git a/src/client/Transport.ts b/src/client/Transport.ts index d1fb2524d..ae71a2e4d 100644 --- a/src/client/Transport.ts +++ b/src/client/Transport.ts @@ -3,7 +3,7 @@ import { SendLogEvent } from "../core/Consolex" import { EventBus, GameEvent } from "../core/EventBus" import { AllianceRequest, AllPlayers, Cell, GameType, Player, PlayerID, PlayerType, Tile, UnitType } from "../core/game/Game" import { ClientID, ClientIntentMessageSchema, ClientJoinMessageSchema, GameID, Intent, ServerMessage, ServerMessageSchema, ClientPingMessageSchema, GameConfig, ClientLogMessageSchema } from "../core/Schemas" -import { LobbyConfig } from "./GameRunner" +import { LobbyConfig } from "./ClientGameRunner" import { LocalServer } from "./LocalServer" import { UsernameInput } from "./UsernameInput"; import { HostLobbyModal as HostPrivateLobbyModal } from "./HostLobbyModal"; diff --git a/src/core/GameRunner.ts b/src/core/GameRunner.ts new file mode 100644 index 000000000..850304fe0 --- /dev/null +++ b/src/core/GameRunner.ts @@ -0,0 +1,50 @@ +import { getConfig } from "./configuration/Config"; +import { EventBus } from "./EventBus"; +import { Executor } from "./execution/ExecutionManager"; +import { Game } from "./game/Game"; +import { createGame } from "./game/GameImpl"; +import { loadTerrainMap } from "./game/TerrainMapLoader"; +import { GameConfig, Turn } from "./Schemas"; + +export interface GameUpdate { + players: PlayerUpdate[] + units: UnitUpdate[] + +} + +export interface PlayerUpdate { + +} + +export interface UnitUpdate { + +} + +export interface TileUpdate { + x: number + y: number + isBorder: boolean + +} + +export async function createGameRunner(gameID: string, gameConfig: GameConfig): Promise { + const config = getConfig(gameConfig) + const terrainMap = await loadTerrainMap(gameConfig.gameMap); + const eventBus = new EventBus() + const game = createGame(terrainMap.map, terrainMap.miniMap, eventBus, config) + return new GameRunner(game, eventBus, new Executor(game, gameID)) +} + +export class GameRunner { + + constructor(private game: Game, private eventBus: EventBus, private execManager: Executor) { + + } + + public executeNextTick(turn: Turn): GameUpdate { + + this.game.executeNextTick() + return null + } + +} \ No newline at end of file diff --git a/src/core/GameView.ts b/src/core/GameView.ts new file mode 100644 index 000000000..1822723f3 --- /dev/null +++ b/src/core/GameView.ts @@ -0,0 +1,26 @@ +import { Cell, PlayerID } from "./game/Game"; +import { GameUpdate } from "./GameRunner"; + +export class TileView { + +} + +export class PlayerView { + +} + +export class GameView { + + public update(gu: GameUpdate) { + + } + + tile(cell: Cell): TileView { + return null + } + + player(id: PlayerID): PlayerView { + return null + } + +} \ No newline at end of file diff --git a/src/core/execution/ExecutionManager.ts b/src/core/execution/ExecutionManager.ts index 4bd5c459c..359aab580 100644 --- a/src/core/execution/ExecutionManager.ts +++ b/src/core/execution/ExecutionManager.ts @@ -32,7 +32,7 @@ export class Executor { // private random = new PseudoRandom(999) private random: PseudoRandom = null - constructor(private gs: Game, private gameID: GameID, private workerClient: WorkerClient) { + constructor(private gs: Game, private gameID: GameID) { // Add one to avoid id collisions with bots. this.random = new PseudoRandom(simpleHash(gameID) + 1) } @@ -94,7 +94,7 @@ export class Executor { case UnitType.Battleship: return new BattleshipExecution(intent.player, new Cell(intent.x, intent.y)) case UnitType.Port: - return new PortExecution(intent.player, new Cell(intent.x, intent.y), this.workerClient) + return new PortExecution(intent.player, new Cell(intent.x, intent.y)) case UnitType.MissileSilo: return new MissileSiloExecution(intent.player, new Cell(intent.x, intent.y)) case UnitType.DefensePost: @@ -118,7 +118,6 @@ export class Executor { for (const nation of this.gs.nations()) { execs.push(new FakeHumanExecution( this.gameID, - this.workerClient, new PlayerInfo( nation.name, PlayerType.FakeHuman, diff --git a/src/core/execution/FakeHumanExecution.ts b/src/core/execution/FakeHumanExecution.ts index 238c08c59..b3c6b8ea3 100644 --- a/src/core/execution/FakeHumanExecution.ts +++ b/src/core/execution/FakeHumanExecution.ts @@ -33,7 +33,7 @@ export class FakeHumanExecution implements Execution { private lastEmojiSent = new Map() - constructor(gameID: GameID, private worker: WorkerClient, private playerInfo: PlayerInfo, private cell: Cell, private strength: number) { + constructor(gameID: GameID, private playerInfo: PlayerInfo, private cell: Cell, private strength: number) { this.random = new PseudoRandom(simpleHash(playerInfo.id) + simpleHash(gameID)) } @@ -265,7 +265,7 @@ export class FakeHumanExecution implements Execution { const oceanTiles = Array.from(this.player.borderTiles()).filter(t => t.isOceanShore()) if (oceanTiles.length > 0) { const buildTile = this.random.randElement(oceanTiles) - this.mg.addExecution(new PortExecution(this.player.id(), buildTile.cell(), this.worker)) + this.mg.addExecution(new PortExecution(this.player.id(), buildTile.cell())) } return } diff --git a/src/core/execution/PortExecution.ts b/src/core/execution/PortExecution.ts index fdd608623..848bbd788 100644 --- a/src/core/execution/PortExecution.ts +++ b/src/core/execution/PortExecution.ts @@ -7,6 +7,7 @@ import { bfs, dist, manhattanDist } from "../Util"; import { TradeShipExecution } from "./TradeShipExecution"; import { ParallelAStar, WorkerClient } from "../worker/WorkerClient"; import { consolex } from "../Consolex"; +import { MiniAStar } from "../pathfinding/MiniAStar"; export class PortExecution implements Execution { @@ -15,12 +16,11 @@ export class PortExecution implements Execution { private port: MutableUnit private random: PseudoRandom private portPaths = new Map() - private computingPaths = new Map() + private computingPaths = new Map() constructor( private _owner: PlayerID, private cell: Cell, - private worker: WorkerClient ) { } @@ -84,9 +84,16 @@ export class PortExecution implements Execution { } continue } - const asyncPF = this.worker.createParallelAStar(this.port.tile(), port.tile(), 25, [TerrainType.Ocean]) - // consolex.log(`adding new port path from ${this.player().name()}:${this.port.tile().cell()} to ${port.owner().name()}:${port.tile().cell()}`) - this.computingPaths.set(port, asyncPF) + + const pf = new MiniAStar( + this.mg.terrainMap(), + this.mg.terrainMiniMap(), + this.port.tile(), port.tile(), + sn => sn.terrainType() == TerrainType.Ocean, + 10_000, + 25 + ) + this.computingPaths.set(port, pf) } for (const port of this.portPaths.keys()) { @@ -102,7 +109,7 @@ export class PortExecution implements Execution { const port = this.random.randElement(portConnections) const path = this.portPaths.get(port) if (path != null) { - const pf = PathFinder.Parallel(this.mg, this.worker, 10) + const pf = PathFinder.Mini(this.mg, 10, (sn) => sn.terrainType() == TerrainType.Ocean) this.mg.addExecution(new TradeShipExecution(this.player().id(), this.port, port, pf, path)) } } diff --git a/src/core/pathfinding/PathFinding.ts b/src/core/pathfinding/PathFinding.ts index a1b9b9fe5..a63b34feb 100644 --- a/src/core/pathfinding/PathFinding.ts +++ b/src/core/pathfinding/PathFinding.ts @@ -52,18 +52,6 @@ export class PathFinder { ) } - public static Parallel(game: Game, worker: WorkerClient, numTicks: number, ...types: TerrainType[]): PathFinder { - if (types.length == 0) { - types = [TerrainType.Ocean] - } - return new PathFinder( - game, - (curr: Tile, dst: Tile) => { - return worker.createParallelAStar(curr, dst, numTicks, types) - } - ) - } - nextTile(curr: Tile, dst: Tile, dist: number = 1): TileResult { if (curr == null) { consolex.error('curr is null')