sots-engine/docs/AC-predictions.md

14 KiB
Raw Blame History

Lane AC — predictions, written before the workload was built

Rule 2. Committed before the game was started, before the first End Turn, and before any probe counter was read. Guest VM141 (sots-re-win10-b, 192.168.10.143), starting from lane L3's human-turn15-spyprogram.sav.

The question: does the strategic-turn tail draw RNG when the trade and spy containers hold active contents rather than merely present ones? Lane L3 retired lane W3's risk for populated containers; the residual condition it named is freighters in service (tsnumflt > 0) and a deployed spy (spyon != 0).


0. One fact from the save that changes the prior before anything is run

Lane L3's §3.5 says "every trade sector has tsnumflt = 0 — no freighters in service". Read out of the save L3 shipped, that is not true. human-turn15-spyprogram.sav, trdmgr, sector TradeID 816 (tsgridID 5):

tssec 2   tsct 2   tsnumflt 1   tsflt 2736

and the fleet with id 2736 is Freighters, PID 32 — the AI's. Its six member systems (tssys 192, 288, 304, 336, 352, 464 → indices 9, 15, 16, 18, 19, 26) are all AI-owned. The single serialized route record trdmgr.rt (tro 32, trfow 1, trto 16, trtow 1, trfr 18, trtc 10) is likewise the AI's.

So across L3's seven instrumented turns the game already had a trade sector with a freighter in service and an active route, and TradeManager::Slot13RngCalleeA/B were entered 0 times anyway. The five sectors with tsnumflt = 0 are the ones the human player owns or shares.

This does not make the experiment pointless — it sharpens it. It rules out "any freighter anywhere" as the gate before I spend a turn, and it means the surviving trade-side hypotheses are narrower: a per-player gate, a count threshold, a route-state condition (TROUTESTATUS_* is Inactive/New/Developing/Established/Shutting Down), or the raid-candidate list being the thing that is empty rather than the roll being un-taken.


1. Predictions

P1 — the trade half (primary)

Freighters in service on the human player's own trade sectors will NOT make TradeManager::Slot13RngCalleeA (0x00820ca0) or Slot13RngCalleeB (0x0088b440) fire. Both stay at calls = 0 on every instrumented End Turn, while ServerTradeManagerImpl::vslot13 (0x0088ef80) and vslot15 (0x0082cca0) stay at exactly 1.

Confidence: moderate-to-high, and it rests on §0 rather than on L3's stated reason. An AI freighter has already failed to trip it for seven turns; the only way a human freighter trips it is if the gate is per-player, which is possible (vslot13 may loop players) but is not the simplest reading of "entered once per turn".

Falsification and its symptom. If A or B reports calls >= 1 on the first turn after tsnumflt goes non-zero on a human sector, P1 is dead and the answer to the lane's question is "yes, the tail draws under active contents". Symptom: a non-zero calls in the probe_entries table on the post-turn Autosave record, with installed = true on that row.

P2 — the trade half, second order

If P1 holds, then either (a) the gate is not "a freighter exists" at all, or (b) it is a threshold above 1. I predict (a). Falsifier: if the callees fire only once the human side reaches TRADE_ROUTE_MAX_FREIGHTERS = 5 on a sector, (b) is right and P2 is wrong; symptom is a step change in calls exactly at the turn tsnumflt reaches 5.

P3 — the spy half

A deployed spy (spyon != 0, tdep >= 0, spyat set) WILL make SpyManager::Slot13RngCallee (0x008408e0) fire, at 1 entry per turn per deployed spy.

Confidence: low-to-moderate, and deliberately opposite in sign to P1. The reason to split them is that the spy path has a per-turn stochastic element the trade path does not obviously have — sdet ("spy detection", −1 in the save) and deat are per-spy fields that a deployed spy must have rolled for each turn, and a detection roll is exactly the shape of thing Slot13RngCallee would be. cbh, cm, cmo, ncp are all still zero on the undeployed spy.

Falsification. If a spy reaches spyon != 0 and Slot13RngCallee still reports calls = 0 on the following End Turn, P3 is dead and both containers are confirmed inert at every reachable state — which closes lane W3's risk outright. Symptom: calls = 0 with installed = true on that row while the save shows spyon != 0.

P4 — spies2

