Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/StakeEngine/math-sdk/llms.txt

Use this file to discover all available pages before exploring further.

GameState is the central object that runs a single simulation round. It owns the current board, win data, event book, and all per-spin mutable state. Every game you build subclasses GameState (or its parent chain) and implements run_spin() as the simulation entry point.

Class hierarchy

ClassModuleRole
GeneralGameStatesrc/state/state.pyAbstract base. Owns all state, manages books and win manager.
Conditionssrc/state/state_conditions.pyQuery helpers (in_criteria, is_wincap, is_in_gametype).
Executablessrc/executables/executables.pyReusable spin actions (draw board, free spins, win cap, global multiplier).
GameExecutablesgame_executables.py (per game)Game-specific win evaluation and custom actions.
GameStateOverridegame_override.py (per game)Override reset_book(), define assign_special_sym_function().
GameStategamestate.py (per game)Implements run_spin() and run_freespin().

GameState properties

board
list[list[Symbol]]
The active board after the most recent draw_board() call. Indexed as board[reel][row]. Each entry is a Symbol object with a .name attribute and any special properties set by assign_special_sym_function.
gametype
string
Current game phase. Starts as config.basegame_type (default "basegame") and switches to config.freegame_type (default "freegame") when reset_fs_spin() is called.
repeat
bool
Controls the simulation retry loop in run_spin(). Set to True before the loop begins; reset to False by reset_book(). Set back to True by check_repeat() when distribution criteria are not satisfied.
win_data
dict
Populated by the win evaluation step each spin. Structure:
{
  "totalWin": 0.5,
  "wins": [
    {
      "symbol": "H1",
      "kind": 4,
      "win": 0.5,
      "positions": [{"reel": 0, "row": 1}, ...],
      "meta": {}
    }
  ]
}
win_manager
WinManager
Tracks cumulative, spin, base-game, and free-game win amounts. Updated via win_manager.update_spinwin() and win_manager.update_gametype_wins().
config
GameConfig
Reference to the GameConfig instance passed at construction. Read-only during simulation.
fs
int
Current free spin index (0-based). Incremented by update_freespin() at the start of each free spin.
tot_fs
int
Total free spins awarded this round (including retriggers). Set by update_freespin_amount() and incremented by update_fs_retrigger_amt().
book
Book
Stores all events emitted during the current simulation. Passed to imprint_wins() at the end of the round to persist it in the library.
global_multiplier
int
Running global multiplier value, starting at 1. Incremented by update_global_mult().
wincap_triggered
bool
Set to True by evaluate_wincap() when the running win reaches config.wincap. Prevents further win events from being emitted.
criteria
string
The distribution criteria label assigned to the current simulation number (e.g. "basegame", "freegame", "winCap"). Assigned by the simulation runner before run_spin() is called.

Key methods

reset_seed(sim)

def reset_seed(self, sim: int = 0, seed_override=None) -> None
Seeds the Python random module with sim + 1. Call this as the first line of run_spin() so that every simulation number is fully reproducible.

reset_book()

def reset_book(self) -> None
Resets all per-spin state: clears the board, creates a new Book, zeroes win_data, resets win_manager, sets repeat = False, resets fs, tot_fs, global_multiplier, and wincap_triggered. Call this at the start of each retry loop iteration.

check_repeat()

def check_repeat(self) -> None
Checks whether the completed simulation satisfies the active distribution’s win_criteria and force_freegame constraints. Sets self.repeat = True if any constraint fails. Call this at the end of the spin loop, after evaluate_finalwin().

imprint_wins()

def imprint_wins(self) -> None
Saves the completed simulation to self.library and flushes temp_wins (recorded events) to self.recorded_events. Call this once after the retry loop exits.

update_final_win()

def update_final_win(self) -> None
Computes the final payout multiplier (clamped to wincap), splits it into base-game and free-game portions, and writes values onto self.book. Raises AssertionError if base + free game wins do not match the total. Called inside evaluate_finalwin().

record(description)

