sots-engine/include/generated
alex e1995e6b11 PAR: roll parity -- the AI's per-turn RNG word count is NOT fixed, at any scope
New shim module `ai_rng`: a bracket on StrategyClient::OnResumePlaying over the per-client
generator at +0x134, with two independent measurements per bracket (an observer on the existing
seven draw-site detours, and `left` read straight off the object) plus AI-call-site attribution
through the cl_* facades and an optional seed pin.

Measured on VM140/VM145, six runs, five fresh processes, unpinned autosaves byte-identical to the
published oracle:

  turn2->turn3   human 0, AI 32 -> 3 words, AI 496 -> 0, AI 512 -> 0
  turn1->turn2   human 0, AI 32 -> 7 words, AI 496 -> 0, AI 512 -> 1 word ... or 3

The last row is the answer: 512 makes ONE cl_RandRange call (the research-target tie-break at
0x006a8495, phase 18) and that one call cost 1 word in one process and 3 in another, because
RNG_NextInt is an unbounded rejection loop. The count is not fixed across clients, across turns,
or across processes with the path held fixed.

Also found: cl_RandFloat 0x00579c70, a third cl_* RNG facade that reaches RNG_NextFloat by a TAIL
JUMP and so leaves no rel32 edge for a call-graph sweep -- which is why ai-turn-logic.md 5's "zero
NextFloat calls from the AI module" reads as true when it is not.

The instrument caught its own defect: RNG_Chance calls RNG_NextFloat and both are detoured, so a
drawn word was reported twice. left_delta was never affected, which is the point of having two
measurements.

Gates run separately on a fresh build directory: clean_room_check OK, host ctest 55/55, CT111 shim
cross-build OK.
2026-09-08 19:32:19 -04:00
..
sots_addresses.h PAR: roll parity -- the AI's per-turn RNG word count is NOT fixed, at any scope 2026-09-08 19:32:19 -04:00
sots_stream_schema.h sync generated headers (669 addresses) after aiagent merge 2026-09-08 07:36:15 -04:00