@omnitronix/happy-panda-game-engine 0.0.1

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 (71) hide show
  1. package/README.md +212 -0
  2. package/dist/__tests__/bonus-sequence.test.js +337 -0
  3. package/dist/__tests__/bonus-sequence.test.js.map +1 -0
  4. package/dist/__tests__/cherry-frequency.test.js +128 -0
  5. package/dist/__tests__/cherry-frequency.test.js.map +1 -0
  6. package/dist/__tests__/counter-manager.test.js +316 -0
  7. package/dist/__tests__/counter-manager.test.js.map +1 -0
  8. package/dist/__tests__/cpp-parity.test.js +368 -0
  9. package/dist/__tests__/cpp-parity.test.js.map +1 -0
  10. package/dist/__tests__/fixtures/cpp-parity-vectors.json +438 -0
  11. package/dist/__tests__/happy-panda-engine.test.js +367 -0
  12. package/dist/__tests__/happy-panda-engine.test.js.map +1 -0
  13. package/dist/__tests__/jackpot-manager.test.js +313 -0
  14. package/dist/__tests__/jackpot-manager.test.js.map +1 -0
  15. package/dist/__tests__/jackpot-trigger-trace.test.js +146 -0
  16. package/dist/__tests__/jackpot-trigger-trace.test.js.map +1 -0
  17. package/dist/__tests__/rtp-1million.test.js +156 -0
  18. package/dist/__tests__/rtp-1million.test.js.map +1 -0
  19. package/dist/__tests__/rtp-analysis.test.js +138 -0
  20. package/dist/__tests__/rtp-analysis.test.js.map +1 -0
  21. package/dist/__tests__/rtp-diagnostic.test.js +126 -0
  22. package/dist/__tests__/rtp-diagnostic.test.js.map +1 -0
  23. package/dist/__tests__/rtp-simulation.test.js +409 -0
  24. package/dist/__tests__/rtp-simulation.test.js.map +1 -0
  25. package/dist/__tests__/special-wins.test.js +179 -0
  26. package/dist/__tests__/special-wins.test.js.map +1 -0
  27. package/dist/__tests__/spin-generator.test.js +250 -0
  28. package/dist/__tests__/spin-generator.test.js.map +1 -0
  29. package/dist/__tests__/spin-handler.test.js +210 -0
  30. package/dist/__tests__/spin-handler.test.js.map +1 -0
  31. package/dist/__tests__/symbol-distribution.test.js +119 -0
  32. package/dist/__tests__/symbol-distribution.test.js.map +1 -0
  33. package/dist/__tests__/weighted-random.test.js +165 -0
  34. package/dist/__tests__/weighted-random.test.js.map +1 -0
  35. package/dist/__tests__/win-evaluator.test.js +254 -0
  36. package/dist/__tests__/win-evaluator.test.js.map +1 -0
  37. package/dist/config/happy-panda.config.js +714 -0
  38. package/dist/config/happy-panda.config.js.map +1 -0
  39. package/dist/config/index.js +21 -0
  40. package/dist/config/index.js.map +1 -0
  41. package/dist/domain/index.js +21 -0
  42. package/dist/domain/index.js.map +1 -0
  43. package/dist/domain/types.js +28 -0
  44. package/dist/domain/types.js.map +1 -0
  45. package/dist/engine/happy-panda-engine.js +197 -0
  46. package/dist/engine/happy-panda-engine.js.map +1 -0
  47. package/dist/engine/index.js +21 -0
  48. package/dist/engine/index.js.map +1 -0
  49. package/dist/index.js +34 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/logic/handlers/index.js +21 -0
  52. package/dist/logic/handlers/index.js.map +1 -0
  53. package/dist/logic/handlers/spin-handler.js +256 -0
  54. package/dist/logic/handlers/spin-handler.js.map +1 -0
  55. package/dist/logic/index.js +22 -0
  56. package/dist/logic/index.js.map +1 -0
  57. package/dist/logic/services/counter-manager.js +265 -0
  58. package/dist/logic/services/counter-manager.js.map +1 -0
  59. package/dist/logic/services/index.js +23 -0
  60. package/dist/logic/services/index.js.map +1 -0
  61. package/dist/logic/services/jackpot-manager.js +142 -0
  62. package/dist/logic/services/jackpot-manager.js.map +1 -0
  63. package/dist/logic/services/win-evaluator.js +470 -0
  64. package/dist/logic/services/win-evaluator.js.map +1 -0
  65. package/dist/rng/index.js +22 -0
  66. package/dist/rng/index.js.map +1 -0
  67. package/dist/rng/spin-generator.js +341 -0
  68. package/dist/rng/spin-generator.js.map +1 -0
  69. package/dist/rng/weighted-random.js +58 -0
  70. package/dist/rng/weighted-random.js.map +1 -0
  71. package/package.json +49 -0
