pixi-reels 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +167 -0
  3. package/dist/SpineSymbol-B40TevSr.cjs +2 -0
  4. package/dist/SpineSymbol-B40TevSr.cjs.map +1 -0
  5. package/dist/SpineSymbol-D2jhCzFW.js +82 -0
  6. package/dist/SpineSymbol-D2jhCzFW.js.map +1 -0
  7. package/dist/config/SpeedPresets.d.ts +49 -0
  8. package/dist/config/SpeedPresets.d.ts.map +1 -0
  9. package/dist/config/defaults.d.ts +12 -0
  10. package/dist/config/defaults.d.ts.map +1 -0
  11. package/dist/config/types.d.ts +93 -0
  12. package/dist/config/types.d.ts.map +1 -0
  13. package/dist/core/Reel.d.ts +106 -0
  14. package/dist/core/Reel.d.ts.map +1 -0
  15. package/dist/core/ReelMotion.d.ts +43 -0
  16. package/dist/core/ReelMotion.d.ts.map +1 -0
  17. package/dist/core/ReelSet.d.ts +101 -0
  18. package/dist/core/ReelSet.d.ts.map +1 -0
  19. package/dist/core/ReelSetBuilder.d.ts +102 -0
  20. package/dist/core/ReelSetBuilder.d.ts.map +1 -0
  21. package/dist/core/ReelViewport.d.ts +43 -0
  22. package/dist/core/ReelViewport.d.ts.map +1 -0
  23. package/dist/core/StopSequencer.d.ts +26 -0
  24. package/dist/core/StopSequencer.d.ts.map +1 -0
  25. package/dist/debug/debug.d.ts +65 -0
  26. package/dist/debug/debug.d.ts.map +1 -0
  27. package/dist/events/EventEmitter.d.ts +25 -0
  28. package/dist/events/EventEmitter.d.ts.map +1 -0
  29. package/dist/events/ReelEvents.d.ts +40 -0
  30. package/dist/events/ReelEvents.d.ts.map +1 -0
  31. package/dist/frame/FrameBuilder.d.ts +50 -0
  32. package/dist/frame/FrameBuilder.d.ts.map +1 -0
  33. package/dist/frame/OffsetCalculator.d.ts +19 -0
  34. package/dist/frame/OffsetCalculator.d.ts.map +1 -0
  35. package/dist/frame/RandomSymbolProvider.d.ts +27 -0
  36. package/dist/frame/RandomSymbolProvider.d.ts.map +1 -0
  37. package/dist/index.cjs +5 -0
  38. package/dist/index.cjs.map +1 -0
  39. package/dist/index.d.ts +51 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +1454 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/pool/ObjectPool.d.ts +36 -0
  44. package/dist/pool/ObjectPool.d.ts.map +1 -0
  45. package/dist/speed/SpeedManager.d.ts +38 -0
  46. package/dist/speed/SpeedManager.d.ts.map +1 -0
  47. package/dist/spin/SpinController.d.ts +71 -0
  48. package/dist/spin/SpinController.d.ts.map +1 -0
  49. package/dist/spin/modes/CascadeMode.d.ts +16 -0
  50. package/dist/spin/modes/CascadeMode.d.ts.map +1 -0
  51. package/dist/spin/modes/ImmediateMode.d.ts +10 -0
  52. package/dist/spin/modes/ImmediateMode.d.ts.map +1 -0
  53. package/dist/spin/modes/SpinningMode.d.ts +18 -0
  54. package/dist/spin/modes/SpinningMode.d.ts.map +1 -0
  55. package/dist/spin/modes/StandardMode.d.ts +10 -0
  56. package/dist/spin/modes/StandardMode.d.ts.map +1 -0
  57. package/dist/spin/phases/AnticipationPhase.d.ts +24 -0
  58. package/dist/spin/phases/AnticipationPhase.d.ts.map +1 -0
  59. package/dist/spin/phases/PhaseFactory.d.ts +21 -0
  60. package/dist/spin/phases/PhaseFactory.d.ts.map +1 -0
  61. package/dist/spin/phases/ReelPhase.d.ts +39 -0
  62. package/dist/spin/phases/ReelPhase.d.ts.map +1 -0
  63. package/dist/spin/phases/SpinPhase.d.ts +25 -0
  64. package/dist/spin/phases/SpinPhase.d.ts.map +1 -0
  65. package/dist/spin/phases/StartPhase.d.ts +26 -0
  66. package/dist/spin/phases/StartPhase.d.ts.map +1 -0
  67. package/dist/spin/phases/StopPhase.d.ts +37 -0
  68. package/dist/spin/phases/StopPhase.d.ts.map +1 -0
  69. package/dist/spine/SpineReelSymbol.d.ts +111 -0
  70. package/dist/spine/SpineReelSymbol.d.ts.map +1 -0
  71. package/dist/spine/index.d.ts +5 -0
  72. package/dist/spine/index.d.ts.map +1 -0
  73. package/dist/spine.cjs +2 -0
  74. package/dist/spine.cjs.map +1 -0
  75. package/dist/spine.js +123 -0
  76. package/dist/spine.js.map +1 -0
  77. package/dist/spotlight/SymbolSpotlight.d.ts +70 -0
  78. package/dist/spotlight/SymbolSpotlight.d.ts.map +1 -0
  79. package/dist/symbols/AnimatedSpriteSymbol.d.ts +30 -0
  80. package/dist/symbols/AnimatedSpriteSymbol.d.ts.map +1 -0
  81. package/dist/symbols/ReelSymbol.d.ts +84 -0
  82. package/dist/symbols/ReelSymbol.d.ts.map +1 -0
  83. package/dist/symbols/SpineSymbol.d.ts +34 -0
  84. package/dist/symbols/SpineSymbol.d.ts.map +1 -0
  85. package/dist/symbols/SpriteSymbol.d.ts +29 -0
  86. package/dist/symbols/SpriteSymbol.d.ts.map +1 -0
  87. package/dist/symbols/SymbolFactory.d.ts +20 -0
  88. package/dist/symbols/SymbolFactory.d.ts.map +1 -0
  89. package/dist/symbols/SymbolRegistry.d.ts +25 -0
  90. package/dist/symbols/SymbolRegistry.d.ts.map +1 -0
  91. package/dist/testing/FakeTicker.d.ts +45 -0
  92. package/dist/testing/FakeTicker.d.ts.map +1 -0
  93. package/dist/testing/HeadlessSymbol.d.ts +28 -0
  94. package/dist/testing/HeadlessSymbol.d.ts.map +1 -0
  95. package/dist/testing/index.d.ts +5 -0
  96. package/dist/testing/index.d.ts.map +1 -0
  97. package/dist/testing/testHarness.d.ts +70 -0
  98. package/dist/testing/testHarness.d.ts.map +1 -0
  99. package/dist/utils/Disposable.d.ts +10 -0
  100. package/dist/utils/Disposable.d.ts.map +1 -0
  101. package/dist/utils/TickerRef.d.ts +30 -0
  102. package/dist/utils/TickerRef.d.ts.map +1 -0
  103. package/package.json +86 -0
