Slot Math Specification — Hold & Win Reference

This Math Spec owns whole-game totals and links to the mechanic-owned math. Canonical executable parameters live in the Go backend; this document records their identity and never maintains a second copy. A generated PAR sheet is evidence, not a replacement for the rules, targets, tuning history and approval gates recorded here.

1. Identity and provenance

FieldValue
Game nameHold & Win Reference
Game ID / slughold-and-win-reference
GDDgdd/hold-and-win-reference-gdd.md
Backend response contractgdd/hold-and-win-backend-response.md
GDD versiondraft-v0.1
Math version IDhold-and-win-reference
Math versiondraft-v0.2
Lifecycle statefinal — FREEZE & HANDOFF approved 2026-08-09; mechanic math is final-v1.0
Config schema versionMathVersionConfig as of backend bde8c05
Config hasha22129d99d21eb14acdb303efdf666f4065925fa461012d8e99f2144538d0508
Reference-model versionsealed at cd4c093; shipped build f80cb60 on main (identical in every bound artifact — the delta is CI lint fixes only)
Runtime routinglive — spin orchestrator opens the feature on a paid trigger and advances it one respin per request (cd4c093)
Engine capabilityhold_and_win = SupportFull; still not enumerable, so feature RTP stays a seeded estimate
RNG algorithm/versionsha256-trunc64-be/go1-alfg#1
Ownermath/backend (agent-authored, user-approved)
Created2026-08-09
Updated2026-08-09

Change log

VersionDateAuthorReasonChanged leversEvidence
draft-v0.12026-08-09agentInitial spec for the approved design c44bc01none — first revision2M simulation, superseded
draft-v0.22026-08-09agentTuning pass 2, option A3, after pass 1 proved the landing chance alone insufficientLandingChancePPM 150000→43000; regular-value weights 40/28/16/10/5/1→30/25/18/15/10/22M independent-seed confirmation

2. Math status

GateStatusEvidenceApproved by
Config validationpassgo test ./libs/mathengine/games/hold_and_win_referenceuser, 2026-08-09 (FREEZE & HANDOFF)
Exact mathnot applicablemechanic is not enumerable — see §12. Base RTP and trigger frequency ARE exactn/a
Simulationcompletedraft-v0.2 confirmation, 2M rounds and full-grid confirmation, 2.2M featuresuser, 2026-08-09
Max-win validationcomplete500.0000× observed and never exceeded; reachable, not merely boundeduser, 2026-08-09
Reference/runtime paritypassTestHAWOrch_MatchesTheReferenceDriverStepForStep — live orchestrator vs RunHoldAndWinToCompletion over complete state at 3 landing chances, mutation-checkeduser, 2026-08-09
Live runtime routingpassTestHAWOrch* against real PostgreSQL — trigger in the paid transaction, wager-free respins, replay, reconnect, one credit intent per settlementuser, 2026-08-09
Wire contractpasslive fixtures bound to OpenAPI and to the handler's serialized outputuser, 2026-08-09
Math reviewpassDRAFT MATH gate 2026-08-09, then FREEZE & HANDOFF 2026-08-09user, 2026-08-09
Compliance reviewout of scopereference pack; NOT externally certifiedn/a

3. Bet and payout units

PropertyDefinition
Total betThe single wagered amount per round. There is no line-bet split
Line betnot applicable
Math payout unit× total bet
Money representationexact integer minor units at the wallet boundary (libs/common/money)
Multiplier representationfloat64; money.ApplyMultiplier is the one sanctioned crossing
Rounding ruleno rounding inside the math; conversion to minor units happens once, at the wallet boundary
Win cap500× total bet, applied once to base + feature at settlement
round multiplier  = min(baseWin + featureWin, 500)
monetary win      = ApplyMultiplier(totalBetMinor, round multiplier)

4. Target math profile

Base RTP and trigger frequency are now EXACT, from the design probe's enumeration of all 8000 reachable base grids. Everything else stays pending until the seeded simulation at plan Task 10.

