@slot-engine/core 0.2.9 → 0.2.10
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/index.d.mts +0 -3
- package/dist/index.d.ts +0 -3
- package/dist/index.js +246 -155
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +246 -155
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -371,7 +371,10 @@ var GameSymbol = class _GameSymbol {
|
|
|
371
371
|
constructor(opts) {
|
|
372
372
|
this.id = opts.id;
|
|
373
373
|
this.pays = opts.pays;
|
|
374
|
-
this.properties = new Map(
|
|
374
|
+
this.properties = /* @__PURE__ */ new Map();
|
|
375
|
+
for (const prop in opts.properties) {
|
|
376
|
+
this.properties.set(prop, opts.properties[prop]);
|
|
377
|
+
}
|
|
375
378
|
if (this.pays && Object.keys(this.pays).length === 0) {
|
|
376
379
|
throw new Error(`GameSymbol "${this.id}" must have pays defined.`);
|
|
377
380
|
}
|
|
@@ -387,8 +390,8 @@ var GameSymbol = class _GameSymbol {
|
|
|
387
390
|
if (symbolOrProperties instanceof _GameSymbol) {
|
|
388
391
|
return this.id === symbolOrProperties.id;
|
|
389
392
|
} else {
|
|
390
|
-
for (const
|
|
391
|
-
if (!this.properties.has(
|
|
393
|
+
for (const prop in symbolOrProperties) {
|
|
394
|
+
if (!this.properties.has(prop) || this.properties.get(prop) !== symbolOrProperties[prop]) {
|
|
392
395
|
return false;
|
|
393
396
|
}
|
|
394
397
|
}
|
|
@@ -468,8 +471,8 @@ var Board = class {
|
|
|
468
471
|
updateSymbol(reelIndex, rowIndex, properties) {
|
|
469
472
|
const symbol = this.getSymbol(reelIndex, rowIndex);
|
|
470
473
|
if (symbol) {
|
|
471
|
-
for (const
|
|
472
|
-
symbol.properties.set(
|
|
474
|
+
for (const prop in properties) {
|
|
475
|
+
symbol.properties.set(prop, properties[prop]);
|
|
473
476
|
}
|
|
474
477
|
}
|
|
475
478
|
}
|
|
@@ -485,8 +488,8 @@ var Board = class {
|
|
|
485
488
|
if (symbolOrProperties instanceof GameSymbol) {
|
|
486
489
|
if (symbol.id !== symbolOrProperties.id) matches = false;
|
|
487
490
|
} else {
|
|
488
|
-
for (const
|
|
489
|
-
if (!symbol.properties.has(
|
|
491
|
+
for (const prop in symbolOrProperties) {
|
|
492
|
+
if (!symbol.properties.has(prop) || symbol.properties.get(prop) !== symbolOrProperties[prop]) {
|
|
490
493
|
matches = false;
|
|
491
494
|
break;
|
|
492
495
|
}
|
|
@@ -508,8 +511,8 @@ var Board = class {
|
|
|
508
511
|
if (symbol.id !== symbolOrProperties.id) continue;
|
|
509
512
|
} else {
|
|
510
513
|
let matches = true;
|
|
511
|
-
for (const
|
|
512
|
-
if (!symbol.properties.has(
|
|
514
|
+
for (const prop in symbolOrProperties) {
|
|
515
|
+
if (!symbol.properties.has(prop) || symbol.properties.get(prop) !== symbolOrProperties[prop]) {
|
|
513
516
|
matches = false;
|
|
514
517
|
break;
|
|
515
518
|
}
|
|
@@ -1056,11 +1059,13 @@ var DataService = class extends AbstractService {
|
|
|
1056
1059
|
* Record data for statistical analysis.
|
|
1057
1060
|
*/
|
|
1058
1061
|
record(data) {
|
|
1062
|
+
const properties = {};
|
|
1063
|
+
for (const key in data) {
|
|
1064
|
+
properties[key] = String(data[key]);
|
|
1065
|
+
}
|
|
1059
1066
|
this.recorder.pendingRecords.push({
|
|
1060
1067
|
bookId: this.ctx().state.currentSimulationId,
|
|
1061
|
-
properties
|
|
1062
|
-
Object.entries(data).map(([k, v]) => [k, String(v)])
|
|
1063
|
-
)
|
|
1068
|
+
properties
|
|
1064
1069
|
});
|
|
1065
1070
|
}
|
|
1066
1071
|
/**
|
|
@@ -3956,13 +3961,19 @@ var LinesWinType = class extends WinType {
|
|
|
3956
3961
|
this.validateConfig();
|
|
3957
3962
|
const lineWins = [];
|
|
3958
3963
|
const reels = board;
|
|
3959
|
-
|
|
3964
|
+
const reelsLength = reels.length;
|
|
3965
|
+
const lineNumbers = Object.keys(this.lines);
|
|
3966
|
+
const numLines = lineNumbers.length;
|
|
3967
|
+
for (let lidx = 0; lidx < numLines; lidx++) {
|
|
3968
|
+
const lineNumStr = lineNumbers[lidx];
|
|
3960
3969
|
const lineNum = Number(lineNumStr);
|
|
3970
|
+
const line = this.lines[lineNum];
|
|
3961
3971
|
let baseSymbol;
|
|
3962
3972
|
const potentialWinLine = [];
|
|
3963
3973
|
const potentialWildLine = [];
|
|
3964
3974
|
let isInterrupted = false;
|
|
3965
|
-
for (
|
|
3975
|
+
for (let ridx = 0; ridx < reelsLength; ridx++) {
|
|
3976
|
+
const reel = reels[ridx];
|
|
3966
3977
|
const sidx = line[ridx];
|
|
3967
3978
|
const thisSymbol = reel[sidx];
|
|
3968
3979
|
if (!baseSymbol) {
|
|
@@ -3993,66 +4004,91 @@ var LinesWinType = class extends WinType {
|
|
|
3993
4004
|
break;
|
|
3994
4005
|
}
|
|
3995
4006
|
}
|
|
3996
|
-
const
|
|
3997
|
-
|
|
3998
|
-
)
|
|
4007
|
+
const pays = baseSymbol.pays || {};
|
|
4008
|
+
let minSymLine = Infinity;
|
|
4009
|
+
for (const key in pays) {
|
|
4010
|
+
const num = parseInt(key, 10);
|
|
4011
|
+
if (num < minSymLine) minSymLine = num;
|
|
4012
|
+
}
|
|
3999
4013
|
if (potentialWinLine.length < minSymLine) continue;
|
|
4000
4014
|
const linePayout = this.getLinePayout(potentialWinLine);
|
|
4001
4015
|
const wildLinePayout = this.getLinePayout(potentialWildLine);
|
|
4002
|
-
let finalLine
|
|
4003
|
-
kind: potentialWinLine.length,
|
|
4004
|
-
baseSymbol,
|
|
4005
|
-
symbols: potentialWinLine.map((s) => ({
|
|
4006
|
-
symbol: s.symbol,
|
|
4007
|
-
isWild: this.isWild(s.symbol),
|
|
4008
|
-
reelIndex: s.reel,
|
|
4009
|
-
posIndex: s.row
|
|
4010
|
-
})),
|
|
4011
|
-
lineNumber: lineNum,
|
|
4012
|
-
payout: linePayout
|
|
4013
|
-
};
|
|
4016
|
+
let finalLine;
|
|
4014
4017
|
if (wildLinePayout > linePayout) {
|
|
4015
4018
|
baseSymbol = potentialWildLine[0]?.symbol;
|
|
4019
|
+
const wildSymbols = [];
|
|
4020
|
+
const wildLineLength = potentialWildLine.length;
|
|
4021
|
+
for (let i = 0; i < wildLineLength; i++) {
|
|
4022
|
+
const s = potentialWildLine[i];
|
|
4023
|
+
wildSymbols.push({
|
|
4024
|
+
symbol: s.symbol,
|
|
4025
|
+
isWild: this.isWild(s.symbol),
|
|
4026
|
+
reelIndex: s.reel,
|
|
4027
|
+
posIndex: s.row
|
|
4028
|
+
});
|
|
4029
|
+
}
|
|
4016
4030
|
finalLine = {
|
|
4017
|
-
kind:
|
|
4031
|
+
kind: wildLineLength,
|
|
4018
4032
|
baseSymbol,
|
|
4019
|
-
symbols:
|
|
4033
|
+
symbols: wildSymbols,
|
|
4034
|
+
lineNumber: lineNum,
|
|
4035
|
+
payout: wildLinePayout
|
|
4036
|
+
};
|
|
4037
|
+
} else {
|
|
4038
|
+
const symbols = [];
|
|
4039
|
+
const lineLength = potentialWinLine.length;
|
|
4040
|
+
for (let i = 0; i < lineLength; i++) {
|
|
4041
|
+
const s = potentialWinLine[i];
|
|
4042
|
+
symbols.push({
|
|
4020
4043
|
symbol: s.symbol,
|
|
4021
4044
|
isWild: this.isWild(s.symbol),
|
|
4022
4045
|
reelIndex: s.reel,
|
|
4023
4046
|
posIndex: s.row
|
|
4024
|
-
})
|
|
4047
|
+
});
|
|
4048
|
+
}
|
|
4049
|
+
finalLine = {
|
|
4050
|
+
kind: lineLength,
|
|
4051
|
+
baseSymbol,
|
|
4052
|
+
symbols,
|
|
4025
4053
|
lineNumber: lineNum,
|
|
4026
|
-
payout:
|
|
4054
|
+
payout: linePayout
|
|
4027
4055
|
};
|
|
4028
4056
|
}
|
|
4029
4057
|
lineWins.push(finalLine);
|
|
4030
|
-
}
|
|
4031
|
-
for (const win of lineWins) {
|
|
4032
4058
|
this.ctx.services.data.recordSymbolOccurrence({
|
|
4033
|
-
kind:
|
|
4034
|
-
symbolId:
|
|
4059
|
+
kind: finalLine.kind,
|
|
4060
|
+
symbolId: finalLine.baseSymbol.id,
|
|
4035
4061
|
spinType: this.ctx.state.currentSpinType
|
|
4036
4062
|
});
|
|
4037
4063
|
}
|
|
4038
|
-
|
|
4064
|
+
let totalPayout = 0;
|
|
4065
|
+
for (let i = 0; i < lineWins.length; i++) {
|
|
4066
|
+
totalPayout += lineWins[i].payout;
|
|
4067
|
+
}
|
|
4068
|
+
this.payout = totalPayout;
|
|
4039
4069
|
this.winCombinations = lineWins;
|
|
4040
4070
|
return this;
|
|
4041
4071
|
}
|
|
4042
4072
|
getLinePayout(line) {
|
|
4043
|
-
|
|
4044
|
-
|
|
4073
|
+
const lineLength = line.length;
|
|
4074
|
+
if (lineLength === 0) return 0;
|
|
4075
|
+
let baseSymbol;
|
|
4076
|
+
for (let i = 0; i < lineLength; i++) {
|
|
4077
|
+
const s = line[i];
|
|
4078
|
+
if (!this.isWild(s.symbol)) {
|
|
4079
|
+
baseSymbol = s.symbol;
|
|
4080
|
+
break;
|
|
4081
|
+
}
|
|
4082
|
+
}
|
|
4045
4083
|
if (!baseSymbol) baseSymbol = line[0].symbol;
|
|
4046
|
-
|
|
4047
|
-
const payout = this.getSymbolPayout(baseSymbol, kind);
|
|
4048
|
-
return payout;
|
|
4084
|
+
return this.getSymbolPayout(baseSymbol, lineLength);
|
|
4049
4085
|
}
|
|
4050
4086
|
};
|
|
4051
4087
|
|
|
4052
4088
|
// src/win-types/ClusterWinType.ts
|
|
4053
4089
|
var ClusterWinType = class extends WinType {
|
|
4054
|
-
_checked =
|
|
4055
|
-
_checkedWilds =
|
|
4090
|
+
_checked = /* @__PURE__ */ new Set();
|
|
4091
|
+
_checkedWilds = /* @__PURE__ */ new Set();
|
|
4056
4092
|
_currentBoard = [];
|
|
4057
4093
|
constructor(opts) {
|
|
4058
4094
|
super(opts);
|
|
@@ -4065,121 +4101,169 @@ var ClusterWinType = class extends WinType {
|
|
|
4065
4101
|
*/
|
|
4066
4102
|
evaluateWins(board) {
|
|
4067
4103
|
this.validateConfig();
|
|
4068
|
-
this._checked
|
|
4104
|
+
this._checked.clear();
|
|
4069
4105
|
this._currentBoard = board;
|
|
4070
4106
|
const clusterWins = [];
|
|
4071
4107
|
const potentialClusters = [];
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4108
|
+
const boardLength = board.length;
|
|
4109
|
+
for (let ridx = 0; ridx < boardLength; ridx++) {
|
|
4110
|
+
const reel = board[ridx];
|
|
4111
|
+
const reelLength = reel.length;
|
|
4112
|
+
for (let sidx = 0; sidx < reelLength; sidx++) {
|
|
4113
|
+
const symbol = reel[sidx];
|
|
4114
|
+
this._checkedWilds.clear();
|
|
4075
4115
|
if (this.isWild(symbol)) continue;
|
|
4076
|
-
|
|
4116
|
+
const posKey = ridx * 1e4 + sidx;
|
|
4117
|
+
if (this._checked.has(posKey)) {
|
|
4077
4118
|
continue;
|
|
4078
4119
|
}
|
|
4079
4120
|
const thisSymbol = { reel: ridx, row: sidx, symbol };
|
|
4080
|
-
this._checked.
|
|
4121
|
+
this._checked.add(posKey);
|
|
4081
4122
|
const neighbors = this.getNeighbors(ridx, sidx);
|
|
4082
4123
|
const matchingSymbols = this.evaluateCluster(symbol, neighbors);
|
|
4083
|
-
|
|
4084
|
-
|
|
4124
|
+
const matchingSize = matchingSymbols.size;
|
|
4125
|
+
if (matchingSize >= 1) {
|
|
4126
|
+
const cluster = [thisSymbol];
|
|
4127
|
+
for (const sym of matchingSymbols.values()) {
|
|
4128
|
+
cluster.push(sym);
|
|
4129
|
+
}
|
|
4130
|
+
potentialClusters.push(cluster);
|
|
4085
4131
|
}
|
|
4086
4132
|
}
|
|
4087
4133
|
}
|
|
4088
|
-
for (
|
|
4089
|
-
|
|
4090
|
-
|
|
4134
|
+
for (let ridx = 0; ridx < boardLength; ridx++) {
|
|
4135
|
+
const reel = board[ridx];
|
|
4136
|
+
const reelLength = reel.length;
|
|
4137
|
+
for (let sidx = 0; sidx < reelLength; sidx++) {
|
|
4138
|
+
const symbol = reel[sidx];
|
|
4139
|
+
this._checkedWilds.clear();
|
|
4091
4140
|
if (!this.isWild(symbol)) continue;
|
|
4092
|
-
|
|
4141
|
+
const posKey = ridx * 1e4 + sidx;
|
|
4142
|
+
if (this._checked.has(posKey)) {
|
|
4093
4143
|
continue;
|
|
4094
4144
|
}
|
|
4095
4145
|
const thisSymbol = { reel: ridx, row: sidx, symbol };
|
|
4096
|
-
this._checked.
|
|
4146
|
+
this._checked.add(posKey);
|
|
4097
4147
|
const neighbors = this.getNeighbors(ridx, sidx);
|
|
4098
4148
|
const matchingSymbols = this.evaluateCluster(symbol, neighbors);
|
|
4099
|
-
|
|
4100
|
-
|
|
4149
|
+
const matchingSize = matchingSymbols.size;
|
|
4150
|
+
if (matchingSize >= 1) {
|
|
4151
|
+
const cluster = [thisSymbol];
|
|
4152
|
+
for (const sym of matchingSymbols.values()) {
|
|
4153
|
+
cluster.push(sym);
|
|
4154
|
+
}
|
|
4155
|
+
potentialClusters.push(cluster);
|
|
4101
4156
|
}
|
|
4102
4157
|
}
|
|
4103
4158
|
}
|
|
4104
|
-
|
|
4159
|
+
const numClusters = potentialClusters.length;
|
|
4160
|
+
for (let i = 0; i < numClusters; i++) {
|
|
4161
|
+
const cluster = potentialClusters[i];
|
|
4105
4162
|
const kind = cluster.length;
|
|
4106
|
-
let baseSymbol
|
|
4163
|
+
let baseSymbol;
|
|
4164
|
+
for (let j = 0; j < kind; j++) {
|
|
4165
|
+
const sym = cluster[j].symbol;
|
|
4166
|
+
if (!this.isWild(sym)) {
|
|
4167
|
+
baseSymbol = sym;
|
|
4168
|
+
break;
|
|
4169
|
+
}
|
|
4170
|
+
}
|
|
4107
4171
|
if (!baseSymbol) baseSymbol = cluster[0].symbol;
|
|
4108
4172
|
const payout = this.getSymbolPayout(baseSymbol, kind);
|
|
4109
4173
|
if (payout === 0) continue;
|
|
4110
|
-
|
|
4111
|
-
|
|
4174
|
+
const pays = baseSymbol.pays;
|
|
4175
|
+
if (!pays) continue;
|
|
4176
|
+
let hasPays = false;
|
|
4177
|
+
for (const _ in pays) {
|
|
4178
|
+
hasPays = true;
|
|
4179
|
+
break;
|
|
4112
4180
|
}
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
symbols
|
|
4181
|
+
if (!hasPays) continue;
|
|
4182
|
+
const symbols = [];
|
|
4183
|
+
for (let j = 0; j < kind; j++) {
|
|
4184
|
+
const s = cluster[j];
|
|
4185
|
+
symbols.push({
|
|
4118
4186
|
symbol: s.symbol,
|
|
4119
4187
|
isWild: this.isWild(s.symbol),
|
|
4120
4188
|
reelIndex: s.reel,
|
|
4121
4189
|
posIndex: s.row
|
|
4122
|
-
})
|
|
4190
|
+
});
|
|
4191
|
+
}
|
|
4192
|
+
clusterWins.push({
|
|
4193
|
+
payout,
|
|
4194
|
+
kind,
|
|
4195
|
+
baseSymbol,
|
|
4196
|
+
symbols
|
|
4123
4197
|
});
|
|
4124
|
-
}
|
|
4125
|
-
for (const win of clusterWins) {
|
|
4126
4198
|
this.ctx.services.data.recordSymbolOccurrence({
|
|
4127
|
-
kind
|
|
4128
|
-
symbolId:
|
|
4199
|
+
kind,
|
|
4200
|
+
symbolId: baseSymbol.id,
|
|
4129
4201
|
spinType: this.ctx.state.currentSpinType
|
|
4130
4202
|
});
|
|
4131
4203
|
}
|
|
4132
|
-
|
|
4204
|
+
let totalPayout = 0;
|
|
4205
|
+
for (let i = 0; i < clusterWins.length; i++) {
|
|
4206
|
+
totalPayout += clusterWins[i].payout;
|
|
4207
|
+
}
|
|
4208
|
+
this.payout = totalPayout;
|
|
4133
4209
|
this.winCombinations = clusterWins;
|
|
4134
4210
|
return this;
|
|
4135
4211
|
}
|
|
4136
4212
|
getNeighbors(ridx, sidx) {
|
|
4137
4213
|
const board = this._currentBoard;
|
|
4138
4214
|
const neighbors = [];
|
|
4139
|
-
|
|
4140
|
-
[ridx - 1
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
];
|
|
4145
|
-
potentialNeighbors.forEach(([nridx, nsidx]) => {
|
|
4146
|
-
if (board[nridx] && board[nridx][nsidx]) {
|
|
4147
|
-
neighbors.push({ reel: nridx, row: nsidx, symbol: board[nridx][nsidx] });
|
|
4215
|
+
if (ridx > 0) {
|
|
4216
|
+
const leftReel = board[ridx - 1];
|
|
4217
|
+
const leftSymbol = leftReel[sidx];
|
|
4218
|
+
if (leftSymbol !== void 0) {
|
|
4219
|
+
neighbors.push({ reel: ridx - 1, row: sidx, symbol: leftSymbol });
|
|
4148
4220
|
}
|
|
4149
|
-
}
|
|
4221
|
+
}
|
|
4222
|
+
const rightReel = board[ridx + 1];
|
|
4223
|
+
if (rightReel !== void 0) {
|
|
4224
|
+
const rightSymbol = rightReel[sidx];
|
|
4225
|
+
if (rightSymbol !== void 0) {
|
|
4226
|
+
neighbors.push({ reel: ridx + 1, row: sidx, symbol: rightSymbol });
|
|
4227
|
+
}
|
|
4228
|
+
}
|
|
4229
|
+
const currentReel = board[ridx];
|
|
4230
|
+
const topSymbol = currentReel[sidx - 1];
|
|
4231
|
+
if (topSymbol !== void 0) {
|
|
4232
|
+
neighbors.push({ reel: ridx, row: sidx - 1, symbol: topSymbol });
|
|
4233
|
+
}
|
|
4234
|
+
const bottomSymbol = currentReel[sidx + 1];
|
|
4235
|
+
if (bottomSymbol !== void 0) {
|
|
4236
|
+
neighbors.push({ reel: ridx, row: sidx + 1, symbol: bottomSymbol });
|
|
4237
|
+
}
|
|
4150
4238
|
return neighbors;
|
|
4151
4239
|
}
|
|
4152
4240
|
evaluateCluster(rootSymbol, neighbors) {
|
|
4153
4241
|
const matchingSymbols = /* @__PURE__ */ new Map();
|
|
4154
|
-
neighbors.
|
|
4242
|
+
const numNeighbors = neighbors.length;
|
|
4243
|
+
for (let i = 0; i < numNeighbors; i++) {
|
|
4244
|
+
const neighbor = neighbors[i];
|
|
4155
4245
|
const { reel, row, symbol } = neighbor;
|
|
4156
|
-
|
|
4157
|
-
if (this.
|
|
4246
|
+
const posKey = reel * 1e4 + row;
|
|
4247
|
+
if (this._checked.has(posKey)) continue;
|
|
4248
|
+
if (this._checkedWilds.has(posKey)) continue;
|
|
4158
4249
|
if (this.isWild(symbol) || symbol.compare(rootSymbol)) {
|
|
4159
|
-
const key =
|
|
4250
|
+
const key = String(posKey);
|
|
4160
4251
|
matchingSymbols.set(key, { reel, row, symbol });
|
|
4161
4252
|
if (symbol.compare(rootSymbol)) {
|
|
4162
|
-
this._checked.
|
|
4253
|
+
this._checked.add(posKey);
|
|
4163
4254
|
}
|
|
4164
4255
|
if (this.isWild(symbol)) {
|
|
4165
|
-
this._checkedWilds.
|
|
4256
|
+
this._checkedWilds.add(posKey);
|
|
4166
4257
|
}
|
|
4167
|
-
const
|
|
4168
|
-
const nestedMatches = this.evaluateCluster(rootSymbol,
|
|
4169
|
-
nestedMatches.
|
|
4170
|
-
const nkey = `${nsym.reel}-${nsym.row}`;
|
|
4258
|
+
const nestedNeighbors = this.getNeighbors(reel, row);
|
|
4259
|
+
const nestedMatches = this.evaluateCluster(rootSymbol, nestedNeighbors);
|
|
4260
|
+
for (const [nkey, nsym] of nestedMatches.entries()) {
|
|
4171
4261
|
matchingSymbols.set(nkey, nsym);
|
|
4172
|
-
}
|
|
4262
|
+
}
|
|
4173
4263
|
}
|
|
4174
|
-
}
|
|
4264
|
+
}
|
|
4175
4265
|
return matchingSymbols;
|
|
4176
4266
|
}
|
|
4177
|
-
isChecked(ridx, sidx) {
|
|
4178
|
-
return !!this._checked.find((c) => c.reel === ridx && c.row === sidx);
|
|
4179
|
-
}
|
|
4180
|
-
isCheckedWild(ridx, sidx) {
|
|
4181
|
-
return !!this._checkedWilds.find((c) => c.reel === ridx && c.row === sidx);
|
|
4182
|
-
}
|
|
4183
4267
|
};
|
|
4184
4268
|
|
|
4185
4269
|
// src/win-types/ManywaysWinType.ts
|
|
@@ -4198,7 +4282,7 @@ var ManywaysWinType = class extends WinType {
|
|
|
4198
4282
|
const { jumpGaps = false } = opts;
|
|
4199
4283
|
const waysWins = [];
|
|
4200
4284
|
const reels = board;
|
|
4201
|
-
const
|
|
4285
|
+
const numReels = reels.length;
|
|
4202
4286
|
const candidateSymbols = /* @__PURE__ */ new Map();
|
|
4203
4287
|
if (jumpGaps) {
|
|
4204
4288
|
for (const reel of reels) {
|
|
@@ -4209,7 +4293,7 @@ var ManywaysWinType = class extends WinType {
|
|
|
4209
4293
|
} else {
|
|
4210
4294
|
let searchReelIdx = 0;
|
|
4211
4295
|
let searchActive = true;
|
|
4212
|
-
while (searchActive && searchReelIdx <
|
|
4296
|
+
while (searchActive && searchReelIdx < numReels) {
|
|
4213
4297
|
const reel = reels[searchReelIdx];
|
|
4214
4298
|
let hasWild = false;
|
|
4215
4299
|
for (const symbol of reel) {
|
|
@@ -4225,71 +4309,78 @@ var ManywaysWinType = class extends WinType {
|
|
|
4225
4309
|
}
|
|
4226
4310
|
}
|
|
4227
4311
|
for (const baseSymbol of candidateSymbols.values()) {
|
|
4228
|
-
|
|
4229
|
-
let
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4312
|
+
const symbolList = [];
|
|
4313
|
+
let wayLength = 0;
|
|
4314
|
+
let firstNonWildSymbol;
|
|
4315
|
+
let totalWays = 1;
|
|
4316
|
+
for (let ridx = 0; ridx < numReels; ridx++) {
|
|
4317
|
+
const reel = reels[ridx];
|
|
4318
|
+
let reelMatches;
|
|
4319
|
+
for (let sidx = 0; sidx < reel.length; sidx++) {
|
|
4320
|
+
const symbol = reel[sidx];
|
|
4233
4321
|
const isMatch = baseSymbol.compare(symbol) || this.isWild(symbol);
|
|
4234
4322
|
if (isMatch) {
|
|
4235
|
-
if (!
|
|
4236
|
-
|
|
4323
|
+
if (!reelMatches) {
|
|
4324
|
+
reelMatches = [];
|
|
4325
|
+
}
|
|
4326
|
+
reelMatches.push({ reel: ridx, row: sidx, symbol });
|
|
4327
|
+
if (!firstNonWildSymbol && !this.isWild(symbol)) {
|
|
4328
|
+
firstNonWildSymbol = symbol;
|
|
4237
4329
|
}
|
|
4238
|
-
symbolList[ridx].push({ reel: ridx, row: sidx, symbol });
|
|
4239
4330
|
}
|
|
4240
4331
|
}
|
|
4241
|
-
if (
|
|
4242
|
-
|
|
4332
|
+
if (reelMatches) {
|
|
4333
|
+
symbolList[wayLength++] = reelMatches;
|
|
4334
|
+
totalWays *= reelMatches.length;
|
|
4335
|
+
} else if (!jumpGaps) {
|
|
4243
4336
|
break;
|
|
4244
4337
|
}
|
|
4245
4338
|
}
|
|
4246
|
-
const
|
|
4247
|
-
|
|
4248
|
-
)
|
|
4249
|
-
|
|
4339
|
+
const pays = baseSymbol.pays || {};
|
|
4340
|
+
let minSymLine = Infinity;
|
|
4341
|
+
for (const key in pays) {
|
|
4342
|
+
const num = parseInt(key, 10);
|
|
4343
|
+
if (num < minSymLine) minSymLine = num;
|
|
4344
|
+
}
|
|
4250
4345
|
if (wayLength >= minSymLine) {
|
|
4251
|
-
|
|
4346
|
+
const winBaseSymbol = firstNonWildSymbol || symbolList[0][0].symbol;
|
|
4347
|
+
const singleWayPayout = this.getSymbolPayout(winBaseSymbol, wayLength);
|
|
4348
|
+
const totalPayout2 = singleWayPayout * totalWays;
|
|
4349
|
+
const symbols = [];
|
|
4350
|
+
for (let i = 0; i < wayLength; i++) {
|
|
4351
|
+
const reelSyms = symbolList[i];
|
|
4352
|
+
for (let j = 0; j < reelSyms.length; j++) {
|
|
4353
|
+
const s = reelSyms[j];
|
|
4354
|
+
symbols.push({
|
|
4355
|
+
symbol: s.symbol,
|
|
4356
|
+
isWild: this.isWild(s.symbol),
|
|
4357
|
+
reelIndex: s.reel,
|
|
4358
|
+
posIndex: s.row
|
|
4359
|
+
});
|
|
4360
|
+
}
|
|
4361
|
+
}
|
|
4362
|
+
waysWins.push({
|
|
4363
|
+
kind: wayLength,
|
|
4364
|
+
baseSymbol: winBaseSymbol,
|
|
4365
|
+
symbols,
|
|
4366
|
+
ways: totalWays,
|
|
4367
|
+
payout: totalPayout2
|
|
4368
|
+
});
|
|
4369
|
+
this.ctx.services.data.recordSymbolOccurrence({
|
|
4370
|
+
kind: wayLength,
|
|
4371
|
+
symbolId: winBaseSymbol.id,
|
|
4372
|
+
spinType: this.ctx.state.currentSpinType
|
|
4373
|
+
});
|
|
4252
4374
|
}
|
|
4253
4375
|
}
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
if (!baseSymbol) baseSymbol = symbolList[Object.keys(symbolList)[0]][0].symbol;
|
|
4258
|
-
const singleWayPayout = this.getSymbolPayout(baseSymbol, wayLength);
|
|
4259
|
-
const totalWays = Object.values(symbolList).reduce(
|
|
4260
|
-
(ways, syms) => ways * syms.length,
|
|
4261
|
-
1
|
|
4262
|
-
);
|
|
4263
|
-
const totalPayout = singleWayPayout * totalWays;
|
|
4264
|
-
waysWins.push({
|
|
4265
|
-
kind: wayLength,
|
|
4266
|
-
baseSymbol,
|
|
4267
|
-
symbols: Object.values(symbolList).flatMap(
|
|
4268
|
-
(reel) => reel.map((s) => ({
|
|
4269
|
-
symbol: s.symbol,
|
|
4270
|
-
isWild: this.isWild(s.symbol),
|
|
4271
|
-
reelIndex: s.reel,
|
|
4272
|
-
posIndex: s.row
|
|
4273
|
-
}))
|
|
4274
|
-
),
|
|
4275
|
-
ways: totalWays,
|
|
4276
|
-
payout: totalPayout
|
|
4277
|
-
});
|
|
4278
|
-
}
|
|
4279
|
-
for (const win of waysWins) {
|
|
4280
|
-
this.ctx.services.data.recordSymbolOccurrence({
|
|
4281
|
-
kind: win.kind,
|
|
4282
|
-
symbolId: win.baseSymbol.id,
|
|
4283
|
-
spinType: this.ctx.state.currentSpinType
|
|
4284
|
-
});
|
|
4376
|
+
let totalPayout = 0;
|
|
4377
|
+
for (let i = 0; i < waysWins.length; i++) {
|
|
4378
|
+
totalPayout += waysWins[i].payout;
|
|
4285
4379
|
}
|
|
4286
|
-
this.payout =
|
|
4380
|
+
this.payout = totalPayout;
|
|
4287
4381
|
this.winCombinations = waysWins;
|
|
4288
4382
|
return this;
|
|
4289
4383
|
}
|
|
4290
|
-
getWayLength(symbolList) {
|
|
4291
|
-
return Object.keys(symbolList).length;
|
|
4292
|
-
}
|
|
4293
4384
|
};
|
|
4294
4385
|
|
|
4295
4386
|
// src/reel-set/GeneratedReelSet.ts
|