@slot-engine/core 0.2.1 → 0.2.3

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.
package/dist/index.d.mts CHANGED
@@ -545,6 +545,7 @@ declare class BoardService<TGameModes extends AnyGameModes = AnyGameModes, TSymb
545
545
  getPaddingTop(): Reels;
546
546
  getPaddingBottom(): Reels;
547
547
  getAnticipation(): boolean[];
548
+ getLockedReels(): boolean[];
548
549
  /**
549
550
  * Gets the symbol at the specified reel and row index.
550
551
  */
@@ -557,11 +558,19 @@ declare class BoardService<TGameModes extends AnyGameModes = AnyGameModes, TSymb
557
558
  * Removes the symbol at the specified reel and row index.
558
559
  */
559
560
  removeSymbol(reelIndex: number, rowIndex: number): void;
561
+ /**
562
+ * Updates properties of the symbol at the specified reel and row index.
563
+ */
564
+ updateSymbol(reelIndex: number, rowIndex: number, properties: Record<string, any>): void;
560
565
  private resetReels;
561
566
  /**
562
567
  * Sets the anticipation value for a specific reel.
563
568
  */
564
569
  setAnticipationForReel(reelIndex: number, value: boolean): void;
570
+ /**
571
+ * Sets the locked state for a specific reel.
572
+ */
573
+ setReelLocked(reelIndex: number, value: boolean): void;
565
574
  /**
566
575
  * Counts how many symbols matching the criteria are on a specific reel.
567
576
  */
@@ -1549,7 +1558,9 @@ declare class ManywaysWinType extends WinType {
1549
1558
  * Calculates wins based on the defined paylines and provided board state.\
1550
1559
  * Retrieve the results using `getWins()` after.
1551
1560
  */
1552
- evaluateWins(board: Reels): this;
1561
+ evaluateWins(board: Reels, opts?: {
1562
+ jumpGaps?: boolean;
1563
+ }): this;
1553
1564
  private getWayLength;
1554
1565
  }