Two rows are outside their draft band. That is recorded drift, not a defect to be quietly corrected: the parameters responsible are open for tuning only after DRAFT MATH approval.

MetricTargetDraft toleranceFreeze toleranceCurrentMethodStatus
Total RTP96.0%±1.0pp±0.3pp96.0031% ±0.1189ppexact base + sim featurein band
Base RTP76.0%±1.0pp±0.3pp75.1160% exact / 75.1025% simenumeration + siminside draft band
Feature RTP (hold_and_win)20.884%±2.0pp±0.5pp20.8871%simin band
Hit frequencyno targetn/an/a14.4312%simmeasured
Standard deviationno targetn/an/a4.0194simmeasured (was 17.78 at v0.1)
Volatility tierno targetn/an/anot measuredsimpending
Feature trigger frequency1 in 1501 in 120–200to be set at freeze1 in 155.4 exact / 1 in 154.74 simenumeration + siminside draft band
Average feature payout32.4545×±20%to be set at freeze32.4593× ±0.1848simin band
Median feature payoutno targetn/an/anot measuredsimpending
Max win500×exactexact500.0000× observed, never exceededconstruction + 2M-round validationreachable and contained
Max-win probabilityno targetn/an/a0.000005 per roundsimmeasured

The total/base split was set by the user on 2026-08-09; the design spec fixed only the ≈20% mechanic contribution.

5. RTP decomposition

ComponentRTP contributionCalculation methodEvidence
Base evaluator (lines)76.0% targetexact enumeration of 8000 base grids75.1160% observed — design probe
Scatter pays0 — none configuredn/an/a
Free spins0 — not configuredn/an/a
Hold and spin0 — deliberately absent from this packn/an/a
Hold and win20.8871% observed vs 20.884% requiredsimdraft-v0.2 confirmation
Progressive contribution0 — jackpot tiers are fixed multipliers, not pooledn/an/a
Total96.0031% observed vs 96.0% targetexact + simresidual 0.000000pp

The decomposition must reconcile to total RTP within the simulation's reported confidence interval. BaseGameWin and FeatureWins["hold_and_win"] are separate fields on the engine's round outcome, so the split is measured rather than apportioned.

6. Mathematical model

PropertyDefinition
Grid3 reels × 5 rows
Layoutlines
Reel modelordered weighted entries; one weighted stop draw per reel
Stop selectionweightedPick over the strip's integer weights, then a contiguous 5-row window starting at that entry, wrapping
Evaluatorslines evaluator, then the hold_and_win feature executor
Aggregationbase win plus feature award, capped once

Reel model consequence

Because one draw per reel selects a contiguous wrapping window, rows on a reel are correlated and only len(strip) distinct columns are reachable per reel. Reaching 6 or more BONUS across 15 cells therefore requires contiguous BONUS runs inside the strips. This makes trigger frequency a discrete function of run length and stop weight rather than a continuous parameter, and it is the reason the ≈1/150 target is treated as a tuning objective rather than a value that can simply be set.

State-space size

N = Π_r L_r          (L_r = entry count of reel r)

Note that the base grid state space does not bound the round: the feature draws per empty cell, so the full round is not enumerable regardless of N.

ReelEntry countTotal weightReachable visible columns
12042020
22042020
32042020

N = 20 × 20 × 20 = 8000 reachable base grids. BONUS occupies entry indices 0-4 on every reel, contiguous, so visible BONUS count is a function of distance from that run.

7. Symbols and paytable

Payouts are multipliers of TOTAL bet, awarded per winning payline. Only 3-of-a-kind pays; the grid is 3 reels wide, so 3 is also the maximum count.

Symbol IDType3Special rule
BONUSbonusNo line payout. Counts toward the 6-symbol trigger and carries a prize inside the feature
H1regular180
H2regular90
M1regular45
L1regular24
L2regular15
L3regular9

