Result-Set Architecture: A Modular Slot Game Framework

How a result-set model makes slot development faster and far easier to extend

How a result-set architecture splits a slot game into reusable components: state machine, spin flow, feature triggering and settlement for fast delivery.

What Is the Result Set Architecture?

In slot game development, the result set is a pre-generated seed record pool architecture. Its core idea is to pre-compute the game's random outcomes and package them into replayable records, used to distribute results in specific scenarios while keeping the mathematical expected value exactly consistent with natural probability.

The result set does not replace real-time RNG. Rather, in scenarios that require precise control of the RTP distribution, it provides a mathematically verified collection of outcomes, ensuring that each group's long-term return rate converges strictly to the target value.

Why Pre-generate Instead of Computing in Real Time?

The real-time approach is: draw a random number on each Spin, determine the reel stop positions from the weight table, and then run a full line evaluation on the spot. There is nothing wrong with this flow in itself, but it has three limitations that are hard to avoid.

Put another way, pre-generation splits a slot's randomness into two layers: the randomness of the outcome itself is already determined by the natural probability model in the offline stage, and the online stage retains only the randomness of "which record to draw". The correctness of the mathematical model can therefore be fully verified and sealed in the offline stage, no longer subject to changes in online code.

The Layered Architecture of the Result Set

The result set uses a multi-level tree structure that filters down level by level from the top:

Record Pool Management Layer

The topmost level is a container indexed by identifier that manages multiple result set instances. Each result set represents a specific group of outcome records, corresponding to a target RTP band.

The point of layering is to separate "which group to choose" from "which record to choose". The top level decides the mathematical characteristics (how high an expected value, what shape of volatility), while the bottom level decides the concrete board. This split means RTP adjustment never has to touch any single-round data (swapping one index is enough), and it also lets the same batch of underlying records be shared by several different RTP versions.

Four-layer selection in the result set Each layer from the top picks the pool, the result set and the payout group in turn; only the bottom layer draws a single record uniformly. Pool management Indexed by identifier, holding several result sets Decides: which set of mathematical characteristics Result set One result set per target RTP band Decides: where this round expected value sits Weighted payout groups Split by payout band, usually into two groups Decides: RTP is tuned by shifting weight between groups Record Drawn uniformly inside the chosen group Decides: the board this round actually shows
Separating which group from which record means tuning RTP only swaps an index, with no per-round data regenerated.

Result Set: A Single Result Set

Each result set contains the following core attributes:

The purpose of the grouping design is to manage high-payout and low-payout records separately, fine-tuning overall RTP through weight allocation between the groups.

This design solves a very practical problem: if the whole pool of records were mixed together and drawn uniformly, the pool's RTP would be fixed, and changing it would mean regenerating the entire pool of data. But once records are split into two groups by payout, adjusting the weights between the groups allows the expected value to be continuously tuned within a certain range: raise the weight of the high-multiple group and overall RTP rises with it, without rerunning the underlying data at all. That amounts to buying an entire span of RTP coverage with a single one-dimensional parameter.

The number of groups is itself a trade-off. The more groups, the finer the adjustable granularity and the more precise the control over volatility, but every group must retain a sufficient sample size, or sampling within the group loses its representativeness. In practice two or three groups are usually enough to cover common needs.

Single-Round Result Record

The bottom level is a complete Spin result record, containing the reel stop positions, winning combinations, multiples and everything else needed for replay. Each record is stored compressed in a custom TLV (Type-Length-Value) binary encoding format.

TLV Encoding Format Design

To store large volumes of Spin result records efficiently, the result set adopts a compact TLV binary encoding format:

[numerator u32][denominator u32][segment count u8][types u8×N][lengths u32×N][data...]

The design focuses of this format are:

Byte layout of a TLV record The numerator and denominator of the payout sit at a fixed offset at the start of the record, so filtering never has to decode the whole thing. Numerator u32 - 4 bytes Denominator u32 - 4 bytes Segments u8 Type table u8 x N Length table u32 x N Data ... Payout in the first 8 bytes fixed offset Filtering reads only the leading payout, collapsing to one pointer operation; a fraction rather than a float keeps comparison and summation exact
Putting the payout at a fixed offset at the front is the most consequential decision in this format.

The Space-Versus-Speed Trade-off

Why not simply use a general-purpose serialization format? Mainly because of the order of magnitude of the result records. When one game needs millions of records and dozens of games are live at the same time, a difference of a few dozen bytes per record adds up to a considerable difference in total size, and directly affects whether the whole dataset can stay resident in memory.

Putting the payout in a leading field is the single most critical decision in this format. The filtering stage only needs to know the multiple; if the entire record had to be decoded before the multiple could be judged, you would be paying the cost of a full decode for one number. Placing it at a fixed offset at the head reduces filtering to a single pointer offset read. Using a numerator and denominator rather than a floating-point number is there to guarantee that payout comparison and summation carry no precision error whatsoever. RTP is a number that goes to audit, and it cannot tolerate accumulated floating-point error.

The field-width table embodies the idea of "allocating bytes on demand". A 5-reel game whose per-reel weight sequence is no longer than 255 needs only one byte for a stop position; a game with sequences of a thousand or more needs two bytes. If a single maximum width were used uniformly, most games would be paying for space they never use. Letting each game declare its own width table achieves near-optimal compression without altering the encoding framework.

Of course this design has a price: the format is custom, so it cannot be inspected directly with general-purpose tools. You must therefore additionally provide human-readable output for debugging, and establish a version field for the format itself, so that adding segment types later does not break backward compatibility with existing data.

