@omnitronix/bonnys-fortune-game-engine 1.3.2 → 1.5.0
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 +25 -15
- package/dist/__tests__/base-game.test.js +255 -0
- package/dist/__tests__/base-game.test.js.map +1 -0
- package/dist/__tests__/bonnys-fortune-v1.game-engine.test.js +1 -1
- package/dist/__tests__/bonus-handlers.test.js +303 -0
- package/dist/__tests__/bonus-handlers.test.js.map +1 -0
- package/dist/__tests__/bonus-meters.test.js +508 -0
- package/dist/__tests__/bonus-meters.test.js.map +1 -0
- package/dist/__tests__/collect-feature-handler.test.js +386 -0
- package/dist/__tests__/collect-feature-handler.test.js.map +1 -0
- package/dist/__tests__/comprehensive.test.js +747 -0
- package/dist/__tests__/comprehensive.test.js.map +1 -0
- package/dist/__tests__/error-paths.test.js +373 -0
- package/dist/__tests__/error-paths.test.js.map +1 -0
- package/dist/__tests__/helpers/test-engine-factory.js +268 -0
- package/dist/__tests__/helpers/test-engine-factory.js.map +1 -0
- package/dist/__tests__/rng-gli19-compliance.test.js +292 -0
- package/dist/__tests__/rng-gli19-compliance.test.js.map +1 -0
- package/dist/__tests__/rng-security.test.js +383 -0
- package/dist/__tests__/rng-security.test.js.map +1 -0
- package/dist/__tests__/rtp-simulation.test.js +242 -0
- package/dist/__tests__/rtp-simulation.test.js.map +1 -0
- package/dist/__tests__/state-transitions.test.js +307 -0
- package/dist/__tests__/state-transitions.test.js.map +1 -0
- package/dist/__tests__/steering-fortune-handler.test.js +286 -0
- package/dist/__tests__/steering-fortune-handler.test.js.map +1 -0
- package/dist/__tests__/symbol-distribution.test.js +195 -0
- package/dist/__tests__/symbol-distribution.test.js.map +1 -0
- package/dist/__tests__/treasure-hunt-handler.test.js +295 -0
- package/dist/__tests__/treasure-hunt-handler.test.js.map +1 -0
- package/dist/__tests__/win-calculator.test.js +515 -0
- package/dist/__tests__/win-calculator.test.js.map +1 -0
- package/dist/bonnys-fortune-v1.game-engine.js +14 -25
- package/dist/bonnys-fortune-v1.game-engine.js.map +1 -1
- package/dist/config/game-logic-config/game-logic-config.js +0 -2
- package/dist/config/game-logic-config/game-logic-config.js.map +1 -1
- package/dist/domain/types/{cheat-trigger-bonus-command.js → debug-trigger-bonus-command.js} +1 -1
- package/dist/domain/types/debug-trigger-bonus-command.js.map +1 -0
- package/dist/domain/types/{cheat-trigger-bonus-request.dto.js → debug-trigger-bonus-request.dto.js} +1 -1
- package/dist/domain/types/debug-trigger-bonus-request.dto.js.map +1 -0
- package/dist/domain/types/{cheat-update-bonus-meter-progress-command.js → debug-update-bonus-meter-progress-command.js} +1 -1
- package/dist/domain/types/debug-update-bonus-meter-progress-command.js.map +1 -0
- package/dist/domain/types/{cheat-update-bonus-meter-progress-request.dto.js → debug-update-bonus-meter-progress-request.dto.js} +1 -1
- package/dist/domain/types/debug-update-bonus-meter-progress-request.dto.js.map +1 -0
- package/dist/index.js.map +1 -1
- package/dist/logic/bonnys-fortune.game-logic.js +37 -17
- package/dist/logic/bonnys-fortune.game-logic.js.map +1 -1
- package/dist/logic/handlers/base-game.handler.js +1 -5
- package/dist/logic/handlers/base-game.handler.js.map +1 -1
- package/dist/rng/DummyRngClient.js +8 -1
- package/dist/rng/DummyRngClient.js.map +1 -1
- package/dist/rng/rng-client.factory.js.map +1 -1
- package/dist/validation/bonnys-fortune/bonnys-fortune-config.dto.js +0 -9
- package/dist/validation/bonnys-fortune/bonnys-fortune-config.dto.js.map +1 -1
- package/package.json +6 -6
- package/dist/__tests__/bonnys-fortune-v1.game-engine.test.d.ts +0 -1
- package/dist/bonnys-fortune-v1.game-engine.d.ts +0 -36
- package/dist/config/game-logic-config/file-system.game-logic-config-loader.d.ts +0 -4
- package/dist/config/game-logic-config/game-logic-config-loader.d.ts +0 -3
- package/dist/config/game-logic-config/game-logic-config.d.ts +0 -2
- package/dist/config/reel-strips-config/file-system.reel-strips-config-loader.d.ts +0 -4
- package/dist/config/reel-strips-config/reel-strip-option.dto.d.ts +0 -4
- package/dist/config/reel-strips-config/reel-strips-config-loader.d.ts +0 -3
- package/dist/config/reel-strips-config/reel-strips-config.dto.d.ts +0 -5
- package/dist/config/reel-strips-config/reel.dto.d.ts +0 -5
- package/dist/domain/game-round.types.d.ts +0 -9
- package/dist/domain/mappers/reel-strips-config.mapper.d.ts +0 -4
- package/dist/domain/reel-strip-option.d.ts +0 -7
- package/dist/domain/reel-strips-config.d.ts +0 -9
- package/dist/domain/reel.d.ts +0 -8
- package/dist/domain/types/cheat-trigger-bonus-command.d.ts +0 -5
- package/dist/domain/types/cheat-trigger-bonus-command.js.map +0 -1
- package/dist/domain/types/cheat-trigger-bonus-request.dto.d.ts +0 -5
- package/dist/domain/types/cheat-trigger-bonus-request.dto.js.map +0 -1
- package/dist/domain/types/cheat-update-bonus-meter-progress-command.d.ts +0 -5
- package/dist/domain/types/cheat-update-bonus-meter-progress-command.js.map +0 -1
- package/dist/domain/types/cheat-update-bonus-meter-progress-request.dto.d.ts +0 -5
- package/dist/domain/types/cheat-update-bonus-meter-progress-request.dto.js.map +0 -1
- package/dist/domain/types/game-spin-command.d.ts +0 -8
- package/dist/domain/types/game-spin-input.dto.d.ts +0 -8
- package/dist/domain/types/game-spin-output.dto.d.ts +0 -119
- package/dist/domain/types/game-symbols.response.dto.d.ts +0 -10
- package/dist/domain/types/reel-strip-option.dto.d.ts +0 -4
- package/dist/domain/types/reel-strips-config.dto.d.ts +0 -5
- package/dist/domain/types/reel.dto.d.ts +0 -5
- package/dist/domain/types/start-bonus-round-command.d.ts +0 -8
- package/dist/domain/types/start-bonus-round-input.dto.d.ts +0 -10
- package/dist/game-engine.interface.d.ts +0 -41
- package/dist/helpers/generate-hash.d.ts +0 -1
- package/dist/helpers/number-helper.d.ts +0 -23
- package/dist/helpers/optional-boolean-mapper.d.ts +0 -1
- package/dist/helpers/uuid-helper.d.ts +0 -3
- package/dist/helpers/validation-helper.d.ts +0 -14
- package/dist/index.d.ts +0 -2
- package/dist/logger/logger.d.ts +0 -22
- package/dist/logger/logger.js +0 -140
- package/dist/logger/logger.js.map +0 -1
- package/dist/logic/bonnys-fortune.game-logic.d.ts +0 -32
- package/dist/logic/bonnys-fortune.spin-generator.d.ts +0 -19
- package/dist/logic/bonnys-fortune.types.d.ts +0 -170
- package/dist/logic/bonnys-fortune.win-calculator.d.ts +0 -10
- package/dist/logic/game-logic-config.interface.d.ts +0 -180
- package/dist/logic/handlers/base-game.handler.d.ts +0 -15
- package/dist/logic/handlers/collect-feature-bonus.handler.d.ts +0 -13
- package/dist/logic/handlers/free-spins-bonus.handler.d.ts +0 -11
- package/dist/logic/handlers/steering-to-the-fortune-bonus.handler.d.ts +0 -11
- package/dist/logic/handlers/treasure-hunt-bonus.handler.d.ts +0 -15
- package/dist/rng/DummyRngClient.d.ts +0 -18
- package/dist/rng/rng-client.factory.d.ts +0 -7
- package/dist/rng/rng-client.interface.d.ts +0 -16
- package/dist/rng/rng-service.d.ts +0 -26
- package/dist/validation/abstract-game-logic-config.validator.d.ts +0 -4
- package/dist/validation/bonnys-fortune/bonnys-fortune-config.dto.d.ts +0 -131
- package/dist/validation/bonnys-fortune/bonnys-fortune-config.validator.d.ts +0 -5
- package/dist/validation/custom-decorators/IsNestedIntArray.d.ts +0 -2
- package/dist/validation/game-logic-config-validation.service.d.ts +0 -8
- package/dist/validation/reel-strips-config-validation.service.d.ts +0 -5
- package/src/__tests__/bonnys-fortune-v1.game-engine.test.ts +0 -80
- package/src/bonnys-fortune-v1.game-engine.ts +0 -314
- package/src/config/game-logic-config/file-system.game-logic-config-loader.ts +0 -27
- package/src/config/game-logic-config/game-logic-config-loader.ts +0 -3
- package/src/config/game-logic-config/game-logic-config.ts +0 -382
- package/src/config/reel-strips-config/file-system.reel-strips-config-loader.ts +0 -43
- package/src/config/reel-strips-config/reel-strip-option.dto.ts +0 -13
- package/src/config/reel-strips-config/reel-strips-config-loader.ts +0 -9
- package/src/config/reel-strips-config/reel-strips-config.dto.ts +0 -16
- package/src/config/reel-strips-config/reel.dto.ts +0 -16
- package/src/config/reel-strips-config/reels-BASE.csv +0 -52
- package/src/config/reel-strips-config/reels-BONUS.csv +0 -52
- package/src/domain/game-round.types.ts +0 -10
- package/src/domain/mappers/reel-strips-config.mapper.ts +0 -16
- package/src/domain/reel-strip-option.ts +0 -15
- package/src/domain/reel-strips-config.ts +0 -21
- package/src/domain/reel.ts +0 -17
- package/src/domain/types/cheat-trigger-bonus-command.ts +0 -5
- package/src/domain/types/cheat-trigger-bonus-request.dto.ts +0 -5
- package/src/domain/types/cheat-update-bonus-meter-progress-command.ts +0 -6
- package/src/domain/types/cheat-update-bonus-meter-progress-request.dto.ts +0 -5
- package/src/domain/types/game-spin-command.ts +0 -8
- package/src/domain/types/game-spin-input.dto.ts +0 -8
- package/src/domain/types/game-spin-output.dto.ts +0 -142
- package/src/domain/types/game-symbols.response.dto.ts +0 -11
- package/src/domain/types/reel-strip-option.dto.ts +0 -13
- package/src/domain/types/reel-strips-config.dto.ts +0 -15
- package/src/domain/types/reel.dto.ts +0 -15
- package/src/domain/types/start-bonus-round-command.ts +0 -8
- package/src/domain/types/start-bonus-round-input.dto.ts +0 -10
- package/src/game-engine.interface.ts +0 -59
- package/src/helpers/generate-hash.ts +0 -5
- package/src/helpers/number-helper.ts +0 -41
- package/src/helpers/optional-boolean-mapper.ts +0 -5
- package/src/helpers/uuid-helper.ts +0 -7
- package/src/helpers/validation-helper.ts +0 -27
- package/src/index.ts +0 -3
- package/src/logger/logger.ts +0 -178
- package/src/logic/bonnys-fortune.game-logic.ts +0 -490
- package/src/logic/bonnys-fortune.spin-generator.ts +0 -277
- package/src/logic/bonnys-fortune.types.ts +0 -223
- package/src/logic/bonnys-fortune.win-calculator.ts +0 -210
- package/src/logic/game-logic-config.interface.ts +0 -176
- package/src/logic/handlers/base-game.handler.ts +0 -221
- package/src/logic/handlers/collect-feature-bonus.handler.ts +0 -301
- package/src/logic/handlers/free-spins-bonus.handler.ts +0 -119
- package/src/logic/handlers/steering-to-the-fortune-bonus.handler.ts +0 -118
- package/src/logic/handlers/treasure-hunt-bonus.handler.ts +0 -232
- package/src/rng/DummyRngClient.ts +0 -108
- package/src/rng/rng-client.factory.ts +0 -27
- package/src/rng/rng-client.interface.ts +0 -38
- package/src/rng/rng-service.ts +0 -130
- package/src/validation/abstract-game-logic-config.validator.ts +0 -20
- package/src/validation/bonnys-fortune/bonnys-fortune-config.dto.ts +0 -379
- package/src/validation/bonnys-fortune/bonnys-fortune-config.validator.ts +0 -8
- package/src/validation/custom-decorators/IsNestedIntArray.ts +0 -29
- package/src/validation/game-logic-config-validation.service.ts +0 -28
- package/src/validation/reel-strips-config-validation.service.ts +0 -29
package/README.md
CHANGED
|
@@ -241,19 +241,19 @@ The game engine supports 6 different command types:
|
|
|
241
241
|
|
|
242
242
|
**Returns**: Updated state
|
|
243
243
|
|
|
244
|
-
#### 5.
|
|
244
|
+
#### 5. DEBUG_TRIGGER_BONUS (Testing/Admin)
|
|
245
245
|
|
|
246
246
|
**Purpose**: Force trigger specific bonus game
|
|
247
247
|
|
|
248
|
-
**Payload**: `
|
|
248
|
+
**Payload**: `DebugTriggerBonusCommand`
|
|
249
249
|
|
|
250
250
|
**Returns**: State with pending bonus
|
|
251
251
|
|
|
252
|
-
#### 6.
|
|
252
|
+
#### 6. DEBUG_UPDATE_BONUS_METER_PROGRESS (Testing/Admin)
|
|
253
253
|
|
|
254
254
|
**Purpose**: Manually set bonus meter progress
|
|
255
255
|
|
|
256
|
-
**Payload**: `
|
|
256
|
+
**Payload**: `DebugUpdateBonusMeterProgressCommand`
|
|
257
257
|
|
|
258
258
|
**Returns**: Updated meter state
|
|
259
259
|
|
|
@@ -552,26 +552,26 @@ RNG_CLIENT_GRPC_URL=grpc://rng-prod.omnitronix.com:50051
|
|
|
552
552
|
RNG_CLIENT_POOL_SIZE=5000
|
|
553
553
|
```
|
|
554
554
|
|
|
555
|
-
### Example 4: Testing with
|
|
555
|
+
### Example 4: Testing with Debug Commands
|
|
556
556
|
|
|
557
557
|
```typescript
|
|
558
558
|
async function testBonusGame() {
|
|
559
559
|
const gameEngine = new BonnysFortuneV1GameEngine();
|
|
560
|
-
|
|
560
|
+
|
|
561
561
|
// Initialize session
|
|
562
562
|
const initResult = await gameEngine.processCommand({}, {}, {
|
|
563
563
|
id: 'test-init',
|
|
564
564
|
type: 'INIT_SESSION_STATE',
|
|
565
565
|
payload: { betAmountThresholds: [10], defaultBetAmount: 10 }
|
|
566
566
|
});
|
|
567
|
-
|
|
567
|
+
|
|
568
568
|
// Force trigger treasure hunt bonus
|
|
569
|
-
const
|
|
569
|
+
const debugResult = await gameEngine.processCommand(
|
|
570
570
|
initResult.publicState,
|
|
571
571
|
initResult.privateState,
|
|
572
572
|
{
|
|
573
|
-
id: 'test-
|
|
574
|
-
type: '
|
|
573
|
+
id: 'test-debug',
|
|
574
|
+
type: 'DEBUG_TRIGGER_BONUS',
|
|
575
575
|
payload: {
|
|
576
576
|
sessionId: 'test-session',
|
|
577
577
|
bonusType: 'bonusGame1',
|
|
@@ -579,11 +579,11 @@ async function testBonusGame() {
|
|
|
579
579
|
}
|
|
580
580
|
}
|
|
581
581
|
);
|
|
582
|
-
|
|
582
|
+
|
|
583
583
|
// Now start the bonus
|
|
584
584
|
const bonusResult = await gameEngine.processCommand(
|
|
585
|
-
|
|
586
|
-
|
|
585
|
+
debugResult.publicState,
|
|
586
|
+
debugResult.privateState,
|
|
587
587
|
{
|
|
588
588
|
id: 'test-bonus-start',
|
|
589
589
|
type: 'START_BONUS_ROUND',
|
|
@@ -593,15 +593,25 @@ async function testBonusGame() {
|
|
|
593
593
|
betAmount: 10,
|
|
594
594
|
gameCode: 'bonnys-fortune',
|
|
595
595
|
gameVersion: '1.0.0',
|
|
596
|
-
bonusId:
|
|
596
|
+
bonusId: debugResult.privateState.pendingBonuses[0].bonusId
|
|
597
597
|
}
|
|
598
598
|
}
|
|
599
599
|
);
|
|
600
|
-
|
|
600
|
+
|
|
601
601
|
console.log('Bonus results:', bonusResult.outcome);
|
|
602
602
|
}
|
|
603
603
|
```
|
|
604
604
|
|
|
605
|
+
## Testing
|
|
606
|
+
|
|
607
|
+
This engine uses [@omnitronix/game-test-utils](https://github.com/omnitronix/game-test-utils) for comprehensive testing including:
|
|
608
|
+
- GLI-19 compliance validation
|
|
609
|
+
- RNG security testing
|
|
610
|
+
- Statistical RTP simulation
|
|
611
|
+
- Symbol distribution analysis
|
|
612
|
+
|
|
613
|
+
Run tests: `npm test`
|
|
614
|
+
|
|
605
615
|
## Development
|
|
606
616
|
|
|
607
617
|
### Running Tests
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* Base Game Logic Tests — Bonnys Fortune
|
|
5
|
+
*
|
|
6
|
+
* Tests the core base game mechanics:
|
|
7
|
+
* - Screen generation (5x3 grid, 243 ways)
|
|
8
|
+
* - Win calculation (ways evaluation)
|
|
9
|
+
* - Bonus meter tracking and progression
|
|
10
|
+
* - Bet amount handling
|
|
11
|
+
* - Per-bet-amount meter state
|
|
12
|
+
*/
|
|
13
|
+
const test_engine_factory_1 = require("./helpers/test-engine-factory");
|
|
14
|
+
describe('Base Game Logic — Bonnys Fortune', () => {
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
(0, test_engine_factory_1.resetCommandIdCounter)();
|
|
17
|
+
});
|
|
18
|
+
describe('Screen Generation', () => {
|
|
19
|
+
it('should generate a 5x3 screen on each spin', async () => {
|
|
20
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
21
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
22
|
+
const result = await (0, test_engine_factory_1.executeSpin)(engine, session.publicState, session.privateState);
|
|
23
|
+
expect(result.success).toBe(true);
|
|
24
|
+
const screen = result.outcome?.result?.screen ?? result.outcome?.screen;
|
|
25
|
+
expect(screen).toBeDefined();
|
|
26
|
+
expect(screen.length).toBe(5);
|
|
27
|
+
for (const reel of screen) {
|
|
28
|
+
expect(reel.length).toBe(3);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
it('should produce valid symbol IDs on screen', async () => {
|
|
32
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
33
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
34
|
+
const result = await (0, test_engine_factory_1.executeSpin)(engine, session.publicState, session.privateState);
|
|
35
|
+
expect(result.success).toBe(true);
|
|
36
|
+
const screen = result.outcome?.result?.screen ?? result.outcome?.screen;
|
|
37
|
+
for (const reel of screen) {
|
|
38
|
+
for (const symbol of reel) {
|
|
39
|
+
expect(typeof symbol).toBe('number');
|
|
40
|
+
expect(symbol).toBeGreaterThanOrEqual(0);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
it('should produce different screens across multiple spins', async () => {
|
|
45
|
+
// Use LCG RNG to avoid DummyRng producing identical screens and
|
|
46
|
+
// constant bonus meter triggers that prevent base game spins
|
|
47
|
+
const { engine } = (0, test_engine_factory_1.createEngineWithLcgRng)(54321);
|
|
48
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
49
|
+
let pub = session.publicState;
|
|
50
|
+
let priv = session.privateState;
|
|
51
|
+
const screens = [];
|
|
52
|
+
for (let i = 0; i < 50; i++) {
|
|
53
|
+
if (priv.nextSpinType !== 'BASE_GAME_SPIN') {
|
|
54
|
+
// Bonus triggered — complete it via extractFinalBonusState
|
|
55
|
+
if (priv.pendingBonuses?.length > 0) {
|
|
56
|
+
const bonus = priv.pendingBonuses[0];
|
|
57
|
+
const bonusResult = await (0, test_engine_factory_1.startBonusRound)(engine, pub, priv, bonus.bonusType);
|
|
58
|
+
const finalState = (0, test_engine_factory_1.extractFinalBonusState)(bonusResult);
|
|
59
|
+
pub = finalState.publicState;
|
|
60
|
+
priv = finalState.privateState;
|
|
61
|
+
// Handle chained bonuses (steering fortune)
|
|
62
|
+
while (priv.pendingBonuses?.length > 0) {
|
|
63
|
+
const nextBonus = priv.pendingBonuses[0];
|
|
64
|
+
const chainResult = await (0, test_engine_factory_1.startBonusRound)(engine, pub, priv, nextBonus.bonusType);
|
|
65
|
+
const chainFinal = (0, test_engine_factory_1.extractFinalBonusState)(chainResult);
|
|
66
|
+
pub = chainFinal.publicState;
|
|
67
|
+
priv = chainFinal.privateState;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (priv.nextSpinType !== 'BASE_GAME_SPIN')
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
const result = await (0, test_engine_factory_1.executeSpin)(engine, pub, priv);
|
|
74
|
+
expect(result.success).toBe(true);
|
|
75
|
+
const screen = result.outcome?.result?.screen ?? result.outcome?.screen ?? result.privateState.screen;
|
|
76
|
+
screens.push(JSON.stringify(screen));
|
|
77
|
+
pub = result.publicState;
|
|
78
|
+
priv = result.privateState;
|
|
79
|
+
}
|
|
80
|
+
const unique = new Set(screens);
|
|
81
|
+
expect(unique.size).toBeGreaterThan(1);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
describe('Win Calculation', () => {
|
|
85
|
+
it('should report playerWinning as non-negative number', async () => {
|
|
86
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
87
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
88
|
+
const result = await (0, test_engine_factory_1.executeSpin)(engine, session.publicState, session.privateState);
|
|
89
|
+
expect(result.success).toBe(true);
|
|
90
|
+
const playerWinning = result.outcome?.result?.playerWinning ?? result.outcome?.playerWinning;
|
|
91
|
+
if (playerWinning !== undefined) {
|
|
92
|
+
expect(playerWinning).toBeGreaterThanOrEqual(0);
|
|
93
|
+
expect(typeof playerWinning).toBe('number');
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
it('should produce finite win amounts', async () => {
|
|
97
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
98
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
99
|
+
let pub = session.publicState;
|
|
100
|
+
let priv = session.privateState;
|
|
101
|
+
for (let i = 0; i < 20; i++) {
|
|
102
|
+
if (priv.nextSpinType !== 'BASE_GAME_SPIN')
|
|
103
|
+
break;
|
|
104
|
+
const result = await (0, test_engine_factory_1.executeSpin)(engine, pub, priv);
|
|
105
|
+
expect(result.success).toBe(true);
|
|
106
|
+
const playerWinning = result.outcome?.result?.playerWinning ?? result.outcome?.playerWinning;
|
|
107
|
+
if (playerWinning !== undefined) {
|
|
108
|
+
expect(Number.isFinite(playerWinning)).toBe(true);
|
|
109
|
+
}
|
|
110
|
+
pub = result.publicState;
|
|
111
|
+
priv = result.privateState;
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
describe('Bonus Meter Mechanics', () => {
|
|
116
|
+
it('should have bonus meters in public state after init', async () => {
|
|
117
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
118
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
119
|
+
expect(session.publicState.bonusMeters).toBeDefined();
|
|
120
|
+
const keys = Object.keys(session.publicState.bonusMeters || {});
|
|
121
|
+
expect(keys.length).toBeGreaterThan(0);
|
|
122
|
+
});
|
|
123
|
+
it('should have valid threshold and progress for each meter', async () => {
|
|
124
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
125
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
126
|
+
const meters = session.publicState.bonusMeters;
|
|
127
|
+
for (const [, meter] of Object.entries(meters || {})) {
|
|
128
|
+
const m = meter;
|
|
129
|
+
expect(m.threshold).toBeGreaterThan(0);
|
|
130
|
+
expect(m.progress).toBeGreaterThanOrEqual(0);
|
|
131
|
+
expect(typeof m.threshold).toBe('number');
|
|
132
|
+
expect(typeof m.progress).toBe('number');
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
it('should maintain meter state across spins', async () => {
|
|
136
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
137
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
138
|
+
let pub = session.publicState;
|
|
139
|
+
let priv = session.privateState;
|
|
140
|
+
for (let i = 0; i < 10; i++) {
|
|
141
|
+
if (priv.nextSpinType !== 'BASE_GAME_SPIN')
|
|
142
|
+
break;
|
|
143
|
+
const result = await (0, test_engine_factory_1.executeSpin)(engine, pub, priv);
|
|
144
|
+
expect(result.success).toBe(true);
|
|
145
|
+
expect(result.publicState.bonusMeters).toBeDefined();
|
|
146
|
+
// Verify meter structure integrity
|
|
147
|
+
for (const [, meter] of Object.entries(result.publicState.bonusMeters || {})) {
|
|
148
|
+
const m = meter;
|
|
149
|
+
expect(m.threshold).toBeGreaterThan(0);
|
|
150
|
+
expect(m.progress).toBeGreaterThanOrEqual(0);
|
|
151
|
+
expect(m.progress).toBeLessThanOrEqual(m.threshold);
|
|
152
|
+
}
|
|
153
|
+
pub = result.publicState;
|
|
154
|
+
priv = result.privateState;
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
it('should not allow meter progress to exceed threshold', async () => {
|
|
158
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
159
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
160
|
+
let pub = session.publicState;
|
|
161
|
+
let priv = session.privateState;
|
|
162
|
+
for (let i = 0; i < 30; i++) {
|
|
163
|
+
if (priv.nextSpinType !== 'BASE_GAME_SPIN')
|
|
164
|
+
break;
|
|
165
|
+
const result = await (0, test_engine_factory_1.executeSpin)(engine, pub, priv);
|
|
166
|
+
expect(result.success).toBe(true);
|
|
167
|
+
for (const [, meter] of Object.entries(result.publicState.bonusMeters || {})) {
|
|
168
|
+
const m = meter;
|
|
169
|
+
expect(m.progress).toBeLessThanOrEqual(m.threshold);
|
|
170
|
+
}
|
|
171
|
+
pub = result.publicState;
|
|
172
|
+
priv = result.privateState;
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
it('should have per-bet-amount meter state in private state', async () => {
|
|
176
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
177
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
178
|
+
expect(session.privateState.bonusMetersByAmount).toBeDefined();
|
|
179
|
+
const amounts = Object.keys(session.privateState.bonusMetersByAmount || {});
|
|
180
|
+
expect(amounts.length).toBeGreaterThan(0);
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
describe('RNG Outcome Tracking', () => {
|
|
184
|
+
it('should produce valid RNG outcome on each spin', async () => {
|
|
185
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
186
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
187
|
+
const result = await (0, test_engine_factory_1.executeSpin)(engine, session.publicState, session.privateState);
|
|
188
|
+
expect(result.success).toBe(true);
|
|
189
|
+
expect(result.rngOutcome).toBeDefined();
|
|
190
|
+
const validation = (0, test_engine_factory_1.validateRngOutcome)(result.rngOutcome);
|
|
191
|
+
expect(validation.valid).toBe(true);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
describe('Bet Amount Handling', () => {
|
|
195
|
+
it('should accept different bet amounts', async () => {
|
|
196
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
197
|
+
const session = await (0, test_engine_factory_1.initSession)(engine, 0.5);
|
|
198
|
+
const result = await (0, test_engine_factory_1.executeSpin)(engine, session.publicState, session.privateState, 0.5);
|
|
199
|
+
expect(result.success).toBe(true);
|
|
200
|
+
});
|
|
201
|
+
it('should update currentBetAmount in public state', async () => {
|
|
202
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
203
|
+
const session = await (0, test_engine_factory_1.initSession)(engine, 2.0);
|
|
204
|
+
expect(session.publicState.currentBetAmount).toBe(2.0);
|
|
205
|
+
});
|
|
206
|
+
it('should switch meter state when bet amount changes', async () => {
|
|
207
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
208
|
+
const session = await (0, test_engine_factory_1.initSession)(engine, 1.0);
|
|
209
|
+
const result1 = await (0, test_engine_factory_1.executeSpin)(engine, session.publicState, session.privateState, 1.0);
|
|
210
|
+
expect(result1.success).toBe(true);
|
|
211
|
+
if (result1.privateState.nextSpinType === 'BASE_GAME_SPIN') {
|
|
212
|
+
// Change bet amount
|
|
213
|
+
const result2 = await (0, test_engine_factory_1.executeSpin)(engine, result1.publicState, result1.privateState, 2.0);
|
|
214
|
+
expect(result2.success).toBe(true);
|
|
215
|
+
// Meters should still be valid
|
|
216
|
+
expect(result2.publicState.bonusMeters).toBeDefined();
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
describe('Mock RNG Determinism', () => {
|
|
221
|
+
it('should produce deterministic results with mock RNG', async () => {
|
|
222
|
+
const { engine: engine1 } = (0, test_engine_factory_1.createEngineWithMockRng)([42, 42, 42, 42, 42]);
|
|
223
|
+
const { engine: engine2 } = (0, test_engine_factory_1.createEngineWithMockRng)([42, 42, 42, 42, 42]);
|
|
224
|
+
const session1 = await (0, test_engine_factory_1.initSession)(engine1);
|
|
225
|
+
const session2 = await (0, test_engine_factory_1.initSession)(engine2);
|
|
226
|
+
const result1 = await (0, test_engine_factory_1.executeSpin)(engine1, session1.publicState, session1.privateState);
|
|
227
|
+
const result2 = await (0, test_engine_factory_1.executeSpin)(engine2, session2.publicState, session2.privateState);
|
|
228
|
+
expect(result1.success).toBe(true);
|
|
229
|
+
expect(result2.success).toBe(true);
|
|
230
|
+
const screen1 = JSON.stringify(result1.outcome?.screen || result1.privateState.screen);
|
|
231
|
+
const screen2 = JSON.stringify(result2.outcome?.screen || result2.privateState.screen);
|
|
232
|
+
expect(screen1).toBe(screen2);
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
describe('Multiple Spin Stability', () => {
|
|
236
|
+
it('should handle 30 consecutive base game spins', async () => {
|
|
237
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
238
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
239
|
+
let pub = session.publicState;
|
|
240
|
+
let priv = session.privateState;
|
|
241
|
+
let spinCount = 0;
|
|
242
|
+
for (let i = 0; i < 30; i++) {
|
|
243
|
+
if (priv.nextSpinType !== 'BASE_GAME_SPIN')
|
|
244
|
+
break;
|
|
245
|
+
const result = await (0, test_engine_factory_1.executeSpin)(engine, pub, priv);
|
|
246
|
+
expect(result.success).toBe(true);
|
|
247
|
+
spinCount++;
|
|
248
|
+
pub = result.publicState;
|
|
249
|
+
priv = result.privateState;
|
|
250
|
+
}
|
|
251
|
+
expect(spinCount).toBeGreaterThan(0);
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
//# sourceMappingURL=base-game.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-game.test.js","sourceRoot":"","sources":["../../src/__tests__/base-game.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@ describe('BonnysFortuneV1GameEngine', () => {
|
|
|
10
10
|
it('should initialize the game engine and return info', async () => {
|
|
11
11
|
const info = gameEngine.getGameEngineInfo();
|
|
12
12
|
expect(info.gameCode).toBe('bonnys-fortune');
|
|
13
|
-
expect(info.version).toBe('1.
|
|
13
|
+
expect(info.version).toBe('1.5.0');
|
|
14
14
|
expect(info.rtp).toBe(96);
|
|
15
15
|
expect(info.gameType).toBe('slot');
|
|
16
16
|
});
|