@@ -0,0 +1,43 @@
1
+ import { ReelSymbol } from '../symbols/ReelSymbol.js';
2
+ /**
3
+ * The physics of one reel — move symbols down, wrap them around.
4
+ *
5
+ * Every frame, `ReelMotion.update(delta)` adds `delta` to each symbol's
6
+ * Y coordinate. A symbol whose position falls off the bottom wraps back
7
+ * to the top (and vice versa — reels can run upward). Each wrap fires
8
+ * the `_onSymbolWrapped` callback so the owning `Reel` can ask the
9
+ * `FrameBuilder` for the next identity to paint on it.
10
+ *
11
+ * Maintains the invariant that `_symbols[0]` is always the visually
12
+ * topmost symbol and `_symbols[N-1]` is always the bottommost. On each
13
+ * wrap, the wrapping symbol is moved to the front (or back) of the array
14
+ * so the ordering stays consistent with the grid. `snapToGrid` and the
15
+ * visible window selection rely on this.
16
+ */
17
+ export declare class ReelMotion {
18
+ private _symbols;
19
+ private _bufferAbove;
20
+ private _onSymbolWrapped;
21
+ private _symbolHeight;
22
+ private _symbolGapY;
23
+ private _slotHeight;
24
+ private _minY;
25
+ private _maxY;
26
+ constructor(_symbols: ReelSymbol[], symbolHeight: number, symbolGapY: number, _bufferAbove: number, visibleRows: number, _onSymbolWrapped: (symbol: ReelSymbol, arrayIndex: number, direction: 'up' | 'down') => void);
27
+ /**
28
+ * Move all symbols by deltaY pixels (positive = downward).
29
+ * At most one wrap per call (deltaY is capped at half a symbol by the
30
+ * spinning mode, so a single symbol can cross the boundary per tick).
31
+ */
32
+ displace(deltaY: number): void;
33
+ /** Snap all symbols to their correct grid positions (array index = visual row). */
34
+ snapToGrid(): void;
35
+ /** Position all symbols above the visible area (for cascade mode start). */
36
+ setToTopPosition(): void;
37
+ /** Get the correct Y position for a symbol at a given row. */
38
+ getRowY(row: number): number;
39
+ get slotHeight(): number;
40
+ private _wrapBottomToTop;
41
+ private _wrapTopToBottom;
42
+ }
43
+ //# sourceMappingURL=ReelMotion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReelMotion.d.ts","sourceRoot":"","sources":["../../src/core/ReelMotion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAE3D;;;;;;;;;;;;;;GAcG;AACH,qBAAa,UAAU;IAQnB,OAAO,CAAC,QAAQ;IAGhB,OAAO,CAAC,YAAY;IAEpB,OAAO,CAAC,gBAAgB;IAZ1B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,KAAK,CAAS;gBAGZ,QAAQ,EAAE,UAAU,EAAE,EAC9B,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EACV,YAAY,EAAE,MAAM,EAC5B,WAAW,EAAE,MAAM,EACX,gBAAgB,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,GAAG,MAAM,KAAK,IAAI;IAStG;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAY9B,mFAAmF;IACnF,UAAU,IAAI,IAAI;IAOlB,4EAA4E;IAC5E,gBAAgB,IAAI,IAAI;IAMxB,8DAA8D;IAC9D,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAI5B,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,gBAAgB;CAUzB"}
@@ -0,0 +1,101 @@
1
+ import { Container } from 'pixi.js';
2
+ import { Disposable } from '../utils/Disposable.js';
3
+ import { ReelSetInternalConfig } from '../config/types.js';
4
+ import { EventEmitter } from '../events/EventEmitter.js';
5
+ import { ReelSetEvents, SpinResult } from '../events/ReelEvents.js';
6
+ import { Reel } from './Reel.js';
7
+ import { ReelViewport } from './ReelViewport.js';
8
+ import { SpeedManager } from '../speed/SpeedManager.js';
9
+ import { SymbolSpotlight } from '../spotlight/SymbolSpotlight.js';
10
+ import { SymbolFactory } from '../symbols/SymbolFactory.js';
11
+ import { FrameBuilder } from '../frame/FrameBuilder.js';
12
+ import { PhaseFactory } from '../spin/phases/PhaseFactory.js';
13
+ import { SpinningMode } from '../spin/modes/SpinningMode.js';
14
+ export interface ReelSetParams {
15
+ config: ReelSetInternalConfig;
16
+ reels: Reel[];
17
+ viewport: ReelViewport;
18
+ symbolFactory: SymbolFactory;
19
+ frameBuilder: FrameBuilder;
20
+ phaseFactory: PhaseFactory;
21
+ spinningMode: SpinningMode;
22
+ }
23
+ /**
24
+ * The whole slot board as one object.
25
+ *
26
+ * A `ReelSet` is a PixiJS `Container` that owns every reel, the spin
27
+ * controller, the speed manager, and the win spotlight. You `addChild` it
28
+ * to your stage and then drive it from the four public verbs below:
29
+ *
30
+ * - `spin()` — start the reels moving, returns a promise that resolves
31
+ * when every reel has landed (or been slam-stopped)
32
+ * - `setResult(grid)` — tell the reels what to land on; the spin
33
+ * controller consumes this and each reel queues its target symbols
34
+ * - `setAnticipation(reelIndices)` — slow the given reels before they
35
+ * stop, for "will the third scatter land?" tension
36
+ * - `skip()` — land immediately; useful for slam-stop UX
37
+ *
38
+ * Everything else is subsystems: `speed`, `spotlight`, `events`, `viewport`.
39
+ * Construction goes through {@link ReelSetBuilder}, never `new ReelSet()`
40
+ * directly — the builder enforces that every required piece is wired.
41
+ *
42
+ * ```ts
43
+ * const reelSet = new ReelSetBuilder()
44
+ * .reels(5).visibleSymbols(3).symbolSize(140, 140)
45
+ * .symbols((r) => r.register('cherry', SpriteSymbol, { textures }))
46
+ * .ticker(app.ticker)
47
+ * .build();
48
+ * app.stage.addChild(reelSet);
49
+ *
50
+ * const spin = reelSet.spin();
51
+ * reelSet.setResult(await server.spin());
52
+ * await spin;
53
+ * ```
54
+ *
55
+ * Teardown cascades: one `reelSet.destroy()` disposes every child.
56
+ */
57
+ export declare class ReelSet extends Container implements Disposable {
58
+ private _events;
59
+ private _reels;
60
+ private _viewport;
61
+ private _spinController;
62
+ private _speedManager;
63
+ private _spotlight;
64
+ private _symbolFactory;
65
+ private _isDestroyed;
66
+ constructor(params: ReelSetParams);
67
+ /** The event emitter for reel-specific events. */
68
+ get events(): EventEmitter<ReelSetEvents>;
69
+ /** Start spinning all reels. Returns a promise that resolves when all reels land. */
70
+ spin(): Promise<SpinResult>;
71
+ /** Set the target result symbols. Triggers the stop sequence. */
72
+ setResult(symbols: string[][]): void;
73
+ /** Set which reels should show anticipation before stopping. */
74
+ setAnticipation(reelIndices: number[]): void;
75
+ /**
76
+ * Override the per-reel stop delay for the current spin (in ms).
77
+ * Pass one value per reel. Cleared at the start of each new spin.
78
+ *
79
+ * @example
80
+ * // Stagger the last two reels more than the default for dramatic effect:
81
+ * reelSet.setStopDelays([0, 140, 280, 600, 1100]);
82
+ */
83
+ setStopDelays(delays: number[]): void;
84
+ /** Skip/slam-stop: immediately land all reels on target. */
85
+ skip(): void;
86
+ get isSpinning(): boolean;
87
+ /** Speed profile manager. */
88
+ get speed(): SpeedManager;
89
+ /** Change speed and emit event. */
90
+ setSpeed(name: string): void;
91
+ get spotlight(): SymbolSpotlight;
92
+ /** Get all reels. */
93
+ get reels(): readonly Reel[];
94
+ /** Get a reel by index. */
95
+ getReel(index: number): Reel;
96
+ /** Get the viewport. */
97
+ get viewport(): ReelViewport;
98
+ get isDestroyed(): boolean;
99
+ destroy(): void;
100
+ }
101
+ //# sourceMappingURL=ReelSet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReelSet.d.ts","sourceRoot":"","sources":["../../src/core/ReelSet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAgB,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAkB,MAAM,yBAAyB,CAAC;AACzF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,eAAe,EAA0D,MAAM,iCAAiC,CAAC;AAC1H,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAElE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,qBAAqB,CAAC;IAC9B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,QAAQ,EAAE,YAAY,CAAC;IACvB,aAAa,EAAE,aAAa,CAAC;IAC7B,YAAY,EAAE,YAAY,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,OAAQ,SAAQ,SAAU,YAAW,UAAU;IAC1D,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAe;IAChC,OAAO,CAAC,eAAe,CAAiB;IACxC,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,YAAY,CAAS;gBAEjB,MAAM,EAAE,aAAa;IAkCjC,kDAAkD;IAClD,IAAI,MAAM,IAAI,YAAY,CAAC,aAAa,CAAC,CAExC;IAID,qFAAqF;IAC/E,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC;IAIjC,iEAAiE;IACjE,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,GAAG,IAAI;IAIpC,gEAAgE;IAChE,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI;IAI5C;;;;;;;OAOG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI;IAIrC,4DAA4D;IAC5D,IAAI,IAAI,IAAI;IAIZ,IAAI,UAAU,IAAI,OAAO,CAExB;IAID,6BAA6B;IAC7B,IAAI,KAAK,IAAI,YAAY,CAExB;IAED,mCAAmC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAO5B,IAAI,SAAS,IAAI,eAAe,CAE/B;IAID,qBAAqB;IACrB,IAAI,KAAK,IAAI,SAAS,IAAI,EAAE,CAE3B;IAED,2BAA2B;IAC3B,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI5B,wBAAwB;IACxB,IAAI,QAAQ,IAAI,YAAY,CAE3B;IAID,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,OAAO,IAAI,IAAI;CAkBhB"}
@@ -0,0 +1,102 @@
1
+ import { Ticker } from 'pixi.js';
2
+ import { SpeedProfile, SymbolData, OffsetConfig } from '../config/types.js';
3
+ import { ReelSet } from './ReelSet.js';
4
+ import { SymbolRegistry } from '../symbols/SymbolRegistry.js';
5
+ import { PhaseFactory } from '../spin/phases/PhaseFactory.js';
6
+ import { SpinningMode } from '../spin/modes/SpinningMode.js';
7
+ import { FrameMiddleware } from '../frame/FrameBuilder.js';
8
+ /**
9
+ * The configurator you call before every reel set.
10
+ *
11
+ * `ReelSetBuilder` is a fluent, chainable builder: every call returns the
12
+ * builder so you can string setup onto one expression. It exists for two
13
+ * reasons — it hides the twenty-odd subsystems you'd otherwise have to
14
+ * wire by hand, and its `.build()` step validates that every required
15
+ * piece is present (throws at construction, not at first spin).
16
+ *
17
+ * Required calls (in any order): `.reels(n)`, `.visibleSymbols(n)`,
18
+ * `.symbolSize(w, h)`, `.symbols((registry) => ...)`, `.ticker(app.ticker)`.
19
+ * Optional: `.symbolGap()`, `.weights()`, `.symbolData()`, `.speed()`,
20
+ * `.bufferSymbols()`, `.offset()`, `.frameMiddleware()`, `.phases()`,
21
+ * `.spinningMode()`.
22
+ *
23
+ * Reduces ~100 lines of manual wiring to ~10 lines of configuration.
24
+ *
25
+ * ```ts
26
+ * const reelSet = new ReelSetBuilder()
27
+ * .reels(5)
28
+ * .visibleSymbols(3)
29
+ * .symbolSize(200, 200)
30
+ * .symbols((r) => {
31
+ * r.register('cherry', SpriteSymbol, { textures: { cherry: tex } });
32
+ * })
33
+ * .weights({ cherry: 20 })
34
+ * .ticker(app.ticker)
35
+ * .build();
36
+ * ```
37
+ */
38
+ export declare class ReelSetBuilder {
39
+ private _reelCount?;
40
+ private _visibleRows?;
41
+ private _symbolWidth?;
42
+ private _symbolHeight?;
43
+ private _symbolGap;
44
+ private _bufferSymbols;
45
+ private _symbolRegistry;
46
+ private _weights;
47
+ private _speeds;
48
+ private _initialSpeed;
49
+ private _offset;
50
+ private _ticker?;
51
+ private _spinningMode;
52
+ private _phaseFactory;
53
+ private _middlewares;
54
+ private _initialFrame?;
55
+ private _symbolDataOverrides;
56
+ /** Set number of reel columns. */
57
+ reels(count: number): this;
58
+ /** Set number of visible symbol rows per reel. */
59
+ visibleSymbols(count: number): this;
60
+ /** Set symbol dimensions in pixels. */
61
+ symbolSize(width: number, height: number): this;
62
+ /** Set gap between symbols. Default: { x: 0, y: 0 }. */
63
+ symbolGap(x: number, y: number): this;
64
+ /** Set number of buffer symbols above/below visible area. Default: 1. */
65
+ bufferSymbols(count: number): this;
66
+ /** Configure symbols via a registry callback. */
67
+ symbols(configurator: (registry: SymbolRegistry) => void): this;
68
+ /** Set weights for random symbol generation. */
69
+ weights(weights: Record<string, number>): this;
70
+ /**
71
+ * Per-symbol metadata overrides (zIndex, unmask, or a custom weight that
72
+ * replaces the one from `weights()`). Merged into the final symbolsData map
73
+ * — any field you don't specify falls back to the default.
74
+ *
75
+ * @example
76
+ * .symbolData({
77
+ * wild: { zIndex: 5 }, // render above neighbours
78
+ * bonus: { zIndex: 10, unmask: true }, // render outside the reel mask
79
+ * })
80
+ */
81
+ symbolData(overrides: Record<string, Partial<SymbolData>>): this;
82
+ /** Add a named speed profile. */
83
+ speed(name: string, profile: SpeedProfile): this;
84
+ /** Set which speed profile to use initially. Default: 'normal'. */
85
+ initialSpeed(name: string): this;
86
+ /** Set X-axis offset config (e.g., trapezoid perspective). Default: 'none'. */
87
+ offsetConfig(config: OffsetConfig): this;
88
+ /** Set the PixiJS ticker for frame updates. */
89
+ ticker(ticker: Ticker): this;
90
+ /** Set the spinning mode. Default: StandardMode. */
91
+ spinningMode(mode: SpinningMode): this;
92
+ /** Add custom frame middleware. */
93
+ frameMiddleware(middleware: FrameMiddleware): this;
94
+ /** Override default phases. */
95
+ phases(configurator: (factory: PhaseFactory) => void): this;
96
+ /** Set the initial symbol grid (visible symbols only). */
97
+ initialFrame(frame: string[][]): this;
98
+ /** Build the ReelSet. Validates configuration and assembles all internal objects. */
99
+ build(): ReelSet;
100
+ private _validate;
101
+ }
102
+ //# sourceMappingURL=ReelSetBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReelSetBuilder.d.ts","sourceRoot":"","sources":["../../src/core/ReelSetBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAyB,MAAM,oBAAoB,CAAC;AAGxG,OAAO,EAAE,OAAO,EAAsB,MAAM,cAAc,CAAC;AAG3D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAK9D,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAElE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAGhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,cAAc,CAA0B;IAChD,OAAO,CAAC,eAAe,CAAwB;IAC/C,OAAO,CAAC,QAAQ,CAA8B;IAC9C,OAAO,CAAC,OAAO,CAAmC;IAClD,OAAO,CAAC,aAAa,CAAyB;IAC9C,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,OAAO,CAAC,CAAS;IACzB,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,YAAY,CAAyB;IAC7C,OAAO,CAAC,aAAa,CAAC,CAAa;IACnC,OAAO,CAAC,oBAAoB,CAA2C;IAEvE,kCAAkC;IAClC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK1B,kDAAkD;IAClD,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKnC,uCAAuC;IACvC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAM/C,wDAAwD;IACxD,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI;IAKrC,yEAAyE;IACzE,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKlC,iDAAiD;IACjD,OAAO,CAAC,YAAY,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,IAAI,GAAG,IAAI;IAK/D,gDAAgD;IAChD,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAK9C;;;;;;;;;;OAUG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,IAAI;IAKhE,iCAAiC;IACjC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI;IAKhD,mEAAmE;IACnE,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKhC,+EAA+E;IAC/E,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAKxC,+CAA+C;IAC/C,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAK5B,oDAAoD;IACpD,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAKtC,mCAAmC;IACnC,eAAe,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI;IAKlD,+BAA+B;IAC/B,MAAM,CAAC,YAAY,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,GAAG,IAAI;IAK3D,0DAA0D;IAC1D,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,IAAI;IAKrC,qFAAqF;IACrF,KAAK,IAAI,OAAO;IA4GhB,OAAO,CAAC,SAAS;CA6BlB"}
@@ -0,0 +1,43 @@
1
+ import { Container, Graphics } from 'pixi.js';
2
+ import { Disposable } from '../utils/Disposable.js';
3
+ /**
4
+ * The clipping window + layering tricks for a reel set.
5
+ *
6
+ * The viewport is the "looking-glass" of the slot: a rectangle the size
7
+ * of the visible grid with a PixiJS mask so symbols scrolling above or
8
+ * below the visible rows are hidden. It also provides three stacking
9
+ * layers so win animations can break out of the mask:
10
+ *
11
+ * - `maskedContainer` — the normal place for reels. Clipped to the
12
+ * visible area so buffer rows never leak.
13
+ * - `unmaskedContainer` — rendered on top of the mask. Use for a symbol
14
+ * whose celebration animation expands beyond its cell (a big expanding
15
+ * wild, a splash frame).
16
+ * - `spotlightContainer` — above everything else. Win spotlight lifts
17
+ * winning symbols here temporarily so dim overlay + bounce don't clip.
18
+ *
19
+ * `dimOverlay` is a semi-transparent rectangle the spotlight fades in
20
+ * behind the promoted winners to visually push the losers into the
21
+ * background.
22
+ */
23
+ export declare class ReelViewport extends Container implements Disposable {
24
+ readonly maskedContainer: Container;
25
+ readonly unmaskedContainer: Container;
26
+ readonly spotlightContainer: Container;
27
+ readonly dimOverlay: Graphics;
28
+ private _mask;
29
+ private _isDestroyed;
30
+ constructor(width: number, height: number, position?: {
31
+ x: number;
32
+ y: number;
33
+ });
34
+ get isDestroyed(): boolean;
35
+ /** Show the dim overlay with given opacity. */
36
+ showDim(alpha?: number): void;
37
+ /** Hide the dim overlay. */
38
+ hideDim(): void;
39
+ /** Update mask size (e.g., for Megaways variable rows). */
40
+ updateMaskSize(width: number, height: number): void;
41
+ destroy(): void;
42
+ }
43
+ //# sourceMappingURL=ReelViewport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReelViewport.d.ts","sourceRoot":"","sources":["../../src/core/ReelViewport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,YAAa,SAAQ,SAAU,YAAW,UAAU;IAC/D,SAAgB,eAAe,EAAE,SAAS,CAAC;IAC3C,SAAgB,iBAAiB,EAAE,SAAS,CAAC;IAC7C,SAAgB,kBAAkB,EAAE,SAAS,CAAC;IAC9C,SAAgB,UAAU,EAAE,QAAQ,CAAC;IAErC,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,YAAY,CAAS;gBAG3B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,QAAQ,GAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAmB;IAkCrD,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,+CAA+C;IAC/C,OAAO,CAAC,KAAK,GAAE,MAAY,GAAG,IAAI;IAKlC,4BAA4B;IAC5B,OAAO,IAAI,IAAI;IAIf,2DAA2D;IAC3D,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAKnD,OAAO,IAAI,IAAI;CAKhB"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The "what do I land on" queue for one reel.
3
+ *
4
+ * When a reel enters its stop phase, the `SpinController` loads the
5
+ * target frame (the exact list of symbol ids that should appear on
6
+ * screen, top-to-bottom, including the off-screen buffers). As the reel
7
+ * keeps scrolling downward during deceleration, every `ReelMotion` wrap
8
+ * event asks this sequencer for the next symbol — and it hands them back
9
+ * from the END of the frame first, because new symbols arrive at the
10
+ * top of a reel scrolling downward.
11
+ *
12
+ * After the last symbol is consumed the reel lands, and what you see on
13
+ * screen matches the loaded frame exactly.
14
+ */
15
+ export declare class StopSequencer {
16
+ private _frame;
17
+ private _remaining;
18
+ /** Load a target frame in top-to-bottom order. */
19
+ setFrame(frame: string[]): void;
20
+ /** Deliver the next symbol (consumed from the end of the frame). */
21
+ next(): string;
22
+ get hasRemaining(): boolean;
23
+ get remaining(): number;
24
+ reset(): void;
25
+ }
26
+ //# sourceMappingURL=StopSequencer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StopSequencer.d.ts","sourceRoot":"","sources":["../../src/core/StopSequencer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,UAAU,CAAa;IAE/B,kDAAkD;IAClD,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAK/B,oEAAoE;IACpE,IAAI,IAAI,MAAM;IAQd,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,KAAK,IAAI,IAAI;CAId"}
@@ -0,0 +1,65 @@
1
+ import { ReelSet } from '../core/ReelSet.js';
2
+ /**
3
+ * Debug snapshot — plain JSON representation of the entire reel state.
4
+ *
5
+ * Designed for AI agents that cannot see the canvas.
6
+ * Returns no PixiJS display objects, only serializable data.
7
+ */
8
+ export interface DebugSnapshot {
9
+ timestamp: number;
10
+ isSpinning: boolean;
11
+ currentSpeed: string;
12
+ availableSpeeds: string[];
13
+ spotlightActive: boolean;
14
+ reelCount: number;
15
+ visibleRows: number;
16
+ reels: DebugReelSnapshot[];
17
+ grid: string[][];
18
+ }
19
+ export interface DebugReelSnapshot {
20
+ index: number;
21
+ speed: number;
22
+ isStopping: boolean;
23
+ allSymbols: {
24
+ row: number;
25
+ symbolId: string;
26
+ y: number;
27
+ }[];
28
+ visibleSymbols: string[];
29
+ }
30
+ /**
31
+ * Take a plain-JSON snapshot of the entire reel set state.
32
+ *
33
+ * This is the primary debugging tool for AI agents. The output is
34
+ * a serializable object with no circular references, no PixiJS types.
35
+ *
36
+ * ```ts
37
+ * const state = debugSnapshot(reelSet);
38
+ * console.log(JSON.stringify(state, null, 2));
39
+ * ```
40
+ */
41
+ export declare function debugSnapshot(reelSet: ReelSet): DebugSnapshot;
42
+ /**
43
+ * Pretty-print the grid as an ASCII table.
44
+ *
45
+ * ```
46
+ * ┌────────┬────────┬────────┬────────┬────────┐
47
+ * │ cherry │ lemon │ bar │ seven │ cherry │
48
+ * │ plum │ cherry │ wild │ lemon │ orange │
49
+ * │ orange │ bell │ cherry │ plum │ bell │
50
+ * └────────┴────────┴────────┴────────┴────────┘
51
+ * ```
52
+ */
53
+ export declare function debugGrid(reelSet: ReelSet): string;
54
+ /**
55
+ * Enable debug mode: attaches debug utilities to `window.__PIXI_REELS_DEBUG`.
56
+ *
57
+ * After calling this, an AI agent can run in the browser console:
58
+ * ```js
59
+ * __PIXI_REELS_DEBUG.snapshot() // full state JSON
60
+ * __PIXI_REELS_DEBUG.grid() // ASCII grid
61
+ * __PIXI_REELS_DEBUG.log() // console.log the grid
62
+ * ```
63
+ */
64
+ export declare function enableDebug(reelSet: ReelSet): void;
65
+ //# sourceMappingURL=debug.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../src/debug/debug.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAGlD;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3D,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,CA+B7D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAqBlD;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgClD"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Lightweight typed event emitter with zero dependencies.
3
+ *
4
+ * Usage:
5
+ * ```ts
6
+ * interface MyEvents {
7
+ * 'foo': [x: number, y: string];
8
+ * 'bar': [];
9
+ * }
10
+ * const emitter = new EventEmitter<MyEvents>();
11
+ * emitter.on('foo', (x, y) => console.log(x, y));
12
+ * emitter.emit('foo', 42, 'hello');
13
+ * ```
14
+ */
15
+ export declare class EventEmitter<TEvents extends Record<string, unknown[]>> {
16
+ private _listeners;
17
+ on<K extends keyof TEvents>(event: K, fn: (...args: TEvents[K]) => void, context?: unknown): this;
18
+ once<K extends keyof TEvents>(event: K, fn: (...args: TEvents[K]) => void, context?: unknown): this;
19
+ off<K extends keyof TEvents>(event: K, fn?: (...args: TEvents[K]) => void, context?: unknown): this;
20
+ emit<K extends keyof TEvents>(event: K, ...args: TEvents[K]): boolean;
21
+ removeAllListeners(event?: keyof TEvents): this;
22
+ listenerCount(event: keyof TEvents): number;
23
+ private _add;
24
+ }
25
+ //# sourceMappingURL=EventEmitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EventEmitter.d.ts","sourceRoot":"","sources":["../../src/events/EventEmitter.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;GAaG;AACH,qBAAa,YAAY,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;IACjE,OAAO,CAAC,UAAU,CAA6C;IAE/D,EAAE,CAAC,CAAC,SAAS,MAAM,OAAO,EACxB,KAAK,EAAE,CAAC,EACR,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,EACjC,OAAO,CAAC,EAAE,OAAO,GAChB,IAAI;IAIP,IAAI,CAAC,CAAC,SAAS,MAAM,OAAO,EAC1B,KAAK,EAAE,CAAC,EACR,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,EACjC,OAAO,CAAC,EAAE,OAAO,GAChB,IAAI;IAIP,GAAG,CAAC,CAAC,SAAS,MAAM,OAAO,EACzB,KAAK,EAAE,CAAC,EACR,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,EAClC,OAAO,CAAC,EAAE,OAAO,GAChB,IAAI;IAoBP,IAAI,CAAC,CAAC,SAAS,MAAM,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO;IAerE,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,OAAO,GAAG,IAAI;IAS/C,aAAa,CAAC,KAAK,EAAE,MAAM,OAAO,GAAG,MAAM;IAI3C,OAAO,CAAC,IAAI;CAcb"}
@@ -0,0 +1,40 @@
1
+ import { SpeedProfile } from '../config/types.js';
2
+ /** Position of a symbol on the reel grid. */
3
+ export interface SymbolPosition {
4
+ reelIndex: number;
5
+ rowIndex: number;
6
+ }
7
+ /** Result returned when a spin completes. */
8
+ export interface SpinResult {
9
+ /** Final symbol grid [reelIndex][rowIndex]. */
10
+ symbols: string[][];
11
+ /** Whether the spin was skipped/slam-stopped. */
12
+ wasSkipped: boolean;
13
+ /** Total spin duration in milliseconds. */
14
+ duration: number;
15
+ }
16
+ /** Events emitted by a ReelSet. */
17
+ export interface ReelSetEvents extends Record<string, unknown[]> {
18
+ 'spin:start': [];
19
+ 'spin:allStarted': [];
20
+ 'spin:stopping': [reelIndex: number];
21
+ 'spin:reelLanded': [reelIndex: number, symbols: string[]];
22
+ 'spin:allLanded': [result: SpinResult];
23
+ 'spin:complete': [result: SpinResult];
24
+ 'skip:requested': [];
25
+ 'skip:completed': [];
26
+ 'speed:changed': [profile: SpeedProfile, previous: SpeedProfile];
27
+ 'spotlight:start': [positions: SymbolPosition[]];
28
+ 'spotlight:end': [];
29
+ 'destroyed': [];
30
+ }
31
+ /** Events emitted by an individual Reel. */
32
+ export interface ReelEvents extends Record<string, unknown[]> {
33
+ 'phase:enter': [phaseName: string];
34
+ 'phase:exit': [phaseName: string];
35
+ 'symbol:created': [symbolId: string, row: number];
36
+ 'symbol:recycled': [symbolId: string, row: number];
37
+ 'landed': [symbols: string[]];
38
+ 'destroyed': [];
39
+ }
40
+ //# sourceMappingURL=ReelEvents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReelEvents.d.ts","sourceRoot":"","sources":["../../src/events/ReelEvents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,6CAA6C;AAC7C,MAAM,WAAW,UAAU;IACzB,+CAA+C;IAC/C,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC;IACpB,iDAAiD;IACjD,UAAU,EAAE,OAAO,CAAC;IACpB,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,mCAAmC;AACnC,MAAM,WAAW,aAAc,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;IAC9D,YAAY,EAAE,EAAE,CAAC;IACjB,iBAAiB,EAAE,EAAE,CAAC;IACtB,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACrC,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1D,gBAAgB,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACvC,eAAe,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACtC,gBAAgB,EAAE,EAAE,CAAC;IACrB,gBAAgB,EAAE,EAAE,CAAC;IACrB,eAAe,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;IACjE,iBAAiB,EAAE,CAAC,SAAS,EAAE,cAAc,EAAE,CAAC,CAAC;IACjD,eAAe,EAAE,EAAE,CAAC;IACpB,WAAW,EAAE,EAAE,CAAC;CACjB;AAED,4CAA4C;AAC5C,MAAM,WAAW,UAAW,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;IAC3D,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACnC,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAClC,gBAAgB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IAClD,iBAAiB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IACnD,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IAC9B,WAAW,EAAE,EAAE,CAAC;CACjB"}
@@ -0,0 +1,50 @@
1
+ import { RandomSymbolProvider } from './RandomSymbolProvider.js';
2
+ /** Context passed through the middleware pipeline. */
3
+ export interface FrameContext {
4
+ /** Reel column index. */
5
+ readonly reelIndex: number;
6
+ /** Total visible rows. */
7
+ readonly visibleRows: number;
8
+ /** Buffer symbols above visible area. */
9
+ readonly bufferAbove: number;
10
+ /** Buffer symbols below visible area. */
11
+ readonly bufferBelow: number;
12
+ /** The symbol array being built (buffer + visible + buffer). Mutable by middleware. */
13
+ symbols: string[];
14
+ /** Target symbols from setResult() (visible rows only), if available. */
15
+ readonly targetSymbols?: string[];
16
+ /** Whether the reel is currently spinning. */
17
+ readonly isSpinning: boolean;
18
+ /** Arbitrary metadata middleware can use to communicate. */
19
+ metadata: Record<string, unknown>;
20
+ }
21
+ /** Middleware that participates in frame building. */
22
+ export interface FrameMiddleware {
23
+ readonly name: string;
24
+ /** Lower priority runs first. */
25
+ readonly priority: number;
26
+ process(context: FrameContext, next: () => void): void;
27
+ }
28
+ /**
29
+ * Builds symbol frames using a middleware pipeline.
30
+ *
31
+ * Built-in middleware handles random fill and target placement.
32
+ * Users can inject custom middleware for features like multiplier encoding
33
+ * or triple-prevention.
34
+ */
35
+ export declare class FrameBuilder {
36
+ private _randomProvider;
37
+ private _middlewares;
38
+ private _sorted;
39
+ constructor(_randomProvider: RandomSymbolProvider);
40
+ /** Add a middleware to the pipeline. */
41
+ use(middleware: FrameMiddleware): this;
42
+ /** Remove a middleware by name. */
43
+ remove(name: string): this;
44
+ /** Build a frame for a single reel. */
45
+ build(reelIndex: number, visibleRows: number, bufferAbove: number, bufferBelow: number, targetSymbols?: string[], isSpinning?: boolean): string[];
46
+ /** Build frames for all reels. */
47
+ buildAll(reelCount: number, visibleRows: number, bufferAbove: number, bufferBelow: number, targetSymbols?: string[][], isSpinning?: boolean): string[][];
48
+ get randomProvider(): RandomSymbolProvider;
49
+ }
50
+ //# sourceMappingURL=FrameBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FrameBuilder.d.ts","sourceRoot":"","sources":["../../src/frame/FrameBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEtE,sDAAsD;AACtD,MAAM,WAAW,YAAY;IAC3B,yBAAyB;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,0BAA0B;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,uFAAuF;IACvF,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,yEAAyE;IACzE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAClC,8CAA8C;IAC9C,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,sDAAsD;AACtD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;CACxD;AAED;;;;;;GAMG;AACH,qBAAa,YAAY;IAIX,OAAO,CAAC,eAAe;IAHnC,OAAO,CAAC,YAAY,CAAyB;IAC7C,OAAO,CAAC,OAAO,CAAS;gBAEJ,eAAe,EAAE,oBAAoB;IAMzD,wCAAwC;IACxC,GAAG,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI;IAMtC,mCAAmC;IACnC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAK1B,uCAAuC;IACvC,KAAK,CACH,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,aAAa,CAAC,EAAE,MAAM,EAAE,EACxB,UAAU,GAAE,OAAe,GAC1B,MAAM,EAAE;IA+BX,kCAAkC;IAClC,QAAQ,CACN,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,aAAa,CAAC,EAAE,MAAM,EAAE,EAAE,EAC1B,UAAU,GAAE,OAAe,GAC1B,MAAM,EAAE,EAAE;IAab,IAAI,cAAc,IAAI,oBAAoB,CAEzC;CACF"}
@@ -0,0 +1,19 @@
1
+ import { OffsetConfig } from '../config/types.js';
2
+ /**
3
+ * Computes X-position offsets for symbols to create visual effects
4
+ * like trapezoid perspective.
5
+ */
6
+ export declare class OffsetCalculator {
7
+ private _reelCount;
8
+ private _totalRows;
9
+ private _symbolWidth;
10
+ private _config;
11
+ private _offsets;
12
+ constructor(_reelCount: number, _totalRows: number, _symbolWidth: number, _config: OffsetConfig);
13
+ /** Get X offset for a specific reel and row. */
14
+ getOffset(reelIndex: number, rowIndex: number): number;
15
+ /** Get all offsets as a 2D array [reelIndex][rowIndex]. */
16
+ get offsets(): readonly (readonly number[])[];
17
+ private _compute;
18
+ }
19
+ //# sourceMappingURL=OffsetCalculator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OffsetCalculator.d.ts","sourceRoot":"","sources":["../../src/frame/OffsetCalculator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,oBAAoB,CAAC;AAExE;;;GAGG;AACH,qBAAa,gBAAgB;IAIzB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,OAAO;IANjB,OAAO,CAAC,QAAQ,CAAkB;gBAGxB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,YAAY;IAK/B,gDAAgD;IAChD,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAItD,2DAA2D;IAC3D,IAAI,OAAO,IAAI,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAE5C;IAED,OAAO,CAAC,QAAQ;CA8BjB"}
@@ -0,0 +1,27 @@
1
+ import { SymbolData } from '../config/types.js';
2
+ /**
3
+ * Weighted random symbol selector using binary search on cumulative weights.
4
+ *
5
+ * Supports exclusion lists for symbols that shouldn't appear during
6
+ * spinning or in buffer areas.
7
+ */
8
+ export declare class RandomSymbolProvider {
9
+ private _symbols;
10
+ private _weights;
11
+ private _cumulativeWeights;
12
+ private _totalWeight;
13
+ private _excludeSpinning;
14
+ private _excludeBuffer;
15
+ constructor(symbolsData: Record<string, SymbolData>);
16
+ /** Get a random symbol, optionally excluding buffer-only symbols. */
17
+ next(useBufferExclusion?: boolean): string;
18
+ /** Set symbols to exclude during spinning. */
19
+ setExcludeSpinning(symbolIds: string[]): void;
20
+ /** Set symbols to exclude from buffer (above/below) areas. */
21
+ setExcludeBuffer(symbolIds: string[]): void;
22
+ /** Update weights at runtime (e.g., for different game modes). */
23
+ updateWeights(symbolsData: Record<string, SymbolData>): void;
24
+ private _rebuildWeights;
25
+ private _pickWeighted;
26
+ }
27
+ //# sourceMappingURL=RandomSymbolProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RandomSymbolProvider.d.ts","sourceRoot":"","sources":["../../src/frame/RandomSymbolProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;;GAKG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,kBAAkB,CAAgB;IAC1C,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,cAAc,CAAqB;gBAE/B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC;IAMnD,qEAAqE;IACrE,IAAI,CAAC,kBAAkB,GAAE,OAAe,GAAG,MAAM;IAyCjD,8CAA8C;IAC9C,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI;IAI7C,8DAA8D;IAC9D,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI;IAI3C,kEAAkE;IAClE,aAAa,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,IAAI;IAM5D,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,aAAa;CActB"}