The Picking Pipeline

When the system needs to draw a result from the result set, it goes through the following multi-stage picking pipeline:

Step 1: RTP Anchor Selection

Based on the target RTP value, locate the nearest RTP anchor. The system supports up to 3 anchors, and when the target RTP falls between two anchors, a probabilistic choice is made using linear interpolation:

P(choose AnchorA) = (AnchorB.RTP - targetRTP) / (AnchorB.RTP - AnchorA.RTP)

This ensures that a target RTP of arbitrary precision can be produced between two discrete RTP tiers.

What is worth explaining here is why a "probabilistic choice" is used instead of "blending results". If you tried to mix records from the two anchors proportionally and draw from the mixture, the resulting distribution shape would be a superposition of the two, and the volatility characteristics might land outside both. Deciding wholesale, on each round, which anchor group to use gives the same expected value as linear interpolation, but every round's result comes entirely from one verified distribution, so the mathematical properties are cleaner and easier to explain to outside parties.

Step 2: Weighted Selection of a Result Group

Under the selected anchor, one of several candidate result groups is chosen by weighted random draw. Each group carries a weight value that determines its probability of being chosen.

Step 3: Weighted Selection Among Subgroups

Within the selected result group, a further weighted selection is made between 2 subgroups. The split is usually made by payout range, for example a "low-multiple result group" and a "high-multiple result group".

Step 4: Uniform Record Draw

Within the selected subgroup, one result record is drawn at random with a uniform distribution, then decoded back into the game's seed structure for the game engine to replay.

Keeping the bottom level a uniform draw is deliberate. All the mathematical tuning has already been done in the three layers above, and introducing weights again at the last layer would make the derivation of the overall expected value hard to verify. Another benefit of staying uniform is this: as long as the statistical properties of the record pool itself have been verified, the distribution of the sampled results is necessarily identical to that pool's distribution, and no extra proof is required.

Indexing Strategy

Index design is the key to keeping all four selection layers constant-time. The common approach is to pre-build a cumulative weight array for each layer and locate the draw with a binary search, making the cost of a single layer logarithmic; the bottom layer, being a uniform draw, can be addressed directly by offset. Because records are encoded with fixed length or with segment lengths up front, the position of the k-th record can be computed directly without scanning record by record, a concrete example of the encoding format and the indexing strategy working together.

The Deterministic Replay Mechanism

A seed taken from the result set can restore the full game outcome through deterministic replay. For a reel-based slot, an integer seed is broken down into the stop position of each reel through mixed-radix decomposition:

reel[i].stop = seed % len(reel[i]); seed = seed / len(reel[i])

This mechanism guarantees that the same seed value always produces the same game result, making result verification and auditing straightforward.

Why Determinism Matters So Much for Audit

The elegance of mixed-radix decomposition lies in the bijection it establishes between "integers" and "boards": every valid seed value corresponds to exactly one board, and every board corresponds to exactly one seed value, with no duplicates and no omissions. This means storing one integer is equivalent to storing a complete board, and it also guarantees that "drawing seeds uniformly" is equivalent to "drawing boards uniformly", so the probability derivation holds completely.

For audit purposes, determinism brings three concrete benefits:

Note that determinism only holds when the entire computation path carries no hidden state. Any logic that depends on the current time, uninitialized memory, or hash-table iteration order will make the same seed produce different results. Maintaining determinism is therefore an ongoing discipline, not a one-off architectural decision.

Use Cases for the Result Set

Supporting Multiple RTP Versions

The same game often needs to offer several RTP versions to meet the regulatory requirements of different markets. The traditional approach is to build a separate weight table for each version, at the cost of rerunning the full mathematical verification for every one, with the differences between versions scattered across multiple configuration files and maintenance cost rising linearly with the number of versions.

The result set architecture offers another path: the underlying records are generated only once, and different RTP versions are simply different indexes and weight configurations over the same batch of records. Because each record's payout is already stored up front at encoding time, assembling a version with a target RTP is essentially a constrained weight-configuration problem: choosing, subject to the expected value equaling the target, a set of weights whose volatility characteristics come closest to the design intent.

The direct benefit of doing it this way is that the game feel stays consistent across versions. Because every version draws from the same batch of boards, the board combinations, animation rhythm and special-feature trigger patterns the player sees are all identical; the only difference is the relative frequency of each kind of result. By comparison, rebuilding the weight table easily produces differences in feel between versions that are hard to explain.

Relationship with Natural Probability

Every record in the result set comes from a genuine Spin result of the natural probability model, going through extract → encode → store. It does not change the game's mathematical model; it merely converts "real-time computation" into "pre-computed lookup". This means the result set's RTP, volatility, Hit Rate and other metrics are all strictly identical to those of the original natural probability model.

This point deserves to be stated more precisely: the statistical properties of a single result pool are identical to those of the original model, and this is guaranteed by the generation process: records are sampled from the natural probability model according to its native distribution, so when the pool is large enough, the payout distribution inside the pool is a high-fidelity sample of the original model's distribution.

And when multiple pools are combined by weight, the overall expected value is the weighted average of the pools' expected values, which is a tuning dimension deliberately retained by design. In other words, the result set architecture is not "changing the probability", it is choosing among verified distributions. Every board that gets drawn is a result the natural probability model would have produced anyway, with a probability entirely consistent with the model.

To preserve this equivalence, two disciplines must be upheld at the generation stage:

Uphold these two, and the result set genuinely remains nothing more than a storage and distribution form of natural probability, rather than a separate mathematical model of its own.