Three lanes could not build this workload. VM144 built both halves from a cold main
menu on a stock, unmodified install -- no data file touched, no save edited -- and the
answer to the question they were built to ask is no.
TRADE. The premise everyone carried, that trade needs station construction plus its
tech, is wrong about the station: StrategyVars.txt makes a trade station a +2-routes,
+25%-income bonus, and NumTradeRoutesSupported has a floor of 1 per owned system, so
the population thresholds scale the count and do not gate it. The gate is one tech,
CCC_FTLEcon, and Zuul cannot research it at all. 20 routes and 6 trade sectors by
turn 4; 21 by turn 13.
SPY. Lane W3: "no lane has identified which UI produces a spy-program entry." It is
the fleet panel's Special menu, and the reason nobody found it is that the ship a spy
docks with is the Cruiser REPAIR AND SALVAGE mission section -- nothing in the UI
calls it a tender or mentions spies. Prediction S1 holds: the container grows at Build
Spy while the craft is still docked (tdep=-1, atto=<tender>), so no enemy colony and no
asteroid belt are on the critical path, which is what every earlier cost model assumed.
THE MEASUREMENT. With 21 routes, 6 sectors and 1 spy craft live, lane H's eleven entry
probes report the four outer tail callees entered exactly once per turn, as always, and
SpyManager::Slot13RngCallee, TradeManager::Slot13RngCalleeA and CalleeB entered ZERO
times -- this turn and across all seven instrumented turns, every probe installed=true.
The RNG ledger and the standalone's generator model do NOT need extending on account of
either container being non-empty. The next condition is active contents, not present
contents: tsnumflt=0 on every sector and spyon=0 on the spy.
WHAT ELSE FELL OUT. The trade-route vector is torn down and rebuilt every turn inside
ServerTradeManagerImpl::vslot9 (lane V2's phase-23 call 5 of 8, previously "draw-free"
and unexplained) -- an agreement, dropped rather than re-minted, as is the AI2 growth
helper. Two addresses are minted, both trapped live and both `mapped` not `verified`
because ReVa was unreachable: ShipAction_BuildSpy 0x00789620, a sibling of lane B6's
stack-built-fptr-table entry 0x120 bytes away, which is why no call-graph sweep ever
found this writer; and ServerSpyManager_CreateSpyCraft 0x008383c0.
And a correction with teeth: `spies2` is 0 in all 28 systems of a save that DOES have a
spy. The natural reading of lane W's count-0-in-11-saves was "no save has ever had one".
That reading is dead; spies2 is not the spy list, or it only fills for a deployed spy.
The research click path is written down for the first time (§4): clicking a tech node is
a PREVIEW, the bottom-left button confirms, Esc leaves without confirming, and the tree
pans only on a right-drag of about 600 px. That, not the tech cost, is what stopped
three lanes.
Saves: human-turn{5,8}-traderoutes, human-turn11-spytechs, human-turn15-spyprogram --
all --strict clean, 0 errors, 0 warnings.
24 KiB
The trade-route and spy-program workload
Lane L3, 2026-09-08. Guest VM144 (sots-re-win10-144, re@192.168.10.144, a ZFS clone of
VM140). Shim builds l3cont-0117495-20260908T2107Z and l3cont2-0117495-20260908T2124Z.
Three lanes failed to build this workload. This one built both halves, from a cold main menu, in one session on a stock unmodified install. The headline result is nevertheless a negative one, and it retires lane W3's open risk rather than confirming it.
0. Summary
| question | answer |
|---|---|
| Can the trade-route vector be made non-empty? | Yes. 20 routes, 6 trade sectors, from turn 4 of a stock custom game; 21 by turn 13. |
| Can the spy-program vector be made non-empty? | Yes. count=1 on turn 14, from the fleet panel's Special -> Build Spy. |
| Do saves now exist? | Yes. Four, all --strict clean: human-turn5-traderoutes.sav, human-turn8-traderoutes.sav, human-turn11-spytechs.sav, human-turn15-spyprogram.sav (both containers non-empty). |
| With 21 routes and a spy program live, do the four tail callees draw RNG? | No. All three inner RNG-bearing callees are entered 0 times, this turn and cumulatively across 7 instrumented turns. |
| Does the RNG ledger / standalone generator model need extending? | No -- not for either container being non-empty. The gate is deeper than "the container is empty", and §3.5 names the next condition. |
1. Why the previous lanes' cost estimate was wrong
tail-probes.md §3.2 and every brief since carried this premise: trade income needs
trade-station construction plus its tech, which from ref-turn2 is tens of 30-60 s End Turns.
Both halves of that are wrong, and the second one is wrong for a reason worth stating.
A trade station is not a prerequisite. Read out of Data/Strategy/StrategyVars.txt (inside
sots.gob, which is a plain ZIP):
STATION_BONUS_TRADE_INCOME 0.25 // Increases value of system trade routes.
STATION_TRADE_NUMROUTES 2 // Routes possible with trade station.
A station adds two routes and a 25 % income multiplier. The gate is one tech, CCC_FTLEcon,
which sets ServerPlayer+0xff (CnTrd); StrategyServer::RegisterTradeSystems 0x007adc80 then
registers ServerSystem::NumTradeRoutesSupported 0x00819d20 slots for every owned system, and
that function has a floor of 1. The population thresholds
TRADE_ROUTE_REQ_CIVPOPULATION 200000000
TRADE_ROUTE_REQ_IMPPOPULATION 500000000
scale the count; they do not gate it. And they were never close to binding anyway: the
reference game's own homeworld at turn 2 already reads Civilian 520,000,000 / Imperial 2,000,000,000, i.e. 3 + 4 = 7 route slots from the homeworld alone.
The real cost was the tech, and the real obstacle was the research UI. See §4.
2. The recipe that worked, end to end
Stock game, stock data files. Nothing in sots.gob or any loose data file was modified, and no
save was edited; the resulting saves are legitimate corpus members.
- Main menu ->
Single Player(512,449) ->Custom(445,357) ->OK(551,451). - On Custom Game Setup the sliders respond to a plain click on the track. The ones that
matter, and what previous lanes did not know existed:
Initial Colonies10 (max) - ten developed systems at turn 1;Initial Treasury9,850,000 (max);Initial Technologies15 (max) - random techs, and the roll includedCCC_FTLBrdB, which is the parent of bothCCC_FTLEconandCCC_SpyBm;Research Efficiency146 % (max),Economic Efficiency148 % (max);Number of Stars28,Distance5 ly (min) - so systems fall inside oneTRADE_SECTOR_SIZE 10.0cell;- species Human (
CCC_FTLEconisZuul:0inMasterTechList.tech- a Zuul game cannot do this at all), 2 players. Player species defaults to Random: set it explicitly on the launch screen via the card'ssetupbutton (359,486) ->Select Speciesdropdown (557,117).
- Research
CCC_FTLEcon. One turn at these settings. - End Turn. The routes appear on the next End Turn's arming.
Turn 4 -> 5 was the first End Turn with a non-empty container. Total elapsed from a cold main menu: about 50 minutes, most of it spent on §4.
3. The measurement
Instrument: watch.mode=cont, a third mode added to lane W3's watchpoint module
(src/shim/hooks/watchpoints.cpp). Same single arming detour on
StrategyServer::ApplyAllTurnCommands (RVA 0x0038f6a0), same VEH, same canary. Two changes:
all four debug slots go on the two ends of the two containers (_Myfirst and _Mylast, so an
allocation and an append are separable), and it re-arms and re-logs on every End Turn instead
of only the first.
3.1 The control (rule 19)
shim.cfg.l3cont and shim.cfg.l3control differ in exactly one key, watch=. Both were run on
ref-turn2.sav, one End Turn each, on VM144:
| run | (Autosave EndTurn).sav |
(Autosave).sav |
|---|---|---|
watch=off |
bb4fd9ac89f41e3b… |
978041acd168b56e… |
watch=on |
bb4fd9ac89f41e3b… |
978041acd168b56e… |
| published oracle | bb4fd9ac89f41e3b… |
978041acd168b56e… |
Byte-neutral, and the clone reproduces VM140's determinism oracle exactly - which is also the adoption check for VM144.
The armed control run reproduced lane W3's numbers through a different arming path:
watch: trade routes -- manager=0x0d812270 (S+4+0x154) vector@mgr+0x3c first=0 last=0 end=0 count=0
watch: spy programs -- manager=0x0d82da80 (S+4+0x158) vector@mgr+0x10 first=0 last=0 end=0 count=0
watch: SELFTEST canary writes=1 traps=1 dr7=0xdddd0055 PASS
The canary passes on every turn, not just the first (the counter is now read as a delta).
3.2 The workload
turn 1->2 trade routes count=0 spy programs count=0
turn 2->3 trade routes count=0 spy programs count=0
turn 3->4 trade routes count=0 spy programs count=0
turn 4->5 trade routes first=0x33288560 last=0x332885b0 end=0x332885d0 count=20
spy programs count=0
turn 8->9 trade routes count=20 (reloaded from the save - the routes survive save/load)
_Myfirst, _Mylast and _Myend all moved off zero together on the same turn, which is the
first allocation of a default-constructed vector - exactly the transition lane W3 said it could
not distinguish from an emptied one.
3.3 Who fills it, measured not read
Debug-register traps, exe base 0x006b0000 (ASLR delta 0x2b0000), 40 hits on the reload turn:
| slot | writer VA | owning function | x | returns to |
|---|---|---|---|---|
trade _Mylast |
0x00841e57 |
FUN_00841cd0 +0x187 |
20 | 0x00868092 (inside 0x00868060) |
trade _Mylast |
0x00868328 |
FUN_00868060 +0x2c8 |
20 | 0x007d97df |
0x007d97df is the return address of the call at 0x007d97dd, and lane V2 already named that
site: OnAllCombatDone_Tail phase 23, call 5 of 8, target
ServerTradeManagerImpl_vslot9 = 0x00868060 (vftable 0x00a31b74 slot 9). Lane V2 recorded that
slot as "closure 185 functions, draw-free" and did not know what it was for.
ServerTradeManagerImpl::vslot9is the trade-route builder, and it tears the vector down and rebuilds it from scratch every turn: 20_Mylastwrites from a helper called at+0x32(the clear) and 20 from the body at+0x2c8(the refill), on a turn whose count is 20 both before and after. On the first turn the routes existed, the growth helper0x00483410(already named by lane AI2, "vector too long") appears in the trap set as well, because that was the allocation.
This is an agreement, not a new address: 0x00868060 is already lane-v2.json's
ServerTradeManagerImpl_vslot9 and 0x00483410 is already lane-ai2.json's growth helper, so
both are dropped rather than re-minted. ReVa/CT111 was unreachable this session
(ReVa (CONNECTION_CLOSED)), so no body was read in Ghidra and nothing beyond the trap is claimed.
3.4 The spy program
The spy half was built too, on the same game, four turns later. Full click path in §5. The container transition, from the same instrument:
turn 12->13 spy programs count=0 (tender built, Build Spy ordered)
turn 13->14 spy programs count=0 (arming is at ApplyAllTurnCommands ENTRY, before the
order is applied -- the count lags the order by one turn)
turn 14->15 spy programs first=0x3f025ad0 last=0x3f025ad4 end=0x3f025ad4 count=1
_Myfirst, _Mylast and _Myend again moved off zero together: one element, first allocation.
Prediction S1 holds.
ServerSpyManager's vector is the spy-craft list and it grows at Build Spy, while the craft is still docked to its tender -tdep = -1,spyon = 0,atto = <tender ship id>in the save. No second empire, no enemy colony and no asteroid belt are needed to make this container non-empty. Every earlier lane's cost model for the spy half assumed Deploy; Deploy is not on the critical path.
Who writes it, trapped live. The single allocation arrived on the turn thread as one chain:
0x00789620 +0x53 -> 0x008383c0 +0x9c -> 0x0059f1a0 +0x5f -> 0x00483410 +0x7c/+0x82
0x00483410 is lane AI2's already-named vector growth helper and 0x0059f1a0 is the push_back
wrapper lane AI3 already uses by address. The two new ones are recorded in
ghidra/addresses.d/lane-l3.json as ShipAction_BuildSpy 0x00789620 and
ServerSpyManager_CreateSpyCraft 0x008383c0, status: mapped rather than verified because
ReVa/CT111 was unreachable this session and no body was read.
0x00789620 sits 0x120 bytes after lane B6's ShipBorneBuildQueue_ProcessTurn 0x00789500,
which lane B6 flagged as a new indirection class: zero call sites, no vtable slot, its address
written into a stack-built function-pointer table by the ship-action dispatcher. Build Spy
is SHIPACTION_BUILDSPY, so this is that table's sibling entry - which is why no call-graph
sweep ever found the spy container's writer.
3.5 Do the tail callees draw now? No, on either container.
Lane H's eleven register-transparent entry probes, shim.cfg.l3probe (lane H's shim.cfg.hp11
verbatim plus the three watch.* keys, so the counts are comparable line for line). Seven
instrumented End Turns, the last of which had 21 trade routes, 6 trade sectors and 1 spy
program live:
| probe | calls, last turn | since launch (7 turns) | lane H baseline (empty containers) |
|---|---|---|---|
ServerSpyManager::vslot13 |
1 | 7 | 1 |
ServerSpyManager::vslot14 |
1 | 7 | 1 |
ServerTradeManagerImpl::vslot13 |
1 | 7 | 1 |
ServerTradeManagerImpl::vslot15 |
1 | 7 | 1 |
SpyManager::Slot13RngCallee |
0 | 0 | 0 |
TradeManager::Slot13RngCalleeA |
0 | 0 | 0 |
TradeManager::Slot13RngCalleeB |
0 | 0 | 0 |
ServerTradeManager::CreateRaidEncounter |
0 | 5 | 1 |
ServerTradeManager::GenerateTradeRaidEncounters |
1 | 7 | 1 |
ServerSpyManager::vslot15 [control] |
1 | 7 | 1 |
ServerTradeManagerImpl::vslot14 [control] |
1 | 7 | 1 |
Every probe reports installed=true, so these are measured zeros, not MinHook failures.
Filling either container is not sufficient to make the tail draw. The RNG ledger and the standalone's generator model do not need extending on account of the trade-route or the spy-program vector being non-empty. Lane W3's open risk is retired, in the direction nobody expected - and it is retired by evidence, not by the absence of it.
The next condition, and it is now cheap to test. The containers are non-empty but their contents are inert, and the saves say so precisely:
- every trade sector has
tsnumflt = 0- no freighters in service.TRADE_ROUTE_STARTUP_TURNSis 3,TRADE_ROUTE_MAX_FREIGHTERS5, andTRADE_RAID_ODDS_PLAYER0.07: a raid roll needs something to raid. (CreateRaidEncounterwas entered 5 times in 7 turns with, on lane H's reading, an empty candidate list.) - the one spy has
tdep = -1andspyon = 0- built but never deployed.vslot13/vslot14loop over the spy list; the per-element body almost certainly wants a spy that is at a system.
So the hypothesis for the next lane is active contents, not present contents: build freighters
from the sector summary's Build Freighter button, and Deploy the spy at an enemy system with an
asteroid belt (STARMAP_ASTEROIDBELT_ODDS 25 %), then re-run shim.cfg.l3probe. Rule 20 applies
to this paragraph as much as to anything: the table above separates "vslot15 did not run" from
"vslot15 ran and found nothing", and it says the latter.
4. The research click path - the thing that actually cost the day
No lane had written this down, and it is why three lanes could not get a tech. Lane O saw the
bottom-left button on the Research screen and recorded it as "Cancel research, NOT back". It
is both, depending on state, and when nothing is being researched it is the confirm:
map: Research (55,124)
navigate to the tech (see below)
click the tech node -> the bottom bar previews "<tech>, N turns to complete."
THIS DOES NOT ASSIGN ANYTHING
click the bottom-left button (91,715)
Confirm Research dialog -> OK (~(595,393); the dialog is centred, read it off a screenshot)
leave with the bottom-right circle (999,715) -- NOT Esc
Three traps, each of which cost a run:
- A click on a tech node is a preview, not an assignment. The bottom bar says
"N turns to complete" either way. The map's ticker keeps saying
No Research Project Assigned.and savings keep growing by the full income - that is the tell. - Esc leaves the screen but does not confirm, and the previewed selection is lost. Use the bottom-right circle.
- Once a project is running, the top-of-screen
Savings <-> Researchslider does something visible (clicking its right end tookFTL Economicsfrom "2 turns" to "1 turn"), and the in-progress tech shows as an extra icon next to the species portrait on the map.
Navigating the tree. The categories sit on a rotating sphere, the labels do not line up with the branches drawn above them, and the campaign's click helper had no drag verb, which is why earlier attempts read as "the screen ignores input".
- Right-button drag pans; left-drag and edge-scroll do nothing. A
drag/rdrag/sdrag/wheelverb was added toC:\SOTS\ui\click_helper.ps1on VM144 (backup atclick_helper.ps1.preL3); it is additive and existing verbs are untouched. - A ~600 px horizontal right-drag is one category step; the response is non-linear, so shorter
drags fling several categories and are unusable. One drag per
cmd.txt, screenshot between. Batched drags drop about half, exactly like batched clicks. - Dragging left moves the camera right. The order wraps:
… Ballistic, C3, Xenotech, Industrial, Biological, Drone, Star Drives, Warhead, Shield, Power, Torpedo, Energy, C3 … - The wheel zooms but re-centres the camera somewhere else, so zoom is not usable for targeting. Work at the zoom the screen opens at.
- Double-clicking a node opens a large readable detail card for it (title, description, "N turns to complete") with its children drawn below - the one genuinely useful navigation aid.
- The tree only draws the researched frontier plus one step. A tech whose parent is unresearched is not on screen at all, which is why the Industrial branch looked like two nodes.
5. The spy path, start to finish
Lane W3: "no lane has identified which UI produces a spy-program entry." It is the fleet panel's
Special button, and here is the whole thing. Every precondition was read out of the shipped
data files and the binary's own refusal strings first, then executed.
The ability gate. Species/<race>/sections/_Spy.shipsection:
entity_class "SpyShip" section_type mission section_class destroyer
nodesign 1 spy 1 cost 20000
requires CCC_SpyBm
requires IND_SlvgTech
nodesign 1 means the spy craft is never designed and never appears in a build queue - it is
produced by a ship action, which is why looking for it in the Design or Build screens finds
nothing.
The tender. Can't build spy: Fleet does not have a ship spy can dock with. The ship needs a
section carrying spytender, and in this image there is exactly one per race:
CRRepairandSalvage- the Cruiser "Repair and Salvage" mission section (requires IND_SlvgTech, cost 60,000). Nothing in the UI calls it a tender, and nothing links it to spies. This is the single fact that makes the whole path findable.
The tech chain (RP from TechTree/MasterTechList.tech); at this game's settings each of these
completed in one turn:
CCC_ROOT -> CCC_FTLBrdB (4,000) -> CCC_SpyBm (12,000) [spy craft half]
IND_OrbFound -> IND_CruisCon (16,000) -> IND_SlvgTech (12,000) [tender + spy craft half]
CCC_FTLBrdB is shared with the trade chain, and the Initial Technologies 15 roll supplied it.
The click path, executed on turns 11-14 at 1024x768:
- Design (142,124). Click
Cruiserin the left list (104,267) to switch hull class. The design has three slots - Command / Mission / Engine - each with<>arrows; click the Mission slot's right arrow (710,483) until the title readsRepair and Salvage*(five clicks fromArmor, throughMedium Defense Platform). Bottom-leftSave Design(135,715) -> name prompt ->OK. - Build (221,124) ->
Cruiser(104,276) -> theRepair and Salvagerow (74,130) ->Add To Queue(125,715). ETA 2 turns at a developed homeworld. - Two End Turns. The fleet panel then lists
Alpha Fleet* / CR Repair and Salvage 9/9and theManage Fleets/Move/Specialbuttons light up. Special(229,464) -> the menu isRepair / Scuttle /Build Spy/ Auto-repair / Flag As Guard.Build Spyat (277,517).- Dialog
Build Spy At <system>?/ "Select ships for spy craft to dock with:" ->Select All(361,566) ->OK(599,566). The ship's row gains a leading*and a spy glyph: the order is queued, not yet executed. - End Turn - the order is applied. End Turn again and the container reads
count=1; the arming point isApplyAllTurnCommandsentry, so the count lags the order by one turn.
Everything the engine will refuse, from its own strings (none of these bit, but they are the map):
- build - your own system, player has both techs, the fleet contains a tender, that ship is not already carrying a spy and is not busy;
- deploy - not your own system, no enemy fleet present ("You gotta fight 'em."), no spy already
there, and
Can't deploy spy: Spy requires an asteroid belt to hide.(SPYSHIP_NEARBY_ASTEROID_RANGE 500.0;STARMAP_ASTEROIDBELT_ODDS 25%).
Deploy was not done - it needs a fleet move to an enemy system with an asteroid belt, and §3.5 says it is the most likely next gate for the spy RNG callees. It is the one step of this subsystem still unexercised.
What the save now proves about the wire format. spymgr is populated for the first time in
the corpus:
spymgr { xsid 2, nspy 1,
spy { sid 1, sown 16, atto 3728, deat 0, tdep -1, cbh 0,
sdo 0, sdet -1, spyon 0, spyat 0, cm 0, cmo 0, ncp 0 } }
sown 16 is the player id of re; atto 3728 is the tender's ship id; tdep -1 is "never
deployed". Every member layouts.md lists for Game::SpyCraft is present, which confirms that
record - but note that the on-the-wire order is not the memory order: sdo and sdet
(memory +0x3c, +0x40) are written between cbh and spyon, not last. And ncp (memory
+0x2c, typed as a 0x10 vector) serialises here as a bare count of 0, so an empty vector member
is indistinguishable on the wire from a scalar zero until a save has a non-empty one.
6. Artifacts
| what | where |
|---|---|
| turn-5 save, the first trade routes in the corpus | verify/results/saves/human-turn5-traderoutes.sav (72,204 B, --strict clean, 0 issues) |
| turn-8 save, routes matured, one sector secure | verify/results/saves/human-turn8-traderoutes.sav (76,554 B) |
| turn-11 save, all four spy techs researched, no tender yet | verify/results/saves/human-turn11-spytechs.sav (81,702 B) |
| turn-15 save, BOTH containers non-empty - 21 trade routes, 6 sectors, 1 spy craft | verify/results/saves/human-turn15-spyprogram.sav (87,736 B, --strict clean, 0 issues) |
| probe-run trace, 7 End Turns of entry counts + RNG ledger | verify/traces/l3-probe-turn8-turn15.jsonl |
| probe-run shim logs and watch hits | verify/results/shim/l3/l3-probe-run-{shim.log,watch.txt}, l3-spy-run-{shim.log,watch.txt} |
| the two addresses this lane mints | ghidra/addresses.d/lane-l3.json (ShipAction_BuildSpy, ServerSpyManager_CreateSpyCraft) |
| the instrument | sots-engine src/shim/hooks/watchpoints.cpp (watch.mode=cont), src/shim/shim.cfg.l3cont, .l3control, .l3probe |
| predictions written before the build (rule 2) | sots-engine docs/L3-predictions.md |
What the trade saves contain that no earlier save does. trdmgr is populated:
NumTradeSectors 6, SctSize 8.0, and six TradeID/Trade records each with tsgridID,
tsctr, tssec/tsct/tscr, ptssec/ptsct/ptscr, an fwarn vector, tsnumsys and its
tssys member list, and tsnumflt. In turn2-state.sav the same trdmgr block holds
NumTradeSectors and nothing else. spymgr likewise goes from xsid/nspy 0 to a populated
spy record (§5).
spies2 is still 0 in all 28 systems even so. Lane W flagged spies2 / SysMem / mts as
hypotheses with count 0 in all 11 saves, and the natural reading was "no save has ever had a spy".
That reading is now falsified: this save has a spy, in spymgr, and spies2 is still empty in
every system. spies2 is therefore not the spy list - it is something else, or it only fills
for a deployed spy. Whoever picks that up should start from the turn-15 save rather than from
the assumption.
An engine defect found and fixed. hooks=off returned from Shim_Init before
install_watchpoints, so hooks=off watch=on printed watch=on in the banner and armed
absolutely nothing - a config that would have reported a confident zero. src/shim/main.cpp now
installs the watchpoint module (and MinHook) on the hooks=off path when watch=on. This
matters for any long play session: the template hooks cost 30-45 s per End Turn and measure
nothing a container watch is asking about.
7. VM144 as left
Main menu, profile re, screenshot-verified. Shim build l3cont2-0117495-20260908T2124Z from
C:\SOTS\shimdist-l3; C:\SOTS\shim.cfg is a copy of shim.cfg.l3probe. Original config saved
at C:\SOTS\ui\preL3-shim.cfg.
C:\SOTS\ui\click_helper.ps1 has four new verbs and its pre-lane backup is
click_helper.ps1.preL3. The additions are purely additive - every existing verb is byte-for-byte
unchanged - and they are what made the research and design screens drivable at all:
drag x1 y1 x2 y2 left-button drag
rdrag x1 y1 x2 y2 RIGHT-button drag, 30 steps <- the only thing that pans the tech tree
sdrag x1 y1 x2 y2 slow left drag, 40 steps
wheel x y delta [n] n wheel notches (delta may be negative)
SavedGames gained four files (MyGamel3tradeturn{5-traderoutes,8-tr,11-spytechs,15-spy}.sav)
plus the game's three autosaves, so every Load-dialog row position recorded by earlier lanes has
moved on this guest. Screenshot the dialog; do not reuse a remembered row. The repo copies of
those four saves are the canonical ones.
Also left in place, all harmless: C:\SOTS\shimdist-l3\, C:\SOTS\l3data\ (the config text files
extracted from sots.gob), and C:\SOTS\ui\l3-*.ps1 (the gob extractor, the click-helper
patchers, a display-mode lister).
Guest adoption notes for the next clone. VM144 came up with no IPv4 in the host's ARP cache;
it had one all along (192.168.10.144, DHCP from 192.168.0.1, /16). Two things worth knowing:
ssh re@<addr> works directly from the dev box, and when the IPv4 address is genuinely unknown,
ssh -6 re@fe80::…%vmbr0 from the PVE host works - the link-local address is in
ip neigh on spicy even when the v4 one is not, and Windows answers SSH on it while dropping
ICMP. That is a faster route in than a console screendump. The clone reproduces VM140's
determinism oracle byte for byte (§3.1), which is the adoption check worth running first.