@slot-engine/core 0.0.1 → 0.0.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.
Files changed (43) hide show
  1. package/README.md +1 -1
  2. package/dist/index.d.mts +7 -14
  3. package/dist/index.d.ts +7 -14
  4. package/dist/index.js +68 -90
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +68 -90
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +5 -1
  9. package/.turbo/turbo-build.log +0 -33
  10. package/.turbo/turbo-typecheck.log +0 -4
  11. package/CHANGELOG.md +0 -7
  12. package/dist/lib/zstd.exe +0 -0
  13. package/index.ts +0 -205
  14. package/lib/zstd.exe +0 -0
  15. package/optimizer-rust/Cargo.toml +0 -19
  16. package/optimizer-rust/src/exes.rs +0 -154
  17. package/optimizer-rust/src/main.rs +0 -1659
  18. package/src/Board.ts +0 -527
  19. package/src/Book.ts +0 -83
  20. package/src/GameConfig.ts +0 -148
  21. package/src/GameMode.ts +0 -86
  22. package/src/GameState.ts +0 -272
  23. package/src/GameSymbol.ts +0 -61
  24. package/src/ReelGenerator.ts +0 -589
  25. package/src/ResultSet.ts +0 -207
  26. package/src/Simulation.ts +0 -625
  27. package/src/SlotGame.ts +0 -117
  28. package/src/Wallet.ts +0 -203
  29. package/src/WinType.ts +0 -102
  30. package/src/analysis/index.ts +0 -198
  31. package/src/analysis/utils.ts +0 -128
  32. package/src/optimizer/OptimizationConditions.ts +0 -99
  33. package/src/optimizer/OptimizationParameters.ts +0 -46
  34. package/src/optimizer/OptimizationScaling.ts +0 -18
  35. package/src/optimizer/index.ts +0 -142
  36. package/src/utils/math-config.ts +0 -109
  37. package/src/utils/setup-file.ts +0 -36
  38. package/src/utils/zstd.ts +0 -28
  39. package/src/winTypes/ClusterWinType.ts +0 -3
  40. package/src/winTypes/LinesWinType.ts +0 -208
  41. package/src/winTypes/ManywaysWinType.ts +0 -3
  42. package/tsconfig.json +0 -19
  43. package/utils.ts +0 -270
package/dist/index.mjs CHANGED
@@ -1,11 +1,11 @@
1
1
  // src/GameConfig.ts
