@omnitronix/bonnys-fortune-game-engine 1.3.4 → 1.3.5
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/dist/helpers/number-helper.d.ts +2 -1
- package/dist/helpers/number-helper.js +5 -3
- package/dist/helpers/number-helper.js.map +1 -1
- package/dist/logic/bonnys-fortune.types.d.ts +1 -0
- package/dist/logic/bonnys-fortune.types.js.map +1 -1
- package/dist/logic/game-logic-config.interface.d.ts +1 -0
- package/dist/logic/handlers/collect-feature-bonus.handler.d.ts +1 -1
- package/dist/logic/handlers/collect-feature-bonus.handler.js +18 -12
- package/dist/logic/handlers/collect-feature-bonus.handler.js.map +1 -1
- package/dist/logic/handlers/treasure-hunt-bonus.handler.d.ts +0 -1
- package/dist/logic/handlers/treasure-hunt-bonus.handler.js +13 -14
- package/dist/logic/handlers/treasure-hunt-bonus.handler.js.map +1 -1
- package/package.json +1 -1
- package/src/helpers/number-helper.ts +5 -3
- package/src/logic/bonnys-fortune.types.ts +1 -0
- package/src/logic/game-logic-config.interface.ts +9 -0
- package/src/logic/handlers/collect-feature-bonus.handler.ts +35 -30
- package/src/logic/handlers/treasure-hunt-bonus.handler.ts +22 -23
|
@@ -9,7 +9,8 @@ export declare class NumberHelper {
|
|
|
9
9
|
*/
|
|
10
10
|
static safeSum(a: number, b: number, decimals: number): number;
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* Multiplies two numbers and rounds the result to the specified decimal places.
|
|
13
|
+
* Use this to avoid floating-point noise and get a deterministic value.
|
|
13
14
|
*/
|
|
14
15
|
static safeMultiply(a: number, b: number, decimals: number): number;
|
|
15
16
|
/**
|
|
@@ -18,11 +18,13 @@ class NumberHelper {
|
|
|
18
18
|
return result / Math.pow(10, decimals);
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* Multiplies two numbers and rounds the result to the specified decimal places.
|
|
22
|
+
* Use this to avoid floating-point noise and get a deterministic value.
|
|
22
23
|
*/
|
|
23
24
|
static safeMultiply(a, b, decimals) {
|
|
24
|
-
const
|
|
25
|
-
|
|
25
|
+
const scale = Math.pow(10, decimals);
|
|
26
|
+
const product = a * b;
|
|
27
|
+
return Math.round(product * scale) / scale;
|
|
26
28
|
}
|
|
27
29
|
/**
|
|
28
30
|
* Clamps a number between min and max.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-helper.js","sourceRoot":"","sources":["../../src/helpers/number-helper.ts"],"names":[],"mappings":";;;AAAA,MAAa,YAAY;IACvB;;;OAGG;IACI,MAAM,CAAC,aAAa,CAAC,KAAa,EAAE,QAAgB;QACzD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC;IAChE,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,OAAO,CAAC,CAAS,EAAE,CAAS,EAAE,QAAgB;QAC1D,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QACvE,OAAO,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;IACzC,CAAC;IAED
|
|
1
|
+
{"version":3,"file":"number-helper.js","sourceRoot":"","sources":["../../src/helpers/number-helper.ts"],"names":[],"mappings":";;;AAAA,MAAa,YAAY;IACvB;;;OAGG;IACI,MAAM,CAAC,aAAa,CAAC,KAAa,EAAE,QAAgB;QACzD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC;IAChE,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,OAAO,CAAC,CAAS,EAAE,CAAS,EAAE,QAAgB;QAC1D,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QACvE,OAAO,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;IACzC,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,YAAY,CAAC,CAAS,EAAE,CAAS,EAAE,QAAgB;QAC/D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QACrC,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC;IAC7C,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,KAAK,CAAC,KAAa,EAAE,GAAW,EAAE,GAAW;QACzD,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,UAAU,CAAC,CAAS,EAAE,CAAS,EAAE,QAAgB;QAC7D,IAAI,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC7C,CAAC;CACF;AA1CD,oCA0CC"}
|
|
@@ -57,6 +57,7 @@ export interface TreasureHuntSpinResult extends SpinResult {
|
|
|
57
57
|
winningMultiplier: number | null;
|
|
58
58
|
winningCount: number;
|
|
59
59
|
totalMultiplier: number;
|
|
60
|
+
fullGridSelections: string[];
|
|
60
61
|
}
|
|
61
62
|
export interface FreeSpinResult {
|
|
62
63
|
spinType: SpinType.BONUS_GAME_2_SPIN;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bonnys-fortune.types.js","sourceRoot":"","sources":["../../src/logic/bonnys-fortune.types.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"bonnys-fortune.types.js","sourceRoot":"","sources":["../../src/logic/bonnys-fortune.types.ts"],"names":[],"mappings":";;;AA0IA,IAAY,QAMX;AAND,WAAY,QAAQ;IAClB,6CAAiC,CAAA;IACjC,mDAAuC,CAAA;IACvC,mDAAuC,CAAA;IACvC,mDAAuC,CAAA;IACvC,yDAA6C,CAAA;AAC/C,CAAC,EANW,QAAQ,wBAAR,QAAQ,QAMnB;AAED,IAAY,SAGX;AAHD,WAAY,SAAS;IACnB,sCAAyB,CAAA;IACzB,4BAAe,CAAA;AACjB,CAAC,EAHW,SAAS,yBAAT,SAAS,QAGpB"}
|
|
@@ -124,6 +124,7 @@ export interface TreasureHuntBonusConfig {
|
|
|
124
124
|
grand: number;
|
|
125
125
|
};
|
|
126
126
|
}
|
|
127
|
+
export type TreasureHuntExtractedConfig = Pick<TreasureHuntBonusConfig, 'symbolsCount' | 'stepsCount' | 'jackpotMultipliers' | 'winningWeights' | 'jackpotScreenCounts'>;
|
|
127
128
|
export interface FreeSpinBonusGameConfig {
|
|
128
129
|
type: 'free_spins';
|
|
129
130
|
potMeter: BonusGameId;
|
|
@@ -7,7 +7,7 @@ export declare class CollectFeatureBonusHandler {
|
|
|
7
7
|
constructor(rngService: RngService);
|
|
8
8
|
generateFullBonusRound(params: GameSpinInputDto, publicState: BonnysFortunePublicState, privateState: BonnysFortunePrivateState, config: BonnysFortuneGameLogicConfigInterface, commandId: string): Promise<BonusRoundResult<CollectFeatureSpinResult>>;
|
|
9
9
|
private executeSingleSpin;
|
|
10
|
+
private buildCheckpointBySpin;
|
|
10
11
|
private weightedPick;
|
|
11
12
|
private weightedPickSymbol;
|
|
12
|
-
private getBetStake;
|
|
13
13
|
}
|
|
@@ -8,7 +8,7 @@ class CollectFeatureBonusHandler {
|
|
|
8
8
|
this.rngService = rngService;
|
|
9
9
|
}
|
|
10
10
|
async generateFullBonusRound(params, publicState, privateState, config, commandId) {
|
|
11
|
-
const
|
|
11
|
+
const betAmount = params.betAmount;
|
|
12
12
|
const scatterConfig = config.scatterGame.config;
|
|
13
13
|
const results = [];
|
|
14
14
|
const initialPublicState = { ...publicState };
|
|
@@ -17,13 +17,14 @@ class CollectFeatureBonusHandler {
|
|
|
17
17
|
let totalValues = 0;
|
|
18
18
|
let totalMultipliers = 1;
|
|
19
19
|
let totalWin = 0;
|
|
20
|
-
const
|
|
20
|
+
const resolvedSpins = await Promise.all(scatterConfig.scatterCheckpoints.map(async (cp, index) => {
|
|
21
21
|
const actionId = `checkpoint_${index}`;
|
|
22
22
|
const result = await this.rngService.getSingleNumber(0, 1, commandId, actionId);
|
|
23
23
|
return cp.spin - 1 + result.value;
|
|
24
24
|
}));
|
|
25
|
+
const checkpointBySpin = this.buildCheckpointBySpin(resolvedSpins, scatterConfig.scatterCheckpoints);
|
|
25
26
|
for (let spinIndex = 0; spinIndex < scatterConfig.scatterSpins; spinIndex++) {
|
|
26
|
-
const { result, updatedState, updatedPublicState, updatedPrivateState } = await this.executeSingleSpin(spinIndex, spinsLeft, totalValues, totalMultipliers, totalWin,
|
|
27
|
+
const { result, updatedState, updatedPublicState, updatedPrivateState } = await this.executeSingleSpin(spinIndex, spinsLeft, totalValues, totalMultipliers, totalWin, betAmount, scatterConfig, checkpointBySpin, publicState, privateState, commandId);
|
|
27
28
|
results.push({
|
|
28
29
|
result,
|
|
29
30
|
publicState: updatedPublicState,
|
|
@@ -44,7 +45,7 @@ class CollectFeatureBonusHandler {
|
|
|
44
45
|
privateState: initialPrivateState,
|
|
45
46
|
};
|
|
46
47
|
}
|
|
47
|
-
async executeSingleSpin(spinIndex, spinsLeft, totalValues, totalMultipliers, totalWin,
|
|
48
|
+
async executeSingleSpin(spinIndex, spinsLeft, totalValues, totalMultipliers, totalWin, betAmount, scatterConfig, checkpointBySpin, publicState, privateState, commandId) {
|
|
48
49
|
const symbolCount = await this.weightedPick(scatterConfig.scatterSymbolSpins, commandId, `spin_${spinIndex}_symbol_count`);
|
|
49
50
|
const symbols = [];
|
|
50
51
|
let multiCount = 0;
|
|
@@ -57,9 +58,8 @@ class CollectFeatureBonusHandler {
|
|
|
57
58
|
else
|
|
58
59
|
valueCount++;
|
|
59
60
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const cp = scatterConfig.scatterCheckpoints[cpIndex];
|
|
61
|
+
const cp = checkpointBySpin.get(spinsLeft);
|
|
62
|
+
if (cp) {
|
|
63
63
|
if ((totalMultipliers < cp.multiMinValue && multiCount === 0) ||
|
|
64
64
|
(totalValues < cp.valueMinValue && valueCount === 0)) {
|
|
65
65
|
symbols[0] = 'CV1';
|
|
@@ -84,7 +84,7 @@ class CollectFeatureBonusHandler {
|
|
|
84
84
|
}
|
|
85
85
|
const newTotalValues = number_helper_1.NumberHelper.safeSum(totalValues, currentValues, 2);
|
|
86
86
|
const newTotalMultipliers = number_helper_1.NumberHelper.safeSum(totalMultipliers, currentMultipliers, 2);
|
|
87
|
-
const newTotalWin = number_helper_1.NumberHelper.safeMultiply(number_helper_1.NumberHelper.safeMultiply(newTotalValues, newTotalMultipliers, 2),
|
|
87
|
+
const newTotalWin = number_helper_1.NumberHelper.safeMultiply(number_helper_1.NumberHelper.safeMultiply(newTotalValues, newTotalMultipliers, 2), betAmount, 2);
|
|
88
88
|
const playerWinning = number_helper_1.NumberHelper.safeSum(newTotalWin, -totalWin, 2);
|
|
89
89
|
spinsLeft -= 1;
|
|
90
90
|
const result = {
|
|
@@ -121,6 +121,16 @@ class CollectFeatureBonusHandler {
|
|
|
121
121
|
updatedPrivateState,
|
|
122
122
|
};
|
|
123
123
|
}
|
|
124
|
+
buildCheckpointBySpin(resolvedSpins, scatterCheckpoints) {
|
|
125
|
+
const map = new Map();
|
|
126
|
+
for (let i = 0; i < resolvedSpins.length; i++) {
|
|
127
|
+
const spin = resolvedSpins[i];
|
|
128
|
+
if (!map.has(spin)) {
|
|
129
|
+
map.set(spin, scatterCheckpoints[i]);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return map;
|
|
133
|
+
}
|
|
124
134
|
async weightedPick(items, commandId, actionId) {
|
|
125
135
|
const sum = items.reduce((acc, item) => number_helper_1.NumberHelper.safeSum(acc, item.weight, 2), 0);
|
|
126
136
|
let { value: draw } = await this.rngService.getSingleNumber(0, sum - 1, commandId, actionId);
|
|
@@ -143,10 +153,6 @@ class CollectFeatureBonusHandler {
|
|
|
143
153
|
}
|
|
144
154
|
return symbols[0];
|
|
145
155
|
}
|
|
146
|
-
getBetStake(params, config) {
|
|
147
|
-
const baseBet = config.baseGame.baseGameConfig.baseBet;
|
|
148
|
-
return number_helper_1.NumberHelper.safeDivide(params.betAmount, params.creditsPerLine === baseBet ? params.creditsPerLine : baseBet, 3);
|
|
149
|
-
}
|
|
150
156
|
}
|
|
151
157
|
exports.CollectFeatureBonusHandler = CollectFeatureBonusHandler;
|
|
152
158
|
//# sourceMappingURL=collect-feature-bonus.handler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collect-feature-bonus.handler.js","sourceRoot":"","sources":["../../../src/logic/handlers/collect-feature-bonus.handler.ts"],"names":[],"mappings":";;;AAAA,kEAMiC;
|
|
1
|
+
{"version":3,"file":"collect-feature-bonus.handler.js","sourceRoot":"","sources":["../../../src/logic/handlers/collect-feature-bonus.handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,6 @@ export declare class TreasureHuntBonusHandler {
|
|
|
6
6
|
private rngService;
|
|
7
7
|
constructor(rngService: RngService);
|
|
8
8
|
generateFullBonusRound(params: GameSpinInputDto, publicState: BonnysFortunePublicState, privateState: BonnysFortunePrivateState, config: BonnysFortuneGameLogicConfigInterface, commandId: string): Promise<BonusRoundResult<TreasureHuntSpinResult>>;
|
|
9
|
-
private getBetStake;
|
|
10
9
|
private drawWinningSymbol;
|
|
11
10
|
private fillRemainingSteps;
|
|
12
11
|
private weightedDraw;
|
|
@@ -8,28 +8,29 @@ class TreasureHuntBonusHandler {
|
|
|
8
8
|
this.rngService = rngService;
|
|
9
9
|
}
|
|
10
10
|
async generateFullBonusRound(params, publicState, privateState, config, commandId) {
|
|
11
|
-
const
|
|
12
|
-
const { stepsCount, jackpotScreenCounts, jackpotMultipliers, winningWeights, } = this.extractBonusConfig(config);
|
|
11
|
+
const betAmount = params.betAmount;
|
|
12
|
+
const { symbolsCount: gridSize, stepsCount, jackpotScreenCounts, jackpotMultipliers, winningWeights, } = this.extractBonusConfig(config);
|
|
13
13
|
const jackpotKeys = Object.keys(jackpotMultipliers);
|
|
14
14
|
const jackpotsNo = Object.values(jackpotScreenCounts);
|
|
15
15
|
const weightsArray = Object.values(winningWeights);
|
|
16
16
|
const winSymbolIndex = await this.drawWinningSymbol(weightsArray, commandId);
|
|
17
|
-
const selectionsVector = Array(
|
|
17
|
+
const selectionsVector = Array(gridSize).fill(-1);
|
|
18
18
|
if (winSymbolIndex >= 0) {
|
|
19
|
-
const positions = await this.randomPositions(
|
|
19
|
+
const positions = await this.randomPositions(gridSize, 3, commandId);
|
|
20
20
|
positions.forEach((pos) => (selectionsVector[pos] = winSymbolIndex));
|
|
21
21
|
jackpotsNo[winSymbolIndex] = number_helper_1.NumberHelper.safeSum(jackpotsNo[winSymbolIndex], -3, 0);
|
|
22
22
|
}
|
|
23
|
-
await this.fillRemainingSteps(selectionsVector,
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const
|
|
23
|
+
await this.fillRemainingSteps(selectionsVector, gridSize, jackpotsNo, winSymbolIndex, commandId);
|
|
24
|
+
const fullGridSelections = selectionsVector.map((idx) => jackpotKeys[idx]);
|
|
25
|
+
const revealedSelections = fullGridSelections.slice(0, stepsCount);
|
|
26
|
+
const multipliers = revealedSelections.map((name) => jackpotMultipliers[name]);
|
|
27
|
+
const results = revealedSelections.map((symbol, index) => {
|
|
27
28
|
const isFinalStep = index === stepsCount - 1;
|
|
28
29
|
const winningMultiplier = isFinalStep && winSymbolIndex >= 0
|
|
29
30
|
? jackpotMultipliers[jackpotKeys[winSymbolIndex]]
|
|
30
31
|
: 0;
|
|
31
32
|
const playerWinning = isFinalStep && winSymbolIndex >= 0
|
|
32
|
-
? number_helper_1.NumberHelper.safeMultiply(
|
|
33
|
+
? number_helper_1.NumberHelper.safeMultiply(betAmount, winningMultiplier, 2)
|
|
33
34
|
: 0;
|
|
34
35
|
return {
|
|
35
36
|
result: {
|
|
@@ -40,13 +41,14 @@ class TreasureHuntBonusHandler {
|
|
|
40
41
|
: bonnys_fortune_types_1.SpinType.BONUS_GAME_1_SPIN,
|
|
41
42
|
selection: symbol,
|
|
42
43
|
multiplier: multipliers[index],
|
|
43
|
-
multiplierCounts:
|
|
44
|
+
multiplierCounts: revealedSelections.slice(0, index + 1).reduce((acc, key) => {
|
|
44
45
|
acc[key] = (acc[key] || 0) + 1;
|
|
45
46
|
return acc;
|
|
46
47
|
}, {}),
|
|
47
48
|
winningMultiplier,
|
|
48
49
|
winningCount: isFinalStep && winSymbolIndex >= 0 ? 3 : 0,
|
|
49
50
|
totalMultiplier: winningMultiplier,
|
|
51
|
+
fullGridSelections,
|
|
50
52
|
},
|
|
51
53
|
publicState,
|
|
52
54
|
privateState: {
|
|
@@ -64,10 +66,6 @@ class TreasureHuntBonusHandler {
|
|
|
64
66
|
privateState,
|
|
65
67
|
};
|
|
66
68
|
}
|
|
67
|
-
getBetStake(params, config) {
|
|
68
|
-
const baseBet = config.baseGame.baseGameConfig.baseBet;
|
|
69
|
-
return number_helper_1.NumberHelper.safeDivide(params.betAmount, params.creditsPerLine === baseBet ? params.creditsPerLine : baseBet, 3);
|
|
70
|
-
}
|
|
71
69
|
async drawWinningSymbol(weights, commandId) {
|
|
72
70
|
const total = weights.reduce((acc, w) => number_helper_1.NumberHelper.safeSum(acc, w, 2), 0);
|
|
73
71
|
if (total === 0)
|
|
@@ -120,6 +118,7 @@ class TreasureHuntBonusHandler {
|
|
|
120
118
|
}
|
|
121
119
|
extractBonusConfig(config) {
|
|
122
120
|
return {
|
|
121
|
+
symbolsCount: config.bonusGames.bonusGame1.config.symbolsCount,
|
|
123
122
|
stepsCount: config.bonusGames.bonusGame1.config.stepsCount,
|
|
124
123
|
jackpotMultipliers: config.bonusGames.bonusGame1.config.jackpotMultipliers,
|
|
125
124
|
winningWeights: config.bonusGames.bonusGame1.config.winningWeights,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"treasure-hunt-bonus.handler.js","sourceRoot":"","sources":["../../../src/logic/handlers/treasure-hunt-bonus.handler.ts"],"names":[],"mappings":";;;AAAA,kEAMiC;
|
|
1
|
+
{"version":3,"file":"treasure-hunt-bonus.handler.js","sourceRoot":"","sources":["../../../src/logic/handlers/treasure-hunt-bonus.handler.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -17,11 +17,13 @@ export class NumberHelper {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* Multiplies two numbers and rounds the result to the specified decimal places.
|
|
21
|
+
* Use this to avoid floating-point noise and get a deterministic value.
|
|
21
22
|
*/
|
|
22
23
|
public static safeMultiply(a: number, b: number, decimals: number): number {
|
|
23
|
-
const
|
|
24
|
-
|
|
24
|
+
const scale = Math.pow(10, decimals);
|
|
25
|
+
const product = a * b;
|
|
26
|
+
return Math.round(product * scale) / scale;
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
/**
|
|
@@ -114,6 +114,15 @@ export interface TreasureHuntBonusConfig {
|
|
|
114
114
|
};
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
export type TreasureHuntExtractedConfig = Pick<
|
|
118
|
+
TreasureHuntBonusConfig,
|
|
119
|
+
| 'symbolsCount'
|
|
120
|
+
| 'stepsCount'
|
|
121
|
+
| 'jackpotMultipliers'
|
|
122
|
+
| 'winningWeights'
|
|
123
|
+
| 'jackpotScreenCounts'
|
|
124
|
+
>;
|
|
125
|
+
|
|
117
126
|
export interface FreeSpinBonusGameConfig {
|
|
118
127
|
type: 'free_spins';
|
|
119
128
|
potMeter: BonusGameId;
|
|
@@ -6,17 +6,16 @@ import {
|
|
|
6
6
|
SpinType,
|
|
7
7
|
} from '../bonnys-fortune.types';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
BonnysFortuneGameLogicConfigInterface,
|
|
11
|
+
ScatterCheckpoint,
|
|
12
|
+
ScatterGameConfig,
|
|
13
|
+
ScatterSymbol,
|
|
14
|
+
} from '../game-logic-config.interface';
|
|
10
15
|
import { GameSpinInputDto } from '../../domain/types/game-spin-input.dto';
|
|
11
16
|
import { NumberHelper } from '../../helpers/number-helper';
|
|
12
17
|
import { RngService } from '../../rng/rng-service';
|
|
13
18
|
|
|
14
|
-
interface ScatterSymbol {
|
|
15
|
-
symbolId: string;
|
|
16
|
-
value: number;
|
|
17
|
-
weight: number;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
19
|
export class CollectFeatureBonusHandler {
|
|
21
20
|
constructor(private rngService: RngService) {}
|
|
22
21
|
|
|
@@ -27,7 +26,7 @@ export class CollectFeatureBonusHandler {
|
|
|
27
26
|
config: BonnysFortuneGameLogicConfigInterface,
|
|
28
27
|
commandId: string,
|
|
29
28
|
): Promise<BonusRoundResult<CollectFeatureSpinResult>> {
|
|
30
|
-
const
|
|
29
|
+
const betAmount = params.betAmount;
|
|
31
30
|
const scatterConfig = config.scatterGame.config;
|
|
32
31
|
const results = [];
|
|
33
32
|
|
|
@@ -39,7 +38,7 @@ export class CollectFeatureBonusHandler {
|
|
|
39
38
|
let totalMultipliers = 1;
|
|
40
39
|
let totalWin = 0;
|
|
41
40
|
|
|
42
|
-
const
|
|
41
|
+
const resolvedSpins = await Promise.all(
|
|
43
42
|
scatterConfig.scatterCheckpoints.map(async (cp, index) => {
|
|
44
43
|
const actionId = `checkpoint_${index}`;
|
|
45
44
|
const result = await this.rngService.getSingleNumber(
|
|
@@ -52,6 +51,11 @@ export class CollectFeatureBonusHandler {
|
|
|
52
51
|
}),
|
|
53
52
|
);
|
|
54
53
|
|
|
54
|
+
const checkpointBySpin = this.buildCheckpointBySpin(
|
|
55
|
+
resolvedSpins,
|
|
56
|
+
scatterConfig.scatterCheckpoints,
|
|
57
|
+
);
|
|
58
|
+
|
|
55
59
|
for (
|
|
56
60
|
let spinIndex = 0;
|
|
57
61
|
spinIndex < scatterConfig.scatterSpins;
|
|
@@ -64,9 +68,9 @@ export class CollectFeatureBonusHandler {
|
|
|
64
68
|
totalValues,
|
|
65
69
|
totalMultipliers,
|
|
66
70
|
totalWin,
|
|
67
|
-
|
|
71
|
+
betAmount,
|
|
68
72
|
scatterConfig,
|
|
69
|
-
|
|
73
|
+
checkpointBySpin,
|
|
70
74
|
publicState,
|
|
71
75
|
privateState,
|
|
72
76
|
commandId,
|
|
@@ -101,9 +105,9 @@ export class CollectFeatureBonusHandler {
|
|
|
101
105
|
totalValues: number,
|
|
102
106
|
totalMultipliers: number,
|
|
103
107
|
totalWin: number,
|
|
104
|
-
|
|
105
|
-
scatterConfig:
|
|
106
|
-
|
|
108
|
+
betAmount: number,
|
|
109
|
+
scatterConfig: ScatterGameConfig,
|
|
110
|
+
checkpointBySpin: Map<number, ScatterCheckpoint>,
|
|
107
111
|
publicState: BonnysFortunePublicState,
|
|
108
112
|
privateState: BonnysFortunePrivateState,
|
|
109
113
|
commandId: string,
|
|
@@ -139,9 +143,8 @@ export class CollectFeatureBonusHandler {
|
|
|
139
143
|
else valueCount++;
|
|
140
144
|
}
|
|
141
145
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const cp = scatterConfig.scatterCheckpoints[cpIndex];
|
|
146
|
+
const cp = checkpointBySpin.get(spinsLeft);
|
|
147
|
+
if (cp) {
|
|
145
148
|
if (
|
|
146
149
|
(totalMultipliers < cp.multiMinValue && multiCount === 0) ||
|
|
147
150
|
(totalValues < cp.valueMinValue && valueCount === 0)
|
|
@@ -189,7 +192,7 @@ export class CollectFeatureBonusHandler {
|
|
|
189
192
|
);
|
|
190
193
|
const newTotalWin = NumberHelper.safeMultiply(
|
|
191
194
|
NumberHelper.safeMultiply(newTotalValues, newTotalMultipliers, 2),
|
|
192
|
-
|
|
195
|
+
betAmount,
|
|
193
196
|
2,
|
|
194
197
|
);
|
|
195
198
|
const playerWinning = NumberHelper.safeSum(newTotalWin, -totalWin, 2);
|
|
@@ -236,6 +239,20 @@ export class CollectFeatureBonusHandler {
|
|
|
236
239
|
};
|
|
237
240
|
}
|
|
238
241
|
|
|
242
|
+
private buildCheckpointBySpin(
|
|
243
|
+
resolvedSpins: number[],
|
|
244
|
+
scatterCheckpoints: ScatterCheckpoint[],
|
|
245
|
+
): Map<number, ScatterCheckpoint> {
|
|
246
|
+
const map = new Map<number, ScatterCheckpoint>();
|
|
247
|
+
for (let i = 0; i < resolvedSpins.length; i++) {
|
|
248
|
+
const spin = resolvedSpins[i];
|
|
249
|
+
if (!map.has(spin)) {
|
|
250
|
+
map.set(spin, scatterCheckpoints[i]);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return map;
|
|
254
|
+
}
|
|
255
|
+
|
|
239
256
|
private async weightedPick(
|
|
240
257
|
items: Array<{ count?: number; weight: number }>,
|
|
241
258
|
commandId: string,
|
|
@@ -286,16 +303,4 @@ export class CollectFeatureBonusHandler {
|
|
|
286
303
|
}
|
|
287
304
|
return symbols[0];
|
|
288
305
|
}
|
|
289
|
-
|
|
290
|
-
private getBetStake(
|
|
291
|
-
params: GameSpinInputDto,
|
|
292
|
-
config: BonnysFortuneGameLogicConfigInterface,
|
|
293
|
-
): number {
|
|
294
|
-
const baseBet = config.baseGame.baseGameConfig.baseBet;
|
|
295
|
-
return NumberHelper.safeDivide(
|
|
296
|
-
params.betAmount,
|
|
297
|
-
params.creditsPerLine === baseBet ? params.creditsPerLine : baseBet,
|
|
298
|
-
3,
|
|
299
|
-
);
|
|
300
|
-
}
|
|
301
306
|
}
|
|
@@ -6,7 +6,10 @@ import {
|
|
|
6
6
|
TreasureHuntSpinResult,
|
|
7
7
|
} from '../bonnys-fortune.types';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
BonnysFortuneGameLogicConfigInterface,
|
|
11
|
+
TreasureHuntExtractedConfig,
|
|
12
|
+
} from '../game-logic-config.interface';
|
|
10
13
|
import { GameSpinInputDto } from '../../domain/types/game-spin-input.dto';
|
|
11
14
|
import { NumberHelper } from '../../helpers/number-helper';
|
|
12
15
|
import { RngService } from '../../rng/rng-service';
|
|
@@ -21,8 +24,9 @@ export class TreasureHuntBonusHandler {
|
|
|
21
24
|
config: BonnysFortuneGameLogicConfigInterface,
|
|
22
25
|
commandId: string,
|
|
23
26
|
): Promise<BonusRoundResult<TreasureHuntSpinResult>> {
|
|
24
|
-
const
|
|
27
|
+
const betAmount = params.betAmount;
|
|
25
28
|
const {
|
|
29
|
+
symbolsCount: gridSize,
|
|
26
30
|
stepsCount,
|
|
27
31
|
jackpotScreenCounts,
|
|
28
32
|
jackpotMultipliers,
|
|
@@ -38,10 +42,10 @@ export class TreasureHuntBonusHandler {
|
|
|
38
42
|
commandId,
|
|
39
43
|
);
|
|
40
44
|
|
|
41
|
-
const selectionsVector = Array<number>(
|
|
45
|
+
const selectionsVector = Array<number>(gridSize).fill(-1);
|
|
42
46
|
|
|
43
47
|
if (winSymbolIndex >= 0) {
|
|
44
|
-
const positions = await this.randomPositions(
|
|
48
|
+
const positions = await this.randomPositions(gridSize, 3, commandId);
|
|
45
49
|
positions.forEach((pos) => (selectionsVector[pos] = winSymbolIndex));
|
|
46
50
|
jackpotsNo[winSymbolIndex] = NumberHelper.safeSum(
|
|
47
51
|
jackpotsNo[winSymbolIndex],
|
|
@@ -52,16 +56,19 @@ export class TreasureHuntBonusHandler {
|
|
|
52
56
|
|
|
53
57
|
await this.fillRemainingSteps(
|
|
54
58
|
selectionsVector,
|
|
55
|
-
|
|
59
|
+
gridSize,
|
|
56
60
|
jackpotsNo,
|
|
57
61
|
winSymbolIndex,
|
|
58
62
|
commandId,
|
|
59
63
|
);
|
|
60
64
|
|
|
61
|
-
const
|
|
62
|
-
const
|
|
65
|
+
const fullGridSelections = selectionsVector.map((idx) => jackpotKeys[idx]);
|
|
66
|
+
const revealedSelections = fullGridSelections.slice(0, stepsCount);
|
|
67
|
+
const multipliers = revealedSelections.map(
|
|
68
|
+
(name) => jackpotMultipliers[name],
|
|
69
|
+
);
|
|
63
70
|
|
|
64
|
-
const results =
|
|
71
|
+
const results = revealedSelections.map((symbol, index) => {
|
|
65
72
|
const isFinalStep = index === stepsCount - 1;
|
|
66
73
|
|
|
67
74
|
const winningMultiplier =
|
|
@@ -70,7 +77,7 @@ export class TreasureHuntBonusHandler {
|
|
|
70
77
|
: 0;
|
|
71
78
|
const playerWinning =
|
|
72
79
|
isFinalStep && winSymbolIndex >= 0
|
|
73
|
-
? NumberHelper.safeMultiply(
|
|
80
|
+
? NumberHelper.safeMultiply(betAmount, winningMultiplier, 2)
|
|
74
81
|
: 0;
|
|
75
82
|
|
|
76
83
|
return {
|
|
@@ -82,7 +89,7 @@ export class TreasureHuntBonusHandler {
|
|
|
82
89
|
: SpinType.BONUS_GAME_1_SPIN,
|
|
83
90
|
selection: symbol,
|
|
84
91
|
multiplier: multipliers[index],
|
|
85
|
-
multiplierCounts:
|
|
92
|
+
multiplierCounts: revealedSelections.slice(0, index + 1).reduce(
|
|
86
93
|
(acc, key) => {
|
|
87
94
|
acc[key] = (acc[key] || 0) + 1;
|
|
88
95
|
return acc;
|
|
@@ -92,6 +99,7 @@ export class TreasureHuntBonusHandler {
|
|
|
92
99
|
winningMultiplier,
|
|
93
100
|
winningCount: isFinalStep && winSymbolIndex >= 0 ? 3 : 0,
|
|
94
101
|
totalMultiplier: winningMultiplier,
|
|
102
|
+
fullGridSelections,
|
|
95
103
|
},
|
|
96
104
|
publicState,
|
|
97
105
|
privateState: {
|
|
@@ -111,18 +119,6 @@ export class TreasureHuntBonusHandler {
|
|
|
111
119
|
};
|
|
112
120
|
}
|
|
113
121
|
|
|
114
|
-
private getBetStake(
|
|
115
|
-
params: GameSpinInputDto,
|
|
116
|
-
config: BonnysFortuneGameLogicConfigInterface,
|
|
117
|
-
): number {
|
|
118
|
-
const baseBet = config.baseGame.baseGameConfig.baseBet;
|
|
119
|
-
return NumberHelper.safeDivide(
|
|
120
|
-
params.betAmount,
|
|
121
|
-
params.creditsPerLine === baseBet ? params.creditsPerLine : baseBet,
|
|
122
|
-
3,
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
122
|
private async drawWinningSymbol(
|
|
127
123
|
weights: number[],
|
|
128
124
|
commandId: string,
|
|
@@ -219,8 +215,11 @@ export class TreasureHuntBonusHandler {
|
|
|
219
215
|
return selected;
|
|
220
216
|
}
|
|
221
217
|
|
|
222
|
-
private extractBonusConfig(
|
|
218
|
+
private extractBonusConfig(
|
|
219
|
+
config: BonnysFortuneGameLogicConfigInterface,
|
|
220
|
+
): TreasureHuntExtractedConfig {
|
|
223
221
|
return {
|
|
222
|
+
symbolsCount: config.bonusGames.bonusGame1.config.symbolsCount,
|
|
224
223
|
stepsCount: config.bonusGames.bonusGame1.config.stepsCount,
|
|
225
224
|
jackpotMultipliers:
|
|
226
225
|
config.bonusGames.bonusGame1.config.jackpotMultipliers,
|