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.
56 lines
2.5 KiB
Text
56 lines
2.5 KiB
Text
# Lane PAR -- ROLL PARITY. THE THREE CONFIGS parctl / parbr / parpin DIFFER BY ONE KEY EACH.
|
|
#
|
|
# parctl airng=off the rule-19 control
|
|
# parbr airng=on the bracket, UNPINNED (the game's own seeds)
|
|
# parpin airng=on + airng.pin_seed=<hex> the bracket with the client generator re-seeded
|
|
# at bracket entry, so two runs start identical
|
|
#
|
|
# parctl and parbr must produce the SAME autosave. parpin is EXPECTED to differ -- it deliberately
|
|
# changes the AI's random stream, which is the experimental variable, and its autosave is never
|
|
# compared against the published oracle (method rule 19: the perturbation is intended, declared and
|
|
# confined to one configuration).
|
|
#
|
|
# Every template hook is off: this lane wants nothing in the log but the bracket. The seven
|
|
# draw-site detours are installed by main.cpp whenever hooks != off and are therefore present in
|
|
# ALL THREE configs, which is what makes the pair a real single-key control.
|
|
hooks=trace
|
|
hook.Shim::SelfTest::Fill=off
|
|
hook.Mars::GlobalConsts::LoadFile=off
|
|
hook.Game::WeaponDictionary::Init=off
|
|
hook.Game::SectionDictionary::SectionDictionary=off
|
|
hook.Game::TechTree::ProcessResearch=off
|
|
hook.Game::ServerPlayer::ComputeBudget=off
|
|
hook.Game::ServerPlayer::OnTechResearched=off
|
|
hook.Game::ServerPlayer::ProcessTurn=off
|
|
hook.Game::ServerSystem::ProcessTurn=off
|
|
hook.Game::ServerSystem::GroupOutput=off
|
|
hook.Game::ServerSystem::ComputeTotalOutput=off
|
|
hook.Game::StrategyServer::MoveFleet=off
|
|
hook.Game::StrategyServer::ProcessFleetMovement=off
|
|
hook.Game::StrategyHost::Autosave=off
|
|
hook.Game::StrategyServer::ProcessTurn=off
|
|
hook.Game::StrategyServer::OnAllCombatDone_Tail=off
|
|
hook.Game::StrategyServer::ApplyEncounterResult=off
|
|
hook.Game::StrategyServer::NodeLineDecay=off
|
|
hook.Game::StrategyServer::ProcessNodeSpaceTravel=off
|
|
hook.Game::EncounterDetect::AssignContacts=off
|
|
hook.Game::EncounterDetect::ProcessTeamRecord=off
|
|
hook.Game::StrategyServer::BeginProcessTurn=off
|
|
hook.Game::SVSOSwarmQueen::OnTurnBegin=off
|
|
hook.Game::SVSOSwarmQueen::RegisterHives=off
|
|
hook.Game::SVSOSwarmQueen::TickHives=off
|
|
hook.Game::SVSOSlaversRefuel::UpdateDifficultyTier=off
|
|
hook.Mars::RNG::Seed=off
|
|
hook.Game::StrategyApp::RunAI=off
|
|
fpu.sample_turn=off
|
|
fpu.sample_ticks=off
|
|
probes=off
|
|
watch=off
|
|
aiorders=on
|
|
aiprobes=off
|
|
airesearch=off
|
|
trace.path=C:\SOTS\shim.trace.jsonl
|
|
trace.flush=always
|
|
airng.out=C:\SOTS\shim.airng.txt
|
|
airng=on
|
|
aiorders.out=C:\SOTS\shim.aiorders.txt
|