The strategic AI does not search or score. Once a turn (Process Turn phase 20, 0x006cf630) it
rebuilds a candidate task list -- which families it builds at all is a switch on the player's
SPECIES, four arms, and the NPC arm builds nothing -- sorts it by a per-task-type priority, and
walks it twice calling each task's Execute(agent, pass) with pass 0 then 1.
Closed from lane AI1's open list:
* the selection loop (its item 2) and the whole ordering policy: a 33-entry priority table at
0x00691f00 plus five named overrides;
* IAITask's unnamed pure virtuals (item 1) -- seven, not eight: GetTypeId, GetTargetA/B,
Execute, IsFinished, GetTypeName, Describe;
* the order-method -> list mapping (item 5): all 27 of lane Q's lists and all six prologue
gates now have a named producer, and list 14 -- lane Q's "observed but not understood" --
is the AI's fleet order, two elements per fleet;
* g_CurrentClientIndex (item 6): a stack pointer with exactly two writers, pushed around the
whole AI turn by StrategyAIAgent::OnEvent;
* the think-time throttle (item 7): AIProcessMinTime is a trailing Sleep, not a compute
budget. Every pending AI player's turn runs back-to-back inside one Update. The clean
"all AI orders in before the human's End Turn" ordering HOLDS, and Rung B is not at risk;
* Broadcast -> OnAIPacket, read to the call -- AI1's one inferred hop is now verified.
Corrections: 31 concrete task classes, not 34; 26 order methods, not 21; seven pure virtuals,
not eight. lane-ai1.json's Broadcast and g_CurrentClientIndex entries upgraded in place.
Open and said so: slots 11/12/13 unnamed, the nine goal tasks' bodies unread, the two-pass
meaning inferred, the StrategyApp pending-AI enqueue site not found, nothing run under an
instrument. Four predictions in section 9, P1 being a ModCount prediction.
ghidra/addresses.d/lane-ai2.json: 25 entries, 1031 -> 1056, no duplicates.
|
||
|---|---|---|
| .. | ||
| lane-a.json | ||
| lane-a2.json | ||
| lane-ai1.json | ||
| lane-ai2.json | ||
| lane-b5.json | ||
| lane-d2.json | ||
| lane-e1.json | ||
| lane-e3.json | ||
| lane-g2.json | ||
| lane-h.json | ||
| lane-i.json | ||
| lane-j.json | ||
| lane-k.json | ||
| lane-n.json | ||
| lane-o.json | ||
| lane-p2.json | ||
| lane-q.json | ||
| lane-t.json | ||
| lane-u.json | ||
| lane-v2.json | ||
| lane-w.json | ||
| lane-z.json | ||
| README.md | ||
Per-lane address fragments
addresses.json is a single shared file. When several lanes run concurrently they edit the
same lines, and three times on 2026-09-08 one lane's git add swept another's in-flight
entries into the wrong commit. Nothing was lost, but authorship and atomicity were.
A lane may instead drop its own file here:
{ "entries": [ { "name": "...", "addr": "0x...", "convention": "...",
"prototype": "...", "status": "verified", "source": "findings/..." } ] }
Name it after the lane (lane-d.json). tools/gen_addresses.py merges every fragment in
sorted order after addresses.json. A duplicate name across files is a hard error, not
last-wins — two lanes disagreeing about an address is exactly the thing we must not paper over.
The integrator folds fragments back into addresses.json once the lane's work is merged.