@slot-engine/core 0.1.7 → 0.1.8
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 +92 -6
- package/dist/index.d.ts +92 -6
- package/dist/index.js +153 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +153 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -471,6 +471,11 @@ var Board = class {
|
|
|
471
471
|
this.reels[reelIndex] = this.reels[reelIndex] || [];
|
|
472
472
|
this.reels[reelIndex][rowIndex] = symbol;
|
|
473
473
|
}
|
|
474
|
+
removeSymbol(reelIndex, rowIndex) {
|
|
475
|
+
if (this.reels[reelIndex]) {
|
|
476
|
+
this.reels[reelIndex].splice(rowIndex, 1);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
474
479
|
makeEmptyReels(opts) {
|
|
475
480
|
const length = opts.reelsAmount ?? opts.ctx.services.game.getCurrentGameMode().reelsAmount;
|
|
476
481
|
assert3(length, "Cannot make empty reels without context or reelsAmount.");
|
|
@@ -660,18 +665,35 @@ var Board = class {
|
|
|
660
665
|
this.reels[ridx][row] = symbol;
|
|
661
666
|
}
|
|
662
667
|
}
|
|
668
|
+
return {
|
|
669
|
+
stopPositions: this.lastDrawnReelStops
|
|
670
|
+
};
|
|
663
671
|
}
|
|
664
672
|
tumbleBoard(opts) {
|
|
665
673
|
assert3(this.lastDrawnReelStops.length > 0, "Cannot tumble board before drawing it.");
|
|
666
674
|
const reelsAmount = opts.reelsAmount ?? opts.ctx.services.game.getCurrentGameMode().reelsAmount;
|
|
667
675
|
const symbolsPerReel = opts.symbolsPerReel ?? opts.ctx.services.game.getCurrentGameMode().symbolsPerReel;
|
|
668
676
|
const padSymbols = opts.padSymbols ?? opts.ctx.config.padSymbols;
|
|
677
|
+
if (opts.startingStops) {
|
|
678
|
+
assert3(
|
|
679
|
+
opts.startingStops.length === reelsAmount,
|
|
680
|
+
"Starting stops length does not match reels amount."
|
|
681
|
+
);
|
|
682
|
+
assert3(opts.reels, "Reels must be provided when using startingStops.");
|
|
683
|
+
}
|
|
684
|
+
if (opts.reels) {
|
|
685
|
+
assert3(opts.startingStops, "Starting stops must be provided when using reels.");
|
|
686
|
+
}
|
|
669
687
|
if (!opts.ctx && !reelsAmount && !symbolsPerReel) {
|
|
670
688
|
throw new Error(
|
|
671
689
|
"If ctx is not provided, reelsAmount and symbolsPerReel must be given."
|
|
672
690
|
);
|
|
673
691
|
}
|
|
674
|
-
const reels = this.lastUsedReels;
|
|
692
|
+
const reels = opts.reels || this.lastUsedReels;
|
|
693
|
+
assert3(
|
|
694
|
+
reels.length === reelsAmount,
|
|
695
|
+
"Given reels length does not match reels amount."
|
|
696
|
+
);
|
|
675
697
|
const sortedDeletions = [...opts.symbolsToDelete].sort((a, b) => b.rowIdx - a.rowIdx);
|
|
676
698
|
sortedDeletions.forEach(({ reelIdx, rowIdx }) => {
|
|
677
699
|
this.reels[reelIdx].splice(rowIdx, 1);
|
|
@@ -681,7 +703,7 @@ var Board = class {
|
|
|
681
703
|
const newPaddingTopSymbols = {};
|
|
682
704
|
for (let ridx = 0; ridx < reelsAmount; ridx++) {
|
|
683
705
|
while (this.reels[ridx].length < symbolsPerReel[ridx]) {
|
|
684
|
-
const padSymbol = this.paddingTop[ridx]
|
|
706
|
+
const padSymbol = this.paddingTop[ridx]?.pop();
|
|
685
707
|
if (padSymbol) {
|
|
686
708
|
this.reels[ridx].unshift(padSymbol);
|
|
687
709
|
if (!newBoardSymbols[ridx]) {
|
|
@@ -697,7 +719,16 @@ var Board = class {
|
|
|
697
719
|
const symbolsNeeded = symbolsPerReel[ridx] - this.reels[ridx].length;
|
|
698
720
|
for (let s = 0; s < symbolsNeeded; s++) {
|
|
699
721
|
const symbolPos = (stopBeforePad - s + reels[ridx].length) % reels[ridx].length;
|
|
700
|
-
|
|
722
|
+
let newSymbol = reels[ridx][symbolPos];
|
|
723
|
+
const startStops = opts.startingStops;
|
|
724
|
+
if (startStops) {
|
|
725
|
+
const forcedSym = reels[ridx][startStops?.[ridx]];
|
|
726
|
+
assert3(
|
|
727
|
+
forcedSym,
|
|
728
|
+
`Failed to get forced symbol for tumbling. Tried to get symbol for position ${startStops?.[ridx]} on reel ${ridx}.`
|
|
729
|
+
);
|
|
730
|
+
newSymbol = forcedSym;
|
|
731
|
+
}
|
|
701
732
|
assert3(newSymbol, "Failed to get new symbol for tumbling.");
|
|
702
733
|
this.reels[ridx].unshift(newSymbol);
|
|
703
734
|
newFirstSymbolPositions[ridx] = symbolPos;
|
|
@@ -721,9 +752,11 @@ var Board = class {
|
|
|
721
752
|
newPaddingTopSymbols[ridx].unshift(padSymbol);
|
|
722
753
|
}
|
|
723
754
|
}
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
755
|
+
if (!opts.reels && !opts.startingStops) {
|
|
756
|
+
this.lastDrawnReelStops = this.lastDrawnReelStops.map((stop, ridx) => {
|
|
757
|
+
return newFirstSymbolPositions[ridx] ?? stop;
|
|
758
|
+
});
|
|
759
|
+
}
|
|
727
760
|
return {
|
|
728
761
|
newBoardSymbols,
|
|
729
762
|
newPaddingTopSymbols
|
|
@@ -786,6 +819,12 @@ var BoardService = class extends AbstractService {
|
|
|
786
819
|
setSymbol(reelIndex, rowIndex, symbol) {
|
|
787
820
|
this.board.setSymbol(reelIndex, rowIndex, symbol);
|
|
788
821
|
}
|
|
822
|
+
/**
|
|
823
|
+
* Removes the symbol at the specified reel and row index.
|
|
824
|
+
*/
|
|
825
|
+
removeSymbol(reelIndex, rowIndex) {
|
|
826
|
+
this.board.removeSymbol(reelIndex, rowIndex);
|
|
827
|
+
}
|
|
789
828
|
resetReels() {
|
|
790
829
|
this.board.resetReels({
|
|
791
830
|
ctx: this.ctx()
|
|
@@ -861,16 +900,16 @@ var BoardService = class extends AbstractService {
|
|
|
861
900
|
* Draws a board using specified reel stops.
|
|
862
901
|
*/
|
|
863
902
|
drawBoardWithForcedStops(opts) {
|
|
864
|
-
this.drawBoardMixed(opts.reels, opts.forcedStops, opts.randomOffset);
|
|
903
|
+
return this.drawBoardMixed(opts.reels, opts.forcedStops, opts.randomOffset);
|
|
865
904
|
}
|
|
866
905
|
/**
|
|
867
906
|
* Draws a board using random reel stops.
|
|
868
907
|
*/
|
|
869
908
|
drawBoardWithRandomStops(reels) {
|
|
870
|
-
this.drawBoardMixed(reels);
|
|
909
|
+
return this.drawBoardMixed(reels);
|
|
871
910
|
}
|
|
872
911
|
drawBoardMixed(reels, forcedStops, forcedStopsOffset) {
|
|
873
|
-
this.board.drawBoardMixed({
|
|
912
|
+
return this.board.drawBoardMixed({
|
|
874
913
|
ctx: this.ctx(),
|
|
875
914
|
reels,
|
|
876
915
|
forcedStops,
|
|
@@ -886,6 +925,21 @@ var BoardService = class extends AbstractService {
|
|
|
886
925
|
symbolsToDelete
|
|
887
926
|
});
|
|
888
927
|
}
|
|
928
|
+
/**
|
|
929
|
+
* **Experimental - May be changed or replaced in the future**
|
|
930
|
+
*
|
|
931
|
+
* Tumbles the board normally like `tumbleBoard`, but allows specifying a different reel set to get symbols from.\
|
|
932
|
+
* Also requires specifying the starting stops from where the symbols will be tumbled.\
|
|
933
|
+
* **This method does not remember the last tumbled position. Use this if you need to do a singular one-off tumble.**
|
|
934
|
+
*/
|
|
935
|
+
tumbleBoardAndForget(opts) {
|
|
936
|
+
return this.board.tumbleBoard({
|
|
937
|
+
ctx: this.ctx(),
|
|
938
|
+
symbolsToDelete: opts.symbolsToDelete,
|
|
939
|
+
reels: opts.reels,
|
|
940
|
+
startingStops: opts.forcedStops
|
|
941
|
+
});
|
|
942
|
+
}
|
|
889
943
|
/**
|
|
890
944
|
* Dedupes win symbols for tumble.\
|
|
891
945
|
* Returns a list of symbols to remove from the board based on the given win combinations.
|
|
@@ -896,6 +950,26 @@ var BoardService = class extends AbstractService {
|
|
|
896
950
|
dedupeWinSymbolsForTumble(winCombinations) {
|
|
897
951
|
return this.board.dedupeWinSymbolsForTumble(winCombinations);
|
|
898
952
|
}
|
|
953
|
+
/**
|
|
954
|
+
* Sets the symbolsPerReel for the current game mode.
|
|
955
|
+
*
|
|
956
|
+
* The value will be reset to the original value as set in the game mode config in the next simulation.
|
|
957
|
+
*/
|
|
958
|
+
setSymbolsPerReel(symbolsPerReel) {
|
|
959
|
+
this.ctx().config.gameModes[this.ctx().state.currentGameMode]._setSymbolsPerReel(
|
|
960
|
+
symbolsPerReel
|
|
961
|
+
);
|
|
962
|
+
}
|
|
963
|
+
/**
|
|
964
|
+
* Sets the reelsAmount for the current game mode.
|
|
965
|
+
*
|
|
966
|
+
* The value will be reset to the original value as set in the game mode config in the next simulation.
|
|
967
|
+
*/
|
|
968
|
+
setReelsAmount(reelsAmount) {
|
|
969
|
+
this.ctx().config.gameModes[this.ctx().state.currentGameMode]._setReelsAmount(
|
|
970
|
+
reelsAmount
|
|
971
|
+
);
|
|
972
|
+
}
|
|
899
973
|
};
|
|
900
974
|
|
|
901
975
|
// src/service/data.ts
|
|
@@ -1800,6 +1874,9 @@ ${error.stack}
|
|
|
1800
1874
|
criteria: ctx.state.currentResultSet.criteria
|
|
1801
1875
|
})
|
|
1802
1876
|
);
|
|
1877
|
+
Object.values(ctx.config.gameModes).forEach((mode) => {
|
|
1878
|
+
mode._resetTempValues();
|
|
1879
|
+
});
|
|
1803
1880
|
}
|
|
1804
1881
|
resetState(ctx) {
|
|
1805
1882
|
ctx.services.rng.setSeedIfDifferent(ctx.state.currentSimulationId);
|
|
@@ -2748,6 +2825,8 @@ var defineGameModes = (gameModes) => gameModes;
|
|
|
2748
2825
|
import assert10 from "assert";
|
|
2749
2826
|
var GameMode = class {
|
|
2750
2827
|
name;
|
|
2828
|
+
_reelsAmount;
|
|
2829
|
+
_symbolsPerReel;
|
|
2751
2830
|
reelsAmount;
|
|
2752
2831
|
symbolsPerReel;
|
|
2753
2832
|
cost;
|
|
@@ -2757,7 +2836,9 @@ var GameMode = class {
|
|
|
2757
2836
|
isBonusBuy;
|
|
2758
2837
|
constructor(opts) {
|
|
2759
2838
|
this.name = opts.name;
|
|
2839
|
+
this._reelsAmount = opts.reelsAmount;
|
|
2760
2840
|
this.reelsAmount = opts.reelsAmount;
|
|
2841
|
+
this._symbolsPerReel = opts.symbolsPerReel;
|
|
2761
2842
|
this.symbolsPerReel = opts.symbolsPerReel;
|
|
2762
2843
|
this.cost = opts.cost;
|
|
2763
2844
|
this.rtp = opts.rtp;
|
|
@@ -2771,6 +2852,29 @@ var GameMode = class {
|
|
|
2771
2852
|
);
|
|
2772
2853
|
assert10(this.reelSets.length > 0, "GameMode must have at least one ReelSet defined.");
|
|
2773
2854
|
}
|
|
2855
|
+
/**
|
|
2856
|
+
* Intended for internal use only.
|
|
2857
|
+
*/
|
|
2858
|
+
_resetTempValues() {
|
|
2859
|
+
this.reelsAmount = this._reelsAmount;
|
|
2860
|
+
this.symbolsPerReel = this._symbolsPerReel;
|
|
2861
|
+
}
|
|
2862
|
+
/**
|
|
2863
|
+
* Intended for internal use only.
|
|
2864
|
+
*/
|
|
2865
|
+
_setSymbolsPerReel(symbolsPerReel) {
|
|
2866
|
+
assert10(
|
|
2867
|
+
symbolsPerReel.length === this._reelsAmount,
|
|
2868
|
+
"symbolsPerReel length must match reelsAmount."
|
|
2869
|
+
);
|
|
2870
|
+
this.symbolsPerReel = symbolsPerReel;
|
|
2871
|
+
}
|
|
2872
|
+
/**
|
|
2873
|
+
* Intended for internal use only.
|
|
2874
|
+
*/
|
|
2875
|
+
_setReelsAmount(reelsAmount) {
|
|
2876
|
+
this.reelsAmount = reelsAmount;
|
|
2877
|
+
}
|
|
2774
2878
|
};
|
|
2775
2879
|
|
|
2776
2880
|
// src/win-types/index.ts
|
|
@@ -3653,6 +3757,12 @@ var StandaloneBoard = class {
|
|
|
3653
3757
|
setSymbol(reelIndex, rowIndex, symbol) {
|
|
3654
3758
|
this.board.setSymbol(reelIndex, rowIndex, symbol);
|
|
3655
3759
|
}
|
|
3760
|
+
/**
|
|
3761
|
+
* Removes the symbol at the specified reel and row index.
|
|
3762
|
+
*/
|
|
3763
|
+
removeSymbol(reelIndex, rowIndex) {
|
|
3764
|
+
this.board.removeSymbol(reelIndex, rowIndex);
|
|
3765
|
+
}
|
|
3656
3766
|
resetReels() {
|
|
3657
3767
|
this.board.resetReels({
|
|
3658
3768
|
ctx: this.ctx
|
|
@@ -3729,16 +3839,16 @@ var StandaloneBoard = class {
|
|
|
3729
3839
|
* Draws a board using specified reel stops.
|
|
3730
3840
|
*/
|
|
3731
3841
|
drawBoardWithForcedStops(opts) {
|
|
3732
|
-
this.drawBoardMixed(opts.reels, opts.forcedStops, opts.randomOffset);
|
|
3842
|
+
return this.drawBoardMixed(opts.reels, opts.forcedStops, opts.randomOffset);
|
|
3733
3843
|
}
|
|
3734
3844
|
/**
|
|
3735
3845
|
* Draws a board using random reel stops.
|
|
3736
3846
|
*/
|
|
3737
3847
|
drawBoardWithRandomStops(reels) {
|
|
3738
|
-
this.drawBoardMixed(reels);
|
|
3848
|
+
return this.drawBoardMixed(reels);
|
|
3739
3849
|
}
|
|
3740
3850
|
drawBoardMixed(reels, forcedStops, forcedStopsOffset) {
|
|
3741
|
-
this.board.drawBoardMixed({
|
|
3851
|
+
return this.board.drawBoardMixed({
|
|
3742
3852
|
ctx: this.ctx,
|
|
3743
3853
|
reels,
|
|
3744
3854
|
forcedStops,
|
|
@@ -3760,16 +3870,46 @@ var StandaloneBoard = class {
|
|
|
3760
3870
|
padSymbols: this.padSymbols
|
|
3761
3871
|
});
|
|
3762
3872
|
}
|
|
3873
|
+
/**
|
|
3874
|
+
* **Experimental - May be changed or replaced in the future**
|
|
3875
|
+
*
|
|
3876
|
+
* Tumbles the board normally like `tumbleBoard`, but allows specifying a different reel set to get symbols from.\
|
|
3877
|
+
* Also requires specifying the starting stops from where the symbols will be tumbled.\
|
|
3878
|
+
* **This method does not remember the last tumbled position. Use this if you need to do a singular one-off tumble.**
|
|
3879
|
+
*/
|
|
3880
|
+
tumbleBoardAndForget(opts) {
|
|
3881
|
+
return this.board.tumbleBoard({
|
|
3882
|
+
ctx: this.ctx,
|
|
3883
|
+
symbolsToDelete: opts.symbolsToDelete,
|
|
3884
|
+
reelsAmount: this.reelsAmount,
|
|
3885
|
+
symbolsPerReel: this.symbolsPerReel,
|
|
3886
|
+
padSymbols: this.padSymbols,
|
|
3887
|
+
reels: opts.reels,
|
|
3888
|
+
startingStops: opts.forcedStops
|
|
3889
|
+
});
|
|
3890
|
+
}
|
|
3763
3891
|
/**
|
|
3764
3892
|
* Dedupes win symbols for tumble.\
|
|
3765
3893
|
* Returns a list of symbols to remove from the board based on the given win combinations.
|
|
3766
|
-
*
|
|
3894
|
+
*
|
|
3767
3895
|
* Since it may be possible that multiple win combinations include the same symbol (e.g. Wilds),\
|
|
3768
3896
|
* this method ensures that each symbol is only listed once for removal. Otherwise tumbling may break.
|
|
3769
3897
|
*/
|
|
3770
3898
|
dedupeWinSymbolsForTumble(winCombinations) {
|
|
3771
3899
|
return this.board.dedupeWinSymbolsForTumble(winCombinations);
|
|
3772
3900
|
}
|
|
3901
|
+
/**
|
|
3902
|
+
* Sets symbolsPerReel.
|
|
3903
|
+
*/
|
|
3904
|
+
setSymbolsPerReel(symbolsPerReel) {
|
|
3905
|
+
this.symbolsPerReel = symbolsPerReel;
|
|
3906
|
+
}
|
|
3907
|
+
/**
|
|
3908
|
+
* Sets the reelsAmount.
|
|
3909
|
+
*/
|
|
3910
|
+
setReelsAmount(reelsAmount) {
|
|
3911
|
+
this.reelsAmount = reelsAmount;
|
|
3912
|
+
}
|
|
3773
3913
|
};
|
|
3774
3914
|
export {
|
|
3775
3915
|
ClusterWinType,
|