2
+ import assert from "assert";
2
3
  var GameConfig = class _GameConfig {
3
4
  config;
4
5
  constructor(opts) {
5
6
  this.config = {
6
7
  id: opts.id,
7
8
  name: opts.name,
8
- providerNumber: opts.providerNumber,
9
9
  gameModes: opts.gameModes,
10
10
  symbols: /* @__PURE__ */ new Map(),
11
11
  padSymbols: opts.padSymbols || 0,
@@ -23,14 +23,12 @@ var GameConfig = class _GameConfig {
23
23
  userState: opts.userState,
24
24
  outputDir: "__build__"
25
25
  };
26
- for (const symbol of opts.symbols) {
27
- if (!this.config.symbols.has(symbol.id)) {
28
- this.config.symbols.set(symbol.id, symbol);
29
- } else {
30
- console.warn(
31
- `Symbol with id "${symbol.id}" already exists in the game config. Skipping duplicate. This is probably not intentional.`
32
- );
33
- }
26
+ for (const [key, value] of Object.entries(opts.symbols)) {
27
+ assert(
28
+ value.id === key,
29
+ `Symbol key "${key}" does not match symbol id "${value.id}"`
30
+ );
31
+ this.config.symbols.set(key, value);
34
32
  }
35
33
  function getAnticipationTrigger(spinType) {
36
34
  return Math.min(...Object.keys(opts.scatterToFreespins[spinType]).map(Number)) - 1;
@@ -1774,7 +1772,7 @@ var ManywaysWinType = class extends WinType {
1774
1772
  };
1775
1773
 
1776
1774
  // src/optimizer/OptimizationConditions.ts
1777
- import assert from "assert";
1775
+ import assert2 from "assert";
1778
1776
  var OptimizationConditions = class {
1779
1777
  rtp;
1780
1778
  avgWin;
@@ -1785,14 +1783,14 @@ var OptimizationConditions = class {
1785
1783
  constructor(opts) {
1786
1784
  let { rtp, avgWin, hitRate, searchConditions, priority } = opts;
1787
1785
  if (rtp == void 0 || rtp === "x") {
1788
- assert(avgWin !== void 0 && hitRate !== void 0, "If RTP is not specified, hit-rate (hr) and average win amount (av_win) must be given.");
1786
+ assert2(avgWin !== void 0 && hitRate !== void 0, "If RTP is not specified, hit-rate (hr) and average win amount (av_win) must be given.");
1789
1787
  rtp = Math.round(avgWin / Number(hitRate) * 1e5) / 1e5;
1790
1788
  }
1791
1789
  let noneCount = 0;
1792
1790
  for (const val of [rtp, avgWin, hitRate]) {
1793
1791
  if (val === void 0) noneCount++;
1794
1792
  }
1795
- assert(noneCount <= 1, "Invalid combination of optimization conditions.");
1793
+ assert2(noneCount <= 1, "Invalid combination of optimization conditions.");
1796
1794
  this.searchRange = [-1, -1];
1797
1795
  this.forceSearch = {};
1798
1796
  if (typeof searchConditions === "number") {
@@ -1872,41 +1870,11 @@ var OptimizationParameters = class _OptimizationParameters {
1872
1870
 
1873
1871
  // src/Simulation.ts
1874
1872
  import fs3 from "fs";
1875
- import path3 from "path";
1876
- import assert2 from "assert";
1873
+ import path2 from "path";
1874
+ import assert3 from "assert";
1875
+ import zlib from "zlib";
1877
1876
  import { buildSync } from "esbuild";
1878
1877
  import { Worker, isMainThread as isMainThread2, parentPort, workerData } from "worker_threads";
1879
-
1880
- // src/utils/zstd.ts
1881
- import path2 from "path";
1882
- import { spawn } from "child_process";
1883
- async function zstd(...args) {
1884
- return new Promise((resolve, reject) => {
1885
- const task = spawn(path2.join(__dirname, "./lib/zstd.exe"), args);
1886
- task.on("error", (error) => {
1887
- console.error("Error:", error);
1888
- reject(error);
1889
- });
1890
- task.on("exit", () => {
1891
- resolve(true);
1892
- });
1893
- task.on("close", () => {
1894
- resolve(true);
1895
- });
1896
- task.stdout.on("data", (data) => {
1897
- console.log(data.toString());
1898
- });
1899
- task.stderr.on("data", (data) => {
1900
- console.log(data.toString());
1901
- });
1902
- task.stdout.on("error", (data) => {
1903
- console.log(data.toString());
1904
- reject(data.toString());
1905
- });
1906
- });
1907
- }
1908
-
1909
- // src/Simulation.ts
1910
1878
  var completedSimulations = 0;
1911
1879
  var TEMP_FILENAME = "__temp_compiled_src_IGNORE.js";
1912
1880
  var Simulation = class _Simulation {
@@ -1927,7 +1895,7 @@ var Simulation = class _Simulation {
1927
1895
  this.library = /* @__PURE__ */ new Map();
1928
1896
  this.records = [];
1929
1897
  const gameModeKeys = Object.keys(this.gameConfig.config.gameModes);
1930
- assert2(
1898
+ assert3(
1931
1899
  Object.values(this.gameConfig.config.gameModes).map((m) => gameModeKeys.includes(m.name)).every((v) => v === true),
1932
1900
  "Game mode name must match its key in the gameModes object."
1933
1901
  );
@@ -1964,14 +1932,14 @@ Simulating game mode: ${mode}`);
1964
1932
  const simNumsToCriteria = ResultSet.assignCriteriaToSimulations(this, mode);
1965
1933
  await this.spawnWorkersForGameMode({ mode, simNumsToCriteria });
1966
1934
  createDirIfNotExists(
1967
- path3.join(
1935
+ path2.join(
1968
1936
  process.cwd(),
1969
1937
  this.gameConfig.config.outputDir,
1970
1938
  "optimization_files"
1971
1939
  )
1972
1940
  );
1973
1941
  createDirIfNotExists(
1974
- path3.join(process.cwd(), this.gameConfig.config.outputDir, "publish_files")
1942
+ path2.join(process.cwd(), this.gameConfig.config.outputDir, "publish_files")
1975
1943
  );
1976
1944
  _Simulation.writeLookupTableCSV({
1977
1945
  gameMode: mode,
@@ -2067,7 +2035,7 @@ Simulating game mode: ${mode}`);
2067
2035
  }
2068
2036
  }
2069
2037
  return new Promise((resolve, reject) => {
2070
- const scriptPath = path3.join(process.cwd(), basePath, TEMP_FILENAME);
2038
+ const scriptPath = path2.join(process.cwd(), basePath, TEMP_FILENAME);
2071
2039
  const worker = new Worker(scriptPath, {
2072
2040
  workerData: {
2073
2041
  mode,
@@ -2108,14 +2076,17 @@ Simulating game mode: ${mode}`);
2108
2076
  * `weight` defaults to 1.
2109
2077
  */
2110
2078
  static writeLookupTableCSV(opts) {
2111
- const { gameMode, fileNameWithoutExtension, library, gameConfig } = opts;
2079
+ const { gameMode, library, gameConfig } = opts;
2112
2080
  const rows = [];
2113
2081
  for (const [bookId, book] of library.entries()) {
2114
2082
  rows.push(`${book.id},1,${Math.round(book.getPayout())}`);
2115
2083
  }
2116
2084
  rows.sort((a, b) => Number(a.split(",")[0]) - Number(b.split(",")[0]));
2117
- const outputFileName = fileNameWithoutExtension ? `${fileNameWithoutExtension}.csv` : `lookUpTable_${gameMode}.csv`;
2118
- const outputFilePath = path3.join(gameConfig.outputDir, outputFileName);
2085
+ let outputFileName = `lookUpTable_${gameMode}.csv`;
2086
+ let outputFilePath = path2.join(gameConfig.outputDir, outputFileName);
2087
+ writeFile(outputFilePath, rows.join("\n"));
2088
+ outputFileName = `lookUpTable_${gameMode}_0.csv`;
2089
+ outputFilePath = path2.join(gameConfig.outputDir, outputFileName);
2119
2090
  writeFile(outputFilePath, rows.join("\n"));
2120
2091
  return outputFilePath;
2121
2092
  }
@@ -2123,7 +2094,7 @@ Simulating game mode: ${mode}`);
2123
2094
  * Creates a CSV file in the format "simulationId,criteria,payoutBase,payoutFreespins".
2124
2095
  */
2125
2096
  static writeLookupTableSegmentedCSV(opts) {
2126
- const { gameMode, fileNameWithoutExtension, library, gameConfig } = opts;
2097
+ const { gameMode, library, gameConfig } = opts;
2127
2098
  const rows = [];
2128
2099
  for (const [bookId, book] of library.entries()) {
2129
2100
  rows.push(
@@ -2131,22 +2102,22 @@ Simulating game mode: ${mode}`);
2131
2102
  );
2132
2103
  }
2133
2104
  rows.sort((a, b) => Number(a.split(",")[0]) - Number(b.split(",")[0]));
2134
- const outputFileName = fileNameWithoutExtension ? `${fileNameWithoutExtension}.csv` : `lookUpTableSegmented_${gameMode}.csv`;
2135
- const outputFilePath = path3.join(gameConfig.outputDir, outputFileName);
2105
+ const outputFileName = `lookUpTableSegmented_${gameMode}.csv`;
2106
+ const outputFilePath = path2.join(gameConfig.outputDir, outputFileName);
2136
2107
  writeFile(outputFilePath, rows.join("\n"));
2137
2108
  return outputFilePath;
2138
2109
  }
2139
2110
  static writeRecords(opts) {
2140
2111
  const { gameMode, fileNameWithoutExtension, records, gameConfig, debug } = opts;
2141
2112
  const outputFileName = fileNameWithoutExtension ? `${fileNameWithoutExtension}.json` : `force_record_${gameMode}.json`;
2142
- const outputFilePath = path3.join(gameConfig.outputDir, outputFileName);
2113
+ const outputFilePath = path2.join(gameConfig.outputDir, outputFileName);
2143
2114
  writeFile(outputFilePath, JSON.stringify(records, null, 2));
2144
2115
  if (debug) _Simulation.logSymbolOccurrences(records);
2145
2116
  return outputFilePath;
2146
2117
  }
2147
2118
  static writeIndexJson(opts) {
2148
2119
  const { gameConfig } = opts;
2149
- const outputFilePath = path3.join(
2120
+ const outputFilePath = path2.join(
2150
2121
  process.cwd(),
2151
2122
  gameConfig.outputDir,
2152
2123
  "publish_files",
@@ -2163,7 +2134,7 @@ Simulating game mode: ${mode}`);
2163
2134
  static async writeBooksJson(opts) {
2164
2135
  const { gameMode, fileNameWithoutExtension, library, gameConfig } = opts;
2165
2136
  const outputFileName = fileNameWithoutExtension ? `${fileNameWithoutExtension}.jsonl` : `books_${gameMode}.jsonl`;
2166
- const outputFilePath = path3.join(gameConfig.outputDir, outputFileName);
2137
+ const outputFilePath = path2.join(gameConfig.outputDir, outputFileName);
2167
2138
  const books = Array.from(library.values()).map((b) => b.serialize()).map((b) => ({
2168
2139
  id: b.id,
2169
2140
  payoutMultiplier: b.payout,
@@ -2172,14 +2143,15 @@ Simulating game mode: ${mode}`);
2172
2143
  const contents = JSONL.stringify(books);
2173
2144
  writeFile(outputFilePath, contents);
2174
2145
  const compressedFileName = fileNameWithoutExtension ? `${fileNameWithoutExtension}.jsonl.zst` : `books_${gameMode}.jsonl.zst`;
2175
- const compressedFilePath = path3.join(
2146
+ const compressedFilePath = path2.join(
2176
2147
  process.cwd(),
2177
2148
  gameConfig.outputDir,
2178
2149
  "publish_files",
2179
2150
  compressedFileName
2180
2151
  );
2181
2152
  fs3.rmSync(compressedFilePath, { force: true });
2182
- await zstd("-f", outputFilePath, "-o", compressedFilePath);
2153
+ const compressed = zlib.zstdCompressSync(Buffer.from(contents));
2154
+ fs3.writeFileSync(compressedFilePath, compressed);
2183
2155
  }
2184
2156
  static logSymbolOccurrences(records) {
2185
2157
  const validRecords = records.filter(
@@ -2210,14 +2182,14 @@ Simulating game mode: ${mode}`);
2210
2182
  * Compiles user configured game to JS for use in different Node processes
2211
2183
  */
2212
2184
  preprocessFiles() {
2213
- const builtFilePath = path3.join(this.gameConfig.config.outputDir, TEMP_FILENAME);
2185
+ const builtFilePath = path2.join(this.gameConfig.config.outputDir, TEMP_FILENAME);
2214
2186
  fs3.rmSync(builtFilePath, { force: true });
2215
2187
  buildSync({
2216
2188
  entryPoints: [process.cwd()],
2217
2189
  bundle: true,
2218
2190
  platform: "node",
2219
- outfile: path3.join(this.gameConfig.config.outputDir, TEMP_FILENAME),
2220
- external: ["esbuild", "@mongodb-js/zstd"]
2191
+ outfile: path2.join(this.gameConfig.config.outputDir, TEMP_FILENAME),
2192
+ external: ["esbuild"]
2221
2193
  });
2222
2194
  }
2223
2195
  getSimRangesForChunks(total, chunks) {
@@ -2325,8 +2297,8 @@ var SimulationContext = class extends Board {
2325
2297
 
2326
2298
  // src/analysis/index.ts
2327
2299
  import fs4 from "fs";
2328
- import path4 from "path";
2329
- import assert3 from "assert";
2300
+ import path3 from "path";
2301
+ import assert4 from "assert";
2330
2302
 
2331
2303
  // src/analysis/utils.ts
2332
2304
  function parseLookupTable(content) {
@@ -2370,8 +2342,11 @@ function getPayoutWeights(lut, opts = {}) {
2370
2342
  }
2371
2343
  function getNonZeroHitrate(payoutWeights) {
2372
2344
  const totalWeight = getTotalWeight(payoutWeights);
2373
- const nonZeroWeight = totalWeight - (payoutWeights[0] ?? 0) * totalWeight;
2374
- return nonZeroWeight / totalWeight;
2345
+ if (Math.min(...Object.keys(payoutWeights).map(Number)) == 0) {
2346
+ return totalWeight / (totalWeight - (payoutWeights[0] ?? 0) / totalWeight);
2347
+ } else {
2348
+ return 1;
2349
+ }
2375
2350
  }
2376
2351
  function getNullHitrate(payoutWeights) {
2377
2352
  return payoutWeights[0] ?? 0;
@@ -2432,6 +2407,7 @@ function getLessBetHitrate(payoutWeights, cost) {
2432
2407
  }
2433
2408
 
2434
2409
  // src/analysis/index.ts
2410
+ import { isMainThread as isMainThread3 } from "worker_threads";
2435
2411
  var Analysis = class {
2436
2412
  gameConfig;
2437
2413
  optimizerConfig;
@@ -2442,6 +2418,7 @@ var Analysis = class {
2442
2418
  this.filePaths = {};
2443
2419
  }
2444
2420
  async runAnalysis(gameModes) {
2421
+ if (!isMainThread3) return;
2445
2422
  this.filePaths = this.getPathsForModes(gameModes);
2446
2423
  this.getNumberStats(gameModes);
2447
2424
  this.getWinRanges(gameModes);
@@ -2451,28 +2428,28 @@ var Analysis = class {
2451
2428
  const rootPath = process.cwd();
2452
2429
  const paths = {};
2453
2430
  for (const modeStr of gameModes) {
2454
- const lut = path4.join(
2431
+ const lut = path3.join(
2455
2432
  rootPath,
2456
2433
  this.gameConfig.outputDir,
2457
2434
  `lookUpTable_${modeStr}.csv`
2458
2435
  );
2459
- const lutSegmented = path4.join(
2436
+ const lutSegmented = path3.join(
2460
2437
  rootPath,
2461
2438
  this.gameConfig.outputDir,
2462
2439
  `lookUpTableSegmented_${modeStr}.csv`
2463
2440
  );
2464
- const lutOptimized = path4.join(
2441
+ const lutOptimized = path3.join(
2465
2442
  rootPath,
2466
2443
  this.gameConfig.outputDir,
2467
2444
  "publish_files",
2468
2445
  `lookUpTable_${modeStr}_0.csv`
2469
2446
  );
2470
- const booksJsonl = path4.join(
2447
+ const booksJsonl = path3.join(
2471
2448
  rootPath,
2472
2449
  this.gameConfig.outputDir,
2473
2450
  `books_${modeStr}.jsonl`
2474
2451
  );
2475
- const booksJsonlCompressed = path4.join(
2452
+ const booksJsonlCompressed = path3.join(
2476
2453
  rootPath,
2477
2454
  this.gameConfig.outputDir,
2478
2455
  "publish_files",
@@ -2486,7 +2463,7 @@ var Analysis = class {
2486
2463
  booksJsonlCompressed
2487
2464
  };
2488
2465
  for (const p of Object.values(paths[modeStr])) {
2489
- assert3(
2466
+ assert4(
2490
2467
  fs4.existsSync(p),
2491
2468
  `File "${p}" does not exist. Run optimization to auto-create it.`
2492
2469
  );
@@ -2520,7 +2497,7 @@ var Analysis = class {
2520
2497
  });
2521
2498
  }
2522
2499
  writeJsonFile(
2523
- path4.join(process.cwd(), this.gameConfig.outputDir, "stats_summary.json"),
2500
+ path3.join(process.cwd(), this.gameConfig.outputDir, "stats_summary.json"),
2524
2501
  stats
2525
2502
  );
2526
2503
  }
@@ -2558,13 +2535,13 @@ var Analysis = class {
2558
2535
  }
2559
2536
  getGameModeConfig(mode) {
2560
2537
  const config = this.gameConfig.gameModes[mode];
2561
- assert3(config, `Game mode "${mode}" not found in game config`);
2538
+ assert4(config, `Game mode "${mode}" not found in game config`);
2562
2539
  return config;
2563
2540
  }
2564
2541
  };
2565
2542
 
2566
2543
  // src/utils/math-config.ts
2567
- import path5 from "path";
2544
+ import path4 from "path";
2568
2545
  function makeMathConfig(optimizer, opts = {}) {
2569
2546
  const game = optimizer.getGameConfig();
2570
2547
  const gameModesCfg = optimizer.getOptimizerGameModes();
@@ -2608,14 +2585,14 @@ function makeMathConfig(optimizer, opts = {}) {
2608
2585
  }))
2609
2586
  };
2610
2587
  if (writeToFile) {
2611
- const outPath = path5.join(process.cwd(), game.outputDir, "math_config.json");
2588
+ const outPath = path4.join(process.cwd(), game.outputDir, "math_config.json");
2612
2589
  writeJsonFile(outPath, config);
2613
2590
  }
2614
2591
  return config;
2615
2592
  }
2616
2593
 
2617
2594
  // src/utils/setup-file.ts
2618
- import path6 from "path";
2595
+ import path5 from "path";
2619
2596
  function makeSetupFile(optimizer, gameMode) {
2620
2597
  const gameConfig = optimizer.getGameConfig();
2621
2598
  const optimizerGameModes = optimizer.getOptimizerGameModes();
@@ -2651,19 +2628,19 @@ function makeSetupFile(optimizer, gameMode) {
2651
2628
  `;
2652
2629
  content += `simulation_trials;${params.simulationTrials}
2653
2630
  `;
2654
- content += `user_game_build_path;${path6.join(process.cwd(), gameConfig.outputDir)}
2631
+ content += `user_game_build_path;${path5.join(process.cwd(), gameConfig.outputDir)}
2655
2632
  `;
2656
2633
  content += `pmb_rtp;${params.pmbRtp}
2657
2634
  `;
2658
- const outPath = path6.join(__dirname, "./optimizer-rust/src", "setup.txt");
2635
+ const outPath = path5.join(__dirname, "./optimizer-rust/src", "setup.txt");
2659
2636
  writeFile(outPath, content);
2660
2637
  }
2661
2638
 
2662
2639
  // src/optimizer/index.ts
2663
- import { spawn as spawn2 } from "child_process";
2664
- import path7 from "path";
2665
- import assert4 from "assert";
2666
- import { isMainThread as isMainThread3 } from "worker_threads";
2640
+ import { spawn } from "child_process";
2641
+ import path6 from "path";
2642
+ import assert5 from "assert";
2643
+ import { isMainThread as isMainThread4 } from "worker_threads";
2667
2644
  var Optimizer = class {
2668
2645
  gameConfig;
2669
2646
  gameModes;
@@ -2676,12 +2653,13 @@ var Optimizer = class {
2676
2653
  * Runs the optimization process, and runs analysis after.
2677
2654
  */
2678
2655
  async runOptimization({ gameModes }) {
2679
- if (!isMainThread3) return;
2656
+ if (!isMainThread4) return;
2680
2657
  const mathConfig = makeMathConfig(this, { writeToFile: true });
2681
2658
  for (const mode of gameModes) {
2682
2659
  const setupFile = makeSetupFile(this, mode);
2683
2660
  await this.runSingleOptimization();
2684
2661
  }
2662
+ console.log("Optimization complete. Files written to build directory.");
2685
2663
  }
2686
2664
  async runSingleOptimization() {
2687
2665
  return await rustProgram();
@@ -2705,7 +2683,7 @@ var Optimizer = class {
2705
2683
  }
2706
2684
  }
2707
2685
  const criteria = configMode.resultSets.map((r) => r.criteria);
2708
- assert4(
2686
+ assert5(
2709
2687
  conditions.every((c) => criteria.includes(c)),
2710
2688
  `Not all ResultSet criteria in game mode "${k}" are defined as optimization conditions.`
2711
2689
  );
@@ -2717,7 +2695,7 @@ var Optimizer = class {
2717
2695
  }
2718
2696
  gameModeRtp = Math.round(gameModeRtp * 1e3) / 1e3;
2719
2697
  paramRtp = Math.round(paramRtp * 1e3) / 1e3;
2720
- assert4(
2698
+ assert5(
2721
2699
  gameModeRtp === paramRtp,
2722
2700
  `Sum of all RTP conditions (${paramRtp}) does not match the game mode RTP (${gameModeRtp}) in game mode "${k}".`
2723
2701
  );
@@ -2732,9 +2710,9 @@ var Optimizer = class {
2732
2710
  };
2733
2711
  async function rustProgram(...args) {
2734
2712
  return new Promise((resolve, reject) => {
2735
- const task = spawn2("cargo", ["run", "--release", ...args], {
2713
+ const task = spawn("cargo", ["run", "--release", ...args], {
2736
2714
  shell: true,
2737
- cwd: path7.join(__dirname, "./optimizer-rust"),
2715
+ cwd: path6.join(__dirname, "./optimizer-rust"),
2738
2716
  stdio: "pipe"
2739
2717
  });
2740
2718
  task.on("error", (error) => {
@@ -2825,7 +2803,7 @@ var SlotGame = class {
2825
2803
  console.log("No tasks to run. Enable either simulation, optimization or analysis.");
2826
2804
  }
2827
2805
  if (opts.doSimulation) {
2828
- await this.runSimulation({ debug: opts.debug });
2806
+ await this.runSimulation(opts.simulationOpts || {});
2829
2807
  }
2830
2808
  if (opts.doOptimization) {
2831
2809
  await this.runOptimization(opts.optimizationOpts || { gameModes: [] });