import { Game } from "../game/Game"; import { GameMap, TileRef } from "../game/GameMap"; import { TrainStation } from "../game/TrainStation"; import { AStarRail } from "./algorithms/AStar.Rail"; import { AStarWater } from "./algorithms/AStar.Water"; import { AirPathFinder } from "./PathFinder.Air"; import { ParabolaOptions, ParabolaUniversalPathFinder, } from "./PathFinder.Parabola"; import { StationPathFinder } from "./PathFinder.Station"; import { PathFinderBuilder } from "./PathFinderBuilder"; import { StepperConfig } from "./PathFinderStepper"; import { ComponentCheckTransformer } from "./transformers/ComponentCheckTransformer"; import { MiniMapTransformer } from "./transformers/MiniMapTransformer"; import { ShoreCoercingTransformer } from "./transformers/ShoreCoercingTransformer"; import { SmoothingWaterTransformer } from "./transformers/SmoothingWaterTransformer"; import { PathStatus, SteppingPathFinder } from "./types"; /** * Pathfinders that work with GameMap - usable in both simulation and UI layers */ export class UniversalPathFinding { static Parabola( gameMap: GameMap, options?: ParabolaOptions, ): ParabolaUniversalPathFinder { return new ParabolaUniversalPathFinder(gameMap, options); } } /** * Pathfinders that require Game - simulation layer only */ export class PathFinding { static Water(game: Game): SteppingPathFinder { const pf = game.miniWaterHPA(); const graph = game.miniWaterGraph(); if (!pf || !graph || graph.nodeCount < 100) { return PathFinding.WaterSimple(game); } const miniMap = game.miniMap(); const componentCheckFn = (t: TileRef) => graph.getComponentId(t); return PathFinderBuilder.create(pf) .wrap((pf) => new ComponentCheckTransformer(pf, componentCheckFn)) .wrap((pf) => new SmoothingWaterTransformer(pf, miniMap)) .wrap((pf) => new ShoreCoercingTransformer(pf, miniMap)) .wrap((pf) => new MiniMapTransformer(pf, game.map(), miniMap)) .buildWithStepper(tileStepperConfig(game)); } static WaterSimple(game: Game): SteppingPathFinder { const miniMap = game.miniMap(); const pf = new AStarWater(miniMap); return PathFinderBuilder.create(pf) .wrap((pf) => new ShoreCoercingTransformer(pf, miniMap)) .wrap((pf) => new MiniMapTransformer(pf, game.map(), miniMap)) .buildWithStepper(tileStepperConfig(game)); } static Rail(game: Game): SteppingPathFinder { const miniMap = game.miniMap(); const pf = new AStarRail(miniMap); return PathFinderBuilder.create(pf) .wrap((pf) => new MiniMapTransformer(pf, game.map(), miniMap)) .buildWithStepper(tileStepperConfig(game)); } static Stations(game: Game): SteppingPathFinder { const pf = new StationPathFinder(game); return PathFinderBuilder.create(pf).buildWithStepper({ equals: (a, b) => a.id === b.id, distance: (a, b) => game.manhattanDist(a.tile(), b.tile()), }); } static Air(game: Game): SteppingPathFinder { const pf = new AirPathFinder(game); return PathFinderBuilder.create(pf).buildWithStepper({ equals: (a, b) => a === b, }); } } function tileStepperConfig(game: Game): StepperConfig { return { equals: (a, b) => a === b, distance: (a, b) => game.manhattanDist(a, b), preCheck: (from, to) => typeof from !== "number" || typeof to !== "number" || !game.isValidRef(from) || !game.isValidRef(to) ? { status: PathStatus.NOT_FOUND } : null, }; }