Hold & Win Reference Mechanic — Design
Status and scope
- Status:
DESIGN APPROVED - Mechanic ID:
hold-and-win - Backend feature type:
hold_and_win - Reference Game ID:
hold-and-win-reference - Initial version:
draft-v0.1 - Certification status:
DRAFT / NOT FOR CERTIFICATION - Design approval: user, 2026-08-09
Build a reusable Hold & Win mechanic in the canonical Go libs/mathengine runtime and a separate reference math pack. Do not modify the frozen classic-fruits-3x3 v1 configuration or the existing partial hold_and_spin feature and sample packs.
Player and math contract
The mechanic uses a 3-column × 5-row grid with 15 cells. Cells use reel-major order: column 0 rows 0–4, then column 1 rows 0–4, then column 2 rows 0–4. This order is normative for masks, RNG draws, persistence and replay vectors.
The base outcome triggers Hold & Win when at least six BONUS symbols are visible. A non-triggering base outcome consumes no Hold & Win RNG draws. On trigger, the initial BONUS positions are copied into locked state and assigned prizes in normative cell order.
The feature starts with three respins. Each step visits only empty cells in normative order. Every visited empty cell consumes one landing draw with a draft probability of 15%. A landed prize locks the cell. If at least one new prize lands, remaining respins reset to three. Otherwise remaining respins decrement by one. Locked cells consume no further draws.
The feature settles when remaining respins reach zero or all 15 cells are locked. It charges no additional wager.
For an ordinary settlement, the award is the sum of locked prizes, capped once at 500× total bet. A full grid instead awards exactly Grand 500×; it replaces the sum of prizes rather than adding to it.
Collectors, multipliers, feature buy and other secondary mechanics are outside v0.1.
Prize model
Regular coin values are multipliers of total bet.
Landed prize types use this independent draft pool:
Grand does not appear in the landed prize pool. It is awarded only for a full grid.
Jackpot values, the full-grid Grand rule, grid geometry, cell order, trigger boundary and three-respin reset rule are locked at the design gate. Landing probability, regular value weights, jackpot weights and base trigger weights remain open for draft tuning.
RNG contract
- The base evaluator produces BONUS positions.
- If fewer than six BONUS symbols appear, the mechanic consumes no RNG.
Startvisits initial locked cells in normative order. For each cell it draws prize type, then draws a regular value only when the type is Regular.Stepvisits empty cells in normative order. For each cell it draws land/miss. On land it draws prize type, then a regular value only for Regular.- Locked cells consume no draws.
- Settlement consumes no draws.
The same mechanic version, initial state, step identity and RNG input must reproduce the same state and result. A repeated step returns the persisted result and must not consume RNG again.
Architecture
Add a new hold_and_win feature type rather than changing the existing partial hold_and_spin behavior.
The canonical implementation is a pure, versioned state machine in libs/mathengine:
StartHoldAndWinStepHoldAndWinSettleHoldAndWinRunHoldAndWinToCompletion
HoldAndWinState persists at least mechanic version, grid dimensions, locked mask, prize per cell, respins remaining, step index, accumulated award, settlement state and replay identity.
Production executes steps and persists the state between requests. Reference simulation calls RunHoldAndWinToCompletion, which must be an adapter over the same Start and Step functions, not a second implementation.
Backend integration includes config/schema validation, JSON mapping, Math Studio domain/build mapping, feature registration, simulation metrics and persistent game-engine replay. The capability may report SupportFull only after runtime persistence, reference/runtime parity and regression evidence are complete.
Reference pack and documents
Create hold-and-win-reference as a separate reference game/pack. It uses a 3×5 base layout and base weights tuned toward a draft trigger target near 1 in 150 rounds. It does not inherit or modify Classic Fruits mathematics.
Create:
Canonical executable parameters remain in the Go backend. Workspace documents record the backend config path, SHA-256, Git SHA, mechanic/RNG versions and evidence identities without maintaining an uncontrolled duplicate config.
Draft math targets
These are design targets, not calculated results:
- Mechanic RTP contribution: approximately 20% of total bet.
- Trigger frequency: approximately 1 in 150 base rounds.
- Conditional feature mean: approximately 30× total bet.
- Maximum feature award: 500× total bet.
Exact enumeration is optional only if a correct tractable state-space method is demonstrated. Otherwise the authoritative draft evidence is a seeded backend simulation, clearly labelled estimated, reporting total/base/feature RTP with confidence intervals, trigger frequency, conditional mean/median/percentiles, duration, reset rate, full-grid probability, prize/jackpot frequencies, standard deviation, observed maximum and validated bound.
Error, recovery and compatibility rules
- Reject invalid grid dimensions, trigger count, respin count, probabilities, prize weights, jackpot tiers and cap.
- Never silently fall back to
hold_and_spinbehavior. - Never edit frozen game versions in place.
- Persisted state includes a mechanic version; incompatible state fails closed or follows an explicit migration/version-routing rule.
- Retry and reconnect resume the same step without new RNG or wager.
- Full-grid Grand and the 500× cap apply exactly once at settlement.
- Existing games without
hold_and_winmust remain byte-for-byte and behaviorally unchanged in golden/parity evidence.
Backend response contract and documentation gate
Runtime routing and its real serialized response are required deliverables, not optional follow-up work. The canonical response contract is the implemented game-engine handler/domain types plus apps/game-engine/api/openapi.yaml; design examples are never treated as proof of the wire format.
Every trigger, respin, reconnect/replay and settlement response must provide enough authoritative state for a client to reconstruct the 3×5 feature without local outcome inference. The contract must expose a complete ordered snapshot of all 15 cells and a per-step delta of newly landed prizes. Each cell identifies its stable index, column, row, locked/empty state and prize when locked. The response also carries mechanic version, feature status, current and expected step index, respins remaining, locked count, accumulated award and settlement/Grand/cap fields when applicable.
After the runtime response exists and integration tests capture its serialized form, create games/hold-and-win-reference/gdd/hold-and-win-backend-response.md. Derive this document from the actual backend response and OpenAPI schema. Include trigger, ordinary respin, duplicate-step replay, reconnect and settlement examples taken from deterministic test fixtures. Link it from the game README, GDD, Math Spec and handoff protocol.
Any backend response-field change invalidates the response examples and runtime parity evidence. Regenerate and review the documentation before FREEZE & HANDOFF.
Required verification
- Trigger boundary at five and six BONUS symbols.
- Initial lock import and prize assignment order.
- Empty-cell-only redraw.
- Landing resets respins; miss-only step decrements.
- Zero-respin and full-grid termination.
- Mini, Minor, Major and full-grid Grand semantics.
- Ordinary sum and single 500× cap.
- Stable draw order and same seed/state/step identity reproduction.
- Interrupted-state replay and duplicate-step idempotency.
- Step execution equals
RunToCompletion. - JSON/domain/engine round trip and invalid-config rejection.
- Reference pack → engine → seeded batch simulation parity.
- Serialized backend responses contain a complete 15-cell snapshot plus the exact newly-landed delta and match OpenAPI/documented deterministic fixtures.
- Regression proving existing games and the partial
hold_and_spinfeature are unchanged.
Approval gates
AWAITING_USER_APPROVAL — DESIGN: approve this contract and the initial Draft documents before production code.AWAITING_USER_APPROVAL — DRAFT MATH: approve observed behavior and tuning direction before tuning.AWAITING_USER_APPROVAL — FREEZE & HANDOFF: approve the reconciled Final and protocol hashes before declaring developer-ready.
No internal test, simulation or handoff approval is external certification.