Scatter payouts

None. BONUS is deliberately not a scatter: the mechanic counts it directly, and a scatter pay would add an unattributed base contribution to exactly the rounds that trigger the feature.

Paylines

Five straight rows. Positions[i] is the row index on reel i.

LineReel 1Reel 2Reel 3
1000
2111
3222
4333
5444

The paytable and the reel strips are the pack's own design inputs, not part of the approved mechanic contract. They were chosen so the enumerated base RTP lands near its 76% target; payouts are linear in that figure, so they were scaled as one block rather than tuned individually.

8. Reel strips / weights

Canonical machine-readable reels remain in the versioned backend configuration.

ReelArtifactHashBase/feature use
alllibs/mathengine/games/hold_and_win_reference/hold-and-win-reference.yaml888f134c…917d88base only — the feature does not spin reels

The feature never spins a reel strip. It draws land/miss and prize values directly, so there is no feature reel set.

9. Evaluation order

StepOperationMathematical effectCap/rounding effect
1Spin base grid3 weighted stop drawsnone
2Evaluate linesbase win multipliernone
3Count BONUStrigger decision at ≥6none
4Run hold_and_winfeature award multiplier, itself capped once at 500×mechanic cap applied here
5Sum and cap the roundmin(base + feature, 500)round cap applied once
grid       = spinReels(reelSet)
baseWin    = evaluateLines(grid)
featureWin = countVisible(grid, "BONUS") >= 6 ? holdAndWin(grid) : 0
roundWin   = min(baseWin + featureWin, MaxWinMultiplier = 500)

10. Feature model

Feature: hold_and_win

Authoritative math is mechanic-owned: math/mechanics/hold-and-win/hold-and-win-math-draft-v0.1.md.

ParameterValue
Trigger conditionat least 6 visible BONUS
Trigger probability1 in 155.4 exact, 1 in 154.74 simulated
Award3 respins over locked/empty cells; a prize per locked cell
Reel setnone — the feature does not spin reels
Multipliernone in v0.1
Retriggernot a retrigger; a landed prize resets remaining respins to 3
Terminationzero respins remaining, or all 15 cells locked
RTP contribution79.7860% observed against a 20.0% target
Average payout123.4600× observed against a 30× target
Median payoutno target; 69.4% of awards fall in [10×, 50×)
Duration distributionmean 8.8711 steps, reset rate 0.4865 per step

Feature state transitions

FromEvent/conditionToState mutationRNG stream
Idle≥6 BONUSTriggeredlock import, prizes assigned in normative order<featureSeed>:hold_and_win:start
Triggeredinit completeRespinningrespinsRemaining = 3, stepIndex = 0none
Respinningstep lands ≥1Respinninglock landed cells, respinsRemaining = 3<featureSeed>:hold_and_win:step:<stepIndex>
Respinningstep lands 0RespinningrespinsRemaining -= 1<featureSeed>:hold_and_win:step:<stepIndex>
RespinningrespinsRemaining == 0Settledaward min(Σ prizes, 500)none
Respinning15 cells lockedSettledaward exactly 500none

Closed-form derivation

Not available for the award. The respin-reset rule makes the number of steps an absorbing random walk whose transition probabilities depend on the current empty-cell count — a step over e empty cells lands nothing with probability (1-p)^e. The expected award is therefore measured, not derived. The two per-draw expectations that are closed form:

E[regular value] = 264 / 100          = 2.64×
E[landed prize]  = 3065 / 1026        ≈ 2.9873×

11. RNG and mapping contract

PropertyDefinition/evidence
Algorithm/versionsha256-trunc64-be/go1-alfg#1 — unchanged by this work
Seed derivationseed string → SHA-256 → first 8 bytes big-endian int64 → math/rand
Stream derivation<featureSeed>:hold_and_win:start and <featureSeed>:hold_and_win:step:<stepIndex>; identical strings in production and simulation
Replay contractmechanic version + persisted state + step identity + feature seed
Integer mappingcumulative integer intervals over configured weights; land/miss is Intn(1_000_000) < LandingChancePPM. A raw draw is never modulo-mapped
Reel-stop mappingweightedPick over strip weights, unchanged
Cross-platform golden vectorsplan Task 9 — pack golden test plus libs/mathengine/parity entries
Statistical screeningmake test-rng; screening is not certification

