sots-engine/tests/game_sim
alex b39bb290e3 L5: the interest literals verified live at a boundary, with a control that fails
`ComputeBudget`'s savings-interest term is now compared against the running game at
a treasury the corpus actually contains. Three runs on VM146 from turn1-state.sav:

  A (widened floats, as shipped)   3,895 calls, 0 diverged, 0 undeclared writes
  B (exact decimals, the control)  2,718 calls, 1,359 diverged

The game fills savingsInterest with 499 at a treasury of 50,000, and with 380 at
38,100 -- the exact decimals pay 500 and 381. Every divergence in B lands on a
treasury that is a multiple of 100 and no other state diverges at all, which is
exactly the arithmetic. G3's rule-23 reading is now measured, not inferred, and the
one-money error is shown to propagate into `available` and `researchMoney` too.

The control also settles why the earlier 4,437-call green run was green: slot 5 IS
diffed and the harness CAN see it, so that run simply presented no boundary state.
Coverage is therefore reported as distinct states, not calls: 5 distinct treasuries,
2 of them on the boundary.

Two further rule-23 constants found in the same routine by an operand-width sweep,
corrected, and honestly marked UNVERIFIED because no reference turn can see them:

  - the research-yield factor is a widened 0.85f while its two neighbours in the
    same product are exact doubles. Boundary: research money a multiple of 40,000;
    the run presented 9 distinct values and none is.
  - the three research modifiers are summed in single precision, not double.
    Boundary: two of the three non-zero; the corpus has shrm = TRM = 0.

Both are pinned by boundary cases in test_economy.cpp that fail with the decimals.

Also verified live, in the same run:
  - T31's difficulty-column recovery. The live ServerPlayer+0xf9 / NPC flags on all
    eight players are exactly what lane PL's save-only inversion claims, including
    the awkward system-owning player that is still ambiguous because it is an NPC.
  - BANKRUPTCY_PROTECTION_LIMIT_FACTOR reads 3.29999995 = (float)3.3. Its file image
    is zero because the loader fills it at run time, so lane PL-3 had to assume the
    value; it is now measured and the assumption was right.

Falsified, and recorded as such: the difficulty-mods record does NOT sit inline at
ServerPlayer+0x36c -- that field is a heap pointer on all eight players. The row IS
reachable from a ServerPlayer (which corrects the hook's standing coverage note),
but the fitted {3.0,1.5}/{1.0,1.0} pair remains unverified. The hook logs the
pointer and does not follow it.

The `verified` column stays 0, deliberately. Every phase this compare touches is
Partial for reasons upstream of it, and promoting one because part of it was checked
is the drift app_test_catalog exists to catch. What moved is models; see
docs/L5-live-verification.md for each one with its coverage.

Gates run separately: clean-room OK, host ctest 54/54, CT111 shim cross-build exit 0.
2026-09-08 17:48:42 -04:00
..
build_and_run.sh SV: the script-object event bus, and what it writes in a turn 2026-09-08 16:46:25 -04:00
check.h 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
CMakeLists.txt PL: decompose the /Sim/players residual; S00 PvSav snapshot; T31 recovers its difficulty column from the save; the bankruptcy protection factor is a widened float 2026-09-08 16:34:40 -04:00
mini_json.h game/sim: strategic formulas as pure functions (economy, research, colony, movement), 356 checks 2026-09-07 17:28:45 -04:00
smoke_real_save.cpp game/sim: strategic formulas as pure functions (economy, research, colony, movement), 356 checks 2026-09-07 17:28:45 -04:00
test_colony.cpp S11 civilian growth; fix ComputeBudget's interest literals 2026-09-08 15:52:38 -04:00
test_construction.cpp game/sim + app: ship construction -- the build-queue completion bookkeeping, and S11's sub-pass wired in 2026-09-08 14:39:20 -04:00
test_economy.cpp L5: the interest literals verified live at a boundary, with a control that fails 2026-09-08 17:48:42 -04:00
test_movement.cpp movefleet: reproduce the original's float32 normalise; 8 of 45 live divergences -> 0 2026-09-08 03:50:04 -04:00
test_player_turn.cpp PL: decompose the /Sim/players residual; S00 PvSav snapshot; T31 recovers its difficulty column from the save; the bankruptcy protection factor is a widened float 2026-09-08 16:34:40 -04:00
test_research.cpp b3: research hook + RNG-snapshot compare design; fix draw mapping to y/(2^32-1), NextInt inclusive, float32 odds, spend floor, decay constants 2026-09-07 23:14:08 -04:00
test_scriptobjects.cpp SV: the script-object event bus, and what it writes in a turn 2026-09-08 16:46:25 -04:00
test_techgraph.cpp U: the SetResearched unlock cascade, and the prediction for the run that checks it 2026-09-08 06:26:00 -04:00
test_visibility.cpp lane E3: the per-system visibility record, the explored sweep and the system observed-stamp 2026-09-08 13:38:12 -04:00