@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,256 @@
1
+ "use strict";
2
+ /**
3
+ * Spin Handler
4
+ *
5
+ * Coordinates the entire spin flow:
6
+ * 1. Determine spin type
7
+ * 2. Generate grid
8
+ * 3. Evaluate wins
9
+ * 4. Update counters
10
+ * 5. Update jackpots
11
+ * 6. Determine next spin type
12
+ * 7. Build response
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.MAX_BET_STAKE = exports.MIN_BET_STAKE = void 0;
16
+ exports.executeSpin = executeSpin;
17
+ exports.validateBetParams = validateBetParams;
18
+ exports.createInitialState = createInitialState;
19
+ exports.updateBet = updateBet;
20
+ const happy_panda_config_1 = require("../../config/happy-panda.config");
21
+ const types_1 = require("../../domain/types");
22
+ const spin_generator_1 = require("../../rng/spin-generator");
23
+ const win_evaluator_1 = require("../services/win-evaluator");
24
+ const counter_manager_1 = require("../services/counter-manager");
25
+ const jackpot_manager_1 = require("../services/jackpot-manager");
26
+ // =============================================================================
27
+ // SPIN TYPE TO BONUS TYPE MAPPING
28
+ // =============================================================================
29
+ function bonusTypeToSpinType(bonusType) {
30
+ switch (bonusType) {
31
+ case 'jackpot': return happy_panda_config_1.SpinType.BONUS_JACKPOT;
32
+ case 'cherry': return happy_panda_config_1.SpinType.BONUS_CHERRY;
33
+ case 'bell': return happy_panda_config_1.SpinType.BONUS_BELL;
34
+ case 'bar1': return happy_panda_config_1.SpinType.BONUS_BAR1;
35
+ case 'respin': return happy_panda_config_1.SpinType.RESPIN_CHERRY;
36
+ default: return happy_panda_config_1.SpinType.PAID_SPIN;
37
+ }
38
+ }
39
+ // =============================================================================
40
+ // MAIN SPIN EXECUTION
41
+ // =============================================================================
42
+ /**
43
+ * Execute a single spin.
44
+ */
45
+ async function executeSpin(state, rng) {
46
+ const { gameDirection, betStake, betGame, currentSpinType, spinsRemaining, counters, pendingBonuses, jackpots, centerCherrySymbol, } = state;
47
+ // Step 1: Generate grid based on spin type
48
+ const grid = await (0, spin_generator_1.generateGrid)(currentSpinType, gameDirection, rng, currentSpinType === happy_panda_config_1.SpinType.RESPIN_CHERRY ? centerCherrySymbol ?? undefined : undefined);
49
+ // Step 2: Evaluate wins
50
+ const wins = (0, win_evaluator_1.evaluateSpin)(grid, gameDirection, betStake, betGame, currentSpinType);
51
+ // Step 3: Handle special jackpot bonus logic
52
+ let jackpotWon = 0;
53
+ let poolJackpotWon = 0;
54
+ let updatedJackpots = { ...jackpots };
55
+ if (currentSpinType === happy_panda_config_1.SpinType.BONUS_JACKPOT) {
56
+ // Every jackpot bonus spin gets the ADD_WIN bonus (C++ Main Logic line 59)
57
+ // "please note scenario: each screen gets such winning, independent on pieces cherry wins"
58
+ jackpotWon = happy_panda_config_1.BONUS_JACKPOT.ADD_WIN * betGame;
59
+ // Full cherry piece = ALSO triggers progressive jackpot payout
60
+ if ((0, spin_generator_1.isCompleteCherryPiece)(grid)) {
61
+ const { payout, newValue } = (0, jackpot_manager_1.payProgressiveJackpot)(jackpots.bonusJackpotValue, betGame);
62
+ jackpotWon += payout;
63
+ updatedJackpots.bonusJackpotValue = newValue;
64
+ }
65
+ }
66
+ // Step 4: Update counters (only on paid spin and respin)
67
+ let updatedCounters = { ...counters };
68
+ let updatedPending = { ...pendingBonuses };
69
+ let bonusTriggered = null;
70
+ if (currentSpinType === happy_panda_config_1.SpinType.PAID_SPIN || currentSpinType === happy_panda_config_1.SpinType.RESPIN_CHERRY) {
71
+ const counterResult = await (0, counter_manager_1.updateCounters)(counters, pendingBonuses, wins.lineWins, grid, gameDirection, currentSpinType, wins.totalPayout, rng);
72
+ updatedCounters = counterResult.counters;
73
+ updatedPending = counterResult.pendingBonuses;
74
+ // Determine triggered bonus (for animation/display)
75
+ if (counterResult.triggeredJackpot) {
76
+ bonusTriggered = happy_panda_config_1.SpinType.BONUS_JACKPOT;
77
+ }
78
+ else if (counterResult.triggeredCherry) {
79
+ bonusTriggered = happy_panda_config_1.SpinType.BONUS_CHERRY;
80
+ }
81
+ else if (counterResult.triggeredBell) {
82
+ bonusTriggered = happy_panda_config_1.SpinType.BONUS_BELL;
83
+ // Bell bonus also pays pool jackpot
84
+ const poolResult = (0, jackpot_manager_1.payPoolJackpot)(jackpots.poolJackpotValue, betGame);
85
+ poolJackpotWon = poolResult.payout;
86
+ updatedJackpots.poolJackpotValue = poolResult.newValue;
87
+ }
88
+ else if (counterResult.triggeredBar1) {
89
+ bonusTriggered = happy_panda_config_1.SpinType.BONUS_BAR1;
90
+ }
91
+ else if (counterResult.triggeredRespin > 0) {
92
+ bonusTriggered = happy_panda_config_1.SpinType.RESPIN_CHERRY;
93
+ }
94
+ }
95
+ // Step 5: Update jackpots (progressive and pool on paid spins)
96
+ if (currentSpinType === happy_panda_config_1.SpinType.PAID_SPIN) {
97
+ const jackpotUpdate = await (0, jackpot_manager_1.updateJackpots)(updatedJackpots, grid, gameDirection, betGame, betStake, currentSpinType, wins.totalPayout, rng);
98
+ updatedJackpots = jackpotUpdate.jackpots;
99
+ }
100
+ // Step 6: Determine next spin type and remaining spins
101
+ let nextSpinType = happy_panda_config_1.SpinType.PAID_SPIN;
102
+ let nextSpinsRemaining = 0;
103
+ let newAccumulatedBonusWins = state.accumulatedBonusWins;
104
+ let newCenterCherrySymbol = state.centerCherrySymbol;
105
+ let isBonusComplete = false;
106
+ // Handle ongoing bonus spins
107
+ if (currentSpinType !== happy_panda_config_1.SpinType.PAID_SPIN && spinsRemaining > 1) {
108
+ // Continue current bonus
109
+ nextSpinType = currentSpinType;
110
+ nextSpinsRemaining = spinsRemaining - 1;
111
+ newAccumulatedBonusWins += wins.totalPayout + jackpotWon + poolJackpotWon;
112
+ }
113
+ else if (currentSpinType !== happy_panda_config_1.SpinType.PAID_SPIN && spinsRemaining === 1) {
114
+ // Bonus sequence ending, check for more pending bonuses
115
+ newAccumulatedBonusWins += wins.totalPayout + jackpotWon + poolJackpotWon;
116
+ const nextBonusType = (0, counter_manager_1.getNextBonusType)(updatedPending);
117
+ if (nextBonusType) {
118
+ // Start next bonus
119
+ const { pending: newPending, spins } = (0, counter_manager_1.consumeBonus)(updatedPending, nextBonusType);
120
+ updatedPending = newPending;
121
+ nextSpinType = bonusTypeToSpinType(nextBonusType);
122
+ nextSpinsRemaining = spins;
123
+ // Set center cherry symbol if starting respin
124
+ if (nextBonusType === 'respin') {
125
+ newCenterCherrySymbol = grid[1][1];
126
+ }
127
+ }
128
+ else {
129
+ // All bonuses complete, return to paid spin
130
+ nextSpinType = happy_panda_config_1.SpinType.PAID_SPIN;
131
+ nextSpinsRemaining = 0;
132
+ isBonusComplete = true;
133
+ newAccumulatedBonusWins = 0; // Reset for next bonus sequence
134
+ newCenterCherrySymbol = null;
135
+ }
136
+ }
137
+ else if (currentSpinType === happy_panda_config_1.SpinType.PAID_SPIN) {
138
+ // Check if any bonuses were triggered
139
+ const nextBonusType = (0, counter_manager_1.getNextBonusType)(updatedPending);
140
+ if (nextBonusType) {
141
+ const { pending: newPending, spins } = (0, counter_manager_1.consumeBonus)(updatedPending, nextBonusType);
142
+ updatedPending = newPending;
143
+ nextSpinType = bonusTypeToSpinType(nextBonusType);
144
+ nextSpinsRemaining = spins;
145
+ // Set center cherry symbol if starting respin
146
+ if (nextBonusType === 'respin') {
147
+ newCenterCherrySymbol = grid[1][1];
148
+ }
149
+ }
150
+ }
151
+ // Build updated state
152
+ const updatedState = {
153
+ ...state,
154
+ currentSpinType: nextSpinType,
155
+ nextSpinType,
156
+ spinsRemaining: nextSpinsRemaining,
157
+ counters: updatedCounters,
158
+ pendingBonuses: updatedPending,
159
+ jackpots: updatedJackpots,
160
+ grid,
161
+ accumulatedBonusWins: newAccumulatedBonusWins,
162
+ centerCherrySymbol: newCenterCherrySymbol,
163
+ };
164
+ return {
165
+ grid,
166
+ wins,
167
+ state: updatedState,
168
+ jackpotWon,
169
+ poolJackpotWon,
170
+ bonusTriggered,
171
+ isBonusComplete,
172
+ };
173
+ }
174
+ // =============================================================================
175
+ // STATE INITIALIZATION
176
+ // =============================================================================
177
+ /** Minimum bet stake */
178
+ exports.MIN_BET_STAKE = 1;
179
+ /** Maximum bet stake (reasonable upper bound) */
180
+ exports.MAX_BET_STAKE = 100;
181
+ /**
182
+ * Validate bet parameters.
183
+ * @throws Error if parameters are invalid
184
+ */
185
+ function validateBetParams(gameDirection, betStake) {
186
+ if (gameDirection !== types_1.GameDirection.SINGLE && gameDirection !== types_1.GameDirection.BOTH) {
187
+ throw new Error(`Invalid game direction: ${gameDirection}. Must be 0 (8 lines) or 1 (16 lines)`);
188
+ }
189
+ if (!Number.isInteger(betStake)) {
190
+ throw new Error(`Bet stake must be an integer, got: ${betStake}`);
191
+ }
192
+ if (betStake < exports.MIN_BET_STAKE || betStake > exports.MAX_BET_STAKE) {
193
+ throw new Error(`Bet stake must be between ${exports.MIN_BET_STAKE} and ${exports.MAX_BET_STAKE}, got: ${betStake}`);
194
+ }
195
+ }
196
+ /**
197
+ * Create initial game state.
198
+ * @throws Error if parameters are invalid
199
+ */
200
+ function createInitialState(gameDirection, betStake) {
201
+ validateBetParams(gameDirection, betStake);
202
+ const baseBet = gameDirection === types_1.GameDirection.SINGLE ? 8 : 16;
203
+ const betGame = baseBet * betStake;
204
+ return {
205
+ gameDirection,
206
+ betStake,
207
+ betGame,
208
+ currentSpinType: happy_panda_config_1.SpinType.PAID_SPIN,
209
+ nextSpinType: happy_panda_config_1.SpinType.PAID_SPIN,
210
+ spinsRemaining: 0,
211
+ counters: {
212
+ jackpot: 1,
213
+ cherry: 9, // Will be randomized on first trigger
214
+ bell: 5, // Will be randomized on first trigger
215
+ bar1: 1,
216
+ },
217
+ pendingBonuses: {
218
+ jackpot: 0,
219
+ cherry: 0,
220
+ bell: 0,
221
+ bar1: 0,
222
+ respin: 0,
223
+ },
224
+ jackpots: {
225
+ bonusJackpotValue: 100 * betGame,
226
+ poolJackpotValue: 0,
227
+ },
228
+ grid: [
229
+ [happy_panda_config_1.Symbol.NONE, happy_panda_config_1.Symbol.NONE, happy_panda_config_1.Symbol.NONE],
230
+ [happy_panda_config_1.Symbol.NONE, happy_panda_config_1.Symbol.NONE, happy_panda_config_1.Symbol.NONE],
231
+ [happy_panda_config_1.Symbol.NONE, happy_panda_config_1.Symbol.NONE, happy_panda_config_1.Symbol.NONE],
232
+ ],
233
+ accumulatedBonusWins: 0,
234
+ centerCherrySymbol: null,
235
+ };
236
+ }
237
+ /**
238
+ * Update state for new bet.
239
+ * @throws Error if parameters are invalid
240
+ */
241
+ function updateBet(state, gameDirection, betStake) {
242
+ validateBetParams(gameDirection, betStake);
243
+ // Can only change bet during paid spin with no pending bonuses
244
+ if (state.currentSpinType !== happy_panda_config_1.SpinType.PAID_SPIN || (0, counter_manager_1.hasPendingBonus)(state.pendingBonuses)) {
245
+ throw new Error('Cannot change bet during bonus or with pending bonuses');
246
+ }
247
+ const baseBet = gameDirection === types_1.GameDirection.SINGLE ? 8 : 16;
248
+ const betGame = baseBet * betStake;
249
+ return {
250
+ ...state,
251
+ gameDirection,
252
+ betStake,
253
+ betGame,
254
+ };
255
+ }
256
+ //# sourceMappingURL=spin-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spin-handler.js","sourceRoot":"","sources":["../../../src/logic/handlers/spin-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ /**
18
+ * Logic module exports
19
+ */
20
+ __exportStar(require("./services"), exports);
21
+ __exportStar(require("./handlers"), exports);
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/logic/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA;;GAEG;AACH,6CAA2B;AAC3B,6CAA2B"}
@@ -0,0 +1,265 @@
1
+ "use strict";
2
+ /**
3
+ * Counter Manager Service
4
+ *
5
+ * Manages bonus counters and trigger detection.
6
+ * Each bonus type has a counter that decrements on specific events.
7
+ * When a counter reaches 0, the bonus is triggered.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.createInitialCounters = createInitialCounters;
11
+ exports.createEmptyPendingBonuses = createEmptyPendingBonuses;
12
+ exports.randomizeCherryCounter = randomizeCherryCounter;
13
+ exports.randomizeBellCounter = randomizeBellCounter;
14
+ exports.updateCounters = updateCounters;
15
+ exports.getNextBonusType = getNextBonusType;
16
+ exports.consumeBonus = consumeBonus;
17
+ exports.hasPendingBonus = hasPendingBonus;
18
+ const happy_panda_config_1 = require("../../config/happy-panda.config");
19
+ const weighted_random_1 = require("../../rng/weighted-random");
20
+ // =============================================================================
21
+ // COUNTER INITIALIZATION
22
+ // =============================================================================
23
+ /**
24
+ * Create initial bonus counters.
25
+ */
26
+ function createInitialCounters() {
27
+ return {
28
+ jackpot: happy_panda_config_1.BONUS_JACKPOT.COUNTER_INIT,
29
+ cherry: happy_panda_config_1.BONUS_CHERRY.COUNTER_INIT[1], // Default to 9, will be randomized
30
+ bell: happy_panda_config_1.BONUS_BELL.COUNTER_INIT[1], // Default to 5, will be randomized
31
+ bar1: happy_panda_config_1.BONUS_BAR1.COUNTER_INIT,
32
+ };
33
+ }
34
+ /**
35
+ * Create empty pending bonuses.
36
+ */
37
+ function createEmptyPendingBonuses() {
38
+ return {
39
+ jackpot: 0,
40
+ cherry: 0,
41
+ bell: 0,
42
+ bar1: 0,
43
+ respin: 0,
44
+ };
45
+ }
46
+ /**
47
+ * Randomize cherry counter initial value (6 or 9).
48
+ */
49
+ async function randomizeCherryCounter(gameDirection, rng) {
50
+ const weights = happy_panda_config_1.BONUS_CHERRY.COUNTER_INIT_WEIGHTS[gameDirection];
51
+ const idx = await (0, weighted_random_1.selectWeightedIndex)(weights, rng);
52
+ return happy_panda_config_1.BONUS_CHERRY.COUNTER_INIT[idx];
53
+ }
54
+ /**
55
+ * Randomize bell counter initial value (3 or 5).
56
+ */
57
+ async function randomizeBellCounter(gameDirection, rng) {
58
+ const weights = happy_panda_config_1.BONUS_BELL.COUNTER_INIT_WEIGHTS[gameDirection];
59
+ const idx = await (0, weighted_random_1.selectWeightedIndex)(weights, rng);
60
+ return happy_panda_config_1.BONUS_BELL.COUNTER_INIT[idx];
61
+ }
62
+ /**
63
+ * Update counters based on spin results.
64
+ * Only applies during paid_spin and respin_cherry.
65
+ */
66
+ async function updateCounters(currentCounters, currentPending, lineWins, grid, gameDirection, spinType, totalWin, rng) {
67
+ // Only update counters during paid spins and respins
68
+ if (spinType !== happy_panda_config_1.SpinType.PAID_SPIN && spinType !== happy_panda_config_1.SpinType.RESPIN_CHERRY) {
69
+ return {
70
+ counters: { ...currentCounters },
71
+ pendingBonuses: { ...currentPending },
72
+ triggeredJackpot: false,
73
+ triggeredCherry: false,
74
+ triggeredBell: false,
75
+ triggeredBar1: false,
76
+ triggeredRespin: 0,
77
+ };
78
+ }
79
+ const counters = { ...currentCounters };
80
+ const pendingBonuses = { ...currentPending };
81
+ let triggeredJackpot = false;
82
+ let triggeredCherry = false;
83
+ let triggeredBell = false;
84
+ let triggeredBar1 = false;
85
+ let triggeredRespin = 0;
86
+ // Count specific line win patterns
87
+ let cherryTripleCount = 0; // 3x Cherry wins (only first 8 lines)
88
+ let cherryPairCount = 0; // 2x Cherry wins
89
+ let bellTripleCount = 0; // 3x Bell wins
90
+ let bar1TripleCount = 0; // 3x Bar1 wins
91
+ for (const win of lineWins) {
92
+ // Only first 8 lines count for Jackpot, Bell, and Bar1 triggers (per C++ math model)
93
+ const isFirst8Lines = win.lineIndex < 8;
94
+ if (win.symbol === happy_panda_config_1.Symbol.CHERRY || win.symbol === happy_panda_config_1.Symbol.SUPER_CHERRY) {
95
+ if (win.matchLength === 3 && isFirst8Lines) {
96
+ // C++ BEHAVIOR: During RESPIN_CHERRY, C++ only regenerates corners.
97
+ // Center row (line 1) edges (0,1) and (2,1) are preserved from paid_spin.
98
+ // Since the triggering paid_spin had only 1 cherry at center, these edges are NOT cherry.
99
+ // Line 1 can NEVER form 3x cherry during respin. Other lines may still form 3x cherry
100
+ // through corner positions which are regenerated.
101
+ const isCenterRow = win.lineIndex === 1;
102
+ if (spinType === happy_panda_config_1.SpinType.RESPIN_CHERRY && isCenterRow) {
103
+ // Skip line 1 - center row edges are preserved non-cherry in C++
104
+ }
105
+ else {
106
+ cherryTripleCount++;
107
+ }
108
+ }
109
+ else if (win.matchLength === 2) {
110
+ // Cherry pairs count on ALL lines for cherry bonus
111
+ cherryPairCount++;
112
+ }
113
+ }
114
+ else if (win.symbol === happy_panda_config_1.Symbol.BELL && win.matchLength === 3 && isFirst8Lines) {
115
+ // Bell bonus only counts first 8 lines
116
+ bellTripleCount++;
117
+ }
118
+ else if (win.symbol === happy_panda_config_1.Symbol.BAR1 && win.matchLength === 3 && isFirst8Lines) {
119
+ // Bar1 bonus only counts first 8 lines
120
+ bar1TripleCount++;
121
+ }
122
+ }
123
+ // JACKPOT BONUS: Triggered by 3x Cherry on first 8 lines
124
+ // C++ line 945: number_bonus_jackpot+=1 for EACH 3x cherry line
125
+ // C++ line 2464: spins_upto_end = number_bonus_jackpot * BonusJackpot_SpinsNo
126
+ // So C++ runs one bonus spin per cherry line, not per trigger event!
127
+ if (cherryTripleCount > 0) {
128
+ pendingBonuses.jackpot += cherryTripleCount; // Per C++ - one bonus spin per cherry line
129
+ counters.jackpot = 0;
130
+ triggeredJackpot = true;
131
+ }
132
+ // CHERRY BONUS: Triggered when counter reaches 0
133
+ // Decremented by 2x Cherry pairs on any line
134
+ // Per C++ math model: process each pair individually, trigger can occur multiple times
135
+ for (let i = 0; i < cherryPairCount; i++) {
136
+ counters.cherry--;
137
+ if (counters.cherry <= 0) {
138
+ pendingBonuses.cherry++;
139
+ triggeredCherry = true;
140
+ // Reset counter with random value before processing next pair
141
+ counters.cherry = await randomizeCherryCounter(gameDirection, rng);
142
+ }
143
+ }
144
+ // BELL BONUS: Triggered when counter reaches 0
145
+ // Decremented by 3x Bell wins - process each win individually
146
+ for (let i = 0; i < bellTripleCount; i++) {
147
+ counters.bell--;
148
+ if (counters.bell <= 0) {
149
+ pendingBonuses.bell++;
150
+ triggeredBell = true;
151
+ // Reset counter with random value before processing next win
152
+ counters.bell = await randomizeBellCounter(gameDirection, rng);
153
+ }
154
+ }
155
+ // BAR1 BONUS: Triggered when counter reaches 0
156
+ // Decremented by 3x Bar1 wins - process each win individually
157
+ for (let i = 0; i < bar1TripleCount; i++) {
158
+ counters.bar1--;
159
+ if (counters.bar1 <= 0) {
160
+ pendingBonuses.bar1++;
161
+ triggeredBar1 = true;
162
+ // Reset counter before processing next win
163
+ counters.bar1 = happy_panda_config_1.BONUS_BAR1.COUNTER_INIT;
164
+ }
165
+ }
166
+ // CENTER CHERRY RESPIN: Only on paid spins, no other wins
167
+ if (spinType === happy_panda_config_1.SpinType.PAID_SPIN && totalWin === 0) {
168
+ const centerSymbol = grid[1][1];
169
+ if (happy_panda_config_1.CHERRY_SYMBOLS.includes(centerSymbol)) {
170
+ // Check if it's the ONLY cherry on the screen
171
+ let cherryCount = 0;
172
+ for (let reel = 0; reel < 3; reel++) {
173
+ for (let row = 0; row < 3; row++) {
174
+ if (happy_panda_config_1.CHERRY_SYMBOLS.includes(grid[reel][row])) {
175
+ cherryCount++;
176
+ }
177
+ }
178
+ }
179
+ if (cherryCount === 1) {
180
+ // Award respins: 1 for Cherry, 2 for Super Cherry
181
+ triggeredRespin = centerSymbol === happy_panda_config_1.Symbol.SUPER_CHERRY ? 2 : 1;
182
+ pendingBonuses.respin += triggeredRespin;
183
+ }
184
+ }
185
+ }
186
+ return {
187
+ counters,
188
+ pendingBonuses,
189
+ triggeredJackpot,
190
+ triggeredCherry,
191
+ triggeredBell,
192
+ triggeredBar1,
193
+ triggeredRespin,
194
+ };
195
+ }
196
+ /**
197
+ * Get the next bonus type to execute (priority order).
198
+ * Returns null if no bonuses pending.
199
+ */
200
+ function getNextBonusType(pending) {
201
+ // Priority: Jackpot > Cherry > Bell > Bar1 > Respin
202
+ if (pending.jackpot > 0)
203
+ return 'jackpot';
204
+ if (pending.cherry > 0)
205
+ return 'cherry';
206
+ if (pending.bell > 0)
207
+ return 'bell';
208
+ if (pending.bar1 > 0)
209
+ return 'bar1';
210
+ if (pending.respin > 0)
211
+ return 'respin';
212
+ return null;
213
+ }
214
+ /**
215
+ * Consume one bonus from pending.
216
+ * Returns updated pending and number of spins for that bonus.
217
+ */
218
+ function consumeBonus(pending, bonusType) {
219
+ const updated = { ...pending };
220
+ let spins = 0;
221
+ switch (bonusType) {
222
+ case 'jackpot':
223
+ if (updated.jackpot > 0) {
224
+ updated.jackpot--;
225
+ spins = happy_panda_config_1.BONUS_JACKPOT.SPINS;
226
+ }
227
+ break;
228
+ case 'cherry':
229
+ if (updated.cherry > 0) {
230
+ updated.cherry--;
231
+ spins = happy_panda_config_1.BONUS_CHERRY.SPINS;
232
+ }
233
+ break;
234
+ case 'bell':
235
+ if (updated.bell > 0) {
236
+ updated.bell--;
237
+ spins = happy_panda_config_1.BONUS_BELL.SPINS;
238
+ }
239
+ break;
240
+ case 'bar1':
241
+ if (updated.bar1 > 0) {
242
+ updated.bar1--;
243
+ spins = happy_panda_config_1.BONUS_BAR1.SPINS;
244
+ }
245
+ break;
246
+ case 'respin':
247
+ if (updated.respin > 0) {
248
+ spins = updated.respin;
249
+ updated.respin = 0;
250
+ }
251
+ break;
252
+ }
253
+ return { pending: updated, spins };
254
+ }
255
+ /**
256
+ * Check if any bonus is pending.
257
+ */
258
+ function hasPendingBonus(pending) {
259
+ return (pending.jackpot > 0 ||
260
+ pending.cherry > 0 ||
261
+ pending.bell > 0 ||
262
+ pending.bar1 > 0 ||
263
+ pending.respin > 0);
264
+ }
265
+ //# sourceMappingURL=counter-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"counter-manager.js","sourceRoot":"","sources":["../../../src/logic/services/counter-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ /**
18
+ * Logic services exports
19
+ */
20
+ __exportStar(require("./win-evaluator"), exports);
21
+ __exportStar(require("./counter-manager"), exports);
22
+ __exportStar(require("./jackpot-manager"), exports);
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/logic/services/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA;;GAEG;AACH,kDAAgC;AAChC,oDAAkC;AAClC,oDAAkC"}