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.
36 lines
4.3 KiB
JSON
36 lines
4.3 KiB
JSON
{
|
|
"entries": [
|
|
{
|
|
"name": "TradeSector_RecomputeStatusMasks",
|
|
"addr": "0x0088df90",
|
|
"convention": "thiscall",
|
|
"prototype": "void TradeSector::RecomputeStatusMasks(TradeSector* this, bool full) -- the writer of all three of the serialised sector masks, and of their `p`-prefixed previous copies. At 0x0088e031-0x0088e058 it copies tssec/tsct/tscr (+0x88/+0x8c/+0x90) into ptssec/ptsct/ptscr (+0x94/+0x98/+0x9c). Then: (1) tssec, written at 0x0088e0af, is the mask over players p of `TradeSector_GetPlayerStatus(this, players[p]) == 0`; (2) tscr, written at 0x0088e733, is the mask over players p of `players[p]->+0x100 != 0` -- the `CnRad` (Commerce Raiding) bool, so tscr is a PLAYER-TECH ROSTER and not a sector property at all; (3) tsct, written at 0x0088e73c, is the mask over players p of `players[p]->+0xff (CnTrd) != 0 AND (tssec >> p) & 1 AND (localMask >> p) & 1`, where localMask is OR'd over the triples FUN_00864670 returns for this sector. Players are StrategyServer+0x50..+0x54 and the bit index is the player's own index field, matching the news-post loop in Slot13RngCalleeB",
|
|
"status": "verified",
|
|
"source": "findings/control-flow/raid-intercept-z-word.md (lane CZ 2026-09-09); disassembled from dumps/sots.exe, cross-checked live against az-turn23-tarka-comraid.sav (tscr=127 over seven players all carrying CnRad=True) and against the 24-save AC lineage (tscr=253 over eight players with exactly one CnRad=False)"
|
|
},
|
|
{
|
|
"name": "TradeSector_GetPlayerStatus",
|
|
"addr": "0x00819f00",
|
|
"convention": "thiscall",
|
|
"prototype": "int TradeSector::GetPlayerStatus(TradeSector* this, ServerPlayer* p) -- returns a status code for one player in one sector; 0 means the player may trade here and is the value TradeSector_RecomputeStatusMasks turns into a tssec bit. 1 = p is null; 5 = p->+0xff (CnTrd) is false; 4 = the sector's member-system vector (this+0x78..+0x7c) is empty, or any member system fails FUN_00743880(sys, p); 2 = no member system counted as friendly; 3 = hostile-owned members outnumber friendly ones; 0 otherwise. Per member system: FUN_007469e0(sys) and sys->+0xc6 skip it; owner = sys->+0x100; FUN_00743fa0(sys) or FUN_0080ecb0(p, owner) counts it friendly, else hostile",
|
|
"status": "verified",
|
|
"source": "findings/control-flow/raid-intercept-z-word.md (lane CZ 2026-09-09); disassembled to the next function start from dumps/sots.exe"
|
|
},
|
|
{
|
|
"name": "TradeManager_GetNumRoutesSupportedFrom",
|
|
"addr": "0x008209e0",
|
|
"convention": "thiscall",
|
|
"prototype": "int TradeManager::GetNumRoutesSupportedFrom(TradeManager* this, TradeEndpoint* ep, ServerPlayer* owner, bool ignoreInfra) -- the top-of-loop gate in the route rebuilder's per-source helper (called at 0x0086494c, whose caller returns immediately when this is <= 0). Returns 0 unless: owner is non-null; the containing-sector table this->+0x0c indexed by ep->+0x4 (a system index) is non-null; and, for an owner whose Species != 4, the containing sector's tssec (+0x88) has the owner's index bit set. With ep->+0x8 == 0 the source is a SYSTEM and the system's own owner (sys->+0x100) must be this player, and the answer is min(FUN_00819d20(sys), FUN_00819dd0(sys, ignoreInfra ? 1.0f : sys->+0x88)); with ep->+0x8 != 0 the source is a station looked up in StrategyServer+0x80 and the answer is the global at 0x00af0c48",
|
|
"status": "verified",
|
|
"source": "findings/control-flow/raid-intercept-z-word.md (lane CZ 2026-09-09); disassembled from dumps/sots.exe"
|
|
},
|
|
{
|
|
"name": "TradeManager_BuildRoutesForSource",
|
|
"addr": "0x008648e0",
|
|
"convention": "thiscall",
|
|
"prototype": "void TradeManager::BuildRoutesForSource(TradeManager* this, vector<TradeRoute>* out, TradeEndpoint* from, vector<TradeEndpoint>* candidates) -- called once per source endpoint by ServerTradeManagerImpl_vslot9 (0x00868060). Returns with nothing appended when TradeManager_GetNumRoutesSupportedFrom(from, owner, true) <= 0 at 0x00864956. Otherwise, for each candidate `to`: FUN_0083a690(from, to) must pass and FUN_008194a0(&this->+0x3c, from, to) must find no existing route, and only then is a TradeRoute (vtable 0x00a2d848, 0x38 bytes) constructed and appended",
|
|
"status": "verified",
|
|
"source": "findings/control-flow/raid-intercept-z-word.md (lane CZ 2026-09-09); disassembled from dumps/sots.exe"
|
|
}
|
|
]
|
|
}
|