def record(self, description: dict) -> None
Appends an event descriptor to temp_wins for tracking distributions. Typically called when a free spin trigger or other trackable event occurs:
self.record({
    "kind": self.count_special_symbols("scatter"),
    "symbol": "scatter",
    "gametype": self.gametype,
})
Data is written to the force/ output files and consumed by the optimization algorithm to identify which simulations belong to which event type.

run_spin() — simulation entry point

run_spin(sim, simulation_seed=None) is an abstract method in GeneralGameState that you must implement in your GameState class. The simulation runner calls it once per simulation number.
gamestate.py
def run_spin(self, sim, simulation_seed=None):
    self.reset_seed(sim)          # seed RNG for reproducibility
    self.repeat = True
    while self.repeat:
        self.reset_book()         # clear per-spin state
        self.draw_board()         # draw from reel strips

        # 1. Evaluate win_data for the current board
        # 2. Update win_manager with the spin win
        # 3. Emit reveal and winInfo events

        self.win_manager.update_gametype_wins(self.gametype)

        if self.check_fs_condition():
            self.run_freespin_from_base()

        self.evaluate_finalwin()  # compute payout multiplier
        self.check_repeat()       # verify distribution criteria

    self.imprint_wins()           # persist to library
Each iteration of the while self.repeat loop is a complete spin attempt. reset_book() resets repeat to False; check_repeat() sets it back to True only if a constraint is violated. The loop continues until the spin satisfies all distribution criteria.

run_freespin()

Also abstract. Implement alongside run_spin() for games with free spin features:
gamestate.py
def run_freespin(self):
    self.reset_fs_spin()                   # switch gametype to freegame
    while self.fs < self.tot_fs:
        self.update_freespin()             # emit updateFreeSpin event, advance fs counter
        self.draw_board()                  # draw using freegame reel weights

        # evaluate wins, update win_manager, emit events

        if self.check_fs_condition():      # retrigger check
            self.update_fs_retrigger_amt()

        self.win_manager.update_gametype_wins(self.gametype)

    self.end_freespin()                    # emit freeSpinEnd event

create_books()

src/state/run_sims.py
from src.state.run_sims import create_books

create_books(
    gamestate,
    config,
    num_sim_args,
    batch_size,
    threads,
    compress,
    profiling,
)
The main simulation driver. Allocates distribution criteria to simulation numbers, launches multi-threaded workers, and writes all output files.
gamestate
GameState
Instantiated GameState object.
config
GameConfig
The game configuration object.
num_sim_args
dict
Maps bet mode names to simulation counts: {"base": 1000000, "bonus": 100000}.
batch_size
int
Number of simulations per thread batch. Typical value: 50000.
threads
int
Number of parallel worker processes.
compress
bool
When True, output books are written as .jsonl.zst (Zstandard compressed). When False, plain .jsonl files are written — useful during development.
profiling
bool
When True, runs a single-threaded cProfile pass and generates a flame graph. threads must equal 1 when profiling.
num_sim_args values must satisfy n % (threads × batch_size) == 0 when n > batch_size². Set any mode’s value to 0 to skip it during a run.

generate_configs()

src/write_data/write_configs.py
from src.write_data.write_configs import generate_configs

generate_configs(gamestate)
Produces all configuration files required by the RGS and frontend after simulations complete:
FilePurpose
config_fe_<game_id>.jsonFrontend config: symbol list, bet modes, reel strips, paylines.
config_be_<game_id>.jsonBackend config: file hashes, RTP, denominations, book shelf layout.
math_config.jsonOptimization algorithm input: RTP targets, fence conditions, scaling rules.
manifest.jsonRGS manifest listing all published files and their S3/CDN paths.
Call generate_configs() once after create_books() completes:
run.py
if __name__ == "__main__":
    config = GameConfig()
    gamestate = GameState(config)

    create_books(gamestate, config, num_sim_args, batch_size, threads, compress, profiling)
    generate_configs(gamestate)

Build docs developers (and LLMs) love