@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 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(Object.entries(opts.properties || {}));
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 [key, value] of Object.entries(symbolOrProperties)) {
440
- if (!this.properties.has(key) || this.properties.get(key) !== value) {
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 [key, value] of Object.entries(properties)) {
521
- symbol.properties.set(key, value);
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 [key, value] of Object.entries(symbolOrProperties)) {
538
- if (!symbol.properties.has(key) || symbol.properties.get(key) !== value) {
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 [key, value] of Object.entries(symbolOrProperties)) {
561
- if (!symbol.properties.has(key) || symbol.properties.get(key) !== value) {
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: Object.fromEntries(
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
- for (const [lineNumStr, line] of Object.entries(this.lines)) {
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 (const [ridx, reel] of reels.entries()) {
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 minSymLine = Math.min(
4046
- ...Object.keys(baseSymbol.pays || {}).map((k) => parseInt(k, 10))
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: potentialWildLine.length,
4080
+ kind: wildLineLength,
4067
4081
  baseSymbol,
4068
- symbols: potentialWildLine.map((s) => ({
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: wildLinePayout
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: win.kind,
4083
- symbolId: win.baseSymbol.id,
4108
+ kind: finalLine.kind,
4109
+ symbolId: finalLine.baseSymbol.id,
4084
4110
  spinType: this.ctx.state.currentSpinType
4085
4111
  });
4086
4112
  }
4087
- this.payout = lineWins.reduce((sum, l) => sum + l.payout, 0);
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
- if (line.length === 0) return 0;
4093
- let baseSymbol = line.find((s) => !this.isWild(s.symbol))?.symbol;
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
- const kind = line.length;
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
- for (const [ridx, reel] of board.entries()) {
4122
- for (const [sidx, symbol] of reel.entries()) {
4123
- this._checkedWilds = [];
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
- if (this.isChecked(ridx, sidx)) {
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.push(thisSymbol);
4170
+ this._checked.add(posKey);
4130
4171
  const neighbors = this.getNeighbors(ridx, sidx);
4131
4172
  const matchingSymbols = this.evaluateCluster(symbol, neighbors);
4132
- if (matchingSymbols.size >= 1) {
4133
- potentialClusters.push([thisSymbol, ...matchingSymbols.values()]);
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 (const [ridx, reel] of board.entries()) {
4138
- for (const [sidx, symbol] of reel.entries()) {
4139
- this._checkedWilds = [];
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
- if (this.isChecked(ridx, sidx)) {
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.push(thisSymbol);
4195
+ this._checked.add(posKey);
4146
4196
  const neighbors = this.getNeighbors(ridx, sidx);
4147
4197
  const matchingSymbols = this.evaluateCluster(symbol, neighbors);
4148
- if (matchingSymbols.size >= 1) {
4149
- potentialClusters.push([thisSymbol, ...matchingSymbols.values()]);
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
- for (const cluster of potentialClusters) {
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 = cluster.find((s) => !this.isWild(s.symbol))?.symbol;
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
- if (!baseSymbol.pays || Object.keys(baseSymbol.pays).length === 0) {
4160
- continue;
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
- clusterWins.push({
4163
- payout,
4164
- kind,
4165
- baseSymbol,
4166
- symbols: cluster.map((s) => ({
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: win.kind,
4177
- symbolId: win.baseSymbol.id,
4248
+ kind,
4249
+ symbolId: baseSymbol.id,
4178
4250
  spinType: this.ctx.state.currentSpinType
4179
4251
  });
4180
4252
  }
4181
- this.payout = clusterWins.reduce((sum, c) => sum + c.payout, 0);
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
- const potentialNeighbors = [
4189
- [ridx - 1, sidx],
4190
- [ridx + 1, sidx],
4191
- [ridx, sidx - 1],
4192
- [ridx, sidx + 1]
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.forEach((neighbor) => {
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
- if (this.isChecked(reel, row)) return;
4206
- if (this.isCheckedWild(reel, row)) return;
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 = `${reel}-${row}`;
4299
+ const key = String(posKey);
4209
4300
  matchingSymbols.set(key, { reel, row, symbol });
4210
4301
  if (symbol.compare(rootSymbol)) {
4211
- this._checked.push(neighbor);
4302
+ this._checked.add(posKey);
4212
4303
  }
4213
4304
  if (this.isWild(symbol)) {
4214
- this._checkedWilds.push(neighbor);
4305
+ this._checkedWilds.add(posKey);
4215
4306
  }
4216
- const neighbors2 = this.getNeighbors(reel, row);
4217
- const nestedMatches = this.evaluateCluster(rootSymbol, neighbors2);
4218
- nestedMatches.forEach((nsym) => {
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 possibleWaysWins = /* @__PURE__ */ new Map();
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 < reels.length) {
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
- let symbolList = {};
4278
- let isInterrupted = false;
4279
- for (const [ridx, reel] of reels.entries()) {
4280
- if (isInterrupted) break;
4281
- for (const [sidx, symbol] of reel.entries()) {
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 (!symbolList[ridx]) {
4285
- symbolList[ridx] = [];
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 (!symbolList[ridx] && !jumpGaps) {
4291
- isInterrupted = true;
4381
+ if (reelMatches) {
4382
+ symbolList[wayLength++] = reelMatches;
4383
+ totalWays *= reelMatches.length;
4384
+ } else if (!jumpGaps) {
4292
4385
  break;
4293
4386
  }
4294
4387
  }
4295
- const minSymLine = Math.min(
4296
- ...Object.keys(baseSymbol.pays || {}).map((k) => parseInt(k, 10))
4297
- );
4298
- const wayLength = this.getWayLength(symbolList);
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
- possibleWaysWins.set(baseSymbol.id, symbolList);
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
- for (const [, symbolList] of possibleWaysWins.entries()) {
4304
- const wayLength = this.getWayLength(symbolList);
4305
- let baseSymbol = Object.values(symbolList).flatMap((l) => l.map((s) => s)).find((s) => !this.isWild(s.symbol))?.symbol;
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 = waysWins.reduce((sum, l) => sum + l.payout, 0);
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