spies2 will become non-empty in exactly the system a spy is deployed at, and nowhere else. i.e. spies2 is a per-system spy list and it fills only for a deployed spy. That is the second of the two readings L3 left open, and it is the one I expect.

Confidence: moderate. spies2 sits on ServerSystem, and a built-but-docked spy has no system to belong to (tdep = -1, spyat = 0), so a container keyed by system cannot hold it.

Falsification. If a spy is deployed and spies2 is still 0 in all 28 systems, then spies2 is not the spy list and the first reading is right; the rule-6 flags on spies2, SysMem and mts stay up and the field needs a different explanation. Symptom: post-deploy save parses with spies2 count 0 everywhere while spymgr.spy.spyon != 0.

P5 — reachability of the active spy state at all

Deploying a spy in this save may be unreachable, and if so I will say so rather than infer. The engine's own refusals require a system that is not mine, has no enemy fleet present, has no spy already, and has an asteroid belt. ARes2 on ServerSystem is the asteroid-resource field (its non-zero values 1703–2531 sit inside SYSTEM_MIN/MAX_ASTEROID_RESOURCES 1500–3000). In the turn-15 save only five of 28 systems have ARes2 > 0:

idx id name ARes2 owner
1 64 Ka'Palum 2061 unowned
4 112 Regulus 1703 unowned
10 208 Kam'Tara 1948 unowned, AI fleet present (Omikron Fleet II, 4 ships)
12 240 Downbelow 2172 mine
27 480 Hitomi 2531 player 576, AFlags 128, position (0,0,0)

No AI-owned system has an asteroid belt. So the textbook target — an enemy colony with a belt — does not exist here. I predict the reachable routes are, in order: deploy at an unowned belt system (Regulus is 9.01 ly from the tender's berth at Epsilon Eridani against a hull range of 9.0, so this is marginal and node travel may or may not save it); or wait for the AI to colonize Kam'Tara, where it already has a fleet, and deploy once its fleet leaves.

Falsification. If the Special menu offers Deploy Spy at an unowned belt system, P5's pessimism is wrong and the path is short. Symptom: the menu entry is enabled and the action is accepted.


2. What would make me wrong about the whole framing

  • The outer callees may not iterate the containers that were measured. vslot13/vslot15 are entered once per turn regardless of container contents, which is equally consistent with their loop being over players or over encounters and the trade/spy containers being read further in. If so, "active contents" is the wrong axis entirely and no workload on these two vectors will ever trip the inner callees. Symptom: a static read of the gate shows a predicate on neither container.
  • The instrument may not be armed. probes=11 is L3's config and is line-for-line comparable with lane H, but lane H bisected probes=11 as not determinism-neutral (the detour on probe index 8, GenerateTradeRaidEncounters, suppresses a draw elsewhere). probes=8 is the largest proven byte-neutral configuration and it still installs indices 0–7, i.e. all four outer callees and all three inner ones. I will take the primary reading at probes=8 for that reason and cross-check at probes=11 for comparability, and I will report installed= for every row rather than a bare zero (rule 20; and lane L3's own hooks=off watch=on defect is the worked example of a config that reports a confident nothing).
  • A control that does not agree with itself is not a control (rule 26). The watch=on/watch=off pair goes on ref-turn2.sav in two fresh processes before any workload number is trusted.

3. Addendum — written after the static decode of the gates, before any measurement of an active state

The gates on all three inner callees were decoded out of the instruction stream (sots.exe, image base 0x00400000) before the workload was played. That changes what is worth measuring, so the new predictions are written here rather than fitted afterwards. Nothing below had been measured when it was written; the only live readings so far are the VM141 determinism-oracle control (matched the published hashes exactly) and the shim banner showing the watchpoint module armed.

The decoded gates

Slot13RngCalleeA (Q, 0x00820ca0) and Slot13RngCalleeB (R, 0x0088b440) are called directly from ServerTradeManagerImpl::vslot13 (0x0088ef80) at 0x0088f036 and 0x0088f042. That function does not iterate trade routes or trade sectors — it iterates StrategyServer+0x64..+0x68, the fleet vector, and for each fleet requires:

  • StarFleet+0xa0 (LocID) to resolve to a node whose kind word (node+0x14) is 2. Kind is set by the StarMapNode(int) ctor: StarSystem passes 0, StarFleet 1, TradeSector 2. So the fleet must be located at a trade-sector node, not at a star.
  • the fleet's Pos (+0x18) to be bit-equal to the sector's Pos — arrived, not in transit.
  • sector+0x90 (tscr) to have the fleet owner's player-index bit set;
  • and if sector+0x8c (tsct) also has that bit, the fleet to carry FtFlg & 0x800.

