@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,524 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* HappyPandaV1GameEngine
|
|
4
|
+
*
|
|
5
|
+
* Wrapper class that adapts HappyPandaEngine to the standard GameEngine interface
|
|
6
|
+
* expected by the game-engine-service infrastructure.
|
|
7
|
+
*
|
|
8
|
+
* Uses the proper RNG infrastructure matching Heroes of Aether and Bonny's Fortune:
|
|
9
|
+
* - RngClientFactory for environment-based client selection
|
|
10
|
+
* - RngService for audit trail tracking
|
|
11
|
+
* - Full RNG outcome reporting for compliance
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.HappyPandaV1GameEngine = void 0;
|
|
15
|
+
const game_engine_sdk_1 = require("@omnitronix/game-engine-sdk");
|
|
16
|
+
const debug_command_definitions_1 = require("./debug/debug-command-definitions");
|
|
17
|
+
const happy_panda_engine_1 = require("./engine/happy-panda-engine");
|
|
18
|
+
const types_1 = require("./domain/types");
|
|
19
|
+
const happy_panda_config_1 = require("./config/happy-panda.config");
|
|
20
|
+
const rng_client_factory_1 = require("./rng/rng-client.factory");
|
|
21
|
+
const rng_service_1 = require("./rng/rng-service");
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
23
|
+
const packageJson = require('../package.json');
|
|
24
|
+
/**
|
|
25
|
+
* RNG Provider adapter that bridges RngService to the engine's RngProvider interface
|
|
26
|
+
*/
|
|
27
|
+
class RngServiceAdapter {
|
|
28
|
+
constructor(rngService) {
|
|
29
|
+
this.rngService = rngService;
|
|
30
|
+
this.currentCommandId = '';
|
|
31
|
+
this.actionCounter = 0;
|
|
32
|
+
}
|
|
33
|
+
setCommandId(commandId) {
|
|
34
|
+
this.currentCommandId = commandId;
|
|
35
|
+
this.actionCounter = 0;
|
|
36
|
+
}
|
|
37
|
+
async random(max) {
|
|
38
|
+
const actionId = `rng_${this.actionCounter++}`;
|
|
39
|
+
const { value } = await this.rngService.getSingleNumber(0, max - 1, this.currentCommandId, actionId);
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
async randomBatch(count, max) {
|
|
43
|
+
const results = [];
|
|
44
|
+
for (let i = 0; i < count; i++) {
|
|
45
|
+
results.push(await this.random(max));
|
|
46
|
+
}
|
|
47
|
+
return results;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Happy Panda V1 Game Engine
|
|
52
|
+
*
|
|
53
|
+
* Implements the standard GameEngine interface for use with game-engine-service.
|
|
54
|
+
* Uses proper RNG infrastructure with full audit trail support.
|
|
55
|
+
*/
|
|
56
|
+
class HappyPandaV1GameEngine extends game_engine_sdk_1.SlotGameHandler {
|
|
57
|
+
constructor(config = {}) {
|
|
58
|
+
super();
|
|
59
|
+
this.gameCode = 'happy-panda';
|
|
60
|
+
this.version = packageJson.version;
|
|
61
|
+
this.rtp = 96.05;
|
|
62
|
+
this.gameType = 'slot';
|
|
63
|
+
this.gameName = 'Happy Panda';
|
|
64
|
+
this.provider = 'Omnitronix';
|
|
65
|
+
// Create RNG client based on environment (local for dev, external for prod)
|
|
66
|
+
const rngClient = rng_client_factory_1.RngClientFactory.create({ metrics: config.metrics });
|
|
67
|
+
// Wrap in service for audit trail tracking
|
|
68
|
+
this.rngService = new rng_service_1.RngService(rngClient);
|
|
69
|
+
// Create adapter to bridge to engine's RngProvider interface
|
|
70
|
+
this.rngAdapter = new RngServiceAdapter(this.rngService);
|
|
71
|
+
// Initialize engine with RNG adapter
|
|
72
|
+
this.engine = new happy_panda_engine_1.HappyPandaEngine(this.rngAdapter);
|
|
73
|
+
}
|
|
74
|
+
// ── SlotGameHandler abstract method implementations ──────────────
|
|
75
|
+
/**
|
|
76
|
+
* Implements SlotGameHandler.spin().
|
|
77
|
+
*
|
|
78
|
+
* Delegates to the internal HappyPandaEngine SPIN command and maps
|
|
79
|
+
* the result to the SDK SpinResult contract.
|
|
80
|
+
*/
|
|
81
|
+
async spin(bet, state) {
|
|
82
|
+
const commandId = `spin-${Date.now()}`;
|
|
83
|
+
this.rngService.registerCommand(commandId);
|
|
84
|
+
this.rngAdapter.setCommandId(commandId);
|
|
85
|
+
try {
|
|
86
|
+
const lines = bet.lines ?? 8;
|
|
87
|
+
const betStake = bet.amount / lines;
|
|
88
|
+
const publicState = {
|
|
89
|
+
...(state.currentRound ?? {}),
|
|
90
|
+
betStake,
|
|
91
|
+
betGame: bet.amount,
|
|
92
|
+
balance: state.balance,
|
|
93
|
+
};
|
|
94
|
+
const sessionState = {
|
|
95
|
+
sessionId: commandId,
|
|
96
|
+
publicState,
|
|
97
|
+
privateState: state.currentRound?.privateState ?? {},
|
|
98
|
+
createdAt: new Date(),
|
|
99
|
+
updatedAt: new Date(),
|
|
100
|
+
};
|
|
101
|
+
const result = await this.engine.handleCommand({ command: types_1.CommandType.SPIN, sessionId: commandId }, sessionState);
|
|
102
|
+
const spinResponse = result.response;
|
|
103
|
+
return {
|
|
104
|
+
outcome: spinResponse,
|
|
105
|
+
winAmount: spinResponse.playerWinning,
|
|
106
|
+
nextState: {
|
|
107
|
+
balance: state.balance - bet.amount + spinResponse.playerWinning,
|
|
108
|
+
currentRound: { ...result.state.publicState, privateState: result.state.privateState },
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
this.rngService.removeCommand(commandId);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Implements SlotGameHandler.startBonus().
|
|
118
|
+
*
|
|
119
|
+
* Delegates to the internal HappyPandaEngine by executing all bonus
|
|
120
|
+
* spins in a loop (precomputed-queue strategy) and returns a
|
|
121
|
+
* BonusResult with attached delivery strategy metadata.
|
|
122
|
+
*/
|
|
123
|
+
async startBonus(trigger, state) {
|
|
124
|
+
const commandId = `bonus-${Date.now()}`;
|
|
125
|
+
this.rngService.registerCommand(commandId);
|
|
126
|
+
this.rngAdapter.setCommandId(commandId);
|
|
127
|
+
try {
|
|
128
|
+
const roundData = state.currentRound;
|
|
129
|
+
const publicState = roundData?.publicState
|
|
130
|
+
?? roundData
|
|
131
|
+
?? {};
|
|
132
|
+
const privateState = roundData?.privateState
|
|
133
|
+
?? {};
|
|
134
|
+
const sessionState = {
|
|
135
|
+
sessionId: commandId,
|
|
136
|
+
publicState,
|
|
137
|
+
privateState,
|
|
138
|
+
createdAt: new Date(),
|
|
139
|
+
updatedAt: new Date(),
|
|
140
|
+
};
|
|
141
|
+
const spinResults = [];
|
|
142
|
+
let currentState = sessionState;
|
|
143
|
+
let totalWin = 0;
|
|
144
|
+
let iteration = 0;
|
|
145
|
+
while (currentState.publicState.currentSpinType !== happy_panda_config_1.SpinType.BASE_GAME_SPIN ||
|
|
146
|
+
currentState.publicState.spinsRemaining > 0 ||
|
|
147
|
+
currentState.publicState.hasPendingBonus) {
|
|
148
|
+
iteration++;
|
|
149
|
+
if (iteration > 100)
|
|
150
|
+
break;
|
|
151
|
+
const spinResult = await this.engine.handleCommand({ command: types_1.CommandType.SPIN, sessionId: commandId }, currentState);
|
|
152
|
+
const response = spinResult.response;
|
|
153
|
+
totalWin += response.playerWinning;
|
|
154
|
+
spinResults.push({
|
|
155
|
+
outcome: response,
|
|
156
|
+
winAmount: response.playerWinning,
|
|
157
|
+
nextState: {
|
|
158
|
+
balance: state.balance + totalWin,
|
|
159
|
+
currentRound: { ...spinResult.state.publicState, privateState: spinResult.state.privateState },
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
currentState = spinResult.state;
|
|
163
|
+
if (currentState.publicState.currentSpinType === happy_panda_config_1.SpinType.BASE_GAME_SPIN &&
|
|
164
|
+
currentState.publicState.spinsRemaining === 0 &&
|
|
165
|
+
!currentState.publicState.hasPendingBonus) {
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return { spins: spinResults, totalWin };
|
|
170
|
+
}
|
|
171
|
+
finally {
|
|
172
|
+
this.rngService.removeCommand(commandId);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// ── GameEngine + DebugIntrospectable interface ──────────────────
|
|
176
|
+
getGameEngineInfo() {
|
|
177
|
+
return {
|
|
178
|
+
gameCode: this.gameCode,
|
|
179
|
+
version: this.version,
|
|
180
|
+
rtp: this.rtp,
|
|
181
|
+
gameType: this.gameType,
|
|
182
|
+
gameName: this.gameName,
|
|
183
|
+
provider: this.provider,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
getDebugCommandDefinitions() {
|
|
187
|
+
return (0, debug_command_definitions_1.getDebugCommandDefinitions)();
|
|
188
|
+
}
|
|
189
|
+
async processCommand(publicState, privateState, command) {
|
|
190
|
+
// Register command for RNG audit trail
|
|
191
|
+
this.rngService.registerCommand(command.id);
|
|
192
|
+
this.rngAdapter.setCommandId(command.id);
|
|
193
|
+
try {
|
|
194
|
+
switch (command.type) {
|
|
195
|
+
case 'INIT_SESSION_STATE': {
|
|
196
|
+
const payload = command.payload || {};
|
|
197
|
+
const gameDirection = payload.gameDirection ?? types_1.GameDirection.SINGLE;
|
|
198
|
+
const betStake = payload.betStake ?? 1;
|
|
199
|
+
const result = await this.engine.handleCommand({
|
|
200
|
+
command: types_1.CommandType.INIT_SESSION_STATE,
|
|
201
|
+
sessionId: command.id,
|
|
202
|
+
gameDirection,
|
|
203
|
+
betStake,
|
|
204
|
+
});
|
|
205
|
+
const rngOutcome = this.rngService.getRngOutcomeForCommand(command.id);
|
|
206
|
+
this.rngService.removeCommand(command.id);
|
|
207
|
+
return {
|
|
208
|
+
success: true,
|
|
209
|
+
publicState: result.state.publicState,
|
|
210
|
+
privateState: result.state.privateState,
|
|
211
|
+
outcome: result.response,
|
|
212
|
+
message: 'Session initialized',
|
|
213
|
+
rngOutcome,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
case 'SPIN': {
|
|
217
|
+
if (!publicState || !privateState) {
|
|
218
|
+
this.rngService.removeCommand(command.id);
|
|
219
|
+
return {
|
|
220
|
+
success: false,
|
|
221
|
+
publicState: publicState,
|
|
222
|
+
privateState: privateState,
|
|
223
|
+
message: 'State not initialized',
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
// Extract betAmount and lines from payload - this is the TOTAL bet from RGS
|
|
227
|
+
const payload = command.payload || {};
|
|
228
|
+
const betAmount = payload.betAmount;
|
|
229
|
+
const payloadLines = payload.lines;
|
|
230
|
+
// Update bet if betAmount provided (RGS sends total bet, not stake)
|
|
231
|
+
let updatedPublicState = publicState;
|
|
232
|
+
if (betAmount !== undefined && betAmount > 0) {
|
|
233
|
+
// Use lines from payload if provided, otherwise fall back to gameDirection
|
|
234
|
+
const lines = payloadLines || (publicState.gameDirection === types_1.GameDirection.SINGLE ? 8 : 16);
|
|
235
|
+
const betStake = betAmount / lines;
|
|
236
|
+
const betGame = betAmount; // Total bet = lines × stake
|
|
237
|
+
updatedPublicState = {
|
|
238
|
+
...publicState,
|
|
239
|
+
betStake,
|
|
240
|
+
betGame,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
// Create a proper SessionState from public/private state
|
|
244
|
+
const sessionState = {
|
|
245
|
+
sessionId: command.id,
|
|
246
|
+
publicState: updatedPublicState,
|
|
247
|
+
privateState,
|
|
248
|
+
createdAt: new Date(),
|
|
249
|
+
updatedAt: new Date(),
|
|
250
|
+
};
|
|
251
|
+
const result = await this.engine.handleCommand({
|
|
252
|
+
command: types_1.CommandType.SPIN,
|
|
253
|
+
sessionId: command.id,
|
|
254
|
+
}, sessionState);
|
|
255
|
+
const rngOutcome = this.rngService.getRngOutcomeForCommand(command.id);
|
|
256
|
+
this.rngService.removeCommand(command.id);
|
|
257
|
+
// SpinResponse now uses 'screen' directly (unified with other games)
|
|
258
|
+
const spinResponse = result.response;
|
|
259
|
+
return {
|
|
260
|
+
success: true,
|
|
261
|
+
publicState: result.state.publicState,
|
|
262
|
+
privateState: result.state.privateState,
|
|
263
|
+
outcome: {
|
|
264
|
+
result: spinResponse, // Wrap in result object for RGS compatibility
|
|
265
|
+
publicState: result.state.publicState, // Required for RGS state persistence
|
|
266
|
+
privateState: result.state.privateState, // Required for RGS state persistence
|
|
267
|
+
},
|
|
268
|
+
message: 'Spin completed',
|
|
269
|
+
rngOutcome,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
case 'GET_SYMBOLS': {
|
|
273
|
+
const result = await this.engine.handleCommand({
|
|
274
|
+
command: types_1.CommandType.GET_SYMBOLS,
|
|
275
|
+
sessionId: command.id,
|
|
276
|
+
});
|
|
277
|
+
this.rngService.removeCommand(command.id);
|
|
278
|
+
return {
|
|
279
|
+
success: true,
|
|
280
|
+
publicState: publicState,
|
|
281
|
+
privateState: privateState,
|
|
282
|
+
outcome: result.response,
|
|
283
|
+
message: 'Symbols retrieved',
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
case 'START_BONUS_ROUND': {
|
|
287
|
+
if (!publicState || !privateState) {
|
|
288
|
+
this.rngService.removeCommand(command.id);
|
|
289
|
+
return {
|
|
290
|
+
success: false,
|
|
291
|
+
publicState: publicState,
|
|
292
|
+
privateState: privateState,
|
|
293
|
+
message: 'State not initialized',
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
const payload = command.payload;
|
|
297
|
+
if (!payload || !payload.bonusType) {
|
|
298
|
+
this.rngService.removeCommand(command.id);
|
|
299
|
+
return {
|
|
300
|
+
success: false,
|
|
301
|
+
publicState,
|
|
302
|
+
privateState,
|
|
303
|
+
message: 'Missing bonusType in payload',
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
// Check if there's actually a bonus to start (prevents double-start issues)
|
|
307
|
+
const hasBonusToStart = publicState.currentSpinType !== happy_panda_config_1.SpinType.BASE_GAME_SPIN ||
|
|
308
|
+
publicState.spinsRemaining > 0 ||
|
|
309
|
+
publicState.hasPendingBonus;
|
|
310
|
+
if (!hasBonusToStart) {
|
|
311
|
+
this.rngService.removeCommand(command.id);
|
|
312
|
+
return {
|
|
313
|
+
success: false,
|
|
314
|
+
publicState,
|
|
315
|
+
privateState,
|
|
316
|
+
message: 'No pending bonuses to start.',
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
// Create session state for executing bonus spins
|
|
320
|
+
const sessionState = {
|
|
321
|
+
sessionId: command.id,
|
|
322
|
+
publicState,
|
|
323
|
+
privateState,
|
|
324
|
+
createdAt: new Date(),
|
|
325
|
+
updatedAt: new Date(),
|
|
326
|
+
};
|
|
327
|
+
// Execute ALL bonus spins and collect results
|
|
328
|
+
const bonusResults = [];
|
|
329
|
+
let currentState = sessionState;
|
|
330
|
+
let totalBonusWin = 0;
|
|
331
|
+
// Execute spins until bonus is complete
|
|
332
|
+
// Loop while: not in BASE_GAME_SPIN mode, OR has spins remaining, OR has pending bonuses
|
|
333
|
+
let iteration = 0;
|
|
334
|
+
while (currentState.publicState.currentSpinType !== happy_panda_config_1.SpinType.BASE_GAME_SPIN ||
|
|
335
|
+
currentState.publicState.spinsRemaining > 0 ||
|
|
336
|
+
currentState.publicState.hasPendingBonus) {
|
|
337
|
+
iteration++;
|
|
338
|
+
const spinResult = await this.engine.handleCommand({
|
|
339
|
+
command: types_1.CommandType.SPIN,
|
|
340
|
+
sessionId: command.id,
|
|
341
|
+
}, currentState);
|
|
342
|
+
const response = spinResult.response;
|
|
343
|
+
bonusResults.push(response);
|
|
344
|
+
totalBonusWin += response.playerWinning;
|
|
345
|
+
// Update state for next iteration
|
|
346
|
+
currentState = spinResult.state;
|
|
347
|
+
// Safety check - if we've done 100 spins, something is wrong
|
|
348
|
+
if (bonusResults.length > 100) {
|
|
349
|
+
this.rngService.removeCommand(command.id);
|
|
350
|
+
return {
|
|
351
|
+
success: false,
|
|
352
|
+
publicState: currentState.publicState,
|
|
353
|
+
privateState: currentState.privateState,
|
|
354
|
+
message: 'Bonus round exceeded maximum iterations',
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
// If we're back to BASE_GAME_SPIN and no more pending bonuses, break
|
|
358
|
+
if (currentState.publicState.currentSpinType === happy_panda_config_1.SpinType.BASE_GAME_SPIN &&
|
|
359
|
+
currentState.publicState.spinsRemaining === 0 &&
|
|
360
|
+
!currentState.publicState.hasPendingBonus) {
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
const rngOutcome = this.rngService.getRngOutcomeForCommand(command.id);
|
|
365
|
+
this.rngService.removeCommand(command.id);
|
|
366
|
+
// Declare delivery strategy for the platform (precomputed-queue for slots)
|
|
367
|
+
const deliveryStrategy = {
|
|
368
|
+
type: 'precomputed-queue',
|
|
369
|
+
getResultsArray: () => bonusResults,
|
|
370
|
+
};
|
|
371
|
+
return {
|
|
372
|
+
success: true,
|
|
373
|
+
publicState: currentState.publicState,
|
|
374
|
+
privateState: currentState.privateState,
|
|
375
|
+
outcome: {
|
|
376
|
+
results: bonusResults,
|
|
377
|
+
activeBonus: {
|
|
378
|
+
bonusId: payload.bonusId,
|
|
379
|
+
bonusType: payload.bonusType,
|
|
380
|
+
betAmount: publicState.betGame,
|
|
381
|
+
},
|
|
382
|
+
totalBonusWin,
|
|
383
|
+
deliveryStrategy,
|
|
384
|
+
publicState: currentState.publicState,
|
|
385
|
+
privateState: currentState.privateState,
|
|
386
|
+
},
|
|
387
|
+
message: 'Bonus round completed',
|
|
388
|
+
rngOutcome,
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
case 'DEBUG_TRIGGER_BONUS': {
|
|
392
|
+
if (!publicState || !privateState) {
|
|
393
|
+
this.rngService.removeCommand(command.id);
|
|
394
|
+
return {
|
|
395
|
+
success: false,
|
|
396
|
+
publicState: publicState,
|
|
397
|
+
privateState: privateState,
|
|
398
|
+
message: 'State not initialized',
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
const params = command.payload;
|
|
402
|
+
const bonusId = `debug-${Date.now()}-${Math.random().toString(36).substring(7)}`;
|
|
403
|
+
// Map bonus type string to SpinType
|
|
404
|
+
let nextSpinType;
|
|
405
|
+
switch (params.bonusType) {
|
|
406
|
+
case 'BONUS_BAMBOO_TRIPLETS':
|
|
407
|
+
nextSpinType = happy_panda_config_1.SpinType.BONUS_BAMBOO_TRIPLETS;
|
|
408
|
+
break;
|
|
409
|
+
case 'BONUS_BAMBOO_TWINS':
|
|
410
|
+
nextSpinType = happy_panda_config_1.SpinType.BONUS_BAMBOO_TWINS;
|
|
411
|
+
break;
|
|
412
|
+
case 'BONUS_CAMERA':
|
|
413
|
+
nextSpinType = happy_panda_config_1.SpinType.BONUS_CAMERA;
|
|
414
|
+
break;
|
|
415
|
+
case 'BONUS_FIREWORKS':
|
|
416
|
+
nextSpinType = happy_panda_config_1.SpinType.BONUS_FIREWORKS;
|
|
417
|
+
break;
|
|
418
|
+
case 'RESPIN_CENTER_BAMBOO':
|
|
419
|
+
nextSpinType = happy_panda_config_1.SpinType.RESPIN_CENTER_BAMBOO;
|
|
420
|
+
break;
|
|
421
|
+
default:
|
|
422
|
+
this.rngService.removeCommand(command.id);
|
|
423
|
+
return {
|
|
424
|
+
success: false,
|
|
425
|
+
publicState,
|
|
426
|
+
privateState,
|
|
427
|
+
message: `Unknown bonus type: ${params.bonusType}`,
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
// Update state to trigger bonus on next spin
|
|
431
|
+
const updatedPublicState = {
|
|
432
|
+
...publicState,
|
|
433
|
+
hasPendingBonus: true,
|
|
434
|
+
};
|
|
435
|
+
// Increment the internal pending bonus counter
|
|
436
|
+
const internalPending = privateState.internalPendingBonuses || {
|
|
437
|
+
bambooTriplets: 0, bambooTwins: 0, camera: 0, fireworks: 0, centerBamboo: 0
|
|
438
|
+
};
|
|
439
|
+
const updatedInternalPending = {
|
|
440
|
+
...internalPending,
|
|
441
|
+
bambooTriplets: params.bonusType === 'BONUS_BAMBOO_TRIPLETS' ? internalPending.bambooTriplets + 1 : internalPending.bambooTriplets,
|
|
442
|
+
bambooTwins: params.bonusType === 'BONUS_BAMBOO_TWINS' ? internalPending.bambooTwins + 1 : internalPending.bambooTwins,
|
|
443
|
+
camera: params.bonusType === 'BONUS_CAMERA' ? internalPending.camera + 1 : internalPending.camera,
|
|
444
|
+
fireworks: params.bonusType === 'BONUS_FIREWORKS' ? internalPending.fireworks + 1 : internalPending.fireworks,
|
|
445
|
+
centerBamboo: params.bonusType === 'RESPIN_CENTER_BAMBOO' ? internalPending.centerBamboo + 1 : internalPending.centerBamboo,
|
|
446
|
+
};
|
|
447
|
+
// Add to RGS-compatible pendingBonuses array
|
|
448
|
+
const newPendingBonus = {
|
|
449
|
+
bonusId,
|
|
450
|
+
bonusType: params.bonusType,
|
|
451
|
+
betAmount: params.betAmount,
|
|
452
|
+
};
|
|
453
|
+
const updatedPendingBonusesArray = [
|
|
454
|
+
...(privateState.pendingBonuses || []),
|
|
455
|
+
newPendingBonus,
|
|
456
|
+
];
|
|
457
|
+
const updatedPrivateState = {
|
|
458
|
+
...privateState,
|
|
459
|
+
nextSpinType,
|
|
460
|
+
internalPendingBonuses: updatedInternalPending,
|
|
461
|
+
pendingBonuses: updatedPendingBonusesArray,
|
|
462
|
+
};
|
|
463
|
+
const rngOutcome = this.rngService.getRngOutcomeForCommand(command.id);
|
|
464
|
+
this.rngService.removeCommand(command.id);
|
|
465
|
+
return {
|
|
466
|
+
success: true,
|
|
467
|
+
publicState: updatedPublicState,
|
|
468
|
+
privateState: updatedPrivateState,
|
|
469
|
+
outcome: {
|
|
470
|
+
triggeredBonus: {
|
|
471
|
+
bonusId,
|
|
472
|
+
bonusType: params.bonusType,
|
|
473
|
+
betAmount: params.betAmount,
|
|
474
|
+
},
|
|
475
|
+
nextSpinType: updatedPrivateState.nextSpinType,
|
|
476
|
+
autoStarted: false,
|
|
477
|
+
requiresStartCommand: true,
|
|
478
|
+
},
|
|
479
|
+
message: 'Bonus triggered via debug command',
|
|
480
|
+
rngOutcome,
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
default: {
|
|
484
|
+
this.rngService.removeCommand(command.id);
|
|
485
|
+
return {
|
|
486
|
+
success: false,
|
|
487
|
+
publicState: publicState,
|
|
488
|
+
privateState: privateState,
|
|
489
|
+
message: `Unknown command type: ${command.type}`,
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
catch (error) {
|
|
495
|
+
this.rngService.removeCommand(command.id);
|
|
496
|
+
return {
|
|
497
|
+
success: false,
|
|
498
|
+
publicState: publicState,
|
|
499
|
+
privateState: privateState,
|
|
500
|
+
message: error.message || 'Unknown error',
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
exports.HappyPandaV1GameEngine = HappyPandaV1GameEngine;
|
|
506
|
+
/**
|
|
507
|
+
* SDK GameTypeConfig declaration.
|
|
508
|
+
*
|
|
509
|
+
* Declares this engine as a slot game with immediate result delivery
|
|
510
|
+
* and token-encoded state management.
|
|
511
|
+
*/
|
|
512
|
+
HappyPandaV1GameEngine.gameTypeConfig = {
|
|
513
|
+
gameType: 'slot',
|
|
514
|
+
resultDelivery: { mode: 'immediate' },
|
|
515
|
+
stateStrategy: {
|
|
516
|
+
type: 'token-encoded',
|
|
517
|
+
tokenConfig: {
|
|
518
|
+
algorithm: 'aes-256-gcm',
|
|
519
|
+
keyDerivation: 'hkdf',
|
|
520
|
+
tokenTtlSeconds: 3600,
|
|
521
|
+
},
|
|
522
|
+
},
|
|
523
|
+
};
|
|
524
|
+
//# sourceMappingURL=happy-panda-v1.game-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"happy-panda-v1.game-engine.js","sourceRoot":"","sources":["../src/happy-panda-v1.game-engine.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Happy Panda Game Engine
|
|
3
|
+
*
|
|
4
|
+
* A 3x3 slot game engine with 8/16 bidirectional paylines.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
export { HappyPandaV1GameEngine } from './happy-panda-v1.game-engine';
|
|
9
|
+
export type { GameTypeConfig, BonusResultDeliveryStrategy, BonusRoundResponse } from '@omnitronix/game-engine-sdk';
|
|
10
|
+
export type { GameEngine, GameEngineInfo, GameActionCommand, CommandProcessingResult, RngOutcome, RngOutcomeRecord, ILogger, HappyPandaV1GameEngineConfig, } from './game-engine.interface';
|
|
11
|
+
export { GameType, GameRoundType, GameRoundStatus, CommandType as ContractCommandType, DEBUG_COMMAND_TYPES, isDebugCommand, ConsoleLogger, DebugIntrospectable, DebugCommandDefinition, isDebugIntrospectable, } from '@omnitronix/game-engine-contract';
|
|
12
|
+
export { HAPPY_PANDA_BONUS_TYPES, HAPPY_PANDA_DEBUG_DEFINITIONS, getDebugCommandDefinitions, DebugSecurityError, } from './debug/debug-command-definitions';
|
|
13
|
+
export { HappyPandaEngine } from './engine';
|
|
14
|
+
export { Symbol, SpinType, ScreenWinType, GRID, LINE_SHAPES, LINES_PER_DIRECTION, } from './config';
|
|
15
|
+
export { Grid, Position, LineWin, WallWin, ScatterWin, SpecialWin, SpinWinResult, BonusCounters, PendingBonuses, JackpotState, GameDirection, GameState, PublicState, PrivateState, SpinRequest, SpinResponse, SessionState, RngProvider, CommandType, GameCommand, InitSessionRequest, SpinCommandRequest, GetSymbolsRequest, } from './domain';
|
|
16
|
+
export { evaluateSpin, evaluateLineWins, evaluateWallWin, evaluateScatterWins } from './logic/services';
|
|
17
|
+
export { generateGrid } from './rng';
|
|
18
|
+
export { IRngClient, RngSingleResponse, RngBatchResponse, } from './rng/rng-client.interface';
|
|
19
|
+
export { DummyRngClient } from './rng/dummy-rng-client';
|
|
20
|
+
export { RngClientFactory, RngClientConfig } from './rng/rng-client.factory';
|
|
21
|
+
export { RngService } from './rng/rng-service';
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAGtE,YAAY,EAAE,cAAc,EAAE,2BAA2B,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAGnH,YAAY,EACV,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,uBAAuB,EACvB,UAAU,EACV,gBAAgB,EAChB,OAAO,EACP,4BAA4B,GAC7B,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACL,QAAQ,EACR,aAAa,EACb,eAAe,EACf,WAAW,IAAI,mBAAmB,EAClC,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,kCAAkC,CAAC;AAG1C,OAAO,EACL,uBAAuB,EACvB,6BAA6B,EAC7B,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAG5C,OAAO,EACL,MAAM,EACN,QAAQ,EACR,aAAa,EACb,IAAI,EACJ,WAAW,EACX,mBAAmB,GACpB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,OAAO,EACP,UAAU,EACV,UAAU,EACV,aAAa,EACb,aAAa,EACb,cAAc,EACd,YAAY,EACZ,aAAa,EACb,SAAS,EACT,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACxG,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAGrC,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Happy Panda Game Engine
|
|
4
|
+
*
|
|
5
|
+
* A 3x3 slot game engine with 8/16 bidirectional paylines.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.RngService = exports.RngClientFactory = exports.DummyRngClient = exports.generateGrid = exports.evaluateScatterWins = exports.evaluateWallWin = exports.evaluateLineWins = exports.evaluateSpin = exports.CommandType = exports.GameDirection = exports.LINES_PER_DIRECTION = exports.LINE_SHAPES = exports.GRID = exports.ScreenWinType = exports.SpinType = exports.Symbol = exports.HappyPandaEngine = exports.DebugSecurityError = exports.getDebugCommandDefinitions = exports.HAPPY_PANDA_DEBUG_DEFINITIONS = exports.HAPPY_PANDA_BONUS_TYPES = exports.isDebugIntrospectable = exports.ConsoleLogger = exports.isDebugCommand = exports.DEBUG_COMMAND_TYPES = exports.ContractCommandType = exports.GameRoundStatus = exports.GameRoundType = exports.GameType = exports.HappyPandaV1GameEngine = void 0;
|
|
11
|
+
// V1 Game Engine (for game-engine-service integration)
|
|
12
|
+
var happy_panda_v1_game_engine_1 = require("./happy-panda-v1.game-engine");
|
|
13
|
+
Object.defineProperty(exports, "HappyPandaV1GameEngine", { enumerable: true, get: function () { return happy_panda_v1_game_engine_1.HappyPandaV1GameEngine; } });
|
|
14
|
+
// Re-export contract types for convenience
|
|
15
|
+
var game_engine_contract_1 = require("@omnitronix/game-engine-contract");
|
|
16
|
+
Object.defineProperty(exports, "GameType", { enumerable: true, get: function () { return game_engine_contract_1.GameType; } });
|
|
17
|
+
Object.defineProperty(exports, "GameRoundType", { enumerable: true, get: function () { return game_engine_contract_1.GameRoundType; } });
|
|
18
|
+
Object.defineProperty(exports, "GameRoundStatus", { enumerable: true, get: function () { return game_engine_contract_1.GameRoundStatus; } });
|
|
19
|
+
Object.defineProperty(exports, "ContractCommandType", { enumerable: true, get: function () { return game_engine_contract_1.CommandType; } });
|
|
20
|
+
Object.defineProperty(exports, "DEBUG_COMMAND_TYPES", { enumerable: true, get: function () { return game_engine_contract_1.DEBUG_COMMAND_TYPES; } });
|
|
21
|
+
Object.defineProperty(exports, "isDebugCommand", { enumerable: true, get: function () { return game_engine_contract_1.isDebugCommand; } });
|
|
22
|
+
Object.defineProperty(exports, "ConsoleLogger", { enumerable: true, get: function () { return game_engine_contract_1.ConsoleLogger; } });
|
|
23
|
+
Object.defineProperty(exports, "isDebugIntrospectable", { enumerable: true, get: function () { return game_engine_contract_1.isDebugIntrospectable; } });
|
|
24
|
+
// Debug command definitions
|
|
25
|
+
var debug_command_definitions_1 = require("./debug/debug-command-definitions");
|
|
26
|
+
Object.defineProperty(exports, "HAPPY_PANDA_BONUS_TYPES", { enumerable: true, get: function () { return debug_command_definitions_1.HAPPY_PANDA_BONUS_TYPES; } });
|
|
27
|
+
Object.defineProperty(exports, "HAPPY_PANDA_DEBUG_DEFINITIONS", { enumerable: true, get: function () { return debug_command_definitions_1.HAPPY_PANDA_DEBUG_DEFINITIONS; } });
|
|
28
|
+
Object.defineProperty(exports, "getDebugCommandDefinitions", { enumerable: true, get: function () { return debug_command_definitions_1.getDebugCommandDefinitions; } });
|
|
29
|
+
Object.defineProperty(exports, "DebugSecurityError", { enumerable: true, get: function () { return debug_command_definitions_1.DebugSecurityError; } });
|
|
30
|
+
// Core engine
|
|
31
|
+
var engine_1 = require("./engine");
|
|
32
|
+
Object.defineProperty(exports, "HappyPandaEngine", { enumerable: true, get: function () { return engine_1.HappyPandaEngine; } });
|
|
33
|
+
// Configuration
|
|
34
|
+
var config_1 = require("./config");
|
|
35
|
+
Object.defineProperty(exports, "Symbol", { enumerable: true, get: function () { return config_1.Symbol; } });
|
|
36
|
+
Object.defineProperty(exports, "SpinType", { enumerable: true, get: function () { return config_1.SpinType; } });
|
|
37
|
+
Object.defineProperty(exports, "ScreenWinType", { enumerable: true, get: function () { return config_1.ScreenWinType; } });
|
|
38
|
+
Object.defineProperty(exports, "GRID", { enumerable: true, get: function () { return config_1.GRID; } });
|
|
39
|
+
Object.defineProperty(exports, "LINE_SHAPES", { enumerable: true, get: function () { return config_1.LINE_SHAPES; } });
|
|
40
|
+
Object.defineProperty(exports, "LINES_PER_DIRECTION", { enumerable: true, get: function () { return config_1.LINES_PER_DIRECTION; } });
|
|
41
|
+
// Domain types
|
|
42
|
+
var domain_1 = require("./domain");
|
|
43
|
+
Object.defineProperty(exports, "GameDirection", { enumerable: true, get: function () { return domain_1.GameDirection; } });
|
|
44
|
+
Object.defineProperty(exports, "CommandType", { enumerable: true, get: function () { return domain_1.CommandType; } });
|
|
45
|
+
// Logic services (for testing/extension)
|
|
46
|
+
var services_1 = require("./logic/services");
|
|
47
|
+
Object.defineProperty(exports, "evaluateSpin", { enumerable: true, get: function () { return services_1.evaluateSpin; } });
|
|
48
|
+
Object.defineProperty(exports, "evaluateLineWins", { enumerable: true, get: function () { return services_1.evaluateLineWins; } });
|
|
49
|
+
Object.defineProperty(exports, "evaluateWallWin", { enumerable: true, get: function () { return services_1.evaluateWallWin; } });
|
|
50
|
+
Object.defineProperty(exports, "evaluateScatterWins", { enumerable: true, get: function () { return services_1.evaluateScatterWins; } });
|
|
51
|
+
var rng_1 = require("./rng");
|
|
52
|
+
Object.defineProperty(exports, "generateGrid", { enumerable: true, get: function () { return rng_1.generateGrid; } });
|
|
53
|
+
var dummy_rng_client_1 = require("./rng/dummy-rng-client");
|
|
54
|
+
Object.defineProperty(exports, "DummyRngClient", { enumerable: true, get: function () { return dummy_rng_client_1.DummyRngClient; } });
|
|
55
|
+
var rng_client_factory_1 = require("./rng/rng-client.factory");
|
|
56
|
+
Object.defineProperty(exports, "RngClientFactory", { enumerable: true, get: function () { return rng_client_factory_1.RngClientFactory; } });
|
|
57
|
+
var rng_service_1 = require("./rng/rng-service");
|
|
58
|
+
Object.defineProperty(exports, "RngService", { enumerable: true, get: function () { return rng_service_1.RngService; } });
|
|
59
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAEH,uDAAuD;AACvD,2EAAsE;AAA7D,oIAAA,sBAAsB,OAAA;AAiB/B,2CAA2C;AAC3C,yEAW0C;AAVxC,gHAAA,QAAQ,OAAA;AACR,qHAAA,aAAa,OAAA;AACb,uHAAA,eAAe,OAAA;AACf,2HAAA,WAAW,OAAuB;AAClC,2HAAA,mBAAmB,OAAA;AACnB,sHAAA,cAAc,OAAA;AACd,qHAAA,aAAa,OAAA;AAGb,6HAAA,qBAAqB,OAAA;AAGvB,4BAA4B;AAC5B,+EAK2C;AAJzC,oIAAA,uBAAuB,OAAA;AACvB,0IAAA,6BAA6B,OAAA;AAC7B,uIAAA,0BAA0B,OAAA;AAC1B,+HAAA,kBAAkB,OAAA;AAGpB,cAAc;AACd,mCAA4C;AAAnC,0GAAA,gBAAgB,OAAA;AAEzB,gBAAgB;AAChB,mCAOkB;AANhB,gGAAA,MAAM,OAAA;AACN,kGAAA,QAAQ,OAAA;AACR,uGAAA,aAAa,OAAA;AACb,8FAAA,IAAI,OAAA;AACJ,qGAAA,WAAW,OAAA;AACX,6GAAA,mBAAmB,OAAA;AAGrB,eAAe;AACf,mCAwBkB;AAbhB,uGAAA,aAAa,OAAA;AAQb,qGAAA,WAAW,OAAA;AAOb,yCAAyC;AACzC,6CAAwG;AAA/F,wGAAA,YAAY,OAAA;AAAE,4GAAA,gBAAgB,OAAA;AAAE,2GAAA,eAAe,OAAA;AAAE,+GAAA,mBAAmB,OAAA;AAC7E,6BAAqC;AAA5B,mGAAA,YAAY,OAAA;AAQrB,2DAAwD;AAA/C,kHAAA,cAAc,OAAA;AACvB,+DAA6E;AAApE,sHAAA,gBAAgB,OAAA;AACzB,iDAA+C;AAAtC,yGAAA,UAAU,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/logic/handlers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,gBAAgB,CAAC"}
|