import { Container, Graphics, Ticker } from 'pixi.js'; import { Direction, Orientation } from '../core/ReelAxis.js'; import { ReelSet } from '../core/ReelSet.js'; import { ReelSymbol } from '../symbols/ReelSymbol.js'; import { SymbolRegistry } from '../symbols/SymbolRegistry.js'; import { SpeedProfile, SymbolData } from '../config/types.js'; import { Disposable } from '../utils/Disposable.js'; /** A cell coordinate in the grid. */ export interface BoardCell { reel: number; cell: number; } /** A landing target: spin `cell` and stop it showing `id`. */ export interface BoardSpinTarget { cell: BoardCell; id: string; } /** A speed profile, or a per-cell function of one (e.g. a stagger wave). */ export type BoardProfile = SpeedProfile | ((cell: BoardCell) => SpeedProfile); export interface BoardGridOptions { /** Grid dimensions. */ cols: number; rows: number; /** Cell edge length in pixels. */ cellSize: number; /** Gap between cells. Default 4. */ gap?: number; /** Id a cell shows when blank - also placed in the off-window buffers. Default `'empty'`. */ emptyId?: string; /** Register symbol classes, exactly like `ReelSetBuilder.symbols`. Applied to every cell. */ symbols: (registry: SymbolRegistry) => void; /** Strip weights during the spin. */ weights?: Record; /** Per-symbol engine overrides, exactly like `ReelSetBuilder.symbolData`. */ symbolData?: Record>; /** Injected RNG for the spin strips (deterministic demos / tests). */ rng?: () => number; /** Drives every cell's reel - required. */ ticker: Ticker; /** Per-cell background, drawn behind each reel. */ chrome?: (g: Graphics, size: number) => void; /** * Which way each cell's own strip travels while it spins. Every cell is a * 1x1 reel set, so this changes the direction a symbol scrolls in from, not * the board layout - `cols` and `rows` stay board dimensions either way. * Defaults to the engine default (vertical / forward), i.e. symbols drop in * from above. */ orientation?: Orientation; direction?: Direction; /** * Named speed profiles, each registered on every cell and selected by name * via {@link BoardGrid.setProfile}. A value may be a flat profile or a * per-cell function (for stagger waves). Defaults to a single `'default'` * profile, which is the active one until you `setProfile` otherwise. */ profiles?: Record; } /** * A grid of cells that each spin **independently** - the generic "board of * reels" primitive. Every cell is its own 1×1 {@link ReelSet}, so it inherits * the engine's phases, speed modes and pooling rather than a parallel lighter * reel. * * Deliberately mechanism-only: it knows nothing about coins, locks, respins, * value or any game rule. It lays the grid out, hands back per-cell geometry * and live symbol instances, places symbols instantly, and spins a * **caller-chosen** set of cells to caller-chosen results. Build your own * feature on top by owning the rules in your own code; {@link HoldAndWinBoard} * is one such opinionated layer, built entirely on this public surface. * * ```ts * const grid = new BoardGrid({ * cols: 3, rows: 3, cellSize: 80, * symbols: (r) => r.register('prize', PrizeSymbol, {}), * weights: { prize: 1, empty: 4 }, * ticker: app.ticker, * }); * app.stage.addChild(grid.container); * * await grid.spinCells( * grid.cells().map((cell) => ({ cell, id: pick() })), // you decide each result * (cell, id) => console.log('landed', cell, id), // react as each settles * ); * ``` */ export declare class BoardGrid implements Disposable { readonly container: Container; readonly cols: number; readonly rows: number; readonly cellSize: number; readonly gap: number; readonly emptyId: string; private readonly _reels; private readonly _cells; private _destroyed; constructor(opts: BoardGridOptions); /** Every cell coordinate, reel-major: (0,0), (0,1), ... then (1,0). */ cells(): BoardCell[]; /** Board-local bounds of a cell. `container.toGlobal` for stage space. */ cellBounds(cell: BoardCell): { x: number; y: number; width: number; height: number; }; /** Board-local center of a cell - flight / trail start and end points. */ cellCenter(cell: BoardCell): { x: number; y: number; }; /** Live symbol instance currently shown in a cell. */ symbolAt(cell: BoardCell): ReelSymbol; /** The cell's underlying 1×1 ReelSet, for driving one cell directly. */ reelAt(cell: BoardCell): ReelSet; /** Select a registered speed profile by name for one cell. */ setProfile(cell: BoardCell, name: string): void; /** Place a symbol instantly (no spin), with blank off-window buffers. */ place(cell: BoardCell, id: string): void; /** * Spin each target cell and stop it showing its `id`; `onLanded` fires per * cell as it settles, in stagger order. The caller selects which cells spin * and to what - this layer applies no lock/free policy of its own. Set * profiles via {@link setProfile} first. * * `onLanded` may be **async**: if it returns a promise, that cell's task * awaits it, so the returned promise resolves only once every cell has landed * *and* its after-land work has finished. Cells still run concurrently, so an * early cell's reveal overlaps with later cells still spinning. */ spinCells(targets: BoardSpinTarget[], onLanded?: (cell: BoardCell, id: string) => void | Promise): Promise; /** Slam every in-flight cell to its landed position. Returns the count. */ skipSpinning(): number; get isDestroyed(): boolean; destroy(): void; private _origin; private _reel; } //# sourceMappingURL=BoardGrid.d.ts.map