@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.d.mts
CHANGED
|
@@ -1571,8 +1571,6 @@ declare class ClusterWinType extends WinType {
|
|
|
1571
1571
|
evaluateWins(board: Reels): this;
|
|
1572
1572
|
private getNeighbors;
|
|
1573
1573
|
private evaluateCluster;
|
|
1574
|
-
private isChecked;
|
|
1575
|
-
private isCheckedWild;
|
|
1576
1574
|
}
|
|
1577
1575
|
interface ClusterWinTypeOpts extends WinTypeOpts {
|
|
1578
1576
|
}
|
|
@@ -1594,7 +1592,6 @@ declare class ManywaysWinType extends WinType {
|
|
|
1594
1592
|
evaluateWins(board: Reels, opts?: {
|
|
1595
1593
|
jumpGaps?: boolean;
|
|
1596
1594
|
}): this;
|
|
1597
|
-
private getWayLength;
|
|
1598
1595
|
}
|
|
1599
1596
|
interface ManywaysWinTypeOpts extends WinTypeOpts {
|
|
1600
1597
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1571,8 +1571,6 @@ declare class ClusterWinType extends WinType {
|
|
|
1571
1571
|
evaluateWins(board: Reels): this;
|
|
1572
1572
|
private getNeighbors;
|
|
1573
1573
|
private evaluateCluster;
|
|
1574
|
-
private isChecked;
|
|
1575
|
-
private isCheckedWild;
|
|
1576
1574
|
}
|
|
1577
1575
|
interface ClusterWinTypeOpts extends WinTypeOpts {
|
|
1578
1576
|
}
|
|
@@ -1594,7 +1592,6 @@ declare class ManywaysWinType extends WinType {
|
|
|
1594
1592
|
evaluateWins(board: Reels, opts?: {
|
|
1595
1593
|
jumpGaps?: boolean;
|
|
1596
1594
|
}): this;
|
|
1597
|
-
private getWayLength;
|
|
1598
1595
|
}
|
|
1599
1596
|
interface ManywaysWinTypeOpts extends WinTypeOpts {
|
|
1600
1597
|
}
|
package/dist/index.js
CHANGED
|
@@ -420,7 +420,10 @@ var GameSymbol = class _GameSymbol {
|
|
|
420
420
|
constructor(opts) {
|
|
421
421
|
this.id = opts.id;
|
|
422
422
|
this.pays = opts.pays;
|
|
423
|
-
this.properties = new Map(
|
|
423
|
+
this.properties = /* @__PURE__ */ new Map();
|
|
424
|
+
for (const prop in opts.properties) {
|
|
425
|
+
this.properties.set(prop, opts.properties[prop]);
|
|
426
|
+
}
|
|
424
427
|
if (this.pays && Object.keys(this.pays).length === 0) {
|
|
425
428
|
throw new Error(`GameSymbol "${this.id}" must have pays defined.`);
|
|
426
429
|
}
|
|
@@ -436,8 +439,8 @@ var GameSymbol = class _GameSymbol {
|
|
|
436
439
|
if (symbolOrProperties instanceof _GameSymbol) {
|
|
437
440
|
return this.id === symbolOrProperties.id;
|
|
438
441
|
} else {
|
|
439
|
-
for (const
|
|
440
|
-
if (!this.properties.has(
|
|
442
|
+
for (const prop in symbolOrProperties) {
|
|
443
|
+
if (!this.properties.has(prop) || this.properties.get(prop) !== symbolOrProperties[prop]) {
|
|
441
444
|
return false;
|
|
442
445
|
}
|
|
443
446
|
}
|
|
@@ -517,8 +520,8 @@ var Board = class {
|
|
|
517
520
|
updateSymbol(reelIndex, rowIndex, properties) {
|
|
518
521
|
const symbol = this.getSymbol(reelIndex, rowIndex);
|
|
519
522
|
if (symbol) {
|
|
520
|
-
for (const
|
|
521
|
-
symbol.properties.set(
|
|
523
|
+
for (const prop in properties) {
|
|
524
|
+
symbol.properties.set(prop, properties[prop]);
|
|
522
525
|
}
|
|
523
526
|
}
|
|
524
527
|
}
|
|
@@ -534,8 +537,8 @@ var Board = class {
|
|
|
534
537
|
if (symbolOrProperties instanceof GameSymbol) {
|
|
535
538
|
if (symbol.id !== symbolOrProperties.id) matches = false;
|
|
536
539
|
} else {
|
|
537
|
-
for (const
|
|
538
|
-
if (!symbol.properties.has(
|
|
540
|
+
for (const prop in symbolOrProperties) {
|
|
541
|
+
if (!symbol.properties.has(prop) || symbol.properties.get(prop) !== symbolOrProperties[prop]) {
|
|
539
542
|
matches = false;
|
|
540
543
|
break;
|
|
541
544
|
}
|
|
@@ -557,8 +560,8 @@ var Board = class {
|
|
|
557
560
|
if (symbol.id !== symbolOrProperties.id) continue;
|
|
558
561
|
} else {
|
|
559
562
|
let matches = true;
|
|
560
|
-
for (const
|
|
561
|
-
if (!symbol.properties.has(
|
|
563
|
+
for (const prop in symbolOrProperties) {
|
|
564
|
+
if (!symbol.properties.has(prop) || symbol.properties.get(prop) !== symbolOrProperties[prop]) {
|
|
562
565
|
matches = false;
|
|
563
566
|
break;
|
|
564
567
|
}
|
|
@@ -1105,11 +1108,13 @@ var DataService = class extends AbstractService {
|
|
|
1105
1108
|
* Record data for statistical analysis.
|
|
1106
1109
|
*/
|
|
1107
1110
|
record(data) {
|
|
1111
|
+
const properties = {};
|
|
1112
|
+
for (const key in data) {
|
|
1113
|
+
properties[key] = String(data[key]);
|
|
1114
|
+
}
|
|
1108
1115
|
this.recorder.pendingRecords.push({
|
|
1109
1116
|
bookId: this.ctx().state.currentSimulationId,
|
|
1110
|
-
properties
|
|
1111
|
-
Object.entries(data).map(([k, v]) => [k, String(v)])
|
|
1112
|
-
)
|
|
1117
|
+
properties
|
|
1113
1118
|
});
|
|
1114
1119
|
}
|
|
1115
1120
|
/**
|
|
@@ -4005,13 +4010,19 @@ var LinesWinType = class extends WinType {
|
|
|
4005
4010
|
this.validateConfig();
|
|
4006
4011
|
const lineWins = [];
|
|
4007
4012
|
const reels = board;
|
|
4008
|
-
|
|
4013
|
+
const reelsLength = reels.length;
|
|
4014
|
+
const lineNumbers = Object.keys(this.lines);
|
|
4015
|
+
const numLines = lineNumbers.length;
|
|
4016
|
+
for (let lidx = 0; lidx < numLines; lidx++) {
|
|
4017
|
+
const lineNumStr = lineNumbers[lidx];
|
|
4009
4018
|
const lineNum = Number(lineNumStr);
|
|
4019
|
+
const line = this.lines[lineNum];
|
|
4010
4020
|
let baseSymbol;
|
|
4011
4021
|
const potentialWinLine = [];
|
|
4012
4022
|
const potentialWildLine = [];
|
|
4013
4023
|
let isInterrupted = false;
|
|
4014
|
-
for (
|
|
4024
|
+
for (let ridx = 0; ridx < reelsLength; ridx++) {
|
|
4025
|
+
const reel = reels[ridx];
|
|
4015
4026
|
const sidx = line[ridx];
|
|
4016
4027
|
const thisSymbol = reel[sidx];
|
|
4017
4028
|
if (!baseSymbol) {
|
|
@@ -4042,66 +4053,91 @@ var LinesWinType = class extends WinType {
|
|
|
4042
4053
|
break;
|
|
4043
4054
|
}
|
|
4044
4055
|
}
|
|
4045
|
-
const
|
|
4046
|
-
|
|
4047
|
-
)
|
|
4056
|
+
const pays = baseSymbol.pays || {};
|
|
4057
|
+
let minSymLine = Infinity;
|
|
4058
|
+
for (const key in pays) {
|
|
4059
|
+
const num = parseInt(key, 10);
|
|
4060
|
+
if (num < minSymLine) minSymLine = num;
|
|
4061
|
+
}
|
|
4048
4062
|
if (potentialWinLine.length < minSymLine) continue;
|
|
4049
4063
|
const linePayout = this.getLinePayout(potentialWinLine);
|
|
4050
4064
|
const wildLinePayout = this.getLinePayout(potentialWildLine);
|
|
4051
|
-
let finalLine
|
|
4052
|
-
kind: potentialWinLine.length,
|
|
4053
|
-
baseSymbol,
|
|
4054
|
-
symbols: potentialWinLine.map((s) => ({
|
|
4055
|
-
symbol: s.symbol,
|
|
4056
|
-
isWild: this.isWild(s.symbol),
|
|
4057
|
-
reelIndex: s.reel,
|
|
4058
|
-
posIndex: s.row
|
|
4059
|
-
})),
|
|
4060
|
-
lineNumber: lineNum,
|
|
4061
|
-
payout: linePayout
|
|
4062
|
-
};
|
|
4065
|
+
let finalLine;
|
|
4063
4066
|
if (wildLinePayout > linePayout) {
|
|
4064
4067
|
baseSymbol = potentialWildLine[0]?.symbol;
|
|
4068
|
+
const wildSymbols = [];
|
|
4069
|
+
const wildLineLength = potentialWildLine.length;
|
|
4070
|
+
for (let i = 0; i < wildLineLength; i++) {
|
|
4071
|
+
const s = potentialWildLine[i];
|
|
4072
|
+
wildSymbols.push({
|
|
4073
|
+
symbol: s.symbol,
|
|
4074
|
+
isWild: this.isWild(s.symbol),
|
|
4075
|
+
reelIndex: s.reel,
|
|
4076
|
+
posIndex: s.row
|
|
4077
|
+
});
|
|
4078
|
+
}
|
|
4065
4079
|
finalLine = {
|
|
4066
|
-
kind:
|
|
4080
|
+
kind: wildLineLength,
|
|
4067
4081
|
baseSymbol,
|
|
4068
|
-
symbols:
|
|
4082
|
+
symbols: wildSymbols,
|
|
4083
|
+
lineNumber: lineNum,
|
|
4084
|
+
payout: wildLinePayout
|
|
4085
|
+
};
|
|
4086
|
+
} else {
|
|
4087
|
+
const symbols = [];
|
|
4088
|
+
const lineLength = potentialWinLine.length;
|
|
4089
|
+
for (let i = 0; i < lineLength; i++) {
|
|
4090
|
+
const s = potentialWinLine[i];
|
|
4091
|
+
symbols.push({
|
|
4069
4092
|
symbol: s.symbol,
|
|
4070
4093
|
isWild: this.isWild(s.symbol),
|
|
4071
4094
|
reelIndex: s.reel,
|
|
4072
4095
|
posIndex: s.row
|
|
4073
|
-
})
|
|
4096
|
+
});
|
|
4097
|
+
}
|
|
4098
|
+
finalLine = {
|
|
4099
|
+
kind: lineLength,
|
|
4100
|
+
baseSymbol,
|
|
4101
|
+
symbols,
|
|
4074
4102
|
lineNumber: lineNum,
|
|
4075
|
-
payout:
|
|
4103
|
+
payout: linePayout
|
|
4076
4104
|
};
|
|
4077
4105
|
}
|
|
4078
4106
|
lineWins.push(finalLine);
|
|
4079
|
-
}
|
|
4080
|
-
for (const win of lineWins) {
|
|
4081
4107
|
this.ctx.services.data.recordSymbolOccurrence({
|
|
4082
|
-
kind:
|
|
4083
|
-
symbolId:
|
|
4108
|
+
kind: finalLine.kind,
|
|
4109
|
+
symbolId: finalLine.baseSymbol.id,
|
|
4084
4110
|
spinType: this.ctx.state.currentSpinType
|
|
4085
4111
|
});
|
|
4086
4112
|
}
|
|
4087
|
-
|
|
4113
|
+
let totalPayout = 0;
|
|
4114
|
+
for (let i = 0; i < lineWins.length; i++) {
|
|
4115
|
+
totalPayout += lineWins[i].payout;
|
|
4116
|
+
}
|
|
4117
|
+
this.payout = totalPayout;
|
|
4088
4118
|
this.winCombinations = lineWins;
|
|
4089
4119
|
return this;
|
|
4090
4120
|
}
|
|
4091
4121
|
getLinePayout(line) {
|
|
4092
|
-
|
|
4093
|
-
|
|
4122
|
+
const lineLength = line.length;
|
|
4123
|
+
if (lineLength === 0) return 0;
|
|
4124
|
+
let baseSymbol;
|
|
4125
|
+
for (let i = 0; i < lineLength; i++) {
|
|
4126
|
+
const s = line[i];
|
|
4127
|
+
if (!this.isWild(s.symbol)) {
|
|
4128
|
+
baseSymbol = s.symbol;
|
|
4129
|
+
break;
|
|
4130
|
+
}
|
|
4131
|
+
}
|
|
4094
4132
|
if (!baseSymbol) baseSymbol = line[0].symbol;
|
|
4095
|
-
|
|
4096
|
-
const payout = this.getSymbolPayout(baseSymbol, kind);
|
|
4097
|
-
return payout;
|
|
4133
|
+
return this.getSymbolPayout(baseSymbol, lineLength);
|
|
4098
4134
|
}
|
|
4099
4135
|
};
|
|
4100
4136
|
|
|
4101
4137
|
// src/win-types/ClusterWinType.ts
|
|
4102
4138
|
var ClusterWinType = class extends WinType {
|
|
4103
|
-
_checked =
|
|
4104
|
-
_checkedWilds =
|
|
4139
|
+
_checked = /* @__PURE__ */ new Set();
|
|
4140
|
+
_checkedWilds = /* @__PURE__ */ new Set();
|
|
4105
4141
|
_currentBoard = [];
|
|
4106
4142
|
constructor(opts) {
|
|
4107
4143
|
super(opts);
|
|
@@ -4114,121 +4150,169 @@ var ClusterWinType = class extends WinType {
|
|
|
4114
4150
|
*/
|
|
4115
4151
|
evaluateWins(board) {
|
|
4116
4152
|
this.validateConfig();
|
|
4117
|
-
this._checked
|
|
4153
|
+
this._checked.clear();
|
|
4118
4154
|
this._currentBoard = board;
|
|
4119
4155
|
const clusterWins = [];
|
|
4120
4156
|
const potentialClusters = [];
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4157
|
+
const boardLength = board.length;
|
|
4158
|
+
for (let ridx = 0; ridx < boardLength; ridx++) {
|
|
4159
|
+
const reel = board[ridx];
|
|
4160
|
+
const reelLength = reel.length;
|
|
4161
|
+
for (let sidx = 0; sidx < reelLength; sidx++) {
|
|
4162
|
+
const symbol = reel[sidx];
|
|
4163
|
+
this._checkedWilds.clear();
|
|
4124
4164
|
if (this.isWild(symbol)) continue;
|
|
4125
|
-
|
|
4165
|
+
const posKey = ridx * 1e4 + sidx;
|
|
4166
|
+
if (this._checked.has(posKey)) {
|
|
4126
4167
|
continue;
|
|
4127
4168
|
}
|
|
4128
4169
|
const thisSymbol = { reel: ridx, row: sidx, symbol };
|
|
4129
|
-
this._checked.
|
|
4170
|
+
this._checked.add(posKey);
|
|
4130
4171
|
const neighbors = this.getNeighbors(ridx, sidx);
|
|
4131
4172
|
const matchingSymbols = this.evaluateCluster(symbol, neighbors);
|
|
4132
|
-
|
|
4133
|
-
|
|
4173
|
+
const matchingSize = matchingSymbols.size;
|
|
4174
|
+
if (matchingSize >= 1) {
|
|
4175
|
+
const cluster = [thisSymbol];
|
|
4176
|
+
for (const sym of matchingSymbols.values()) {
|
|
4177
|
+
cluster.push(sym);
|
|
4178
|
+
}
|
|
4179
|
+
potentialClusters.push(cluster);
|
|
4134
4180
|
}
|
|
4135
4181
|
}
|
|
4136
4182
|
}
|
|
4137
|
-
for (
|
|
4138
|
-
|
|
4139
|
-
|
|
4183
|
+
for (let ridx = 0; ridx < boardLength; ridx++) {
|
|
4184
|
+
const reel = board[ridx];
|
|
4185
|
+
const reelLength = reel.length;
|
|
4186
|
+
for (let sidx = 0; sidx < reelLength; sidx++) {
|
|
4187
|
+
const symbol = reel[sidx];
|
|
4188
|
+
this._checkedWilds.clear();
|
|
4140
4189
|
if (!this.isWild(symbol)) continue;
|
|
4141
|
-
|
|
4190
|
+
const posKey = ridx * 1e4 + sidx;
|
|
4191
|
+
if (this._checked.has(posKey)) {
|
|
4142
4192
|
continue;
|
|
4143
4193
|
}
|
|
4144
4194
|
const thisSymbol = { reel: ridx, row: sidx, symbol };
|
|
4145
|
-
this._checked.
|
|
4195
|
+
this._checked.add(posKey);
|
|
4146
4196
|
const neighbors = this.getNeighbors(ridx, sidx);
|
|
4147
4197
|
const matchingSymbols = this.evaluateCluster(symbol, neighbors);
|
|
4148
|
-
|
|
4149
|
-
|
|
4198
|
+
const matchingSize = matchingSymbols.size;
|
|
4199
|
+
if (matchingSize >= 1) {
|
|
4200
|
+
const cluster = [thisSymbol];
|
|
4201
|
+
for (const sym of matchingSymbols.values()) {
|
|
4202
|
+
cluster.push(sym);
|
|
4203
|
+
}
|
|
4204
|
+
potentialClusters.push(cluster);
|
|
4150
4205
|
}
|
|
4151
4206
|
}
|
|
4152
4207
|
}
|
|
4153
|
-
|
|
4208
|
+
const numClusters = potentialClusters.length;
|
|
4209
|
+
for (let i = 0; i < numClusters; i++) {
|
|
4210
|
+
const cluster = potentialClusters[i];
|
|
4154
4211
|
const kind = cluster.length;
|
|
4155
|
-
let baseSymbol
|
|
4212
|
+
let baseSymbol;
|
|
4213
|
+
for (let j = 0; j < kind; j++) {
|
|
4214
|
+
const sym = cluster[j].symbol;
|
|
4215
|
+
if (!this.isWild(sym)) {
|
|
4216
|
+
baseSymbol = sym;
|
|
4217
|
+
break;
|
|
4218
|
+
}
|
|
4219
|
+
}
|
|
4156
4220
|
if (!baseSymbol) baseSymbol = cluster[0].symbol;
|
|
4157
4221
|
const payout = this.getSymbolPayout(baseSymbol, kind);
|
|
4158
4222
|
if (payout === 0) continue;
|
|
4159
|
-
|
|
4160
|
-
|
|
4223
|
+
const pays = baseSymbol.pays;
|
|
4224
|
+
if (!pays) continue;
|
|
4225
|
+
let hasPays = false;
|
|
4226
|
+
for (const _ in pays) {
|
|
4227
|
+
hasPays = true;
|
|
4228
|
+
break;
|
|
4161
4229
|
}
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
symbols
|
|
4230
|
+
if (!hasPays) continue;
|
|
4231
|
+
const symbols = [];
|
|
4232
|
+
for (let j = 0; j < kind; j++) {
|
|
4233
|
+
const s = cluster[j];
|
|
4234
|
+
symbols.push({
|
|
4167
4235
|
symbol: s.symbol,
|
|
4168
4236
|
isWild: this.isWild(s.symbol),
|
|
4169
4237
|
reelIndex: s.reel,
|
|
4170
4238
|
posIndex: s.row
|
|
4171
|
-
})
|
|
4239
|
+
});
|
|
4240
|
+
}
|
|
4241
|
+
clusterWins.push({
|
|
4242
|
+
payout,
|
|
4243
|
+
kind,
|
|
4244
|
+
baseSymbol,
|
|
4245
|
+
symbols
|
|
4172
4246
|
});
|
|
4173
|
-
}
|
|
4174
|
-
for (const win of clusterWins) {
|
|
4175
4247
|
this.ctx.services.data.recordSymbolOccurrence({
|
|
4176
|
-
kind
|
|
4177
|
-
symbolId:
|
|
4248
|
+
kind,
|
|
4249
|
+
symbolId: baseSymbol.id,
|
|
4178
4250
|
spinType: this.ctx.state.currentSpinType
|
|
4179
4251
|
});
|
|
4180
4252
|
}
|
|
4181
|
-
|
|
4253
|
+
let totalPayout = 0;
|
|
4254
|
+
for (let i = 0; i < clusterWins.length; i++) {
|
|
4255
|
+
totalPayout += clusterWins[i].payout;
|
|
4256
|
+
}
|
|
4257
|
+
this.payout = totalPayout;
|
|
4182
4258
|
this.winCombinations = clusterWins;
|
|
4183
4259
|
return this;
|
|
4184
4260
|
}
|
|
4185
4261
|
getNeighbors(ridx, sidx) {
|
|
4186
4262
|
const board = this._currentBoard;
|
|
4187
4263
|
const neighbors = [];
|
|
4188
|
-
|
|
4189
|
-
[ridx - 1
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
];
|
|
4194
|
-
potentialNeighbors.forEach(([nridx, nsidx]) => {
|
|
4195
|
-
if (board[nridx] && board[nridx][nsidx]) {
|
|
4196
|
-
neighbors.push({ reel: nridx, row: nsidx, symbol: board[nridx][nsidx] });
|
|
4264
|
+
if (ridx > 0) {
|
|
4265
|
+
const leftReel = board[ridx - 1];
|
|
4266
|
+
const leftSymbol = leftReel[sidx];
|
|
4267
|
+
if (leftSymbol !== void 0) {
|
|
4268
|
+
neighbors.push({ reel: ridx - 1, row: sidx, symbol: leftSymbol });
|
|
4197
4269
|
}
|
|
4198
|
-
}
|
|
4270
|
+
}
|
|
4271
|
+
const rightReel = board[ridx + 1];
|
|
4272
|
+
if (rightReel !== void 0) {
|
|
4273
|
+
const rightSymbol = rightReel[sidx];
|
|
4274
|
+
if (rightSymbol !== void 0) {
|
|
4275
|
+
neighbors.push({ reel: ridx + 1, row: sidx, symbol: rightSymbol });
|
|
4276
|
+
}
|
|
4277
|
+
}
|
|
4278
|
+
const currentReel = board[ridx];
|
|
4279
|
+
const topSymbol = currentReel[sidx - 1];
|
|
4280
|
+
if (topSymbol !== void 0) {
|
|
4281
|
+
neighbors.push({ reel: ridx, row: sidx - 1, symbol: topSymbol });
|
|
4282
|
+
}
|
|
4283
|
+
const bottomSymbol = currentReel[sidx + 1];
|
|
4284
|
+
if (bottomSymbol !== void 0) {
|
|
4285
|
+
neighbors.push({ reel: ridx, row: sidx + 1, symbol: bottomSymbol });
|
|
4286
|
+
}
|
|
4199
4287
|
return neighbors;
|
|
4200
4288
|
}
|
|
4201
4289
|
evaluateCluster(rootSymbol, neighbors) {
|
|
4202
4290
|
const matchingSymbols = /* @__PURE__ */ new Map();
|
|
4203
|
-
neighbors.
|
|
4291
|
+
const numNeighbors = neighbors.length;
|
|
4292
|
+
for (let i = 0; i < numNeighbors; i++) {
|
|
4293
|
+
const neighbor = neighbors[i];
|
|
4204
4294
|
const { reel, row, symbol } = neighbor;
|
|
4205
|
-
|
|
4206
|
-
if (this.
|
|
4295
|
+
const posKey = reel * 1e4 + row;
|
|
4296
|
+
if (this._checked.has(posKey)) continue;
|
|
4297
|
+
if (this._checkedWilds.has(posKey)) continue;
|
|
4207
4298
|
if (this.isWild(symbol) || symbol.compare(rootSymbol)) {
|
|
4208
|
-
const key =
|
|
4299
|
+
const key = String(posKey);
|
|
4209
4300
|
matchingSymbols.set(key, { reel, row, symbol });
|
|
4210
4301
|
if (symbol.compare(rootSymbol)) {
|
|
4211
|
-
this._checked.
|
|
4302
|
+
this._checked.add(posKey);
|
|
4212
4303
|
}
|
|
4213
4304
|
if (this.isWild(symbol)) {
|
|
4214
|
-
this._checkedWilds.
|
|
4305
|
+
this._checkedWilds.add(posKey);
|
|
4215
4306
|
}
|
|
4216
|
-
const
|
|
4217
|
-
const nestedMatches = this.evaluateCluster(rootSymbol,
|
|
4218
|
-
nestedMatches.
|
|
4219
|
-
const nkey = `${nsym.reel}-${nsym.row}`;
|
|
4307
|
+
const nestedNeighbors = this.getNeighbors(reel, row);
|
|
4308
|
+
const nestedMatches = this.evaluateCluster(rootSymbol, nestedNeighbors);
|
|
4309
|
+
for (const [nkey, nsym] of nestedMatches.entries()) {
|
|
4220
4310
|
matchingSymbols.set(nkey, nsym);
|
|
4221
|
-
}
|
|
4311
|
+
}
|
|
4222
4312
|
}
|
|
4223
|
-
}
|
|
4313
|
+
}
|
|
4224
4314
|
return matchingSymbols;
|
|
4225
4315
|
}
|
|
4226
|
-
isChecked(ridx, sidx) {
|
|
4227
|
-
return !!this._checked.find((c) => c.reel === ridx && c.row === sidx);
|
|
4228
|
-
}
|
|
4229
|
-
isCheckedWild(ridx, sidx) {
|
|
4230
|
-
return !!this._checkedWilds.find((c) => c.reel === ridx && c.row === sidx);
|
|
4231
|
-
}
|
|
4232
4316
|
};
|
|
4233
4317
|
|
|
4234
4318
|
// src/win-types/ManywaysWinType.ts
|
|
@@ -4247,7 +4331,7 @@ var ManywaysWinType = class extends WinType {
|
|
|
4247
4331
|
const { jumpGaps = false } = opts;
|
|
4248
4332
|
const waysWins = [];
|
|
4249
4333
|
const reels = board;
|
|
4250
|
-
const
|
|
4334
|
+
const numReels = reels.length;
|
|
4251
4335
|
const candidateSymbols = /* @__PURE__ */ new Map();
|
|
4252
4336
|
if (jumpGaps) {
|
|
4253
4337
|
for (const reel of reels) {
|
|
@@ -4258,7 +4342,7 @@ var ManywaysWinType = class extends WinType {
|
|
|
4258
4342
|
} else {
|
|
4259
4343
|
let searchReelIdx = 0;
|
|
4260
4344
|
let searchActive = true;
|
|
4261
|
-
while (searchActive && searchReelIdx <
|
|
4345
|
+
while (searchActive && searchReelIdx < numReels) {
|
|
4262
4346
|
const reel = reels[searchReelIdx];
|
|
4263
4347
|
let hasWild = false;
|
|
4264
4348
|
for (const symbol of reel) {
|
|
@@ -4274,71 +4358,78 @@ var ManywaysWinType = class extends WinType {
|
|
|
4274
4358
|
}
|
|
4275
4359
|
}
|
|
4276
4360
|
for (const baseSymbol of candidateSymbols.values()) {
|
|
4277
|
-
|
|
4278
|
-
let
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4361
|
+
const symbolList = [];
|
|
4362
|
+
let wayLength = 0;
|
|
4363
|
+
let firstNonWildSymbol;
|
|
4364
|
+
let totalWays = 1;
|
|
4365
|
+
for (let ridx = 0; ridx < numReels; ridx++) {
|
|
4366
|
+
const reel = reels[ridx];
|
|
4367
|
+
let reelMatches;
|
|
4368
|
+
for (let sidx = 0; sidx < reel.length; sidx++) {
|
|
4369
|
+
const symbol = reel[sidx];
|
|
4282
4370
|
const isMatch = baseSymbol.compare(symbol) || this.isWild(symbol);
|
|
4283
4371
|
if (isMatch) {
|
|
4284
|
-
if (!
|
|
4285
|
-
|
|
4372
|
+
if (!reelMatches) {
|
|
4373
|
+
reelMatches = [];
|
|
4374
|
+
}
|
|
4375
|
+
reelMatches.push({ reel: ridx, row: sidx, symbol });
|
|
4376
|
+
if (!firstNonWildSymbol && !this.isWild(symbol)) {
|
|
4377
|
+
firstNonWildSymbol = symbol;
|
|
4286
4378
|
}
|
|
4287
|
-
symbolList[ridx].push({ reel: ridx, row: sidx, symbol });
|
|
4288
4379
|
}
|
|
4289
4380
|
}
|
|
4290
|
-
if (
|
|
4291
|
-
|
|
4381
|
+
if (reelMatches) {
|
|
4382
|
+
symbolList[wayLength++] = reelMatches;
|
|
4383
|
+
totalWays *= reelMatches.length;
|
|
4384
|
+
} else if (!jumpGaps) {
|
|
4292
4385
|
break;
|
|
4293
4386
|
}
|
|
4294
4387
|
}
|
|
4295
|
-
const
|
|
4296
|
-
|
|
4297
|
-
)
|
|
4298
|
-
|
|
4388
|
+
const pays = baseSymbol.pays || {};
|
|
4389
|
+
let minSymLine = Infinity;
|
|
4390
|
+
for (const key in pays) {
|
|
4391
|
+
const num = parseInt(key, 10);
|
|
4392
|
+
if (num < minSymLine) minSymLine = num;
|
|
4393
|
+
}
|
|
4299
4394
|
if (wayLength >= minSymLine) {
|
|
4300
|
-
|
|
4395
|
+
const winBaseSymbol = firstNonWildSymbol || symbolList[0][0].symbol;
|
|
4396
|
+
const singleWayPayout = this.getSymbolPayout(winBaseSymbol, wayLength);
|
|
4397
|
+
const totalPayout2 = singleWayPayout * totalWays;
|
|
4398
|
+
const symbols = [];
|
|
4399
|
+
for (let i = 0; i < wayLength; i++) {
|
|
4400
|
+
const reelSyms = symbolList[i];
|
|
4401
|
+
for (let j = 0; j < reelSyms.length; j++) {
|
|
4402
|
+
const s = reelSyms[j];
|
|
4403
|
+
symbols.push({
|
|
4404
|
+
symbol: s.symbol,
|
|
4405
|
+
isWild: this.isWild(s.symbol),
|
|
4406
|
+
reelIndex: s.reel,
|
|
4407
|
+
posIndex: s.row
|
|
4408
|
+
});
|
|
4409
|
+
}
|
|
4410
|
+
}
|
|
4411
|
+
waysWins.push({
|
|
4412
|
+
kind: wayLength,
|
|
4413
|
+
baseSymbol: winBaseSymbol,
|
|
4414
|
+
symbols,
|
|
4415
|
+
ways: totalWays,
|
|
4416
|
+
payout: totalPayout2
|
|
4417
|
+
});
|
|
4418
|
+
this.ctx.services.data.recordSymbolOccurrence({
|
|
4419
|
+
kind: wayLength,
|
|
4420
|
+
symbolId: winBaseSymbol.id,
|
|
4421
|
+
spinType: this.ctx.state.currentSpinType
|
|
4422
|
+
});
|
|
4301
4423
|
}
|
|
4302
4424
|
}
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
if (!baseSymbol) baseSymbol = symbolList[Object.keys(symbolList)[0]][0].symbol;
|
|
4307
|
-
const singleWayPayout = this.getSymbolPayout(baseSymbol, wayLength);
|
|
4308
|
-
const totalWays = Object.values(symbolList).reduce(
|
|
4309
|
-
(ways, syms) => ways * syms.length,
|
|
4310
|
-
1
|
|
4311
|
-
);
|
|
4312
|
-
const totalPayout = singleWayPayout * totalWays;
|
|
4313
|
-
waysWins.push({
|
|
4314
|
-
kind: wayLength,
|
|
4315
|
-
baseSymbol,
|
|
4316
|
-
symbols: Object.values(symbolList).flatMap(
|
|
4317
|
-
(reel) => reel.map((s) => ({
|
|
4318
|
-
symbol: s.symbol,
|
|
4319
|
-
isWild: this.isWild(s.symbol),
|
|
4320
|
-
reelIndex: s.reel,
|
|
4321
|
-
posIndex: s.row
|
|
4322
|
-
}))
|
|
4323
|
-
),
|
|
4324
|
-
ways: totalWays,
|
|
4325
|
-
payout: totalPayout
|
|
4326
|
-
});
|
|
4327
|
-
}
|
|
4328
|
-
for (const win of waysWins) {
|
|
4329
|
-
this.ctx.services.data.recordSymbolOccurrence({
|
|
4330
|
-
kind: win.kind,
|
|
4331
|
-
symbolId: win.baseSymbol.id,
|
|
4332
|
-
spinType: this.ctx.state.currentSpinType
|
|
4333
|
-
});
|
|
4425
|
+
let totalPayout = 0;
|
|
4426
|
+
for (let i = 0; i < waysWins.length; i++) {
|
|
4427
|
+
totalPayout += waysWins[i].payout;
|
|
4334
4428
|
}
|
|
4335
|
-
this.payout =
|
|
4429
|
+
this.payout = totalPayout;
|
|
4336
4430
|
this.winCombinations = waysWins;
|
|
4337
4431
|
return this;
|
|
4338
4432
|
}
|
|
4339
|
-
getWayLength(symbolList) {
|
|
4340
|
-
return Object.keys(symbolList).length;
|
|
4341
|
-
}
|
|
4342
4433
|
};
|
|
4343
4434
|
|
|
4344
4435
|
// src/reel-set/GeneratedReelSet.ts
|