sots-engine/docs
alex dc43f93910 mars::rng: the seven draw entry points, with their word costs
A per-turn RNG budget is only as good as the entry-point table, and ours had
three of the seven. Adds the two that are modellable and documents the rest.

  float_range(lo, hi)     exactly one word.  Narrows TWICE -- the scaled product
                          is stored to a 4-byte float before lo is added, and the
                          sum is stored again.  Evaluating in double and narrowing
                          once disagrees on a measurable fraction of words, and the
                          test asserts the two models are distinguishable so the
                          shortcut cannot creep back.
  int_range_bell(lo, hi)  AT LEAST TWO words.  Triangular, not uniform: the span is
                          split into h/2 and h - h/2 (truncating toward zero) and
                          each half drawn inclusively, first half first.  The bounds
                          reach the draw as unsigned, so an inverted range yields a
                          huge first bound rather than an empty one; reproduced, not
                          corrected.

Documented but deliberately not modelled: a truncated-normal integer range built
on rejection sampling around a Box-Muller pair.  It costs TWO WORDS PER ATTEMPT
and the attempt count is unbounded, and predicting its stream position needs log,
sqrt and cos to agree bit for bit with the original CRT.  Nothing in the strategic
turn reaches it.  It is recorded so a ledger that meets it does not score its two
words as one draw.

Also recorded in docs/mars-rng.md, because each is a way a word budget goes wrong:

  * two calling conventions for one generator -- three entry points take the state
    block (the object plus four bytes) and four take the object itself, and one
    caller uses both within forty bytes of itself;
  * two different divisors in the same image, 1/(2^32 - 1) for the unit draw and
    2^-32 (with a +0.5 offset on the word) for the normal path;
  * the unit draw is inlined at twenty-eight sites across eleven functions, so any
    budget assembled by counting calls is a LOWER BOUND.  Exactly one of those
    eleven is reachable from the strategic turn driver.

Host ctest 36/36 and tools/clean_room_check.sh run as separate commands, both
clean.  No src/shim change, so no cross-build is implicated.
2026-09-08 09:59:05 -04:00
..
B1.md b1: ComputeBudget hook + adapter; fix researchMoneyKept to be charged only with a research target; budget out-param is int[22] 2026-09-07 23:24:10 -04:00
B2.md b2 live: 3 completions compared 0 divergences; float32 confirmed on the game; RollResearchEvent RNG region added; xenotech block size bug fixed 2026-09-08 01:18:39 -04:00
B3.md b3 live results: 13/15 zero-divergence, RNG post-state 14/15; research target is state 3 (no decay); oracle gap = unposted overbudget event 2026-09-08 00:29:44 -04:00
B4.md b4 live: 36 calls 0 divergences, no colony RNG draws as predicted; fix 3 hook bugs (stale args, two-base StrategyServer, raw Ghidra offset) 2026-09-08 02:07:28 -04:00
E-events.md game/events: the player event log and the five research events 2026-09-08 02:45:57 -04:00
G-wire-schema.md A: type the AIAgent custom-data blocks; named coverage 98.0% -> 99.9% 2026-09-08 07:33:06 -04:00
game-data.md game/data: typed catalogs (weapons, sections, turrets, ids, tech tree, strings), cross_check; oracle 229k values 0 diffs 2026-09-07 17:55:08 -04:00
game-design.md game/design: assembly/fit/gating rules + derived stats on game/data; 127/127 designs, 197/197 DOpts, oracle-identical 2026-09-07 22:10:35 -04:00
game-effects.md b2: OnTechResearched hook + 10 effects-table corrections (float32, xenotech block size, no already-researched guard, sticky mask, AI bonus values) 2026-09-08 00:01:04 -04:00
game-sim.md b4: colony + movement hooks; 22 formula corrections (growth curve has no capacity term, range margin +0.05f, ties-to-even rounding); 3 verified signatures 2026-09-08 00:57:55 -04:00
harness-audit.md lane P: post the research events from ours (count-only), declare ObservedTech 2026-09-08 04:16:22 -04:00
M-movefleet.md movefleet: reproduce the original's float32 normalise; 8 of 45 live divergences -> 0 2026-09-08 03:50:04 -04:00
M0.md m0: binkw32 proxy shim, minhook, trace hook on Application::Initialize; build/deploy tooling 2026-09-07 17:22:15 -04:00
M1.md m1: GlobalConsts::LoadFile hook + game/config loader; trace 19 calls, compare 0 div, replace passes End-Turn oracle 2026-09-07 22:16:55 -04:00
M2.md m2: live verification results (weapons compare 0 div, oracle passes; section compare crash documented) 2026-09-07 23:52:50 -04:00
mars-parse.md mars/parse + mars/text: engine parity (Mars::Script tokenizer, first-wins keys, trailing-pair drop); oracles 1531/1531, 64/64 2026-09-07 18:10:18 -04:00
mars-rng.md mars::rng: the seven draw entry points, with their word costs 2026-09-08 09:59:05 -04:00
mars-stream.md mars/stream + mars/rng: Streamable reader/writer/shapes, MT19937; 3 real saves exact + byte-identical round-trip 2026-09-07 17:46:06 -04:00
mars-text.md mars/parse + mars/text: engine parity (Mars::Script tokenizer, first-wins keys, trailing-pair drop); oracles 1531/1531, 64/64 2026-09-07 18:10:18 -04:00
mars-vfs.md mars/vfs: gob ZIP reader + native override, miniz 3.1.2; oracle-verified 8352+2035 entries 2026-09-07 17:40:51 -04:00
P-events-wiring.md lane P: post the research events from ours (count-only), declare ObservedTech 2026-09-08 04:16:22 -04:00
R-recapture.md recapture: golden traces with guards on the live game 2026-09-08 03:04:34 -04:00
shim-trace.md shim: force and verify the x87 control word around the turn gate 2026-09-08 05:09:16 -04:00
T-turn-driver.md lane T merge fixups: name the roll-succeeded branch instead of its FUN_ id (clean-room); mark describe_i32 maybe_unused so the shim cross-builds 2026-09-08 08:13:39 -04:00
U-unlock.md U: live verification - 0 divergences on 35 calls, three workloads 2026-09-08 06:57:15 -04:00
V-eventlive.md V: live verification of lane P's event posting; the advance prediction held 2026-09-08 06:00:01 -04:00