SpyManager::Slot13RngCallee (P, 0x008408e0) is called from ServerSpyManager::vslot13 (0x008877b0) at 0x00887af2, behind: deat != 0 (deployed at a real system), sdet != -1 (already detected on an earlier turn), turn - sdet >= 3, the system still owned, and owned by someone other than the spy's owner.

P6 — the trade half is structurally closed to both real players in this save

tscr is 252 = 0b11111100 on all six sectors of human-turn15-spyprogram.sav, and the save has eight player slots: index 0 re (human), index 1 The Eternal Empire (AI), and indices 2–7 the six NPC = true slots (Spengler ×2 rebel-AI, Alien Menace, Peacekeeper Enforcer, Von Neumann, Independent Colony). 252 is exactly the NPC set and excludes both real players.

So I predict: parking a player-owned fleet exactly on a trade-sector node — even flagged as a raider — will NOT make Q or R fire. Trade raiding is an NPC mechanic; TRADE_RAID_ODDS_NPC and TRADE_RAID_ODDS_REFUGEE exist for that reason and TRADE_RAID_ODDS_PLAYER is what a raid against a player pays.

Falsifier: Q reports calls >= 1 on the turn after a player fleet is parked on a sector node. Symptom: non-zero calls on the TradeManager::Slot13RngCalleeA row with installed = true. That result would kill the tscr-is-a-player-mask reading and reopen the ledger.

This is the experiment worth running because it separates two explanations that seven turns of L3's workload could not: "no lane ever parked a fleet on a sector node" versus "players are excluded by tscr". The AI's own Freighters fleet (LocID 816, the id of trade sector TradeID 816, Pos bit-equal to that sector's) already passes the node-kind and position gates and is still rejected — which is the first evidence for the mask reading and is why P6 is stated with confidence rather than as a coin flip.

P7 — the spy half WILL make the tail draw, but not through an entry probe

This is the prediction that matters most, and it is the one L3's instrument could not have seen.

The sdet == -1 arm of vslot13 (taken at 0x00887856 → 0x00887c5b) is the detection roll: it calls FUN_0081f570(spy, system, owner), tests FUN_00743f80(system) & 1, and on that bit rolls FUN_008e6dd0(StrategyServer+0x16c /* RNG */, spy->sdo), then stamps sdet = turn and posts EVENT_SPY_DETECTED. That roll is inline in the outer callee, not inside P.

But it is unreachable today because the gate before it is deat != 0 at 0x0088781d, and the corpus spy has deat = 0 (tdep = -1, spyon = 0, docked to its tender).

So: deploying the spy is predicted to make OnAllCombatDone_Tail consume more RNG words per turn than it does with the spy docked, while all three inner-callee entry probes still read 0. Roughly one extra draw per deployed spy per turn, conditional on FUN_00743f80(system) & 1.

If that holds, the honest headline is yes, the tail draws under active contents — the RNG ledger and the standalone's generator model do need extending — and the reason seven instrumented turns said otherwise is that the probe table measures entry into P/Q/R while the draw lives in the outer function. That is rule 20 pointing the other way: instrumenting the entry is necessary and was not sufficient. The primary measurement is therefore the side.rng word delta on OnAllCombatDone_Tail, not the probe counts.

Falsifier: the tail's word delta is unchanged after deployment. Symptom: identical rng.after.words - rng.before.words on the tail hook across the docked and deployed turns of the same save lineage.

P8 — where the spy can go

ARes2 is the asteroid-belt field, and the only non-own system with a belt in this save is Hitomi (idx 27, id 480, ARes2 2531), owned by player index 7 Independent Colony (AFlags 128). Not the AI. So the deploy target, if one exists at all, is Hitomi — two fleet moves from the tender's berth at Epsilon Eridani via Aldebaran. If Hitomi is undiscovered or unreachable, the active spy state is out of reach in this save and I will report that rather than infer around it.