No secret production seed material belongs in this document.

12. Exact calculation

PropertyResult
Enumerableno
Rejection reasonthe feature draws RNG per empty cell per step, so the round is not grid-determined. hold_and_win is deliberately excluded from the engine's gridDeterministicFeatures allowlist, which exists so an RNG-driven feature cannot silently return one arbitrary sample and produce a confidently wrong "exact" RTP
States enumeratednone
Probability massnot applicable
Exact total RTPnot available
Distribution coversnot applicable
Exact tool/buildnot applicable
Artifactnone

A tractable exact state-space method was not implemented. Simulation is not a substitute for exact calculation; it is the only method available here, and it is labelled estimated.

13. Monte Carlo specification

PropertyValue
Purposenon-enumerable feature — authoritative Draft evidence
Rounds2,000,000
Master seed / seed set IDhaw-draft-v0.1-sim
Workers8 shards of 250,000, merged
Deterministic mergeyes — ShardSeed + MergeBatches, verified single-shard vs merged-shard identical
Simulator versionbackend 13700ae
Config hash888f134c…917d88
Runtime112.6 s wall, darwin/arm64
n >= (z·σ / ε)²          SE = s / √n          CI = mean ± z·SE

Simulation results

MetricEstimateSE/CIExact/targetDeltaStatus
RTP154.8803%SE 1.2571pp, CI [152.4165, 157.3442]96.0% target+58.88ppoutside
Base RTP75.1025%76.0% target−0.90ppinside band
Feature RTP79.7860%20.0% target+59.79ppoutside
Trigger frequency1 in 154.74CI [152.12, 157.44]1 in 150 target+3.2%inside band
Hit frequency14.4509%no targetmeasured
Standard deviation17.7776no targetmeasured

14. Win distribution

Measured over 2,000,000 rounds — see the simulation report. Bin edges are the engine's existing ones (0, (0,1), [1,5), [5,10), [10,50), [50,100), [100,500), [500,1000), [1000,5000), ≥5000). Note that with a 500× round cap the top three bins can only be reached at the boundary: a capped round lands in [500,1000) exactly at 500.

Threshold probabilities will not be inferred from these coarse bins; any specific threshold claim requires its own counter.

15. Max-win analysis

PropertyValue/evidence
Declared max win500× total bet
Reachable base maxdetermined by the pack paytable; the observed round maximum is the 500× cap
Whole-round bound500× — enforced by Paytable.MaxWinMultiplier
Reachable whole-round max500×, reachable: a full grid awards exactly Grand 500×
Cap probability0.001209 per round
Max-win probability0.001209 per round; the full-grid path, at 0.187079 per trigger
Derivationfull-grid award is 500× by construction; observation recorded at Task 10

500× here is a reachable value, not merely a mathematical upper bound. Both facts are asserted: the value is attainable, and no round exceeds it.

16. Test vectors and parity

Vectors are created at plan Task 9 and indexed in test-vectors/README.md.

Required scenarios:

  • No win, no trigger
  • Base line win without trigger
  • Five BONUS — no trigger, no feature RNG consumed
  • Six BONUS — trigger, exact lock order
  • Miss-only step decrements respins
  • Landed prize resets respins to 3
  • Mini, Minor and Major landed prizes
  • Ordinary sum below the cap
  • Ordinary sum capped once at 500×
  • Full grid awarding exactly Grand 500×
  • Interrupted-round replay and duplicate step idempotency
  • Reference RunToCompletion equals persisted step execution

17. Draft Math handoff

