Scatter pays (pay-anywhere)

TL;DR

Самый простой способ оценки выигрышей: сколько штук одного символа на всём board? Если ≥ MIN_KIND — платим из range-paytable. Никаких линий, никаких кластеров, никаких связности. Wild считается ко всем paying символам. Типичный минимум 8 штук на 6×5 поле.

Info

Не путать со scatter-trigger — символом, который запускает freegame. В терминологии «scatter-pays» это про payout-механику, а не про триггер. Один и тот же символ может быть и тем и другим (но обычно scatter-trigger — это отдельный спецсимвол S без payout, см. mechanics MOC).

Как работает

Конфиг

То же pay_group с диапазонами, что у cluster pays:

pay_group = {
  ((8,8),   "H1"): 5,
  ((9,10),  "H1"): 10,
  ((11,13), "H1"): 50,
  ((14,30), "H1"): 500,
  ...
}
paytable = convert_range_table(pay_group)

Алгоритм evaluate

для каждого base_sym из paying_symbols:
  count = sum(1 for cell in board.flat if cell == base_sym or cell in wildSyms)
  если count < MIN_KIND: continue
  if (count, base_sym) в paytable:
    win = paytable[(count, base_sym)] × multiplier
    wins.append({symbol, kind: count, win, positions: all_positions(base_sym, wildSyms)})

O(num_reels × num_rows × num_paying_symbols). Тривиально.

Wild

Wild контрибьютит ко всем paying-символам. Если на 6×5 поле 6 H1 и 3 W → kind для H1 = 9.

В отличие от cluster — нет «не стартует» правила; wild просто учитывается во всех счётчиках.

Мат-эффект

  • Hit frequency низкая для каждого отдельного символа, но высокая суммарно — обычно несколько символов «попадают» одновременно.
  • Volatility высокая — большой спред между min payout (8 штук) и max (full board).
  • Часто комбинируется с tumbling и global-multiplier для очень volatile профиля.
  • RTP заметно весит во freegame с global mult.

Варианты и подвиды

  • Базовый scatter-pays — без модификаторов.
  • Scatter + tumble (стандарт) — победившие символы исчезают, новые падают.
  • Scatter + global mult — multiplier инкрементируется на каждый tumble, применяется к концу цепочки.
  • Scatter + position-multiplier — multiplier-symbols на board добавляются к global mult в финале раунда.

Реализационные заметки

Бэк (TS)

function evaluateScatterPays(
  board: SymbolName[][],
  paytable: Map<string, number>,
  wildSyms: SymbolName[],
  payingSyms: SymbolName[],
  minKind: number,
): WinData {
  const wins: WinDetail[] = [];
  for (const sym of payingSyms) {
    const positions: Position[] = [];
    for (let r = 0; r < board.length; r++) {
      for (let c = 0; c < board[0].length; c++) {
        const s = board[r][c];
        if (s === sym || wildSyms.includes(s)) positions.push({reel: r, row: c});
      }
    }
    const kind = positions.length;
    if (kind < minKind) continue;
    const key = `${kind}:${sym}`;
    const basePay = paytable.get(key) ?? 0;
    if (basePay > 0) {
      wins.push({symbol: sym, kind, win: basePay, positions, meta: {}});
    }
  }
  return {totalWin: sum(wins, w => w.win), wins};
}

Edge cases

  • Wild-only board — wild считается ко всем paying симсам. Получаем win для каждого, что обычно нежелательно. Решение: запретить full-wild-board через reelstrip-конструкцию (на проде он не выпадает) или явно проверить и обнулить.
  • Несколько paying-символов одновременно платят — нормально, складываем totalWin.
  • Big-cluster свыше последнего range — берём максимальный диапазон через convert_range_table.

Фронт

winInfo.positions — все клетки символа на board. Фронт рисует pulse-highlight всех клеток. С tumble — после tumbleBoard event-а позиции исчезают.

meta.overlay для badge-позиции — обычно центр масс положений символа.

Compliance / cert

  • Help раскрывает: «Symbols pay anywhere on the reels. Pay calculations based on count of symbols on board, not position.»
  • Range-paytable: лучше рисовать таблицей (8): 5×, (9-10): 10×, ... — игроку нужно понимать пороги.
  • Wild contribution к count тоже раскрывается.

Примеры реализаций

  • NetEnt Bonanza (6 reels, scatter+tumble + Megaways).
  • NetEnt Money Train series.
  • Pragmatic Play Gates of Olympus (6×5 scatter+tumble + multipliers).
  • Stake math-sdk sample: games/0_0_scatter/.

Связанные