@omnitronix/happy-panda-game-engine 0.5.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.
- package/README.md +732 -0
- package/dist/__tests__/bonus-sequence.test.d.ts +7 -0
- package/dist/__tests__/bonus-sequence.test.d.ts.map +1 -0
- package/dist/__tests__/bonus-sequence.test.js +381 -0
- package/dist/__tests__/bonus-sequence.test.js.map +1 -0
- package/dist/__tests__/cherry-frequency.test.d.ts +8 -0
- package/dist/__tests__/cherry-frequency.test.d.ts.map +1 -0
- package/dist/__tests__/cherry-frequency.test.js +128 -0
- package/dist/__tests__/cherry-frequency.test.js.map +1 -0
- package/dist/__tests__/comprehensive.test.d.ts +16 -0
- package/dist/__tests__/comprehensive.test.d.ts.map +1 -0
- package/dist/__tests__/comprehensive.test.js +491 -0
- package/dist/__tests__/comprehensive.test.js.map +1 -0
- package/dist/__tests__/counter-manager.test.d.ts +7 -0
- package/dist/__tests__/counter-manager.test.d.ts.map +1 -0
- package/dist/__tests__/counter-manager.test.js +317 -0
- package/dist/__tests__/counter-manager.test.js.map +1 -0
- package/dist/__tests__/coverage-boost.test.d.ts +13 -0
- package/dist/__tests__/coverage-boost.test.d.ts.map +1 -0
- package/dist/__tests__/coverage-boost.test.js +606 -0
- package/dist/__tests__/coverage-boost.test.js.map +1 -0
- package/dist/__tests__/cpp-parity.test.d.ts +39 -0
- package/dist/__tests__/cpp-parity.test.d.ts.map +1 -0
- package/dist/__tests__/cpp-parity.test.js +392 -0
- package/dist/__tests__/cpp-parity.test.js.map +1 -0
- package/dist/__tests__/debug-trigger-bonus.test.d.ts +8 -0
- package/dist/__tests__/debug-trigger-bonus.test.d.ts.map +1 -0
- package/dist/__tests__/debug-trigger-bonus.test.js +359 -0
- package/dist/__tests__/debug-trigger-bonus.test.js.map +1 -0
- package/dist/__tests__/fixtures/cpp-parity-vectors.json +457 -0
- package/dist/__tests__/gdd-validation-1000.test.d.ts +14 -0
- package/dist/__tests__/gdd-validation-1000.test.d.ts.map +1 -0
- package/dist/__tests__/gdd-validation-1000.test.js +418 -0
- package/dist/__tests__/gdd-validation-1000.test.js.map +1 -0
- package/dist/__tests__/happy-panda-engine.test.d.ts +7 -0
- package/dist/__tests__/happy-panda-engine.test.d.ts.map +1 -0
- package/dist/__tests__/happy-panda-engine.test.js +414 -0
- package/dist/__tests__/happy-panda-engine.test.js.map +1 -0
- package/dist/__tests__/jackpot-manager.test.d.ts +8 -0
- package/dist/__tests__/jackpot-manager.test.d.ts.map +1 -0
- package/dist/__tests__/jackpot-manager.test.js +313 -0
- package/dist/__tests__/jackpot-manager.test.js.map +1 -0
- package/dist/__tests__/jackpot-trigger-trace.test.d.ts +6 -0
- package/dist/__tests__/jackpot-trigger-trace.test.d.ts.map +1 -0
- package/dist/__tests__/jackpot-trigger-trace.test.js +146 -0
- package/dist/__tests__/jackpot-trigger-trace.test.js.map +1 -0
- package/dist/__tests__/rng-gli19-compliance.test.d.ts +21 -0
- package/dist/__tests__/rng-gli19-compliance.test.d.ts.map +1 -0
- package/dist/__tests__/rng-gli19-compliance.test.js +480 -0
- package/dist/__tests__/rng-gli19-compliance.test.js.map +1 -0
- package/dist/__tests__/rng-seed-security.test.d.ts +19 -0
- package/dist/__tests__/rng-seed-security.test.d.ts.map +1 -0
- package/dist/__tests__/rng-seed-security.test.js +518 -0
- package/dist/__tests__/rng-seed-security.test.js.map +1 -0
- package/dist/__tests__/rng-seed-type.test.d.ts +16 -0
- package/dist/__tests__/rng-seed-type.test.d.ts.map +1 -0
- package/dist/__tests__/rng-seed-type.test.js +285 -0
- package/dist/__tests__/rng-seed-type.test.js.map +1 -0
- package/dist/__tests__/rng-stress-boundary.test.d.ts +15 -0
- package/dist/__tests__/rng-stress-boundary.test.d.ts.map +1 -0
- package/dist/__tests__/rng-stress-boundary.test.js +590 -0
- package/dist/__tests__/rng-stress-boundary.test.js.map +1 -0
- package/dist/__tests__/rtp-1million.test.d.ts +8 -0
- package/dist/__tests__/rtp-1million.test.d.ts.map +1 -0
- package/dist/__tests__/rtp-1million.test.js +156 -0
- package/dist/__tests__/rtp-1million.test.js.map +1 -0
- package/dist/__tests__/rtp-analysis.test.d.ts +8 -0
- package/dist/__tests__/rtp-analysis.test.d.ts.map +1 -0
- package/dist/__tests__/rtp-analysis.test.js +138 -0
- package/dist/__tests__/rtp-analysis.test.js.map +1 -0
- package/dist/__tests__/rtp-diagnostic.test.d.ts +6 -0
- package/dist/__tests__/rtp-diagnostic.test.d.ts.map +1 -0
- package/dist/__tests__/rtp-diagnostic.test.js +141 -0
- package/dist/__tests__/rtp-diagnostic.test.js.map +1 -0
- package/dist/__tests__/rtp-simulation.test.d.ts +8 -0
- package/dist/__tests__/rtp-simulation.test.d.ts.map +1 -0
- package/dist/__tests__/rtp-simulation.test.js +411 -0
- package/dist/__tests__/rtp-simulation.test.js.map +1 -0
- package/dist/__tests__/special-wins.test.d.ts +7 -0
- package/dist/__tests__/special-wins.test.d.ts.map +1 -0
- package/dist/__tests__/special-wins.test.js +179 -0
- package/dist/__tests__/special-wins.test.js.map +1 -0
- package/dist/__tests__/spin-generator.test.d.ts +7 -0
- package/dist/__tests__/spin-generator.test.d.ts.map +1 -0
- package/dist/__tests__/spin-generator.test.js +297 -0
- package/dist/__tests__/spin-generator.test.js.map +1 -0
- package/dist/__tests__/spin-handler.test.d.ts +7 -0
- package/dist/__tests__/spin-handler.test.d.ts.map +1 -0
- package/dist/__tests__/spin-handler.test.js +210 -0
- package/dist/__tests__/spin-handler.test.js.map +1 -0
- package/dist/__tests__/symbol-distribution.test.d.ts +6 -0
- package/dist/__tests__/symbol-distribution.test.d.ts.map +1 -0
- package/dist/__tests__/symbol-distribution.test.js +119 -0
- package/dist/__tests__/symbol-distribution.test.js.map +1 -0
- package/dist/__tests__/test-protocol-10000-spin.test.d.ts +14 -0
- package/dist/__tests__/test-protocol-10000-spin.test.d.ts.map +1 -0
- package/dist/__tests__/test-protocol-10000-spin.test.js +359 -0
- package/dist/__tests__/test-protocol-10000-spin.test.js.map +1 -0
- package/dist/__tests__/weighted-random.test.d.ts +7 -0
- package/dist/__tests__/weighted-random.test.d.ts.map +1 -0
- package/dist/__tests__/weighted-random.test.js +165 -0
- package/dist/__tests__/weighted-random.test.js.map +1 -0
- package/dist/__tests__/win-evaluator.test.d.ts +7 -0
- package/dist/__tests__/win-evaluator.test.d.ts.map +1 -0
- package/dist/__tests__/win-evaluator.test.js +264 -0
- package/dist/__tests__/win-evaluator.test.js.map +1 -0
- package/dist/config/happy-panda.config.d.ts +217 -0
- package/dist/config/happy-panda.config.d.ts.map +1 -0
- package/dist/config/happy-panda.config.js +721 -0
- package/dist/config/happy-panda.config.js.map +1 -0
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +21 -0
- package/dist/config/index.js.map +1 -0
- package/dist/debug/debug-command-definitions.d.ts +38 -0
- package/dist/debug/debug-command-definitions.d.ts.map +1 -0
- package/dist/debug/debug-command-definitions.js +80 -0
- package/dist/debug/debug-command-definitions.js.map +1 -0
- package/dist/domain/debug-trigger-bonus-command.d.ts +17 -0
- package/dist/domain/debug-trigger-bonus-command.d.ts.map +1 -0
- package/dist/domain/debug-trigger-bonus-command.js +3 -0
- package/dist/domain/debug-trigger-bonus-command.js.map +1 -0
- package/dist/domain/index.d.ts +5 -0
- package/dist/domain/index.d.ts.map +1 -0
- package/dist/domain/index.js +21 -0
- package/dist/domain/index.js.map +1 -0
- package/dist/domain/types.d.ts +228 -0
- package/dist/domain/types.d.ts.map +1 -0
- package/dist/domain/types.js +30 -0
- package/dist/domain/types.js.map +1 -0
- package/dist/engine/happy-panda-engine.d.ts +64 -0
- package/dist/engine/happy-panda-engine.d.ts.map +1 -0
- package/dist/engine/happy-panda-engine.js +324 -0
- package/dist/engine/happy-panda-engine.js.map +1 -0
- package/dist/engine/index.d.ts +5 -0
- package/dist/engine/index.d.ts.map +1 -0
- package/dist/engine/index.js +21 -0
- package/dist/engine/index.js.map +1 -0
- package/dist/game-engine.interface.d.ts +19 -0
- package/dist/game-engine.interface.d.ts.map +1 -0
- package/dist/game-engine.interface.js +9 -0
- package/dist/game-engine.interface.js.map +1 -0
- package/dist/happy-panda-v1.game-engine.d.ts +60 -0
- package/dist/happy-panda-v1.game-engine.d.ts.map +1 -0
- package/dist/happy-panda-v1.game-engine.js +524 -0
- package/dist/happy-panda-v1.game-engine.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/logic/handlers/index.d.ts +5 -0
- package/dist/logic/handlers/index.d.ts.map +1 -0
- package/dist/logic/handlers/index.js +21 -0
- package/dist/logic/handlers/index.js.map +1 -0
- package/dist/logic/handlers/spin-handler.d.ts +58 -0
- package/dist/logic/handlers/spin-handler.d.ts.map +1 -0
- package/dist/logic/handlers/spin-handler.js +265 -0
- package/dist/logic/handlers/spin-handler.js.map +1 -0
- package/dist/logic/index.d.ts +6 -0
- package/dist/logic/index.d.ts.map +1 -0
- package/dist/logic/index.js +22 -0
- package/dist/logic/index.js.map +1 -0
- package/dist/logic/services/counter-manager.d.ts +60 -0
- package/dist/logic/services/counter-manager.d.ts.map +1 -0
- package/dist/logic/services/counter-manager.js +268 -0
- package/dist/logic/services/counter-manager.js.map +1 -0
- package/dist/logic/services/index.d.ts +7 -0
- package/dist/logic/services/index.d.ts.map +1 -0
- package/dist/logic/services/index.js +23 -0
- package/dist/logic/services/index.js.map +1 -0
- package/dist/logic/services/jackpot-manager.d.ts +59 -0
- package/dist/logic/services/jackpot-manager.d.ts.map +1 -0
- package/dist/logic/services/jackpot-manager.js +142 -0
- package/dist/logic/services/jackpot-manager.js.map +1 -0
- package/dist/logic/services/win-evaluator.d.ts +51 -0
- package/dist/logic/services/win-evaluator.d.ts.map +1 -0
- package/dist/logic/services/win-evaluator.js +463 -0
- package/dist/logic/services/win-evaluator.js.map +1 -0
- package/dist/rng/dummy-rng-client.d.ts +39 -0
- package/dist/rng/dummy-rng-client.d.ts.map +1 -0
- package/dist/rng/dummy-rng-client.js +77 -0
- package/dist/rng/dummy-rng-client.js.map +1 -0
- package/dist/rng/index.d.ts +10 -0
- package/dist/rng/index.d.ts.map +1 -0
- package/dist/rng/index.js +27 -0
- package/dist/rng/index.js.map +1 -0
- package/dist/rng/rng-client.factory.d.ts +33 -0
- package/dist/rng/rng-client.factory.d.ts.map +1 -0
- package/dist/rng/rng-client.factory.js +57 -0
- package/dist/rng/rng-client.factory.js.map +1 -0
- package/dist/rng/rng-client.interface.d.ts +51 -0
- package/dist/rng/rng-client.interface.d.ts.map +1 -0
- package/dist/rng/rng-client.interface.js +9 -0
- package/dist/rng/rng-client.interface.js.map +1 -0
- package/dist/rng/rng-service.d.ts +93 -0
- package/dist/rng/rng-service.d.ts.map +1 -0
- package/dist/rng/rng-service.js +124 -0
- package/dist/rng/rng-service.js.map +1 -0
- package/dist/rng/spin-generator.d.ts +32 -0
- package/dist/rng/spin-generator.d.ts.map +1 -0
- package/dist/rng/spin-generator.js +338 -0
- package/dist/rng/spin-generator.js.map +1 -0
- package/dist/rng/weighted-random.d.ts +30 -0
- package/dist/rng/weighted-random.d.ts.map +1 -0
- package/dist/rng/weighted-random.js +58 -0
- package/dist/rng/weighted-random.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Happy Panda Game Engine
|
|
4
|
+
*
|
|
5
|
+
* Main engine class that provides the public API for the game.
|
|
6
|
+
* Implements the command pattern used by other Omnitronix game engines.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.HappyPandaEngine = void 0;
|
|
10
|
+
const types_1 = require("../domain/types");
|
|
11
|
+
const happy_panda_config_1 = require("../config/happy-panda.config");
|
|
12
|
+
const spin_handler_1 = require("../logic/handlers/spin-handler");
|
|
13
|
+
const counter_manager_1 = require("../logic/services/counter-manager");
|
|
14
|
+
// =============================================================================
|
|
15
|
+
// ENGINE CLASS
|
|
16
|
+
// =============================================================================
|
|
17
|
+
class HappyPandaEngine {
|
|
18
|
+
constructor(rngProvider) {
|
|
19
|
+
this.rng = rngProvider;
|
|
20
|
+
}
|
|
21
|
+
// ===========================================================================
|
|
22
|
+
// COMMAND HANDLING
|
|
23
|
+
// ===========================================================================
|
|
24
|
+
/**
|
|
25
|
+
* Handle a game command.
|
|
26
|
+
*/
|
|
27
|
+
async handleCommand(command, currentState) {
|
|
28
|
+
switch (command.command) {
|
|
29
|
+
case types_1.CommandType.INIT_SESSION_STATE:
|
|
30
|
+
return this.handleInitSession(command);
|
|
31
|
+
case types_1.CommandType.SPIN:
|
|
32
|
+
if (!currentState) {
|
|
33
|
+
throw new Error('No session state for SPIN command');
|
|
34
|
+
}
|
|
35
|
+
return this.handleSpin(currentState);
|
|
36
|
+
case types_1.CommandType.GET_SYMBOLS:
|
|
37
|
+
return this.handleGetSymbols(currentState);
|
|
38
|
+
default:
|
|
39
|
+
throw new Error(`Unknown command: ${command.command}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// ===========================================================================
|
|
43
|
+
// INIT SESSION
|
|
44
|
+
// ===========================================================================
|
|
45
|
+
async handleInitSession(request) {
|
|
46
|
+
const gameState = (0, spin_handler_1.createInitialState)(request.gameDirection, request.betStake);
|
|
47
|
+
const sessionState = this.createSessionState(request.sessionId, gameState);
|
|
48
|
+
const publicState = this.extractPublicState(gameState);
|
|
49
|
+
return {
|
|
50
|
+
response: publicState,
|
|
51
|
+
state: sessionState,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
// ===========================================================================
|
|
55
|
+
// SPIN
|
|
56
|
+
// ===========================================================================
|
|
57
|
+
async handleSpin(currentSession) {
|
|
58
|
+
const gameState = this.reconstructGameState(currentSession);
|
|
59
|
+
// Execute spin
|
|
60
|
+
const result = await (0, spin_handler_1.executeSpin)(gameState, this.rng);
|
|
61
|
+
// Build triggered bonus info if a bonus was triggered
|
|
62
|
+
let triggeredBonus;
|
|
63
|
+
if (result.bonusTriggered !== null) {
|
|
64
|
+
triggeredBonus = {
|
|
65
|
+
bonusId: `bonus-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`,
|
|
66
|
+
bonusType: this.spinTypeToBonusType(result.bonusTriggered),
|
|
67
|
+
betAmount: gameState.betGame,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
// Build response
|
|
71
|
+
const executedType = result.executedSpinType;
|
|
72
|
+
const nextType = result.state.nextSpinType;
|
|
73
|
+
const response = {
|
|
74
|
+
// Game-specific fields
|
|
75
|
+
spinType: executedType,
|
|
76
|
+
screen: result.screen,
|
|
77
|
+
wins: result.wins,
|
|
78
|
+
jackpotWon: result.jackpotWon,
|
|
79
|
+
poolJackpotWon: result.poolJackpotWon,
|
|
80
|
+
triggeredBonus,
|
|
81
|
+
isBonusComplete: result.isBonusComplete,
|
|
82
|
+
playerWinning: result.playerWinning,
|
|
83
|
+
nextSpinType: nextType,
|
|
84
|
+
// BaseOutcome standardized fields
|
|
85
|
+
actionType: executedType,
|
|
86
|
+
nextActionType: nextType,
|
|
87
|
+
roundPhase: executedType === happy_panda_config_1.SpinType.BASE_GAME_SPIN ? 'BASE' : 'BONUS',
|
|
88
|
+
isRoundComplete: result.isBonusComplete,
|
|
89
|
+
};
|
|
90
|
+
// Update session state
|
|
91
|
+
const newSession = this.createSessionState(currentSession.sessionId, result.state);
|
|
92
|
+
return {
|
|
93
|
+
response,
|
|
94
|
+
state: newSession,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
// ===========================================================================
|
|
98
|
+
// GET SYMBOLS
|
|
99
|
+
// ===========================================================================
|
|
100
|
+
async handleGetSymbols(currentSession) {
|
|
101
|
+
// Return symbol definitions
|
|
102
|
+
const symbols = Object.entries(happy_panda_config_1.Symbol)
|
|
103
|
+
.filter(([key]) => isNaN(Number(key)))
|
|
104
|
+
.map(([name, value]) => ({ name, value }));
|
|
105
|
+
return {
|
|
106
|
+
response: { symbols },
|
|
107
|
+
state: currentSession || this.createEmptySession(),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
// ===========================================================================
|
|
111
|
+
// STATE MANAGEMENT
|
|
112
|
+
// ===========================================================================
|
|
113
|
+
/**
|
|
114
|
+
* Extract public state from game state.
|
|
115
|
+
*/
|
|
116
|
+
extractPublicState(state) {
|
|
117
|
+
return {
|
|
118
|
+
gameDirection: state.gameDirection,
|
|
119
|
+
betStake: state.betStake,
|
|
120
|
+
betGame: state.betGame,
|
|
121
|
+
currentSpinType: state.currentSpinType,
|
|
122
|
+
spinsRemaining: state.spinsRemaining,
|
|
123
|
+
screen: state.screen,
|
|
124
|
+
bonusJackpotValue: state.jackpots.bonusJackpotValue,
|
|
125
|
+
poolJackpotValue: state.jackpots.poolJackpotValue,
|
|
126
|
+
hasPendingBonus: (0, counter_manager_1.hasPendingBonus)(state.pendingBonuses),
|
|
127
|
+
additionalData: {
|
|
128
|
+
counters: state.counters,
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Extract private state from game state.
|
|
134
|
+
* Converts internal counter-based pendingBonuses to RGS-compatible array format.
|
|
135
|
+
*/
|
|
136
|
+
extractPrivateState(state) {
|
|
137
|
+
// Convert counter-based pending bonuses to RGS-compatible array format
|
|
138
|
+
const pendingBonusesArray = this.convertPendingBonusesToArray(state.pendingBonuses, state.betGame);
|
|
139
|
+
// Determine if there's an active bonus (currently in a bonus round)
|
|
140
|
+
let activeBonus;
|
|
141
|
+
if (state.currentSpinType !== happy_panda_config_1.SpinType.BASE_GAME_SPIN && state.spinsRemaining > 0) {
|
|
142
|
+
activeBonus = {
|
|
143
|
+
bonusId: `active-${state.currentSpinType}-${Date.now()}`,
|
|
144
|
+
bonusType: this.spinTypeToBonusType(state.currentSpinType),
|
|
145
|
+
betAmount: state.betGame,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
counters: state.counters,
|
|
150
|
+
internalPendingBonuses: state.pendingBonuses,
|
|
151
|
+
nextSpinType: state.nextSpinType,
|
|
152
|
+
accumulatedBonusWins: state.accumulatedBonusWins,
|
|
153
|
+
centerBambooSymbol: state.centerBambooSymbol,
|
|
154
|
+
pendingBonuses: pendingBonusesArray,
|
|
155
|
+
activeBonus,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Convert counter-based pending bonuses to RGS-compatible array format.
|
|
160
|
+
*/
|
|
161
|
+
convertPendingBonusesToArray(pending, betAmount) {
|
|
162
|
+
const bonuses = [];
|
|
163
|
+
const timestamp = Date.now();
|
|
164
|
+
// Add bonuses in priority order (bambooTriplets > bambooTwins > camera > fireworks > centerBamboo)
|
|
165
|
+
for (let i = 0; i < pending.bambooTriplets; i++) {
|
|
166
|
+
bonuses.push({
|
|
167
|
+
bonusId: `pending-bambooTriplets-${timestamp}-${i}`,
|
|
168
|
+
bonusType: 'BONUS_BAMBOO_TRIPLETS',
|
|
169
|
+
betAmount,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
for (let i = 0; i < pending.bambooTwins; i++) {
|
|
173
|
+
bonuses.push({
|
|
174
|
+
bonusId: `pending-bambooTwins-${timestamp}-${i}`,
|
|
175
|
+
bonusType: 'BONUS_BAMBOO_TWINS',
|
|
176
|
+
betAmount,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
for (let i = 0; i < pending.camera; i++) {
|
|
180
|
+
bonuses.push({
|
|
181
|
+
bonusId: `pending-camera-${timestamp}-${i}`,
|
|
182
|
+
bonusType: 'BONUS_CAMERA',
|
|
183
|
+
betAmount,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
for (let i = 0; i < pending.fireworks; i++) {
|
|
187
|
+
bonuses.push({
|
|
188
|
+
bonusId: `pending-fireworks-${timestamp}-${i}`,
|
|
189
|
+
bonusType: 'BONUS_FIREWORKS',
|
|
190
|
+
betAmount,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
for (let i = 0; i < pending.centerBamboo; i++) {
|
|
194
|
+
bonuses.push({
|
|
195
|
+
bonusId: `pending-centerBamboo-${timestamp}-${i}`,
|
|
196
|
+
bonusType: 'RESPIN_CENTER_BAMBOO',
|
|
197
|
+
betAmount,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
return bonuses;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Convert SpinType to bonus type string for RGS.
|
|
204
|
+
* Now that SpinType is a string enum, this is a simple cast.
|
|
205
|
+
*/
|
|
206
|
+
spinTypeToBonusType(spinType) {
|
|
207
|
+
return spinType;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Create session state from game state.
|
|
211
|
+
*/
|
|
212
|
+
createSessionState(sessionId, state) {
|
|
213
|
+
return {
|
|
214
|
+
sessionId,
|
|
215
|
+
publicState: this.extractPublicState(state),
|
|
216
|
+
privateState: this.extractPrivateState(state),
|
|
217
|
+
createdAt: new Date(),
|
|
218
|
+
updatedAt: new Date(),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Reconstruct game state from session state.
|
|
223
|
+
*/
|
|
224
|
+
reconstructGameState(session) {
|
|
225
|
+
const pub = session.publicState;
|
|
226
|
+
const priv = session.privateState;
|
|
227
|
+
// Use internalPendingBonuses (counter format) for game logic
|
|
228
|
+
// Fall back to converting from array format if internalPendingBonuses is not present (legacy state)
|
|
229
|
+
const pendingBonuses = priv.internalPendingBonuses ??
|
|
230
|
+
this.convertArrayToPendingBonuses(priv.pendingBonuses);
|
|
231
|
+
return {
|
|
232
|
+
gameDirection: pub.gameDirection,
|
|
233
|
+
betStake: pub.betStake,
|
|
234
|
+
betGame: pub.betGame,
|
|
235
|
+
currentSpinType: pub.currentSpinType,
|
|
236
|
+
nextSpinType: priv.nextSpinType,
|
|
237
|
+
spinsRemaining: pub.spinsRemaining,
|
|
238
|
+
counters: priv.counters,
|
|
239
|
+
pendingBonuses,
|
|
240
|
+
jackpots: {
|
|
241
|
+
bonusJackpotValue: pub.bonusJackpotValue,
|
|
242
|
+
poolJackpotValue: pub.poolJackpotValue,
|
|
243
|
+
},
|
|
244
|
+
screen: pub.screen,
|
|
245
|
+
accumulatedBonusWins: priv.accumulatedBonusWins,
|
|
246
|
+
centerBambooSymbol: priv.centerBambooSymbol,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Convert RGS-compatible array back to counter-based format (for legacy state compatibility).
|
|
251
|
+
*/
|
|
252
|
+
convertArrayToPendingBonuses(bonuses) {
|
|
253
|
+
const result = {
|
|
254
|
+
bambooTriplets: 0,
|
|
255
|
+
bambooTwins: 0,
|
|
256
|
+
camera: 0,
|
|
257
|
+
fireworks: 0,
|
|
258
|
+
centerBamboo: 0,
|
|
259
|
+
};
|
|
260
|
+
if (!bonuses || !Array.isArray(bonuses)) {
|
|
261
|
+
return result;
|
|
262
|
+
}
|
|
263
|
+
for (const bonus of bonuses) {
|
|
264
|
+
switch (bonus.bonusType) {
|
|
265
|
+
case 'BONUS_BAMBOO_TRIPLETS':
|
|
266
|
+
result.bambooTriplets++;
|
|
267
|
+
break;
|
|
268
|
+
case 'BONUS_BAMBOO_TWINS':
|
|
269
|
+
result.bambooTwins++;
|
|
270
|
+
break;
|
|
271
|
+
case 'BONUS_CAMERA':
|
|
272
|
+
result.camera++;
|
|
273
|
+
break;
|
|
274
|
+
case 'BONUS_FIREWORKS':
|
|
275
|
+
result.fireworks++;
|
|
276
|
+
break;
|
|
277
|
+
case 'RESPIN_CENTER_BAMBOO':
|
|
278
|
+
result.centerBamboo++;
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return result;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Create empty session for commands that don't need state.
|
|
286
|
+
*/
|
|
287
|
+
createEmptySession() {
|
|
288
|
+
return {
|
|
289
|
+
sessionId: '',
|
|
290
|
+
publicState: this.extractPublicState((0, spin_handler_1.createInitialState)(types_1.GameDirection.SINGLE, 1)),
|
|
291
|
+
privateState: {
|
|
292
|
+
counters: { bambooTriplets: 1, bambooTwins: 9, camera: 5, fireworks: 1 },
|
|
293
|
+
internalPendingBonuses: { bambooTriplets: 0, bambooTwins: 0, camera: 0, fireworks: 0, centerBamboo: 0 },
|
|
294
|
+
nextSpinType: happy_panda_config_1.SpinType.BASE_GAME_SPIN,
|
|
295
|
+
accumulatedBonusWins: 0,
|
|
296
|
+
centerBambooSymbol: null,
|
|
297
|
+
pendingBonuses: [],
|
|
298
|
+
activeBonus: undefined,
|
|
299
|
+
},
|
|
300
|
+
createdAt: new Date(),
|
|
301
|
+
updatedAt: new Date(),
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
// ===========================================================================
|
|
305
|
+
// UTILITY METHODS
|
|
306
|
+
// ===========================================================================
|
|
307
|
+
/**
|
|
308
|
+
* Update bet settings (only when no bonus pending).
|
|
309
|
+
*/
|
|
310
|
+
updateBet(session, gameDirection, betStake) {
|
|
311
|
+
const gameState = this.reconstructGameState(session);
|
|
312
|
+
const updatedState = (0, spin_handler_1.updateBet)(gameState, gameDirection, betStake);
|
|
313
|
+
return this.createSessionState(session.sessionId, updatedState);
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Check if player can change bet.
|
|
317
|
+
*/
|
|
318
|
+
canChangeBet(session) {
|
|
319
|
+
return (session.publicState.currentSpinType === happy_panda_config_1.SpinType.BASE_GAME_SPIN &&
|
|
320
|
+
!session.publicState.hasPendingBonus);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
exports.HappyPandaEngine = HappyPandaEngine;
|
|
324
|
+
//# sourceMappingURL=happy-panda-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"happy-panda-engine.js","sourceRoot":"","sources":["../../src/engine/happy-panda-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
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
|
+
* Engine module exports
|
|
19
|
+
*/
|
|
20
|
+
__exportStar(require("./happy-panda-engine"), exports);
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA;;GAEG;AACH,uDAAqC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Game Engine Interface Types
|
|
3
|
+
*
|
|
4
|
+
* Re-exports types from @omnitronix/game-engine-contract for use by consumers.
|
|
5
|
+
* Defines Happy Panda-specific configuration types.
|
|
6
|
+
*/
|
|
7
|
+
import type { ILogger as ILoggerType } from '@omnitronix/game-engine-contract';
|
|
8
|
+
export { GameEngine, GameEngineInfo, } from '@omnitronix/game-engine-contract';
|
|
9
|
+
export { GameActionCommand, CommandProcessingResult, } from '@omnitronix/game-engine-contract';
|
|
10
|
+
export { RngOutcome, RngOutcomeRecord, } from '@omnitronix/game-engine-contract';
|
|
11
|
+
export { ILogger } from '@omnitronix/game-engine-contract';
|
|
12
|
+
/**
|
|
13
|
+
* Configuration options for HappyPandaV1GameEngine
|
|
14
|
+
*/
|
|
15
|
+
export interface HappyPandaV1GameEngineConfig {
|
|
16
|
+
logger?: ILoggerType;
|
|
17
|
+
metrics?: unknown;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=game-engine.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"game-engine.interface.d.ts","sourceRoot":"","sources":["../src/game-engine.interface.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAG/E,OAAO,EACL,UAAU,EACV,cAAc,GACf,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,UAAU,EACV,gBAAgB,GACjB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Game Engine Interface Types
|
|
4
|
+
*
|
|
5
|
+
* Re-exports types from @omnitronix/game-engine-contract for use by consumers.
|
|
6
|
+
* Defines Happy Panda-specific configuration types.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
//# sourceMappingURL=game-engine.interface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"game-engine.interface.js","sourceRoot":"","sources":["../src/game-engine.interface.ts"],"names":[],"mappings":";AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HappyPandaV1GameEngine
|
|
3
|
+
*
|
|
4
|
+
* Wrapper class that adapts HappyPandaEngine to the standard GameEngine interface
|
|
5
|
+
* expected by the game-engine-service infrastructure.
|
|
6
|
+
*
|
|
7
|
+
* Uses the proper RNG infrastructure matching Heroes of Aether and Bonny's Fortune:
|
|
8
|
+
* - RngClientFactory for environment-based client selection
|
|
9
|
+
* - RngService for audit trail tracking
|
|
10
|
+
* - Full RNG outcome reporting for compliance
|
|
11
|
+
*/
|
|
12
|
+
import { DebugIntrospectable, DebugCommandDefinition } from '@omnitronix/game-engine-contract';
|
|
13
|
+
import { SlotGameHandler, BetConfig as SdkBetConfig, SlotState as SdkSlotState, SpinResult as SdkSpinResult, BonusTrigger as SdkBonusTrigger, BonusResult as SdkBonusResult, GameTypeConfig } from '@omnitronix/game-engine-sdk';
|
|
14
|
+
import { PublicState, PrivateState } from './domain/types';
|
|
15
|
+
import { GameEngine, GameEngineInfo, GameActionCommand, CommandProcessingResult, HappyPandaV1GameEngineConfig, RngOutcome, RngOutcomeRecord } from './game-engine.interface';
|
|
16
|
+
export type { GameEngine, GameEngineInfo, GameActionCommand, CommandProcessingResult, HappyPandaV1GameEngineConfig, RngOutcome, RngOutcomeRecord, };
|
|
17
|
+
/**
|
|
18
|
+
* Happy Panda V1 Game Engine
|
|
19
|
+
*
|
|
20
|
+
* Implements the standard GameEngine interface for use with game-engine-service.
|
|
21
|
+
* Uses proper RNG infrastructure with full audit trail support.
|
|
22
|
+
*/
|
|
23
|
+
export declare class HappyPandaV1GameEngine extends SlotGameHandler implements GameEngine<PublicState, PrivateState, unknown>, DebugIntrospectable {
|
|
24
|
+
/**
|
|
25
|
+
* SDK GameTypeConfig declaration.
|
|
26
|
+
*
|
|
27
|
+
* Declares this engine as a slot game with immediate result delivery
|
|
28
|
+
* and token-encoded state management.
|
|
29
|
+
*/
|
|
30
|
+
static readonly gameTypeConfig: GameTypeConfig;
|
|
31
|
+
private readonly gameCode;
|
|
32
|
+
private readonly version;
|
|
33
|
+
private readonly rtp;
|
|
34
|
+
private readonly gameType;
|
|
35
|
+
private readonly gameName;
|
|
36
|
+
private readonly provider;
|
|
37
|
+
private readonly rngService;
|
|
38
|
+
private readonly rngAdapter;
|
|
39
|
+
private readonly engine;
|
|
40
|
+
constructor(config?: HappyPandaV1GameEngineConfig);
|
|
41
|
+
/**
|
|
42
|
+
* Implements SlotGameHandler.spin().
|
|
43
|
+
*
|
|
44
|
+
* Delegates to the internal HappyPandaEngine SPIN command and maps
|
|
45
|
+
* the result to the SDK SpinResult contract.
|
|
46
|
+
*/
|
|
47
|
+
spin(bet: SdkBetConfig, state: SdkSlotState): Promise<SdkSpinResult>;
|
|
48
|
+
/**
|
|
49
|
+
* Implements SlotGameHandler.startBonus().
|
|
50
|
+
*
|
|
51
|
+
* Delegates to the internal HappyPandaEngine by executing all bonus
|
|
52
|
+
* spins in a loop (precomputed-queue strategy) and returns a
|
|
53
|
+
* BonusResult with attached delivery strategy metadata.
|
|
54
|
+
*/
|
|
55
|
+
startBonus(trigger: SdkBonusTrigger, state: SdkSlotState): Promise<SdkBonusResult>;
|
|
56
|
+
getGameEngineInfo(): GameEngineInfo;
|
|
57
|
+
getDebugCommandDefinitions(): DebugCommandDefinition[];
|
|
58
|
+
processCommand(publicState: PublicState | null, privateState: PrivateState | null, command: GameActionCommand): Promise<CommandProcessingResult<PublicState, PrivateState, unknown>>;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=happy-panda-v1.game-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"happy-panda-v1.game-engine.d.ts","sourceRoot":"","sources":["../src/happy-panda-v1.game-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAEL,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,eAAe,EACf,SAAS,IAAI,YAAY,EACzB,SAAS,IAAI,YAAY,EACzB,UAAU,IAAI,aAAa,EAC3B,YAAY,IAAI,eAAe,EAC/B,WAAW,IAAI,cAAc,EAC7B,cAAc,EAGf,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EAGL,WAAW,EACX,YAAY,EAKb,MAAM,gBAAgB,CAAC;AAKxB,OAAO,EACL,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,uBAAuB,EACvB,4BAA4B,EAC5B,UAAU,EACV,gBAAgB,EACjB,MAAM,yBAAyB,CAAC;AAGjC,YAAY,EACV,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,uBAAuB,EACvB,4BAA4B,EAC5B,UAAU,EACV,gBAAgB,GACjB,CAAC;AAuCF;;;;;GAKG;AACH,qBAAa,sBACX,SAAQ,eACR,YAAW,UAAU,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,mBAAmB;IAE9E;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAW5C;IAEF,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;IACvD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;IAC1C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IAEzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;gBAE9B,MAAM,GAAE,4BAAiC;IAkBrD;;;;;OAKG;IACG,IAAI,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;IA4C1E;;;;;;OAMG;IACG,UAAU,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC;IAsEjF,iBAAiB,IAAI,cAAc;IAWnC,0BAA0B,IAAI,sBAAsB,EAAE;IAIhD,cAAc,CACzB,WAAW,EAAE,WAAW,GAAG,IAAI,EAC/B,YAAY,EAAE,YAAY,GAAG,IAAI,EACjC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,uBAAuB,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;CAkXxE"}
|