All extensions

@open-rgs/paytable

One shared notion of payout, wild and scatter.

One table, four evaluators

Lines, ways, anywhere and cluster all read this, so a symbol means the same thing in each. When each carried its own idea of a wild, a game using two of them could disagree with itself and the two RTPs would quietly differ.

any of
A wild substitutes for anything except a scatter.
import { paytable, substitutes } from "@open-rgs/paytable";

const PAY   = paytable({ HIGH: { 3: 10, 4: 50, 5: 200 } });
const roles = { wilds: ["WILD"], scatters: ["SC"] };

substitutes("WILD", "HIGH", roles);
substitutes("WILD", "SC",   roles);

Bands for cluster games

Cluster games pay by size range while a paytable stores exact counts, so there is never interpolation to reason about. bands() bridges the two.

Size ranges expanded into the exact counts a paytable stores.
import { bands } from "@open-rgs/paytable";

const CLUSTER = paytable(bands({
  HIGH: [[5, 2], [9, 6], [12, 22], [15, 90]],
}, 49));

Watch the top band

The top band is open-ended: it runs from its start all the way to maxCount. On a five-reel grid seven scatters is impossible, so the intuition is that it is a lottery ticket. On 49 cells it is not.

The top band runs all the way to maxCount.
PAY.maxCount("HIGH");
PAY.best("HIGH");