Paylines (lines pays)
TL;DR
Игрок «покупает» N паттернов линий через reels (классически 5 reels, 3 rows). Выплата за N подряд одинаковых символов слева направо на любой из активных линий. Wild подставляется. Простейшая и старейшая механика выплат, до сих пор основа большинства классических слотов.
Как работает
Конфиг
paytable = {(kind, symbol): payout}— выплата заkindподряд символа.paylines = {line_id: [row_per_reel]}— описание каждой линии: индекс row на каждом reel-е.
Пример из Stake 0_0_lines:
paylines = {
1: [0,0,0,0,0], # верхний горизонт
2: [1,1,1,1,1], # центр
3: [2,2,2,2,2], # нижний
4: [0,1,2,1,0], # V
5: [2,1,0,1,2], # ^
...
20: [1,0,0,0,1],
}
paytable = {
(5, "H1"): 50, (4, "H1"): 20, (3, "H1"): 10,
(5, "L4"): 2, (4, "L4"): 0.5, (3, "L4"): 0.2,
(5, "W"): 50, (4, "W"): 20, (3, "W"): 10,
...
}Алгоритм evaluate
для каждой линии line_id:
symbols = [board[reel][line[reel]] for reel in 0..num_reels]
base_sym = first non-wild from symbols
если все wild — base_sym = "W"
kind = длина prefix-а из {base_sym, wild}
win = paytable[(kind, base_sym)] если ключ есть, иначе 0
если есть wild-only prefix и (kind, "W") в paytable:
sравнить с (kind, base_sym) и взять больший
применить multiplier-strategy
Возвращает winData = {totalWin, wins: [{symbol, kind, win, positions, meta: {lineIndex, multiplier, ...}}]}. Каждая выигранная линия — отдельная запись в wins. См. events-as-stream.
Multiplier strategies
Из wins/multiplier_strategy.py:
global— общий множитель раунда.symbol— суммируются множители всех wild-символов на линии.combined— global × sum(symbol).
В lines-играх multiplier на wild аддитивный: на линии [W×3, W×2, L4, L4, L4] выигрыш L4 умножается на (3+2) = 5x. (Сравните с ways, где multiplier мультипликативный.)
Мат-эффект
- RTP контролируется через
paytable× probabilities из reelstrip-комбинаций. Стандартная PAR-методология (см. PAR sheet). - Hit frequency = доля раундов с хотя бы одной выигрышной линией. На 5×3 поле с 20 линиями типично 25–35% (с учётом LDW).
- Volatility — функция от paytable hi/lo пирамиды и редкости wild.
- Combinatorics: каждое из
len(reelstrip[reel])^num_reelsboard-комбинаций оценивается по 20 линиям независимо.
Wild-override — типичная ловушка
Если (3,"W") есть в paytable и платит больше, чем (5,"L4"), то на линии [W,W,W,L4,L4] алгоритм возьмёт 3-kind wild, а не 5-kind L4. Это часто не то, что хочет дизайн.
Warning
Конвенция Stake (и большинства студий): wild платит только на полную линию (5-kind). Соответственно
(3,"W")и(4,"W")либо отсутствуют в paytable, либо имеют payout=0. Это резко упрощает балансировку.
Если делаем wild с low-kind платой — нужно явно прописать в spec, как разрешать конфликт, и тестить property-based тестом «на любой board нет линии, где payout < max возможного payout этой линии».
Варианты и подвиды
- Fixed paylines vs adjustable — игрок выбирает, сколько линий покупать. Сейчас почти не используется (всегда fixed all-lines).
- Left-to-right vs both-ways (407 ways на 5×3) — обычно left-only.
- Stacked symbols — на reelstrip-е символы идут блоками, что создаёт волатильные кадры.
- Wild-расширения: см. wild-symbol (expanding/sticky/walking/stacked/multiplier wilds).
Реализационные заметки
Бэк (TS)
type Payline = number[]; // index по reel
type Payouts = Map<string, number>; // ключ "kind:sym" → payout
function evaluatePaylines(
board: SymbolName[][],
paylines: Record<number, Payline>,
paytable: Payouts,
wildSyms: SymbolName[],
multStrategy: MultiplierStrategy,
): WinData {
const wins: WinDetail[] = [];
for (const [lineId, line] of Object.entries(paylines)) {
const symbolsOnLine = line.map((row, reel) => board[reel][row]);
const winData = evaluateOneLine(symbolsOnLine, paytable, wildSyms);
if (winData.win > 0) {
const total = applyMult(winData, multStrategy, ctx.globalMult);
wins.push({...winData, lineId, win: total, positions: linePositions(line)});
}
}
return {totalWin: sum(wins, w => w.win), wins};
}Edge cases
- Wild-only prefix — все 5 символов wild →
(5, "W")payout. - Wild на reel 1 — нормально для lines (в отличие от ways).
- Несколько символов в paytable matching — берём max payout (с учётом wild override).
- Multiplier × max-win-cap — после применения multiplier проверяем
runningBetWin >= maxWin(см. wallet manager).
Фронт
Эмитится winInfo с meta.lineIndex, meta.multiplier, meta.winWithoutMult. Фронт рисует:
- highlight winning positions;
- line-trace анимацию;
- multiplier-badge на wild-символах.
Никакой математики — всё в payload.
Compliance / cert
- В paytable / help должны быть все возможные комбинации, включая wild-override и multiplier-effects (UKGC RTS 3, см. RTP disclosure).
- LDW (выплата меньше ставки на all-line bet) — раскрывать как «win less than bet» в UI; см. responsible product design.
- Лаборатория проверит, что paytable × reelstrip = заявленная RTP (полный цикл PAR sheet).
Примеры реализаций
- Большинство классических Pragmatic / NetEnt / Microgaming слотов на 5×3 с 10/15/20/25 fixed lines.
- Stake math-sdk sample game:
games/0_0_lines/.