1555
1566
  interface ManywaysWinTypeOpts extends WinTypeOpts {
@@ -1729,6 +1740,8 @@ declare class StandaloneBoard {
1729
1740
  getBoardReels(): Reels;
1730
1741
  getPaddingTop(): Reels;
1731
1742
  getPaddingBottom(): Reels;
1743
+ getAnticipation(): boolean[];
1744
+ getLockedReels(): boolean[];
1732
1745
  /**
1733
1746
  * Gets the symbol at the specified reel and row index.
1734
1747
  */
@@ -1741,11 +1754,19 @@ declare class StandaloneBoard {
1741
1754
  * Removes the symbol at the specified reel and row index.
1742
1755
  */
1743
1756
  removeSymbol(reelIndex: number, rowIndex: number): void;
1757
+ /**
1758
+ * Updates properties of the symbol at the specified reel and row index.
1759
+ */
1760
+ updateSymbol(reelIndex: number, rowIndex: number, properties: Record<string, any>): void;
1744
1761
  private resetReels;
1745
1762
  /**
1746
1763
  * Sets the anticipation value for a specific reel.
1747
1764
  */
1748
1765
  setAnticipationForReel(reelIndex: number, value: boolean): void;
1766
+ /**
1767
+ * Sets the locked state for a specific reel.
1768
+ */
1769
+ setReelLocked(reelIndex: number, value: boolean): void;
1749
1770
  /**
1750
1771
  * Counts how many symbols matching the criteria are on a specific reel.
1751
1772
  */
package/dist/index.d.ts CHANGED
@@ -545,6 +545,7 @@ declare class BoardService<TGameModes extends AnyGameModes = AnyGameModes, TSymb
545
545
  getPaddingTop(): Reels;
546
546
  getPaddingBottom(): Reels;
547
547
  getAnticipation(): boolean[];
548
+ getLockedReels(): boolean[];
548
549
  /**
549
550
  * Gets the symbol at the specified reel and row index.
550
551
  */
@@ -557,11 +558,19 @@ declare class BoardService<TGameModes extends AnyGameModes = AnyGameModes, TSymb
557
558
  * Removes the symbol at the specified reel and row index.
558
559
  */
559
560
  removeSymbol(reelIndex: number, rowIndex: number): void;
561
+ /**
562
+ * Updates properties of the symbol at the specified reel and row index.
563
+ */
564
+ updateSymbol(reelIndex: number, rowIndex: number, properties: Record<string, any>): void;
560
565
  private resetReels;
561
566
  /**
562
567
  * Sets the anticipation value for a specific reel.
563
568
  */
564
569
  setAnticipationForReel(reelIndex: number, value: boolean): void;
570
+ /**
571
+ * Sets the locked state for a specific reel.
572
+ */
573
+ setReelLocked(reelIndex: number, value: boolean): void;
565
574
  /**
566
575
  * Counts how many symbols matching the criteria are on a specific reel.
567
576
  */
@@ -1549,7 +1558,9 @@ declare class ManywaysWinType extends WinType {
1549
1558
  * Calculates wins based on the defined paylines and provided board state.\
1550
1559
  * Retrieve the results using `getWins()` after.
1551
1560
  */
1552
- evaluateWins(board: Reels): this;
1561
+ evaluateWins(board: Reels, opts?: {
1562
+ jumpGaps?: boolean;
1563
+ }): this;
1553
1564
  private getWayLength;
1554
1565
  }
1555
1566
  interface ManywaysWinTypeOpts extends WinTypeOpts {
@@ -1729,6 +1740,8 @@ declare class StandaloneBoard {
1729
1740
  getBoardReels(): Reels;
1730
1741
  getPaddingTop(): Reels;
1731
1742
  getPaddingBottom(): Reels;
1743
+ getAnticipation(): boolean[];
1744
+ getLockedReels(): boolean[];
1732
1745
  /**
1733
1746
  * Gets the symbol at the specified reel and row index.
1734
1747
  */
@@ -1741,11 +1754,19 @@ declare class StandaloneBoard {
1741
1754
  * Removes the symbol at the specified reel and row index.
1742
1755
  */
1743
1756
  removeSymbol(reelIndex: number, rowIndex: number): void;
1757
+ /**
1758
+ * Updates properties of the symbol at the specified reel and row index.
1759
+ */
1760
+ updateSymbol(reelIndex: number, rowIndex: number, properties: Record<string, any>): void;
1744
1761
  private resetReels;
1745
1762
  /**
1746
1763
  * Sets the anticipation value for a specific reel.
1747
1764
  */
1748
1765
  setAnticipationForReel(reelIndex: number, value: boolean): void;
1766
+ /**
1767
+ * Sets the locked state for a specific reel.
1768
+ */
1769
+ setReelLocked(reelIndex: number, value: boolean): void;
1749
1770
  /**
1750
1771
  * Counts how many symbols matching the criteria are on a specific reel.
1751
1772
  */
package/dist/index.js CHANGED
@@ -477,8 +477,18 @@ var Board = class {
477
477
  * Used for triggering anticipation effects.
478
478
  */
479
479
  anticipation;
480
+ /**
481
+ * The most recent stop positions for the reels.
482
+ */
480
483
  lastDrawnReelStops;
484
+ /**
485
+ * The reel set used in the most recent draw.
486
+ */
481
487
  lastUsedReels;
488
+ /**
489
+ * Indicates whether each reel is locked or not.
490
+ */
491
+ reelsLocked;
482
492
  constructor() {
483
493
  this.reels = [];
484
494
  this.paddingTop = [];
@@ -486,6 +496,7 @@ var Board = class {
486
496
  this.anticipation = [];
487
497
  this.lastDrawnReelStops = [];
488
498
  this.lastUsedReels = [];
499
+ this.reelsLocked = [];
489
500
  }
490
501
  getSymbol(reelIndex, rowIndex) {
491
502
  return this.reels[reelIndex]?.[rowIndex];
@@ -499,6 +510,14 @@ var Board = class {
499
510
  this.reels[reelIndex].splice(rowIndex, 1);
500
511
  }
501
512
  }
513
+ updateSymbol(reelIndex, rowIndex, properties) {
514
+ const symbol = this.getSymbol(reelIndex, rowIndex);
515
+ if (symbol) {
516
+ for (const [key, value] of Object.entries(properties)) {
517
+ symbol.properties.set(key, value);
518
+ }
519
+ }
520
+ }
502
521
  makeEmptyReels(opts) {
503
522
  const length = opts.reelsAmount ?? opts.ctx.services.game.getCurrentGameMode().reelsAmount;
504
523
  (0, import_assert3.default)(length, "Cannot make empty reels without context or reelsAmount.");
@@ -633,14 +652,19 @@ var Board = class {
633
652
  return reelSet;
634
653
  }
635
654
  resetReels(opts) {
636
- const length = opts.reelsAmount ?? opts.ctx.services.game.getCurrentGameMode().reelsAmount;
655
+ const { ctx, reelsAmount, reelsLocked } = opts;
656
+ const length = reelsAmount ?? ctx.services.game.getCurrentGameMode().reelsAmount;
637
657
  this.reels = this.makeEmptyReels(opts);
638
658
  this.anticipation = Array.from({ length }, () => false);
659
+ this.reelsLocked = reelsLocked ?? Array.from({ length }, () => false);
639
660
  this.paddingTop = this.makeEmptyReels(opts);
640
661
  this.paddingBottom = this.makeEmptyReels(opts);
641
662
  }
642
663
  drawBoardMixed(opts) {
643
- this.resetReels(opts);
664
+ this.resetReels({
665
+ ...opts,
666
+ ...this.reelsLocked.length && { reelsLocked: this.reelsLocked }
667
+ });
644
668
  const reelsAmount = opts.reelsAmount ?? opts.ctx.services.game.getCurrentGameMode().reelsAmount;
645
669
  const symbolsPerReel = opts.symbolsPerReel ?? opts.ctx.services.game.getCurrentGameMode().symbolsPerReel;
646
670
  const padSymbols = opts.padSymbols ?? opts.ctx.config.padSymbols;
@@ -669,6 +693,18 @@ var Board = class {
669
693
  );
670
694
  }
671
695
  }
696
+ if (this.reelsLocked.some((locked) => locked) && this.lastDrawnReelStops.length == 0) {
697
+ throw new Error(
698
+ "Cannot draw board with locked reels before drawing it at least once."
699
+ );
700
+ }
701
+ if (this.reelsLocked.some((locked) => locked)) {
702
+ for (let ridx = 0; ridx < reelsAmount; ridx++) {
703
+ if (this.reelsLocked[ridx]) {
704
+ finalReelStops[ridx] = this.lastDrawnReelStops[ridx];
705
+ }
706
+ }
707
+ }
672
708
  this.lastDrawnReelStops = finalReelStops.map((pos) => pos);
673
709
  this.lastUsedReels = opts.reels;
674
710
  for (let ridx = 0; ridx < reelsAmount; ridx++) {
@@ -830,6 +866,9 @@ var BoardService = class extends AbstractService {
830
866
  getAnticipation() {
831
867
  return this.board.anticipation;
832
868
  }
869
+ getLockedReels() {
870
+ return this.board.reelsLocked;
871
+ }
833
872
  /**
834
873
  * Gets the symbol at the specified reel and row index.
835
874
  */
@@ -848,6 +887,12 @@ var BoardService = class extends AbstractService {
848
887
  removeSymbol(reelIndex, rowIndex) {
849
888
  this.board.removeSymbol(reelIndex, rowIndex);
850
889
  }
890
+ /**
891
+ * Updates properties of the symbol at the specified reel and row index.
892
+ */
893
+ updateSymbol(reelIndex, rowIndex, properties) {
894
+ this.board.updateSymbol(reelIndex, rowIndex, properties);
895
+ }
851
896
  resetReels() {
852
897
  this.board.resetReels({
853
898
  ctx: this.ctx()
@@ -859,6 +904,12 @@ var BoardService = class extends AbstractService {
859
904
  setAnticipationForReel(reelIndex, value) {
860
905
  this.board.anticipation[reelIndex] = value;
861
906
  }
907
+ /**
908
+ * Sets the locked state for a specific reel.
909
+ */
910
+ setReelLocked(reelIndex, value) {
911
+ this.board.reelsLocked[reelIndex] = value;
912
+ }
862
913
  /**
863
914
  * Counts how many symbols matching the criteria are on a specific reel.
864
915
  */
@@ -4067,27 +4118,36 @@ var ManywaysWinType = class extends WinType {
4067
4118
  * Calculates wins based on the defined paylines and provided board state.\
4068
4119
  * Retrieve the results using `getWins()` after.
4069
4120
  */
4070
- evaluateWins(board) {
4121
+ evaluateWins(board, opts = {}) {
4071
4122
  this.validateConfig();
4123
+ const { jumpGaps = false } = opts;
4072
4124
  const waysWins = [];
4073
4125
  const reels = board;
4074
4126
  const possibleWaysWins = /* @__PURE__ */ new Map();
4075
4127
  const candidateSymbols = /* @__PURE__ */ new Map();
4076
- let searchReelIdx = 0;
4077
- let searchActive = true;
4078
- while (searchActive && searchReelIdx < reels.length) {
4079
- const reel = reels[searchReelIdx];
4080
- let hasWild = false;
4081
- for (const symbol of reel) {
4082
- candidateSymbols.set(symbol.id, symbol);
4083
- if (this.isWild(symbol)) {
4084
- hasWild = true;
4128
+ if (jumpGaps) {
4129
+ for (const reel of reels) {
4130
+ for (const symbol of reel) {
4131
+ candidateSymbols.set(symbol.id, symbol);
4085
4132
  }
4086
4133
  }
4087
- if (!hasWild) {
4088
- searchActive = false;
4134
+ } else {
4135
+ let searchReelIdx = 0;
4136
+ let searchActive = true;
4137
+ while (searchActive && searchReelIdx < reels.length) {
4138
+ const reel = reels[searchReelIdx];
4139
+ let hasWild = false;
4140
+ for (const symbol of reel) {
4141
+ candidateSymbols.set(symbol.id, symbol);
4142
+ if (this.isWild(symbol)) {
4143
+ hasWild = true;
4144
+ }
4145
+ }
4146
+ if (!hasWild) {
4147
+ searchActive = false;
4148
+ }
4149
+ searchReelIdx++;
4089
4150
  }
4090
- searchReelIdx++;
4091
4151
  }
4092
4152
  for (const baseSymbol of candidateSymbols.values()) {
4093
4153
  let symbolList = {};
@@ -4103,7 +4163,7 @@ var ManywaysWinType = class extends WinType {
4103
4163
  symbolList[ridx].push({ reel: ridx, row: sidx, symbol });
4104
4164
  }
4105
4165
  }
4106
- if (!symbolList[ridx]) {
4166
+ if (!symbolList[ridx] && !jumpGaps) {
4107
4167
  isInterrupted = true;
4108
4168
  break;
4109
4169
  }
@@ -4119,7 +4179,7 @@ var ManywaysWinType = class extends WinType {
4119
4179
  for (const [baseSymbolId, symbolList] of possibleWaysWins.entries()) {
4120
4180
  const wayLength = this.getWayLength(symbolList);
4121
4181
  let baseSymbol = Object.values(symbolList).flatMap((l) => l.map((s) => s)).find((s) => !this.isWild(s.symbol))?.symbol;
4122
- if (!baseSymbol) baseSymbol = symbolList[0][0].symbol;
4182
+ if (!baseSymbol) baseSymbol = symbolList[Object.keys(symbolList)[0]][0].symbol;
4123
4183
  const singleWayPayout = this.getSymbolPayout(baseSymbol, wayLength);
4124
4184
  const totalWays = Object.values(symbolList).reduce(
4125
4185
  (ways, syms) => ways * syms.length,
@@ -4153,7 +4213,7 @@ var ManywaysWinType = class extends WinType {
4153
4213
  return this;
4154
4214
  }
4155
4215
  getWayLength(symbolList) {
4156
- return Math.max(...Object.keys(symbolList).map((k) => parseInt(k, 10))) + 1;
4216
+ return Object.keys(symbolList).length;
4157
4217
  }
4158
4218
  };
4159
4219
 
@@ -4591,6 +4651,12 @@ var StandaloneBoard = class {
4591
4651
  getPaddingBottom() {
4592
4652
  return this.board.paddingBottom;
4593
4653
  }
4654
+ getAnticipation() {
4655
+ return this.board.anticipation;
4656
+ }
4657
+ getLockedReels() {
4658
+ return this.board.reelsLocked;
4659
+ }
4594
4660
  /**
4595
4661
  * Gets the symbol at the specified reel and row index.
4596
4662
  */
@@ -4609,6 +4675,12 @@ var StandaloneBoard = class {
4609
4675
  removeSymbol(reelIndex, rowIndex) {
4610
4676
  this.board.removeSymbol(reelIndex, rowIndex);
4611
4677
  }
4678
+ /**
4679
+ * Updates properties of the symbol at the specified reel and row index.
4680
+ */
4681
+ updateSymbol(reelIndex, rowIndex, properties) {
4682
+ this.board.updateSymbol(reelIndex, rowIndex, properties);
4683
+ }
4612
4684
  resetReels() {
4613
4685
  this.board.resetReels({
4614
4686
  ctx: this.ctx
@@ -4620,6 +4692,12 @@ var StandaloneBoard = class {
4620
4692
  setAnticipationForReel(reelIndex, value) {
4621
4693
  this.board.anticipation[reelIndex] = value;
4622
4694
  }
4695
+ /**
4696
+ * Sets the locked state for a specific reel.
4697
+ */
4698
+ setReelLocked(reelIndex, value) {
4699
+ this.board.reelsLocked[reelIndex] = value;
4700
+ }
4623
4701
  /**
4624
4702
  * Counts how many symbols matching the criteria are on a specific reel.
4625
4703
  */