How It Works¶
Architecture Overview¶
BJW uses a two-component architecture:
Rules Files → Configurator → Manifest (JSON) → Simulator → Results (JSON)
(Python) (validated) (TypeScript)
Configurator (Python): Assembles simulation specifications from rule combinations. Validates all inputs against JSON schemas. Transpiles betting policies to Betting VM bytecode. Outputs a manifest file.
Simulator (TypeScript): High-performance engine that executes manifests. Runs single-threaded or multi-worker parallel. Produces structured JSON results with full telemetry.
Nothing is hardcoded in the simulator. All behavior — rules, strategy, counting system, betting spread, deviations — comes from the manifest.
The Manifest¶
A manifest is a complete, self-contained simulation specification. It includes:
- Ruleset: deck count, S17/H17, DOA/D10, DAS/NDAS, RSA, peek mode, penetration %, burn cards
- Counting system: tag values, balance type, TC divisor method, insurance threshold
- Betting policy: BVM bytecode encoding the spread or progression logic
- Play policy: full basic strategy decision map for the rule configuration
- Deviations: index plays to apply, with their TC thresholds
- Seed: PRNG seed for full reproducibility
Manifests are schema-validated before execution. A manifest hash serves as the experiment identifier — the same manifest + same seed produces the same results on any machine.
If you want a player-friendly walkthrough:
The Betting VM¶
All betting strategies — flat bets, count-based spreads, progressions, state machines — execute through a single Betting VM (BVM) runtime. The configurator transpiles authored betting policies to BVM bytecode; the simulator executes that bytecode each round.
This means any betting strategy expressible in the policy language can be simulated without touching the simulator code.
BVM strategy types:
| Kind | Examples |
|---|---|
flat |
1 unit every hand |
bucket_spread |
Hi-Lo 1-12: bet scales with count (TC for balanced systems, RC for unbalanced) |
progression |
1-3-2-6, Paroli, Martingale |
state_machine |
Custom formulas with session state |
Parallel Execution¶
For large simulations (100M–1B+ rounds), BJW spawns multiple worker processes that each run a subset of rounds and aggregate results. Aggregation uses a declarative rule engine — approximately 120 field-level rules specifying whether each metric is summed, histogrammed, or derived.
Parallel and single-threaded modes produce identical results for any given manifest and seed. This is verified via binary deck regression runs, where a pre-shuffled shoe sequence is fed identically to both modes and the outputs are required to match exactly — not approximately.
Results¶
Simulator output is a structured JSON file containing:
round_summary: rounds played, hands, wins, losses, pushessummary.naive: per-hand and per-round SD using simple Welford variancesummary.chapter10: legacy-named BJW variance block — E[b], E[w], Var(b), Var(w), Cov(b,w), DI, SCORE, N₀summary.di_adjusted: DI-adjusted variance using simulation-derived Var(w)evByBucket: EV breakdown by count bucket (TC for balanced systems, RC for unbalanced) — includes rounds played, average bet, EV per hand, and SD per hand for each bucketcount_histogram: RC, TC, and RC-per-deck frequency distributions sampled at bet-decision pointcounters: doubles, splits, surrenders, insurance events, deviations appliedactions_by_state_upcard: per-decision-state action frequencies broken down by dealer upcard
All metrics feed the validation pipeline, which independently recomputes the variance/risk figures in that block from raw accumulators to verify implementation correctness.
If you want a player-friendly walkthrough: