Skip to main content
The Cluster class detects groups of adjacent matching symbols (clusters) and pays out when the cluster meets a minimum size threshold. Adjacency is defined as sharing the same reel or row — diagonal connections do not count.

How cluster detection works

Clusters are found using a breadth-first search (BFS) algorithm:
  1. Each non-wild, unvisited position on the board is used as a seed.
  2. All orthogonally adjacent positions matching the seed symbol (or wild) are recursively added to the cluster.
  3. The final cluster size is compared against config.paytable to determine the payout.
Wild symbols contribute to any cluster they are adjacent to, and can simultaneously belong to clusters of different symbols.

Configuration

Because cluster sizes can range from the minimum up to the full board size, it is common to use range-based payouts instead of individual entries. The convert_range_table() method on Config generates all config.paytable entries from a compact pay_group definition:
dict
required
Maps (cluster_size, symbol) tuples to payout multipliers. Generated from pay_group via config.convert_range_table(pay_group).
Range bounds are inclusive.

Cluster.get_cluster_data()

Top-level entry point. Calls get_clusters() then evaluate_clusters() and returns win data.
Config
required
Game configuration with config.paytable populated.
list[list[Symbol]]
required
Active game board indexed as board[reel][row].
int
required
Scalar multiplier applied to all cluster wins.
str
default:"multiplier"
Symbol attribute key for reading per-symbol multiplier values.
str
default:"wild"
Symbol attribute key identifying wild symbols.

Return value

float
Sum of all cluster wins for this board state.
list
One entry per paying cluster.

Exploding symbols and tumble integration

During evaluate_clusters(), every symbol in a paying cluster has its explode attribute set to True. This signals the Tumble class to remove those symbols and cascade new ones down. The typical tumble loop looks like:

Lower-level methods

Cluster.get_clusters(board, wild_key)

Returns a dict mapping symbol names to lists of clusters, where each cluster is a list of (reel, row) tuples. All clusters of size ≥ 1 are returned; paytable filtering happens in evaluate_clusters().

Cluster.evaluate_clusters(config, board, clusters, global_multiplier, multiplier_key, return_data)

Determines payouts from the cluster dict, updates symbol explode flags, and populates return_data. Returns (board, return_data, total_win).

Cluster.record_cluster_wins(gamestate)

Writes force-file entries keyed by kind (cluster size), symbol, combined mult, and gametype.
Cluster pays games almost always use a cascading/tumble mechanic. Pair get_cluster_data() with tumble_board() from the Tumble class for a complete cascade loop.