227 lines
14 KiB
Markdown
227 lines
14 KiB
Markdown
# 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.
|