sots-re/findings/control-flow/raid-intercept-z-word.md
alex fb5a4148b3 lane CZ: predictions for the z word, committed before the run
Decodes the route-creation gate first (rule 28 practice 2): TradeSector.tssec
gates which player may source a trade route from a sector, and sector 768's
tssec is 0 for every player on az-turn23-tarka-comraid.sav -- so the briefed
Target 1 cannot be built there at all. The three sector masks are decoded and
reproduce all five sectors x seven players from the save; tscr turns out to be
the CnRad roster, which closes lane AZ's open item.

The workload switches to the alternative: player 0's own Tarka raiders parked
on the node of a sector that sources an AI route, which satisfies G_B3 by war
instead of by ownership.
2026-09-09 09:19:51 -04:00

256 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# `z` — the raid interception draw, measured
- **Type:** control-flow (static decode of the route-creation gate + live measurement of the draw)
- **Owner / date:** lane CZ · 2026-09-09 · guest **VM141** (`sots-re-win10-b`, 192.168.10.143)
- **Status:** *predictions committed; results below the line*
- **Decides:** the `z` term of lane AR's `k + s + z` tail model
(`raid-target-pick-verdict.md` §4.2), never observed through `Slot13RngCalleeB` by any lane;
and lane AZ's committed `k = 2` prediction on `az-turn23-tarka-comraid.sav`
(`raid-intercept-species-word.md` §3.3)
- **Instrument:** `draw_sites` at **`probes=8`** (`shim.cfg.hp8`, unmodified), shim build
`cz-e7e2bd6-dirty-20260909T1312Z`, built in `/srv/re-lab/build/sots-engine-cz` after an
`rm -rf` of the whole tree (rule 24), from lane worktree `~/sots-engine-cz` (branch `wip/cz`,
rule 21). **Never `probes=11`.**
---
## 1. Predictions, committed before the guest was touched (rule 2)
*Everything in §1 was written and committed before the game was launched, before any order was
given and before any counter was read. It is not edited afterwards — only annotated with verdicts
below the line.*
### 1.0 The brief's Target 1 is impossible on this save, and the conjunct that kills it is decoded
My brief names the cheap workload as:
> Give player 0 a trade route sourced at `Ku'Paaka` (system index 17) or `Ka'Palum` (index 26) —
> both player-0 colonies and both members of sector 768, where the AI's `Rho Fleet` is already
> parked. **No fleet movement is required.**
**That state cannot be reached on `az-turn23-tarka-comraid.sav`, and not for want of patience.**
Rule 28 practice 2 says to decode the gate before building the state it names, so I read the route
rebuilder from the instruction stream on the host before launching anything.
`ServerTradeManagerImpl::vslot9` `0x00868060` (already named by lane V2) rebuilds the route vector
every turn. Per source endpoint it calls `0x008648e0`, and that function's **first** act after
initialising its scratch list is:
```
008648e0 TradeManager::BuildRoutesForSource(this, out, from, candidates)
0086494c call 0x8209e0 ; GetNumRoutesSupportedFrom(from, owner, true)
00864954 test eax,eax
00864956 jle 0x864b01 ; <<< <= 0 : NOTHING IS APPENDED, ever
...
00864991 call 0x83a690 ; per-candidate pair predicate
008649a4 call 0x8194a0 ; route already exists?
008649b7 ... operator_new(0x38), vtable 0x00a2d848 -> push_back a TradeRoute
```
and `TradeManager::GetNumRoutesSupportedFrom` `0x008209e0` returns **0** unless
```
008209e0 if (owner == 0) return 0
00820a20 sector = ((TradeSector**)this->+0x0c)[from->+0x4] ; the per-system containing-sector
if (sector == 0) return 0 ; table lane AR found
00820a2b if (owner->Species != 4) {
00820a3b if (!(sector->+0x88 & (1 << owner->+0x28))) return 0 ; <<< TSSEC
}
00820a58 if (from->+0x8 == 0) { ; a SYSTEM source
if (sys->PID != owner) return 0
return min(FUN_00819d20(sys), FUN_00819dd0(sys, ...))
}
... a STATION source: the global at 0x00af0c48
```
`TradeSector+0x88` is the serialised **`tssec`** (`objects/layouts.md`
`Game::ServerTradeSector`). So **a player can only source a trade route from a sector whose
`tssec` bit it holds** — and on `az-turn23-tarka-comraid.sav`, `tssec` reads
| `TradeID` | `tssec` | `tsct` | `tscr` |
|---|---|---|---|
| 736 | **0** | 0 | 127 |
| 752 | **2** | 2 | 127 |
| **768** | **0** | 0 | 127 |
| 784 | **0** | 0 | 127 |
| 800 | **2** | 2 | 127 |
**Sector 768's `tssec` is 0 — for the AI as well as for me.** Player 0's bit is set in no sector
at all. So the route the brief asks me to create cannot be created, and no number of turns fixes
it by itself.
### 1.1 The three sector masks decoded, and verified against the save
Because a conjunct that blocks a briefed workload has to be more than an assertion, I decoded the
writer and checked it against every sector of every player in the save.
**`TradeSector::RecomputeStatusMasks` `0x0088df90` writes all three masks and their `p`-prefixed
previous copies** (`0x0088e031`–`0x0088e058` saves `tssec`/`tsct`/`tscr` into
`ptssec`/`ptsct`/`ptscr`):
| mask | offset | written at | value |
|---|---|---|---|
| `tssec` | `+0x88` | `0x0088e0af` | bit `p` set iff `TradeSector_GetPlayerStatus(this, players[p]) == 0` |
| `tscr` | `+0x90` | `0x0088e733` | bit `p` set iff `players[p]->+0x100 != 0` — the **`CnRad`** bool |
| `tsct` | `+0x8c` | `0x0088e73c` | bit `p` set iff `players[p]->+0xff (CnTrd) != 0` **and** `tssec` bit `p` **and** a local mask OR'd from the triples `FUN_00864670` returns for this sector |
**`tscr` is a player-tech roster, not a sector property.** That closes lane AZ's open item, which
recorded the writer of `TradeSector+0x90` as unfound and refused to guess (`§3.2`,
`raid-intercept-species-word.md`). This save has **seven** players and **every one of them carries
`CnRad = True`**, so the mask is `0b1111111 = 127`. Lane AC's lineage has **eight** players with
exactly one `CnRad` false — the AI at index 1 — so the mask is `0b11111101 = 253`, and 252 is the
same roster one turn before the human's own Commerce Raiding completed. Three values, one rule, and
the "NPC slots default set" reading in `gate-indexed-rng-audit.md` §3.3 and `raid-gate-multiplicity.md`
§4 is retired: the NPC slots are set because **the NPC factions have the tech**, not because they
are NPCs.
**`TradeSector::GetPlayerStatus` `0x00819f00`** — twelve exits, decoded to the next function start:
```
if (p == 0) return 1
if (!p->+0xff) /* CnTrd */ return 5
members = this->+0x78..+0x7c
if (members.empty()) return 4
unexplored = friendly = hostile = 0
for (sys : members) {
if (sys->Dstyd || (sys->vnh && sys->vnex3)) continue ; 0x007469e0
if (sys->vnh) continue
if (!((sys->EFlags >> p->+0x28) & 1)) unexplored++ ; 0x00743880
owner = sys->PID
if (owner) {
if (sys->indi != 0 || !AtWar(p, owner)) friendly++ ; 0x00743fa0 / 0x0080ecb0
else hostile++
}
}
if (unexplored > 0) return 4
if (friendly <= 0) return 2
return (hostile <= friendly) ? 0 : 3
```
`sys->+0xd0` is the serialised **`EFlags`**, `+0x100` is **`PID`**, `+0x1c8` is **`indi`**, and
`FUN_0080ecb0` is `a == b || PlayerAlliances_Relation(a, b) >= 1` — i.e. **not at war** — which
reuses lane T2's relation decode from the other side.
**Checked against the save, all five sectors and all seven players, and it reproduces exactly:**
| sector | predicted `tssec` | observed | player 0 status | AI (32) status |
|---|---|---|---|---|
| 736 | 0 | **0** | 4 (3 unexplored; friendly 3, hostile 0) | 4 (5 unexplored; friendly 0) |
| 752 | 2 | **2** | 4 (5 unexplored; **friendly 0, hostile 5**) | **0** (friendly 5, hostile 0) |
| 768 | 0 | **0** | 4 (5 unexplored; **friendly 3, hostile 9**) | 4 (2 unexplored) |
| 784 | 0 | **0** | 4 (3 unexplored; friendly 0, hostile 2) | 4 (1 unexplored) |
| 800 | 2 | **2** | 4 (2 unexplored; friendly 0, hostile 1) | **0** (friendly 1, hostile 0) |
Five sectors, seven players, thirty-five predicates, no disagreement.
**And it says exactly how dead Target 1 is.** In sector 768 player 0 holds **3** systems against the
AI's **9**. Even if I explored all five systems I have not surveyed there, `hostile (9) > friendly
(3)` returns **3**, not 0. The same arithmetic kills 752 (0 vs 5), 784 (0 vs 2) and 800 (0 vs 1).
**The only sector player 0 could ever qualify in is 736** — friendly 3, hostile 0, and only three
unexplored systems, all of them unowned and empty — and no AI fleet is parked at 736's node
(`tsnumflt = 0`). So the briefed "no fleet movement is required" route does not exist here, and the
cheapest state that reaches `z` is the one the brief lists as its **alternative**.
### 1.2 The workload I will actually build, named from the conjunct that survives
`G_B3` needs *a route owned by someone the raider is at war with*. Target 1 tried to satisfy it by
changing the **route**; I will satisfy it by changing the **raider**.
> **Park player 0's own Tarka raiders on the node of a sector that sources an AI route.**
Read from the save rather than inherited (the routes are `trfr = 4 → 9`, `trfr = 27 → 15`,
`trfr = 27 → 1`, all `tro = 32`, and `index = id/16 − 3` maps 4 to `Ke'Sothram` in sector **752** and
27 to `Keo'Va` in sector **800**):
| conjunct | how it is satisfied | evidence |
|---|---|---|
| G0–G2 fleet at a trade-sector node | order fleets to sector 752's node at `[0, 0, 8.0]` | AR's recipe |
| G3b raider's bit in `tscr` | `tscr = 127`, bit 0 set — player 0 has `CnRad = True` | §1.1 |
| G3c `FtFlg & 0x800` where armed | **not armed**: `tsct = 2` is the AI's bit, so `TradeSector_PlayerTradesHere(752, player 0)` is false | §1.1 |
| G4 `Pos` bit-equal | arrival at the node | AR §3.2 |
| `B` `flag` arm dead | `PlayerTradesHere` false ⇒ `FUN_0080ecf0` false ⇒ the diplomacy arm | AG §3.3 |
| G_B1b route sourced in this sector | `trfr = 4` lies in 752 | above |
| **G_B3 relation is 0 = war** | route owner is PID 32; player 0 and 32 both carry `AL = NA = CF = 0` | §1.4 |
| `SC1` route owner not Hiver | PID 32 is **species 2** | AZ §3.2 |
| `SC2` raider crew species not Hiver | player 0 is **species 2**, and `0x0081a2d0` returns the owner's species for a non-`_NPC` owner | AZ §1.2 |
| `SC3` `SpeciesDef[2]+0x144 == 0` | the flag word is written only for species 0 and 5 | AR §4.2 |
**Every conjunct is satisfied by a fleet move I control.** The build site is chosen from the save's
own geometry — distance from each player-0 system to sector 752's node, all three floats:
| player-0 system | idx | to 752's node | to 800's node |
|---|---|---|---|
| **`Ke'Rassak`** | **20** | **7.36** | 13.41 |
| `Kuo’Soro` | 16 | 9.85 | 15.08 |
| `Ku’Paaka` | 17 | 9.99 | 17.21 |
| `Kao’Thraal` | 0 | 12.31 | 17.33 |
| `Kea’Donum` | 3 | 13.16 | 17.15 |
| `Ka'Palum` | 26 | 13.93 | 18.24 |
A Tarka stock `Extended Range` destroyer has **Range 20.0** (lane AZ, from this game's own Build
screen), so **every one of the six is in range of 752's node** and five are in range of 800's.
Design `Extended Range` (`DesID 624`) is already in player 0's design list, and all six systems have
an **empty build queue**.
**The roll is per fleet, so I will build in several systems rather than splitting one stack.** A
fleet's odds are `0.05 + 0.01·nShips` for destroyers, doubled if a freighter shares the sector
(AC's read, undecided) — and **sector 752 holds the AI's `Freighters` fleet 3248**, so the doubling
is live here if it is live at all. Four two-ship fleets roll `4 × 0.07 = 0.28` per turn, or `0.56`
doubled; one eight-ship stack rolls `0.13`. Building two ships in each of four systems produces four
fleets **with no splitting at all**, which removes the right-click-menu step that cost lane AR time
and the staging error that cost lane AZ a 16-ship fleet.
**And I will not stage through a member system.** Lane AZ ordered a fleet to `Ku'Valt`, a sector-752
*member* system that is an AI colony, and lost sixteen destroyers to a real battle. The node is the
destination; nothing else is.
### 1.3 The numbered predictions
| # | prediction |
|---|---|
| **P0** | **`k = 2` on `az-turn23-tarka-comraid.sav` with the player owning no fleets** — lane AZ's committed prediction, taken as briefed. `Slot13RngCalleeA` is entered exactly **twice** on the first End Turn and `NextFloat 0x00820e18` reads `calls == words == 2`. The two are `Rho Fleet` (274, `LocID 768`, `FtFlg 0x80c`) and `Escorts` (3344, `LocID 752`, `FtFlg 0xc00`); `Freighters` 3248 and 4160 and `Nu Fleet IV` 1490 are rejected at G3c for lacking `FtFlg & 0x800` in a sector whose `tsct` bit is their owner's. Re-read from the save by this lane, not inherited |
| **P1** | **Neither AI raider can ever cost a word past `A`.** `Rho Fleet` stands on 768, which sources **no** route (`trfr ∈ {4, 27, 27}` lie in 752 and 800), so its `B` returns at **G_B4**. `Escorts` stands on 752, which sources one route — owned by its own player 32, so `PlayerAlliances_Relation` returns **3 for self**, `B` rejects at **G_B3** and the list empties, also G_B4. Two fleets, two different failed conjuncts, both at zero words |
| **P2** | **`tssec` gates route creation, and sector 768's is 0 for everyone**, so the briefed Target 1 is unreachable. Decoded at `0x00820a3b`; the mask's writer is `0x0088e0af`; the predicate is `TradeSector_GetPlayerStatus 0x00819f00`; and it reproduces all five sectors × seven players from the save (§1.1) |
| **P3** | **`tscr` is the `CnRad` roster.** Bit `p` is `players[p]->CnRad`, written at `0x0088e733`. 127 here (7 players, all true), 253 in the AC lineage (8 players, the AI false), 252 the turn before the human's tech landed. AZ's "the writer is unfound" is closed and the "NPC slots default set" reading is retired |
| **P4** | **`z` draws.** On the first turn one of my parked Tarka fleets succeeds, `draw_sites` shows **`NextFloat 0x00820c1b` `calls == words == 1`**, and the tail costs **`k + 2`** rather than `k + 1`. This is the first observation of that site through `Slot13RngCalleeB` in the campaign |
| **P5** | **The attribution is proved at the site, not at the bracket** (rule 23's corollary). A `0x00820c1b` row belongs to `B` on a turn where **`NextInt 0x008939ee` reads 0** — lane AZ's P6, whose static half is an image-wide `E8 rel32` scan finding exactly two callers of `FUN_00820af0`, with `0x0082cf65` reachable only through `CreateRaidEncounter`'s straight-line path past `0x008939ee`. If `0x008939ee` is non-zero on a turn I want to read, I will call that turn ambiguous and use another, not argue |
| **P6** | **The general model is `k + s + z` with `z = s`**, i.e. `OnAllCombatDone_Tail` costs **`k + 2s`** on this state, where `s` counts successes **by my fleets only** (P1 says the AI's two contribute nothing past `A`). Bracket residual **0** on every turn |
| **P7** | **`NextInt 0x0088b613` costs exactly one word per success.** Sector 752 sources one route, so `n = 1`, `bound = 0`, the mask smear gives 0 and `RNG_NextInt` cannot reject (AG §3.3, read in full). On sector 800, `n = 2`, `bound = 1`, mask 1, also exactly one. **If the AI's route set changes under me so that a target sector sources three or more, the rejection loop goes live and I will report `words > calls` rather than hide it** |
| **P8** | **A success displaces the raider off the node** (`fleet->Pos = out` at `0x0088b672`, AR §4.3), so `k` **falls by one** on the turn after each of my successes, and each fleet contributes at most one success per parking. The same applies to the AI's `Escorts` on 752 — if it succeeds, `k` drops to 1 + mine even before I arrive |
| **P9** | **The `hooks=off` control will NOT agree with itself.** Rule 26 corollary (c)'s screen fires: `Player[32]` (`Fane Kona`, `PlyrIdx 1`, `NumOwn 17`, `NumDes 58`, an AI player that runs) enters the turn with **`ResTNm == ''`**, which is a research-pick turn. I expect variation confined to `Player[32]`'s `TechTree` leaves and the derived `/Summary/Checksum`, and I expect **`/Sim/trdmgr`, the five `Trade` records and `/Sim/fleets` to be sub-tree identical** across processes — which would leave `k`, the route set and the raid arm reproducible even though the whole-save hash is not. **I am predicting the sub-trees my measurement depends on, in advance, so that "the control varied" cannot be turned into "the measurement is fine" after the fact.** Note (c)'s own restatement: `ResTNm == ''` predicts that a pick is *made*, not that it *varies*, so an agreeing control would not surprise me either |
| **P10** | **The AI-client roster is `{32, 496, 512}`** — three clients out of six non-human players — by lane BP's rule that the NPC factions at net ids 528 and above get no client. `528 Peacekeeper Enforcer`, `544 Von Neumann` and `560 Independent Colony` carry `ResTNm == ''` **and** `NumOwn == 0` **and** no client, so their signature is inert. **This is an inference from another save and I will label it as one unless I measure it** with an `aiseed=log` process |
| **P11** | **Not settled by this lane, predicted in advance** (rule 15): the freighter doubling of the raid odds (one or two successes cannot separate 0.07 from 0.14); `design+0x12c > 1`; `bestScale`; the `0x0088b613` rejection loop at `n >= 3`; whether `SC2` (a Hiver raider) is reachable at all; and the leaf semantics of `FUN_00819d20` / `FUN_00819dd0`, the two route-count sources `GetNumRoutesSupportedFrom` takes the `min` of |
### 1.4 The falsifier, stated as the sentence I will have to write
> **If one of my parked Tarka fleets succeeds — `Slot13RngCalleeB` is entered, `NextInt 0x0088b613`
> fires for one word, `0x008939ee` reads 0 — and there is still no `NextFloat 0x00820c1b` row,
> then `SpeciesDef+0x144` is not the whole gate**, and the two short-circuits ahead of it become
> the live suspects: `owner->+0x5c == 1` on the route owner (checkable in the save: PID 32 carries
> `Species 2`) and `FUN_0081a2d0(fleet) == 1` on the raider's crew species (checkable the same way:
> player 0 carries `Species 2`). If both check out, the static decode that three lanes have now
> read the same way is retired, and the interesting question becomes what `0x0053baf0` actually
> reads.
And the other direction, which is the more likely negative:
> **If `Slot13RngCalleeB` is never entered with a non-empty candidate list**, I will report *which*
> conjunct failed by reading it out of the turn's own autosave — `LocID`, all three floats of `Pos`
> against the sector's, `FtFlg`, the sector's `tsct`/`tscr`, and the live `trfr` set — and not as
> "the species word did not fire". A negative without a named conjunct is "not reached in the states
> measured", which is a different sentence (rule 28 practice 1).
### 1.5 What could go wrong with the workload, and the symptom of each
| way it fails | symptom |
|---|---|
| the AI's route set moves and 752 stops sourcing a route | `trfr` in the per-turn autosave no longer contains 4; `B` entered, 0 words, G_B4 — mitigated by also sending fleets to 800's node |
| a sector I target starts sourcing three or more routes | `0x0088b613` `words > calls`; reported, not hidden (P7) |
| the node cannot be aimed at from the default camera | AZ's §6: the Move-mode hover snaps to the nearest **system** over >100 px. Sector 752's node is 2.4 ly from `Ke'Sothram`. **`rdrag` rotates the star map** — rotate first, then aim, and confirm from the hover readout (`Sector 2 / Range / ETA`) before committing |
| a fleet is intercepted in transit | it dies; the arm shrinks. Fleets are ordered **to the node**, never through a member system (AZ's §6 cause 1) |
| an encounter query blocks a scripted End Turn | the driver polls the **autosave mtime**, never a button colour, and **stalls with a screenshot** rather than clicking blind. AZ lost a 16-ship fleet to a blind `Auto Resolve Peacefully` sequence, and `Auto Resolve Peacefully` means "I commit no ships", not "no combat occurs" |
| the control varies | expected (P9). Localise by sub-tree with `state_checksum.py --tree` and state which leaves the measurement depends on |
---
*Results, and the verdicts, follow below. Nothing above this line is edited after the run.*