@slot-engine/core 0.1.4 → 0.1.6

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.mjs CHANGED
@@ -645,14 +645,15 @@ var Board = class {
645
645
  this.lastUsedReels = opts.reels;
646
646
  for (let ridx = 0; ridx < reelsAmount; ridx++) {
647
647
  const reelPos = finalReelStops[ridx];
648
+ const reelLength = opts.reels[ridx].length;
648
649
  for (let p = padSymbols - 1; p >= 0; p--) {
649
- const topPos = (reelPos - (p + 1)) % opts.reels[ridx].length;
650
+ const topPos = ((reelPos - (p + 1)) % reelLength + reelLength) % reelLength;
650
651
  this.paddingTop[ridx].push(opts.reels[ridx][topPos]);
651
- const bottomPos = (reelPos + symbolsPerReel[ridx] + p) % opts.reels[ridx].length;
652
+ const bottomPos = (reelPos + symbolsPerReel[ridx] + p) % reelLength;
652
653
  this.paddingBottom[ridx].unshift(opts.reels[ridx][bottomPos]);
653
654
  }
654
655
  for (let row = 0; row < symbolsPerReel[ridx]; row++) {
655
- const symbol = opts.reels[ridx][(reelPos + row) % opts.reels[ridx].length];
656
+ const symbol = opts.reels[ridx][(reelPos + row) % reelLength];
656
657
  if (!symbol) {
657
658
  throw new Error(`Failed to get symbol at pos ${reelPos + row} on reel ${ridx}`);
658
659
  }
@@ -720,11 +721,27 @@ var Board = class {
720
721
  newPaddingTopSymbols[ridx].unshift(padSymbol);
721
722
  }
722
723
  }
724
+ this.lastDrawnReelStops = this.lastDrawnReelStops.map((stop, ridx) => {
725
+ return newFirstSymbolPositions[ridx] ?? stop;
726
+ });
723
727
  return {
724
728
  newBoardSymbols,
725
729
  newPaddingTopSymbols
726
730
  };
727
731
  }
732
+ dedupeWinSymbolsForTumble(winCombinations) {
733
+ const symbolsMap = /* @__PURE__ */ new Map();
734
+ winCombinations.forEach((wc) => {
735
+ wc.symbols.forEach((s) => {
736
+ symbolsMap.set(`${s.reelIndex},${s.posIndex}`, {
737
+ reelIdx: s.reelIndex,
738
+ rowIdx: s.posIndex
739
+ });
740
+ });
741
+ });
742
+ const symbolsToRemove = Array.from(symbolsMap.values());
743
+ return symbolsToRemove;
744
+ }
728
745
  };
729
746
 
730
747
  // src/service/board.ts
@@ -869,6 +886,16 @@ var BoardService = class extends AbstractService {
869
886
  symbolsToDelete
870
887
  });
871
888
  }
889
+ /**
890
+ * Dedupes win symbols for tumble.\
891
+ * Returns a list of symbols to remove from the board based on the given win combinations.
892
+ *
893
+ * Since it may be possible that multiple win combinations include the same symbol (e.g. Wilds),\
894
+ * this method ensures that each symbol is only listed once for removal. Otherwise tumbling may break.
895
+ */
896
+ dedupeWinSymbolsForTumble(winCombinations) {
897
+ return this.board.dedupeWinSymbolsForTumble(winCombinations);
898
+ }
872
899
  };
873
900
 
874
901
  // src/service/data.ts
@@ -1065,6 +1092,27 @@ var GameService = class extends AbstractService {
1065
1092
  this.ctx().state.totalFreespinAmount += amount;
1066
1093
  this.ctx().state.triggeredFreespins = true;
1067
1094
  }
1095
+ /**
1096
+ * Dedupes win symbols.
1097
+ *
1098
+ * Since it may be possible that multiple win combinations include the same symbol (e.g. Wilds),\
1099
+ * this method ensures that each symbol is only listed once.
1100
+ *
1101
+ * If you want to tumble based on winning symbols, run them through this method first.
1102
+ */
1103
+ dedupeWinSymbols(winCombinations) {
1104
+ const symbolsMap = /* @__PURE__ */ new Map();
1105
+ winCombinations.forEach((wc) => {
1106
+ wc.symbols.forEach((s) => {
1107
+ symbolsMap.set(`${s.reelIndex},${s.posIndex}`, {
1108
+ reelIdx: s.reelIndex,
1109
+ rowIdx: s.posIndex
1110
+ });
1111
+ });
1112
+ });
1113
+ const symbolsToRemove = Array.from(symbolsMap.values());
1114
+ return symbolsToRemove;
1115
+ }
1068
1116
  };
1069
1117
 
1070
1118
  // src/service/wallet.ts
@@ -1679,7 +1727,12 @@ Simulating game mode: ${mode}`);
1679
1727
  }
1680
1728
  });
1681
1729
  worker.on("error", (error) => {
1682
- console.error("Error:", error);
1730
+ process.stdout.write(`
1731
+ ${error.message}
1732
+ `);
1733
+ process.stdout.write(`
1734
+ ${error.stack}
1735
+ `);
1683
1736
  reject(error);
1684
1737
  });
1685
1738
  worker.on("exit", (code) => {
@@ -2241,28 +2294,12 @@ var Analysis = class {
2241
2294
  const payoutRanges = {};
2242
2295
  for (const modeStr of gameModes) {
2243
2296
  payoutRanges[modeStr] = { overall: {}, criteria: {} };
2244
- const lutOptimized = parseLookupTable(
2245
- fs3.readFileSync(this.filePaths[modeStr].lutOptimized, "utf-8")
2246
- );
2247
2297
  const lutSegmented = parseLookupTableSegmented(
2248
2298
  fs3.readFileSync(this.filePaths[modeStr].lutSegmented, "utf-8")
2249
2299
  );
2250
- lutOptimized.forEach(([, , p]) => {
2251
- const payout = p / 100;
2252
- for (const [min, max] of winRanges) {
2253
- if (payout >= min && payout <= max) {
2254
- const rangeKey = `${min}-${max}`;
2255
- if (!payoutRanges[modeStr].overall[rangeKey]) {
2256
- payoutRanges[modeStr].overall[rangeKey] = 0;
2257
- }
2258
- payoutRanges[modeStr].overall[rangeKey] += 1;
2259
- break;
2260
- }
2261
- }
2262
- });
2263
2300
  lutSegmented.forEach(([, criteria, bp, fsp]) => {
2264
- const basePayout = bp / 100;
2265
- const freeSpinPayout = fsp / 100;
2301
+ const basePayout = bp;
2302
+ const freeSpinPayout = fsp;
2266
2303
  const payout = basePayout + freeSpinPayout;
2267
2304
  for (const [min, max] of winRanges) {
2268
2305
  if (payout >= min && payout <= max) {
@@ -3719,6 +3756,16 @@ var StandaloneBoard = class {
3719
3756
  padSymbols: this.padSymbols
3720
3757
  });
3721
3758
  }
3759
+ /**
3760
+ * Dedupes win symbols for tumble.\
3761
+ * Returns a list of symbols to remove from the board based on the given win combinations.
3762
+ *
3763
+ * Since it may be possible that multiple win combinations include the same symbol (e.g. Wilds),\
3764
+ * this method ensures that each symbol is only listed once for removal. Otherwise tumbling may break.
3765
+ */
3766
+ dedupeWinSymbolsForTumble(winCombinations) {
3767
+ return this.board.dedupeWinSymbolsForTumble(winCombinations);
3768
+ }
3722
3769
  };
3723
3770
  export {
3724
3771
  ClusterWinType,