ArtifactPath/linkVersion/hashOwner
Math configlibs/mathengine/games/hold_and_win_reference/hold-and-win-reference.yaml888f134c…917d88backend
Reel setssame file888f134c…917d88math
Paytablesame file888f134c…917d88math
Exact reportnot applicablen/an/a
Simulation reportevidence/simulation/2026-08-09-draft-v0.1-2m.md2M rounds, seed haw-draft-v0.1-simmath
Test vectorstest-vectors/pendingbackend
PAR sheetnot produced for this reference packn/an/a
Manifesthold-and-win-math-handoff-v0.1.mdunsealedmath

Open and locked parameters

ParameterStateAllowed range/changeOwner
Grid, cell order, trigger count, respin count and reset rulelockedrequires new DESIGN approvaldesign
Jackpot tier values and the full-grid Grand rulelockedrequires new DESIGN approvaldesign
500× cap and its single applicationlockedrequires new DESIGN approvaldesign
Landing chance PPMopenafter DRAFT MATH approval onlymath
Regular value weightsopenafter DRAFT MATH approval onlymath
Prize-type weightsopenafter DRAFT MATH approval onlymath
Base trigger weights (reel strips)openafter DRAFT MATH approval onlymath

Draft handoff criteria:

  • All payout-affecting rules are defined.
  • Draft metrics meet draft tolerances.
  • Config and evidence are versioned and hashed.
  • Test vectors cover critical paths.
  • Unsupported mechanics are rejected or explicitly excluded.

18. Tuning record

No tuning has been performed. Tuning is prohibited before DRAFT MATH approval; entries are added under math/tuning/ at plan Task 11, one per traceable revision, never overwriting the baseline.

19. Lifecycle and freeze

stateDiagram-v2
    [*] --> Draft
    Draft --> Integration: Draft gate
    Integration --> Tuning: Measured change request
    Tuning --> Integration: New candidate
    Integration --> Frozen: Sim/parity/max-win gates
    Frozen --> Certification: Immutable package
    Certification --> Certified: External approval
    Certification --> Tuning: Rejected with new revision
    Certified --> Retired

Current state: draft. Frozen parameters at freeze time: reel strips and weights, paytable, landing probability, prize and jackpot weights, evaluation and cap order, RTP split, RNG algorithm/version and mapping, max win and cap.

20. Certification evidence bundle

Not assembled. DRAFT / NOT FOR CERTIFICATION. Internal tests and simulations are not external certification, and this reference pack is not a certification candidate.

21. Risks and limitations

Risk/limitationImpactMitigationRelease blocker
No exact cross-check for the mechanicA systematic state-machine error would not be caught by a second calculationGolden/parity corpus plus reference-versus-runtime equality, now executed on the LIVE orchestrator path over complete statecleared for freeze
Trigger frequency is coarse-grained in strip space≈1/150 may not be hittable exactlyReport observed drift at DRAFT MATH; accept a nearby value by decisionno
Feature spans requestsA lost or ambiguous step is a money eventDurable PostgreSQL state, duplicate-step idempotency, typed ahead/stale reconciliation, fail-closed on unknown version, quarantine blocks paid play before debit — all exercised against real PostgreSQL through the live orchestratorcleared for freeze
Whole-game split is an unmeasured targetBase and feature RTP may not land at 76/20Task 10 measures and reports before any tuningno

22. Final sign-off

Approved 2026-08-09 by the user (Bogdan), verbatim APPROVE FREEZE & HANDOFF, for the scope recorded in math/mechanics/hold-and-win/hold-and-win-math-handoff-v0.1.md.

The immutable Final is math/mechanics/hold-and-win/hold-and-win-math-final-v1.0.md, a verbatim copy of the approved draft-v0.2. The mechanic is developer-ready.

Developer-ready is not a certification claim and not a switch-on. Internal tests, simulations and this approval are not external certification, and the durable runtime is dormant in production until an operator flag is explicitly enabled.