Skip to main content

Prerequisites

  • Rust and Cargo installed (used to build and run the optimizer binary).
  • A completed simulation run with lookup tables already generated. For production games, 100,000+ simulations per mode are recommended to ensure a diverse payout distribution and reduce the chance of repeated round results.

Overview

OptimizationSetup is a per-game class (defined in game_optimization.py) that takes a GameConfig instance and builds the opt_params dictionary. OptimizationExecution then reads those params and invokes the Rust binary for each mode.

The opt_params structure

For each bet mode, opt_params requires three keys:
Each key has a corresponding construction class in optimization_program/optimization_config.py.

Setup steps

1

Define conditions with ConstructConditions

ConstructConditions partitions simulations by win type and sets the RTP target for each partition.Each condition requires 2 of the 3 variables: rtp, av_win (average win), and hr (hit-rate). The third is derived automatically.The 0-win condition is a special case: its hit-rate can be left as a free variable (pass "x" or omit it) because all hit-rates across all conditions must sum to exactly 1, so the 0-win hit-rate can be deduced from the remainder.
The search_conditions argument tells the optimizer which simulation IDs belong to this condition:
  • A number matches simulations with that exact payout.
  • A tuple (min, max) matches simulations within that payout range.
  • A dict (e.g., {"symbol": "scatter"}) matches by recorded event data in the force records.
2

Configure scaling with ConstructScaling

ConstructScaling biases specific win ranges during trial distribution generation. Each entry requires:
Large scale factors significantly reduce the probability that a randomly generated trial distribution will be accepted, so use them conservatively.
3

Set run parameters with ConstructParameters

ConstructParameters defines the optimizer’s computational budget and volatility bounds.
The min_m2m / max_m2m bounds control volatility: a higher mean-to-median ratio means the distribution has a heavier tail relative to its median, producing a more volatile game.
4

Instantiate OptimizationSetup

Create the OptimizationSetup class in your run.py. It attaches opt_params to the GameConfig and validates that the conditions match the configured bet modes.
5

Run the optimizer with OptimizationExecution

Pass the configured GameConfig and the list of modes you want to optimize to OptimizationExecution.run_all_modes().
This generates a setup.toml for each mode and invokes the Rust binary via cargo run --release. Optimized lookup tables are written to library/lookup_tables/lookUpTable_<mode>_0.csv.

Complete example (run.py)

The following is the full run.py from the 0_0_lines sample game, showing how all pieces connect:
Set run_optimization: True in run_conditions to enable the optimization step. Set it to False to skip optimization and only run simulations or analysis.

Next steps

Optimization algorithm

Understand how the iterative weighted sampling algorithm works under the hood.

Game analysis

Generate a PAR sheet and analyze the optimized win distribution.