@@ -0,0 +1,341 @@
1
+ "use strict";
2
+ /**
3
+ * Spin Generator with Symbol Limitation System
4
+ *
5
+ * Generates 3x3 grids with weighted symbol distribution and limitation constraints.
6
+ * Each symbol type has a randomly selected maximum count (2, 4, 7, or 9).
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.generateGrid = generateGrid;
10
+ exports.generateCherryPieceGrid = generateCherryPieceGrid;
11
+ exports.isCompleteCherryPiece = isCompleteCherryPiece;
12
+ const happy_panda_config_1 = require("../config/happy-panda.config");
13
+ const weighted_random_1 = require("./weighted-random");
14
+ /** Get configuration for a spin type */
15
+ function getSpinConfig(spinType) {
16
+ switch (spinType) {
17
+ case happy_panda_config_1.SpinType.PAID_SPIN:
18
+ return {
19
+ symbols: happy_panda_config_1.PAID_SPIN_SYMBOLS,
20
+ weights: happy_panda_config_1.PAID_SPIN_WEIGHTS,
21
+ limitationWeights: happy_panda_config_1.PAID_SPIN_LIMITATION_WEIGHTS,
22
+ has3x3: true,
23
+ weights3x3: happy_panda_config_1.PAID_SPIN_3X3_WEIGHTS,
24
+ symbolWeights3x3: happy_panda_config_1.PAID_SPIN_3X3_SYMBOL_WEIGHTS,
25
+ };
26
+ case happy_panda_config_1.SpinType.BONUS_JACKPOT:
27
+ return {
28
+ symbols: happy_panda_config_1.JACKPOT_BONUS_SYMBOLS,
29
+ weights: happy_panda_config_1.JACKPOT_BONUS_WEIGHTS,
30
+ limitationWeights: happy_panda_config_1.JACKPOT_BONUS_LIMITATION_WEIGHTS,
31
+ has3x3: true,
32
+ weights3x3: happy_panda_config_1.JACKPOT_BONUS_3X3_WEIGHTS,
33
+ symbolWeights3x3: happy_panda_config_1.JACKPOT_BONUS_3X3_SYMBOL_WEIGHTS,
34
+ };
35
+ case happy_panda_config_1.SpinType.BONUS_CHERRY:
36
+ return {
37
+ symbols: happy_panda_config_1.CHERRY_BONUS_SYMBOLS,
38
+ weights: happy_panda_config_1.CHERRY_BONUS_WEIGHTS,
39
+ limitationWeights: happy_panda_config_1.CHERRY_BONUS_LIMITATION_WEIGHTS,
40
+ has3x3: true,
41
+ weights3x3: happy_panda_config_1.CHERRY_BONUS_3X3_WEIGHTS,
42
+ symbolWeights3x3: happy_panda_config_1.CHERRY_BONUS_3X3_SYMBOL_WEIGHTS,
43
+ };
44
+ case happy_panda_config_1.SpinType.BONUS_BELL:
45
+ return {
46
+ symbols: happy_panda_config_1.BELL_BONUS_SYMBOLS,
47
+ weights: happy_panda_config_1.BELL_BONUS_WEIGHTS,
48
+ limitationWeights: happy_panda_config_1.BELL_BONUS_LIMITATION_WEIGHTS,
49
+ has3x3: true,
50
+ weights3x3: happy_panda_config_1.BELL_BONUS_3X3_WEIGHTS,
51
+ symbolWeights3x3: happy_panda_config_1.BELL_BONUS_3X3_SYMBOL_WEIGHTS,
52
+ };
53
+ case happy_panda_config_1.SpinType.BONUS_BAR1:
54
+ return {
55
+ symbols: happy_panda_config_1.BAR1_BONUS_SYMBOLS,
56
+ weights: happy_panda_config_1.BAR1_BONUS_WEIGHTS,
57
+ limitationWeights: happy_panda_config_1.BAR1_BONUS_LIMITATION_WEIGHTS,
58
+ has3x3: true,
59
+ weights3x3: happy_panda_config_1.BAR1_BONUS_3X3_WEIGHTS,
60
+ symbolWeights3x3: happy_panda_config_1.BAR1_BONUS_3X3_SYMBOL_WEIGHTS,
61
+ };
62
+ case happy_panda_config_1.SpinType.RESPIN_CHERRY:
63
+ return {
64
+ symbols: happy_panda_config_1.RESPIN_CHERRY_SYMBOLS,
65
+ weights: happy_panda_config_1.RESPIN_CHERRY_WEIGHTS,
66
+ limitationWeights: happy_panda_config_1.RESPIN_CHERRY_LIMITATION_WEIGHTS,
67
+ has3x3: false, // No 3x3 override for respin
68
+ };
69
+ default:
70
+ throw new Error(`Unknown spin type: ${spinType}`);
71
+ }
72
+ }
73
+ /** Convert position index (0-8) to [reel, row] */
74
+ function positionToCoords(posIdx) {
75
+ const reel = Math.floor(posIdx / happy_panda_config_1.GRID.ROWS);
76
+ const row = posIdx % happy_panda_config_1.GRID.ROWS;
77
+ return [reel, row];
78
+ }
79
+ /**
80
+ * Select limitation tiers for all symbols.
81
+ * @param config Spin configuration
82
+ * @param gameDirection Game direction (0 = 8 lines, 1 = 16 lines)
83
+ * @param rng RNG provider
84
+ * @returns Map of symbol index to maximum count
85
+ */
86
+ async function selectLimitationTiers(config, gameDirection, rng) {
87
+ const limitations = new Map();
88
+ for (let symbolIdx = 0; symbolIdx < config.symbols.length; symbolIdx++) {
89
+ const weights = config.limitationWeights[gameDirection][symbolIdx];
90
+ // Skip if all weights are zero (symbol has no limitation)
91
+ const totalWeight = weights.reduce((sum, w) => sum + w, 0);
92
+ if (totalWeight === 0) {
93
+ limitations.set(symbolIdx, happy_panda_config_1.GRID.POSITIONS); // No limit
94
+ continue;
95
+ }
96
+ const tierIdx = await (0, weighted_random_1.selectWeightedIndex)(weights, rng);
97
+ limitations.set(symbolIdx, happy_panda_config_1.LIMITATION_TIERS[tierIdx]);
98
+ }
99
+ return limitations;
100
+ }
101
+ /**
102
+ * Generate a grid with weighted symbols and limitation constraints.
103
+ *
104
+ * IMPORTANT: C++ logic requires limitations to be selected FIRST, then
105
+ * 3x3 check only happens if a symbol has limit=9 (max symbols).
106
+ *
107
+ * @param spinType Type of spin
108
+ * @param gameDirection Game direction
109
+ * @param rng RNG provider
110
+ * @param centerSymbol Optional fixed center symbol (for respin)
111
+ * @returns Generated 3x3 grid
112
+ */
113
+ async function generateGrid(spinType, gameDirection, rng, centerSymbol) {
114
+ const config = getSpinConfig(spinType);
115
+ // Step 1: Select limitation tiers for each symbol FIRST (C++ order!)
116
+ const limitations = await selectLimitationTiers(config, gameDirection, rng);
117
+ // Step 2: Check for matrix win - C++ EXACT LOGIC
118
+ // Gate: ONLY SEV_S (idx 0) or SEV (idx 1) having limit=9 triggers the check
119
+ let matrixSymbol = null;
120
+ let matrixCount = 0;
121
+ if (config.has3x3 && config.weights3x3 && config.symbolWeights3x3) {
122
+ const sevSLimit = limitations.get(0) || 0; // SEV_S
123
+ const sevLimit = limitations.get(1) || 0; // SEV
124
+ // C++ line 69: if((maxLimits[SEV_S] == 9) || (maxLimits[SEV] == 9))
125
+ if (sevSLimit === 9 || sevLimit === 9) {
126
+ // Gate passed - now check PaidSpins3x3 weights
127
+ const [yesWeight, noWeight] = config.weights3x3[gameDirection];
128
+ const shouldMatrix = await (0, weighted_random_1.weightedBoolean)(yesWeight, noWeight, rng);
129
+ if (shouldMatrix) {
130
+ // Determine matrix count (7, 8, or 9) based on which has limit=9
131
+ // C++ lines 86-88
132
+ if (sevSLimit === 9 && sevLimit === 9) {
133
+ matrixCount = 9; // Full 3x3
134
+ }
135
+ else if (sevSLimit === 9 && sevLimit !== 9) {
136
+ matrixCount = 8; // 8 symbols
137
+ }
138
+ else if (sevSLimit !== 9 && sevLimit === 9) {
139
+ matrixCount = 7; // 7 symbols
140
+ }
141
+ // Select which symbol for the matrix from PaidSpins3x3_symbol weights
142
+ // C++ lines 91-100: ALL symbols are eligible, not just those with limit=9
143
+ const symbolIdx = await (0, weighted_random_1.selectWeightedIndex)(config.symbolWeights3x3, rng);
144
+ matrixSymbol = config.symbols[symbolIdx];
145
+ }
146
+ }
147
+ }
148
+ // If matrix win, generate grid with matrixCount of that symbol
149
+ if (matrixSymbol !== null && matrixCount > 0) {
150
+ return createMatrixGrid(matrixSymbol, matrixCount, config, gameDirection, rng, limitations);
151
+ }
152
+ // Step 3: Generate symbols position by position (using pre-selected limitations)
153
+ const grid = [
154
+ [happy_panda_config_1.Symbol.NONE, happy_panda_config_1.Symbol.NONE, happy_panda_config_1.Symbol.NONE],
155
+ [happy_panda_config_1.Symbol.NONE, happy_panda_config_1.Symbol.NONE, happy_panda_config_1.Symbol.NONE],
156
+ [happy_panda_config_1.Symbol.NONE, happy_panda_config_1.Symbol.NONE, happy_panda_config_1.Symbol.NONE],
157
+ ];
158
+ // Track symbol counts
159
+ const symbolCounts = new Map();
160
+ for (let i = 0; i < config.symbols.length; i++) {
161
+ symbolCounts.set(i, 0);
162
+ }
163
+ // CRITICAL: For RESPIN_CHERRY, pre-count the center symbol BEFORE generating other positions
164
+ // This ensures the limitation system correctly restricts cherries across ALL positions
165
+ // Without this, positions 0-3 (generated before center at position 4) ignore the center cherry
166
+ if (centerSymbol !== undefined) {
167
+ grid[1][1] = centerSymbol;
168
+ const centerIdx = config.symbols.indexOf(centerSymbol);
169
+ if (centerIdx >= 0) {
170
+ symbolCounts.set(centerIdx, 1);
171
+ }
172
+ }
173
+ // Generate each position
174
+ for (let posIdx = 0; posIdx < happy_panda_config_1.GRID.POSITIONS; posIdx++) {
175
+ const [reel, row] = positionToCoords(posIdx);
176
+ // Skip center position - already placed above for RESPIN_CHERRY
177
+ if (reel === 1 && row === 1 && centerSymbol !== undefined) {
178
+ continue;
179
+ }
180
+ // Get base weights for this position
181
+ const baseWeights = [...config.weights[gameDirection][posIdx]];
182
+ // C++ BEHAVIOR: During RESPIN_CHERRY, only corners are regenerated.
183
+ // Non-corner positions (center row AND column edges) are preserved from paid_spin.
184
+ // Since paid_spin had only 1 cherry at center, these preserved positions are NOT cherry.
185
+ // Preserved positions: (0,1), (1,0), (1,2), (2,1) - all edges touching center
186
+ const isRespin = centerSymbol !== undefined;
187
+ const isCenterRowEdge = row === 1 && reel !== 1; // (0,1), (2,1)
188
+ const isCenterColEdge = reel === 1 && row !== 1; // (1,0), (1,2)
189
+ if (isRespin && isCenterRowEdge) {
190
+ // Center row edges fully suppressed (line 1 can never form 3x cherry)
191
+ if (baseWeights.length > 9)
192
+ baseWeights[9] = 0;
193
+ if (baseWeights.length > 10)
194
+ baseWeights[10] = 0;
195
+ }
196
+ else if (isRespin && isCenterColEdge) {
197
+ // Center column edges: reduce superCherry only (from 4 to 3)
198
+ // Cherry weight=1 stays unchanged (0.92*1 floors to 0, too aggressive)
199
+ // This provides a smaller RTP reduction than zeroing both
200
+ if (baseWeights.length > 10)
201
+ baseWeights[10] = Math.max(0, baseWeights[10] - 1);
202
+ }
203
+ // Apply limitation constraints
204
+ for (let symbolIdx = 0; symbolIdx < config.symbols.length; symbolIdx++) {
205
+ const currentCount = symbolCounts.get(symbolIdx) || 0;
206
+ const maxCount = limitations.get(symbolIdx) || happy_panda_config_1.GRID.POSITIONS;
207
+ if (currentCount >= maxCount) {
208
+ baseWeights[symbolIdx] = 0; // Disable this symbol
209
+ }
210
+ }
211
+ // Select symbol
212
+ const totalWeight = baseWeights.reduce((sum, w) => sum + w, 0);
213
+ if (totalWeight === 0) {
214
+ // Fallback: all symbols limited, pick any available
215
+ for (let symbolIdx = 0; symbolIdx < config.symbols.length; symbolIdx++) {
216
+ const currentCount = symbolCounts.get(symbolIdx) || 0;
217
+ const maxCount = limitations.get(symbolIdx) || happy_panda_config_1.GRID.POSITIONS;
218
+ if (currentCount < maxCount) {
219
+ // C++ line 1956-1957: Cherry pieces are POSITION-SPECIFIC
220
+ // main_screen[reel][row] = CH_00 + reel*3 + row;
221
+ const baseSymbol = config.symbols[symbolIdx];
222
+ if (baseSymbol === happy_panda_config_1.Symbol.CHERRY_00) {
223
+ grid[reel][row] = happy_panda_config_1.Symbol.CHERRY_00 + reel * 3 + row;
224
+ }
225
+ else {
226
+ grid[reel][row] = baseSymbol;
227
+ }
228
+ symbolCounts.set(symbolIdx, currentCount + 1);
229
+ break;
230
+ }
231
+ }
232
+ }
233
+ else {
234
+ const symbolIdx = await (0, weighted_random_1.selectWeightedIndex)(baseWeights, rng);
235
+ // C++ line 1956-1957: Cherry pieces are POSITION-SPECIFIC
236
+ // main_screen[reel][row] = CH_00 + reel*3 + row;
237
+ const baseSymbol = config.symbols[symbolIdx];
238
+ if (baseSymbol === happy_panda_config_1.Symbol.CHERRY_00) {
239
+ grid[reel][row] = happy_panda_config_1.Symbol.CHERRY_00 + reel * 3 + row;
240
+ }
241
+ else {
242
+ grid[reel][row] = baseSymbol;
243
+ }
244
+ symbolCounts.set(symbolIdx, (symbolCounts.get(symbolIdx) || 0) + 1);
245
+ }
246
+ }
247
+ return grid;
248
+ }
249
+ /**
250
+ * Create a grid filled with a single symbol (for full 3x3 wins).
251
+ * C++ line 1956-1957: Cherry pieces are POSITION-SPECIFIC.
252
+ */
253
+ function createFilledGrid(symbol) {
254
+ // Cherry pieces need position-specific symbols
255
+ if (symbol === happy_panda_config_1.Symbol.CHERRY_00) {
256
+ return [
257
+ [happy_panda_config_1.Symbol.CHERRY_00, happy_panda_config_1.Symbol.CHERRY_01, happy_panda_config_1.Symbol.CHERRY_02],
258
+ [happy_panda_config_1.Symbol.CHERRY_10, happy_panda_config_1.Symbol.CHERRY_11, happy_panda_config_1.Symbol.CHERRY_12],
259
+ [happy_panda_config_1.Symbol.CHERRY_20, happy_panda_config_1.Symbol.CHERRY_21, happy_panda_config_1.Symbol.CHERRY_22],
260
+ ];
261
+ }
262
+ return [
263
+ [symbol, symbol, symbol],
264
+ [symbol, symbol, symbol],
265
+ [symbol, symbol, symbol],
266
+ ];
267
+ }
268
+ /**
269
+ * Create a matrix grid with 7, 8, or 9 of the same symbol.
270
+ * C++ lines 103-118: When matrix < 9, other positions get a filler symbol.
271
+ * C++ line 1956-1957: Cherry pieces are POSITION-SPECIFIC.
272
+ */
273
+ async function createMatrixGrid(matrixSymbol, matrixCount, config, gameDirection, rng, limitations) {
274
+ // Full 3x3
275
+ if (matrixCount === 9) {
276
+ return createFilledGrid(matrixSymbol);
277
+ }
278
+ // For 7 or 8, we need to fill some positions with a different symbol
279
+ // C++ uses idx=4 (or 3 if matrixSymbol is 4) as the filler
280
+ const matrixSymbolIdx = config.symbols.indexOf(matrixSymbol);
281
+ let fillerIdx = 4; // BA1 in most configs
282
+ if (fillerIdx === matrixSymbolIdx) {
283
+ fillerIdx = 3; // BA2 if matrixSymbol is BA1
284
+ }
285
+ const fillerSymbol = config.symbols[fillerIdx] || config.symbols[0];
286
+ // Create grid - fill with matrix symbol first (position-specific for cherry)
287
+ const isCherryMatrix = matrixSymbol === happy_panda_config_1.Symbol.CHERRY_00;
288
+ const grid = isCherryMatrix
289
+ ? [
290
+ [happy_panda_config_1.Symbol.CHERRY_00, happy_panda_config_1.Symbol.CHERRY_01, happy_panda_config_1.Symbol.CHERRY_02],
291
+ [happy_panda_config_1.Symbol.CHERRY_10, happy_panda_config_1.Symbol.CHERRY_11, happy_panda_config_1.Symbol.CHERRY_12],
292
+ [happy_panda_config_1.Symbol.CHERRY_20, happy_panda_config_1.Symbol.CHERRY_21, happy_panda_config_1.Symbol.CHERRY_22],
293
+ ]
294
+ : [
295
+ [matrixSymbol, matrixSymbol, matrixSymbol],
296
+ [matrixSymbol, matrixSymbol, matrixSymbol],
297
+ [matrixSymbol, matrixSymbol, matrixSymbol],
298
+ ];
299
+ // Replace (9 - matrixCount) positions with filler
300
+ const positionsToReplace = 9 - matrixCount;
301
+ const positions = [0, 1, 2, 3, 4, 5, 6, 7, 8];
302
+ // Randomly select positions to replace
303
+ for (let i = 0; i < positionsToReplace; i++) {
304
+ const randIdx = await rng.random(positions.length);
305
+ const pos = positions.splice(randIdx, 1)[0];
306
+ const [reel, row] = positionToCoords(pos);
307
+ grid[reel][row] = fillerSymbol;
308
+ }
309
+ return grid;
310
+ }
311
+ /**
312
+ * Generate cherry piece grid for jackpot bonus.
313
+ * Each position gets the appropriate piece symbol.
314
+ */
315
+ function generateCherryPieceGrid() {
316
+ return [
317
+ [happy_panda_config_1.Symbol.CHERRY_00, happy_panda_config_1.Symbol.CHERRY_01, happy_panda_config_1.Symbol.CHERRY_02],
318
+ [happy_panda_config_1.Symbol.CHERRY_10, happy_panda_config_1.Symbol.CHERRY_11, happy_panda_config_1.Symbol.CHERRY_12],
319
+ [happy_panda_config_1.Symbol.CHERRY_20, happy_panda_config_1.Symbol.CHERRY_21, happy_panda_config_1.Symbol.CHERRY_22],
320
+ ];
321
+ }
322
+ /**
323
+ * Check if grid is a complete cherry piece (jackpot).
324
+ */
325
+ function isCompleteCherryPiece(grid) {
326
+ const cherryPieces = [
327
+ happy_panda_config_1.Symbol.CHERRY_00, happy_panda_config_1.Symbol.CHERRY_01, happy_panda_config_1.Symbol.CHERRY_02,
328
+ happy_panda_config_1.Symbol.CHERRY_10, happy_panda_config_1.Symbol.CHERRY_11, happy_panda_config_1.Symbol.CHERRY_12,
329
+ happy_panda_config_1.Symbol.CHERRY_20, happy_panda_config_1.Symbol.CHERRY_21, happy_panda_config_1.Symbol.CHERRY_22,
330
+ ];
331
+ let foundPieces = 0;
332
+ for (let reel = 0; reel < happy_panda_config_1.GRID.REELS; reel++) {
333
+ for (let row = 0; row < happy_panda_config_1.GRID.ROWS; row++) {
334
+ if (cherryPieces.includes(grid[reel][row])) {
335
+ foundPieces++;
336
+ }
337
+ }
338
+ }
339
+ return foundPieces === 9;
340
+ }
341
+ //# sourceMappingURL=spin-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spin-generator.js","sourceRoot":"","sources":["../../src/rng/spin-generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ /**
3
+ * Weighted Random Selection Utilities
4
+ *
5
+ * Helper functions for weighted random selection using the RNG provider.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.selectWeightedIndex = selectWeightedIndex;
9
+ exports.weightedBoolean = weightedBoolean;
10
+ exports.selectMultipleWeighted = selectMultipleWeighted;
11
+ /**
12
+ * Select an index from an array of weights.
13
+ * @param weights Array of weights (must be positive integers)
14
+ * @param rng RNG provider
15
+ * @returns Selected index
16
+ */
17
+ async function selectWeightedIndex(weights, rng) {
18
+ const totalWeight = weights.reduce((sum, w) => sum + w, 0);
19
+ if (totalWeight === 0) {
20
+ throw new Error('All weights are zero');
21
+ }
22
+ const roll = await rng.random(totalWeight);
23
+ let cumulative = 0;
24
+ for (let i = 0; i < weights.length; i++) {
25
+ cumulative += weights[i];
26
+ if (roll < cumulative) {
27
+ return i;
28
+ }
29
+ }
30
+ // Fallback (shouldn't happen with valid weights)
31
+ return weights.length - 1;
32
+ }
33
+ /**
34
+ * Check if a weighted random selection succeeds.
35
+ * @param yesWeight Weight for "yes" outcome
36
+ * @param noWeight Weight for "no" outcome
37
+ * @param rng RNG provider
38
+ * @returns true if "yes" was selected
39
+ */
40
+ async function weightedBoolean(yesWeight, noWeight, rng) {
41
+ const index = await selectWeightedIndex([yesWeight, noWeight], rng);
42
+ return index === 0;
43
+ }
44
+ /**
45
+ * Select multiple weighted indices (with replacement).
46
+ * @param weights Array of weights
47
+ * @param count Number of selections
48
+ * @param rng RNG provider
49
+ * @returns Array of selected indices
50
+ */
51
+ async function selectMultipleWeighted(weights, count, rng) {
52
+ const results = [];
53
+ for (let i = 0; i < count; i++) {
54
+ results.push(await selectWeightedIndex(weights, rng));
55
+ }
56
+ return results;
57
+ }
58
+ //# sourceMappingURL=weighted-random.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weighted-random.js","sourceRoot":"","sources":["../../src/rng/weighted-random.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAUH,kDAqBC;AASD,0CAOC;AASD,wDAUC;AA9DD;;;;;GAKG;AACI,KAAK,UAAU,mBAAmB,CACvC,OAA0B,EAC1B,GAAgB;IAEhB,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3D,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC3C,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,UAAU,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,IAAI,GAAG,UAAU,EAAE,CAAC;YACtB,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IAED,iDAAiD;IACjD,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,eAAe,CACnC,SAAiB,EACjB,QAAgB,EAChB,GAAgB;IAEhB,MAAM,KAAK,GAAG,MAAM,mBAAmB,CAAC,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,GAAG,CAAC,CAAC;IACpE,OAAO,KAAK,KAAK,CAAC,CAAC;AACrB,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,sBAAsB,CAC1C,OAA0B,EAC1B,KAAa,EACb,GAAgB;IAEhB,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,MAAM,mBAAmB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@omnitronix/happy-panda-game-engine",
3
+ "version": "0.0.1",
4
+ "description": "Happy Panda Game Engine",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc && copyfiles -u 1 'src/**/*.csv' dist/",
9
+ "dev": "tsc --watch",
10
+ "clean": "rm -rf dist",
11
+ "lint": "eslint src/**/*.ts",
12
+ "lint:fix": "eslint src/**/*.ts --fix",
13
+ "test": "cross-env RNG_CLIENT_MODE=local npm run build && jest",
14
+ "test:watch": "jest --watch",
15
+ "test:coverage": "jest --coverage",
16
+ "prepublishOnly": "npm run clean && npm run build"
17
+ },
18
+ "author": "Omnitronix",
19
+ "license": "UNLICENSED",
20
+ "dependencies": {
21
+ "@omnitronix/rng-client-core": "^1.0.9",
22
+ "class-transformer": "^0.5.1",
23
+ "class-validator": "^0.14.1",
24
+ "reflect-metadata": "^0.1.13",
25
+ "uuid": "^9.0.0",
26
+ "winston": "^3.17.0"
27
+ },
28
+ "devDependencies": {
29
+ "@types/jest": "^29.5.0",
30
+ "@types/node": "^20.0.0",
31
+ "@types/uuid": "^9.0.0",
32
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
33
+ "@typescript-eslint/parser": "^6.0.0",
34
+ "copyfiles": "^2.4.1",
35
+ "cross-env": "^10.1.0",
36
+ "eslint": "^8.0.0",
37
+ "jest": "^29.5.0",
38
+ "nodemon": "^3.0.0",
39
+ "ts-jest": "^29.1.0",
40
+ "typescript": "^5.0.0"
41
+ },
42
+ "files": [
43
+ "dist/**/*",
44
+ "README.md"
45
+ ],
46
+ "publishConfig": {
47
+ "registry": "https://registry.npmjs.org/"
48
+ }
49
+ }