Compare commits
No commits in common. "1c30a95c9d9560a857a41584facff37ee8828cc8" and "947f20586790bfb5ef6e65e4d0ff9523ed7d5b97" have entirely different histories.
1c30a95c9d
...
947f205867
16 changed files with 15 additions and 1434 deletions
|
|
@ -1,16 +1,16 @@
|
|||
# SotS RE campaign — coverage dashboard
|
||||
|
||||
Generated 2026-09-09 05:36 UTC · `sots-re` @ f14e845,2026-09-09 · `sots-engine` @ 989c692,2026-09-08 (240 commits) · regenerate with `tools/dashboard.py`
|
||||
Generated 2026-09-09 04:56 UTC · `sots-re` @ 1fecff8,2026-09-09 · `sots-engine` @ 989c692,2026-09-08 (240 commits) · regenerate with `tools/dashboard.py`
|
||||
|
||||
> **North star:** A functional reimplementation of the engine — behavior-equivalent, NOT byte-for-byte
|
||||
|
||||
## 1. Map coverage (campaign/board.md)
|
||||
|
||||
422 targets · mapped-or-better **375/422** `[█████████░] 89%` · verified **333/422** `[████████░░] 79%`
|
||||
419 targets · mapped-or-better **372/419** `[█████████░] 89%` · verified **330/419** `[████████░░] 79%`
|
||||
|
||||
| Status | Count | % |
|
||||
|---|---:|---:|
|
||||
| verified | 333 | 79% |
|
||||
| verified | 330 | 79% |
|
||||
| mapped | 42 | 10% |
|
||||
| in-progress | 4 | 1% |
|
||||
| backlog | 41 | 10% |
|
||||
|
|
@ -22,23 +22,23 @@ Generated 2026-09-09 05:36 UTC · `sots-re` @ f14e845,2026-09-09 · `sots-engine
|
|||
| control-flow | 32 | 2 | 0 | 0 | 0 | 34 |
|
||||
| subsystems | 4 | 8 | 0 | 2 | 1 | 15 |
|
||||
| engine | 30 | 0 | 0 | 0 | 0 | 30 |
|
||||
| verify | 104 | 15 | 3 | 35 | 0 | 157 |
|
||||
| verify | 102 | 15 | 3 | 35 | 0 | 155 |
|
||||
| phase2 | 13 | 3 | 1 | 0 | 0 | 17 |
|
||||
| meta | 85 | 6 | 0 | 1 | 0 | 92 |
|
||||
| meta | 84 | 6 | 0 | 1 | 0 | 91 |
|
||||
| other | 19 | 2 | 0 | 0 | 0 | 21 |
|
||||
|
||||
## 2. Binary understanding
|
||||
|
||||
- RTTI type descriptors: **1,924** (`Game::` 1,404, `Mars::` 194; serializable types 179)
|
||||
- Classes with recovered member layouts: **384** / 1,598 named classes `[██░░░░░░░░] 24%` — `objects/layouts.json` (serializer recovery) plus classes recovered by hand in `struct-recovery.md` + `schema-gaps-resolved.md`. Note 179 types are *serializable*; the recovery also reaches non-serializable ones, so this is not a subset of that
|
||||
- Functions: **41,411** (parsed from `01-fingerprint.md`); named/annotated in the **address contract** (`ghidra/addresses.json`, not Ghidra's full rename count): **1291**, verified **1160** `[█████████░] 90%`
|
||||
- Functions: **41,411** (parsed from `01-fingerprint.md`); named/annotated in the **address contract** (`ghidra/addresses.json`, not Ghidra's full rename count): **1283**, verified **1152** `[█████████░] 90%`
|
||||
|
||||
## 3. Data layer
|
||||
|
||||
- Catalogs: **1,595/1,595** files parsed (91 block kinds in `schema_stats.json`), dangling cross-refs **0** (`crosslink.json`)
|
||||
- Oracle `mars-parse`: **1,531/1,531** files agree `[██████████] 100%`
|
||||
- Oracle `mars-text`: **64/64** files agree `[██████████] 100%`
|
||||
- Saves: **38/38** real saves strict-clean — strict exit 0, 0 errors, 0 warnings
|
||||
- Saves: **35/35** real saves strict-clean — strict exit 0, 0 errors, 0 warnings
|
||||
- Design rules: **127/127** stock designs pass `[██████████] 100%`
|
||||
- Value domains: **490/724** typed fields have been seen to vary `[███████░░░] 68%` — the other **234** have only ever held one value across the corpus, so their typing is untested (`value-domain-census.md`)
|
||||
|
||||
|
|
@ -112,7 +112,7 @@ Detail: `verify/results/standalone/report.txt`.
|
|||
|
||||
## 7. Verification ledger
|
||||
|
||||
- ✅ Saves strict: 38/38 (strict exit 0, 0 errors, 0 warnings)
|
||||
- ✅ Saves strict: 35/35 (strict exit 0, 0 errors, 0 warnings)
|
||||
- ✅ Design rules: 127/127
|
||||
- ✅ oracle mars-parse 1531/1531 · ✅ oracle mars-text 64/64
|
||||
- ✅ Compare harness present (`verify/harness/compare/`)
|
||||
|
|
@ -133,11 +133,11 @@ Most recent open:
|
|||
|
||||
## 9. Delta since previous dashboard
|
||||
|
||||
- verified targets: 330 → 333 (+3) · mapped-or-better: 372 → 375 (+3)
|
||||
- verified targets: 329 → 330 (+1) · mapped-or-better: 371 → 372 (+1)
|
||||
- engine LOC: 58,647 → 58,647 (+0) · test files: 122 → 122 (+0) · checks: 4,257 → 4,257 (+0)
|
||||
- addresses verified: 1,152 → 1,160 (+8) · recovered layouts: 384 → 384 (+0) · open questions: 26 → 26 (+0)
|
||||
- addresses verified: 1,151 → 1,152 (+1) · recovered layouts: 384 → 384 (+0) · open questions: 26 → 26 (+0)
|
||||
- standalone leaves closed: 45 → 45 (+0) · leaves still diverging: 63 → 63 (+0)
|
||||
|
||||
---
|
||||
warnings: board.md: unknown types subsystems; mars-rng.md: no oracle total row parsed; mars-stream.md: no oracle total row parsed; mars-vfs.md: no oracle total row parsed
|
||||
<!-- dashboard-metrics {"verified": 333, "mapped_plus": 375, "targets": 422, "loc": 58647, "tests": 122, "checks": 4257, "addr_verified": 1160, "addr_total": 1291, "layouts": 384, "open_q": 26, "sa_closed": 45, "sa_left": 63} -->
|
||||
<!-- dashboard-metrics {"verified": 330, "mapped_plus": 372, "targets": 419, "loc": 58647, "tests": 122, "checks": 4257, "addr_verified": 1152, "addr_total": 1283, "layouts": 384, "open_q": 26, "sa_closed": 45, "sa_left": 63} -->
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1,202 +0,0 @@
|
|||
# The pinned-seed probe on a rich AI turn — is the client seed the *only* per-process input?
|
||||
|
||||
- **Owner / date:** lane BP · 2026-09-09 · guest **VM146** (`sots-re-win10-146`, `re@192.168.10.146`)
|
||||
- **Held:** VM146, from the time this prediction was committed. VM140 (reference), VM141 (lane AZ)
|
||||
and VM144 (lane AP) untouched.
|
||||
- **Trigger:** `findings/resolutions/2026-09-09-seed-exposure-is-a-predicate.md` §6, **probe 2** —
|
||||
the first of the three probes, because it can invalidate C-exact.
|
||||
- **Build:** `bp-989c692-20260909T0505Z`, built in `/srv/re-lab/build/sots-engine-bp` after
|
||||
`ssh spicy 'rm -rf …'` of the whole tree (rule 24), from a lane-private `git worktree` at
|
||||
`~/sots-engine-bp` (branch `wip/bp`) with no local `build*` shipped (rule 21). Deployed to
|
||||
`C:\SOTS\shimdist-bp`.
|
||||
- **Input:** `verify/results/saves/ad-turn27-two-raiders.sav`, sha256
|
||||
`1c8baa27680809d585ab1728391e82729642d32aaedffd5bf95b616f0a11a436` (lane AD's published value;
|
||||
re-verified on this guest before the first run — §3.1).
|
||||
|
||||
---
|
||||
|
||||
## 0. The question, in one paragraph
|
||||
|
||||
The campaign holds that the original's AI is a deterministic function of **(save, per-client
|
||||
seed)** — "C-exact" — and that its apparent non-determinism is one 32-bit word drawn per AI client
|
||||
at construction from a per-process global (resolution 2026-09-08, board row 326). Row 360 proved
|
||||
that *pinning* those seeds collapses three processes to one autosave. **It proved it on
|
||||
`turn1-state`, an early-game turn, and nowhere else.** `ad-turn27-two-raiders.sav` is the richest
|
||||
AI turn this campaign owns — thirteen ships complete into five new fleets, a design is created, a
|
||||
system is colonised — and two `hooks=off` processes on it differ in **94 leaves**
|
||||
(`raid-gate-multiplicity.md` §5). The resolver established that that variation is **not** the
|
||||
design content (the two `Bravestar Mk 3` bodies are byte-identical apart from `DesID`) and **not**
|
||||
a research pick (`ResTNm` held for Player[32]); it is the build / fleet-assignment / colony layer
|
||||
and the id allocation downstream of it, **and its consumer is unidentified**. So reading 3 — *a
|
||||
non-seed per-process input* — is not excluded on rich states. This probe decides it.
|
||||
|
||||
---
|
||||
|
||||
## 1. The prediction, committed before the run
|
||||
|
||||
> **P1 (the headline).** Two fresh processes loading `ad-turn27-two-raiders.sav` with the AI client
|
||||
> seeds pinned by the constructor-argument overwrite, one End Turn each, write **byte-identical**
|
||||
> `(Autosave).sav` files, and `state_checksum.py --floats bits --mask none` prints **IDENTICAL**
|
||||
> over roughly 67,000 leaves.
|
||||
>
|
||||
> **P2.** The `(Autosave EndTurn).sav` (pre-turn snapshot, written before the AI runs) is
|
||||
> byte-identical between the two processes as well. This is the weaker half and it is expected to
|
||||
> hold whatever P1 does: lane AD saw the pre-turn autosave agree bit-for-bit across three processes
|
||||
> and two configurations, so the load path is already known to be deterministic.
|
||||
>
|
||||
> **P3.** The pinned pair also reproduces run L — the unpinned `aiseed=log` run whose observed
|
||||
> seeds the pin uses (§2.3). This is CB's C3/C5a/C5b shape applied to a rich turn: three processes,
|
||||
> three sets of natural seeds, one autosave. Weaker than P1 (it can fail for a reason that leaves
|
||||
> P1 intact — see the falsifiers) and worth much more if it holds, because it says the pinned run
|
||||
> reproduces **a turn that actually happened** rather than a synthetic one.
|
||||
>
|
||||
> **P4 (the exposure predicate, tested in passing).** `ad-turn27` is exposed on all three of the
|
||||
> resolution's counts for Player[32] — a design is created, thirteen ships complete, a system is
|
||||
> colonised. If P1 holds, then **an exposed turn is reproducible once the seed is pinned**, which
|
||||
> is the whole content of C-exact on the turns that matter.
|
||||
>
|
||||
> **P5.** The AI command blocks dumped by `aiorders` are identical between the two processes,
|
||||
> element for element, on every list of every block. If P1 fails, P5 is the localiser: blocks
|
||||
> identical + autosaves different puts the non-seed input **downstream of the AI's decision**;
|
||||
> blocks different puts it **inside** it.
|
||||
|
||||
### 1.1 How this could be wrong, and the symptom of each way
|
||||
|
||||
| way | symptom |
|
||||
|---|---|
|
||||
| **Reading 3 is alive** — some per-process input other than the seed feeds this turn | P1 fails. The leaf diff localises it. **This is a resolution trigger, not a lane result:** the resolution says so in as many words, so this lane localises by sub-tree, names the leaves, and stops. |
|
||||
| The pin is **half-applied** — a client with a net id not in the list passes through unpinned | The two processes differ, for a reason that has nothing to do with reading 3. Defended by construction: the wildcard `*=<hex>` is set *as well as* every observed id, so no client can pass through, and `shim.log` prints `aiseed call=… observed=… used=… pinned=1` for every single call. **Every call must read `pinned=1`.** A run with even one `pinned=0` is void. |
|
||||
| The pin is **not applied at all** — `aiseed=pin` with no values | `shim.log` prints `aiseed: PIN MODE WITH NO PINS -- every seed passes through unchanged, so this run is NOT pinned and must not be reported as one`. Checked before either autosave is read. |
|
||||
| The **wrong mechanism** was used | `airng.pin_seed` re-seeds the generator at bracket entry and is a *declared perturbation*; it would test a different thing. This lane does not set it. `airng=off` is explicit in both configs. |
|
||||
| The **instrument** perturbs the turn (rule 19) | Not separable here, and stated rather than hidden: a pin *cannot* be applied by a process with no hooks, because `hooks=off` returns from `Shim_Init` before the aiseed module is installed. §2.2 lists exactly what is installed. Both processes carry the identical instrument, so the A/B comparison is internally valid; what it cannot do is speak about the un-instrumented game. |
|
||||
| A stale binary (rule 24) | The build tree was `rm -rf`'d on CT111 before the rsync; `BUILD_ID` is checked in `shim.log` on every run and quoted in §3. |
|
||||
| The **click path** lands somewhere else | Every dialog step is screenshotted and verified; no sleep-and-click. Row positions are re-derived from a screenshot of the Load dialog, not carried over from another lane. |
|
||||
|
||||
### 1.2 What this probe cannot decide, whatever it says
|
||||
|
||||
It is a statement about **one save, one procedure, one build**. Rule 26 corollary (c): a control
|
||||
that agrees certifies a *procedure*, not a state. If P1 holds it says "on this turn, with these
|
||||
seven clients pinned, nothing else per-process reached the save" — it does **not** say the AI is
|
||||
deterministic, and it does not transfer to a turn that reaches a consumer this one does not. In
|
||||
particular the 3–40-turn fuse at `0x0069dbb0` cannot fire inside one turn of a load and is
|
||||
therefore **untested by this probe**, exactly as it was untested by AR's two-turn pair.
|
||||
|
||||
---
|
||||
|
||||
## 2. The procedure
|
||||
|
||||
### 2.1 Why the constructor-argument overwrite and not `airng.pin_seed`
|
||||
|
||||
`aiseed=pin` detours `Game::StrategyApp::RunAI` and replaces its **fourth stack argument** — the
|
||||
word the `StrategyClient` constructor is about to hand to `RNG_Seed` — before the callee reads it.
|
||||
The client's generator is therefore *constructed* from the pinned word and its whole stream, from
|
||||
the first draw, is the stream that word implies. `airng.pin_seed` (lane PAR) re-seeds an already
|
||||
constructed generator at bracket entry; it discards whatever the client drew before that point and
|
||||
is a **declared perturbation**. The resolution names the first and forbids the second. Getting this
|
||||
wrong would invalidate the probe, so it is stated here rather than left to the config.
|
||||
|
||||
### 2.2 The hook set, stated in full — and a defect in the mechanism this lane inherited
|
||||
|
||||
`aiseed` lives in the `ai_orders` module, and `install_ai_orders()` is only reached when
|
||||
`hooks != off`. So **there is no such thing as a `hooks=off` pinned run.** The minimum instrument
|
||||
that can carry a pin, and the one both processes carry, is:
|
||||
|
||||
* the `Mars::Application::Initialize` detour (the shim's own entry point);
|
||||
* the **seven draw-site detours** — installed unconditionally whenever `hooks != off`;
|
||||
* **one** `aiorders` detour on `StrategySim::ApplyTurnCommandBatch` (`aiprobes=off`, so none of the
|
||||
entry probes; lane H's non-neutral probe index 8 is not installed);
|
||||
* **one** `aiseed` detour on `StrategyApp::RunAI`.
|
||||
|
||||
Every template hook is off **by name**. That matters more than it looks:
|
||||
`trace::Config::mode_for` falls through to `default_mode` for any hook **not** named, and
|
||||
`default_mode` under `hooks=trace` is `trace` — so **a hook omitted from the list is silently left
|
||||
installed.**
|
||||
|
||||
> **Inherited defect, reported not worked around.** `src/shim/shim.cfg.cbpin` — the file the
|
||||
> resolution points at — names 20 template hooks and **omits six that existed when it was
|
||||
> written**: `Game::StrategyServer::BeginProcessTurn`, the three `Game::SVSOSwarmQueen::*` hooks,
|
||||
> `Game::SVSOSlaversRefuel::UpdateDifficultyTier` and `Mars::RNG::Seed`. Under `hooks=trace` those
|
||||
> six default to trace mode, so lane CB's pinned runs C5a/C5b carried a larger instrument than
|
||||
> their config comment implies. It does not damage CB's result — both processes carried the same
|
||||
> six, and CB's conclusion rests on an A/B agreement — but the next lane to copy that file inherits
|
||||
> them. `shim.cfg.bppin` names **all 28** registered hooks.
|
||||
>
|
||||
> **Second, smaller defect in the same file.** Its header comment wraps onto a line that is *not*
|
||||
> commented: line 4 of `shim.cfg.cbpin` reads `aiseed.values=32=e70a4703,496=0c63ca36,512=372be4df\`.`
|
||||
> — a live config line ending in a stray backtick and a full stop, four lines above the real one.
|
||||
> Harmless if the parser is last-wins, and nobody has checked which it is. Reported so it can be
|
||||
> fixed rather than rediscovered.
|
||||
|
||||
### 2.3 Three runs, not two
|
||||
|
||||
The resolution costs the probe at two loads. This lane takes three, and the extra one is run **L**:
|
||||
|
||||
| run | config | seeds | End Turns | purpose |
|
||||
|---|---|---|---|---|
|
||||
| **L** | `shim.cfg.bplog` | `aiseed=log` — observed, **not** changed | 1 | enumerate the net ids and their *natural* seeds; produce a natural reference autosave |
|
||||
| **A** | `shim.cfg.bppin` | pinned to L's observed values, every id **plus** the wildcard | 1 | the probe |
|
||||
| **B** | `shim.cfg.bppin` | identical | 1 | the probe, second fresh process |
|
||||
|
||||
Why the third run is worth its nine minutes:
|
||||
|
||||
1. **Nobody has ever listed this save's AI net ids.** The save has seven non-human players (§2.4)
|
||||
but the number of players is not the number of `StrategyClient`s. The alternative the resolution
|
||||
allows — the bare wildcard — pins every client to the *same* word, which is a valid intervention
|
||||
but not a natural one.
|
||||
2. **It makes the pin reproduce a turn that happened.** Lane CB's rule: pin to values an unpinned
|
||||
run of the same save observed for itself. P3 is then a real prediction rather than a definition.
|
||||
3. **Two runs agreeing on a `k > 1` workload is a `1/k` coincidence; three is `1/k²`.** That is
|
||||
exactly the argument CB used to justify its own third run, and it applies here with more force
|
||||
because nobody knows `k` on a build turn.
|
||||
|
||||
`shim.cfg.bplog` and `shim.cfg.bppin` are **byte-identical except the `aiseed=` line and the
|
||||
values**, so run L is comparable with A and B.
|
||||
|
||||
### 2.4 The exposure facts, read off the input save before any run
|
||||
|
||||
Rule 26 corollary (c) says to write the exposure facts next to the hashes. Read from
|
||||
`ad-turn27-two-raiders.sav` with `verify/save-reader/save_reader.py --dump --json`:
|
||||
|
||||
| PlyrIdx | PlayerID | name | `ResTNm` at turn start | `NumOwn` | `NumDes` |
|
||||
|---:|---:|---|---|---:|---:|
|
||||
| 0 | 16 | `re` (**human**) | `''` | 3 | 6 |
|
||||
| 1 | **32** | **The Eternal Empire** (Tarka) | **`BIO_TerBac`** (held) | **15** | **46** |
|
||||
| 2 | 496 | Spengler (RebelAI) | `DRV_PlsFiss` | 0 | 0 |
|
||||
| 3 | 512 | Spengler (RebelAI) | `XNC_TrnsMorr2` | 0 | 0 |
|
||||
| 4 | 528 | Alien Menace | `''` | 0 | 19 |
|
||||
| 5 | 544 | Peacekeeper Enforcer | `''` | 0 | 1 |
|
||||
| 6 | 560 | Von Neumann | `''` | 0 | 6 |
|
||||
| 7 | 576 | Independent Colony | `''` | 0 | 1 |
|
||||
|
||||
Ships completing this turn: **13**, into five new fleets (`ShipIDs` +13 −1), with `NumDes` 46→47
|
||||
(`Bravestar Mk 3`) and `NumOwn` 15→16 — measured by the resolver from the 27→28 transition, quoted
|
||||
here as the prior it is, and re-derivable from this lane's own output saves.
|
||||
|
||||
**One thing this table says that the resolution's §3 does not.** The resolution reports "AD's
|
||||
variation was not a research pick — Player[32] entered turn 28 with `ResTNm = 'BIO_TerBac'`", which
|
||||
is correct. But **four other AI players enter this turn with `ResTNm == ''`** (528/544/560/576) and
|
||||
**none of them contributed a leaf to AD's 94** — every one of the 94 is Player[32]'s or the global
|
||||
id counters'. All four have `NumOwn == 0`. So the predicate as written in rule 26 corollary (c) —
|
||||
"`ResTNm == ''` names a pick turn" — is **necessary and not sufficient**: a player with no colonies
|
||||
has no research income and does not reach the pick, whatever its `ResTNm` says. That is a
|
||||
measurement on the input save, independent of how the runs come out, and it is offered as a
|
||||
refinement of the predicate rather than a correction of the resolution's Player[32] claim, which
|
||||
stands.
|
||||
|
||||
---
|
||||
|
||||
## 3. The result
|
||||
|
||||
*(Filled after the runs. This section is empty in the commit that carries the prediction.)*
|
||||
|
||||
---
|
||||
|
||||
## 4. Verdict
|
||||
|
||||
*(Filled after the runs.)*
|
||||
|
||||
---
|
||||
|
||||
## Proposed board rows
|
||||
|
||||
*(Filled after the runs.)*
|
||||
|
|
@ -1,223 +0,0 @@
|
|||
# The seed-exposure predicate's first forward test — probe 1 (parts 1b and 1)
|
||||
|
||||
- **Type:** control-flow / determinism (two `hooks=off` measurements from saves already on disk; no
|
||||
build, no shim config change, no instrument)
|
||||
- **Owner / date:** lane **BQ** · 2026-09-09 · guest **VM145** (`sots-re-win10-145`, 192.168.10.145)
|
||||
- **Spec:** `findings/resolutions/2026-09-09-seed-exposure-is-a-predicate.md` §6, probe 1
|
||||
- **Tests:** `guides/method-rules.md` rule 26 corollary (c) — the predicate written from lane AR's
|
||||
falsified P7, so far supported only by three states read *after* the fact
|
||||
- **Depends on:** `findings/control-flow/raid-target-pick-verdict.md` §6 (lane AR's pair)
|
||||
|
||||
---
|
||||
|
||||
## 1. Predictions, committed before either run (rule 2)
|
||||
|
||||
*Everything in §1 and §2 was written and committed before the game was launched on VM145 and before
|
||||
any hash was read. It is not edited after the fact, only annotated with verdicts in §5.*
|
||||
|
||||
### 1.1 What is actually at stake
|
||||
|
||||
The resolver ruled that the per-process AI client seed (row 326) is present in **every** process on
|
||||
**every** turn, and reaches the save **only** through a decision whose outcome set is larger than one
|
||||
given the state — and that whether such a decision is reached is a **predicate on the pre-turn save**.
|
||||
That ruling currently rests on three states read *after* their controls were run (lane AD's turn 28,
|
||||
lane AS's turn 16, lane AR's turns 38–39). It has never made a forward prediction.
|
||||
|
||||
This lane makes two, on states nobody has run, and both can fail.
|
||||
|
||||
### 1.2 Part 1b — the precondition
|
||||
|
||||
**Procedure.** `ar-oracle-A-pre.sav` (Frame 38, sha256 `15b99255e1f03dab3e35ab8c1ac64f221cb5aa9321f113c7a6e3d1263c3f34ca`),
|
||||
one fresh process, `hooks=off`, **one End Turn**, no other input.
|
||||
|
||||
> **P1b — committed.** The resulting `(Autosave).sav` (Frame 39) hashes to
|
||||
> `7a8b3d5eb3a60ebac9f40646d3e4b15768a24a0af047a439ce090c7cf38e8b38`.
|
||||
|
||||
Why it matters. Lane AR's `15b99255…` → `7a8b3d5e…` step has only ever been reached **by
|
||||
continuation** — the second of two End Turns inside one process that started from
|
||||
`ar-turn37-816raiders.sav`. A calibration pair for the standalone must be a **load → turn**
|
||||
procedure. If P1b holds, the single-turn pair is certified in that form and is the first pair
|
||||
anywhere that exercises the trade-raid roll (four raid rolls, one word each, no encounter). If it
|
||||
fails, the pair remains valid **only** as the two-turn procedure from turn 37, and the resolution
|
||||
names the first suspect: the **resave canonicalisation** (`determinism-oracle.md`, round-trip
|
||||
section).
|
||||
|
||||
> **P1b-aux — committed, and it costs nothing.** The same run also writes
|
||||
> `(Autosave EndTurn).sav`, which is the state **as End Turn is pressed** — i.e. a resave of the
|
||||
> file that was loaded. I predict it hashes to `15b99255…`, the input's own hash. **This is a direct
|
||||
> test of the resave-canonicalisation suspect**, taken in the same run whichever way P1b goes:
|
||||
>
|
||||
> - P1b holds **and** P1b-aux holds ⇒ load→resave is byte-exact here and the pair is clean.
|
||||
> - P1b fails **and** P1b-aux fails ⇒ the divergence is present *before the turn runs*; it is the
|
||||
> round trip, not the turn, and the resave canonicalisation is confirmed as the cause.
|
||||
> - P1b fails **and** P1b-aux holds ⇒ the round trip is exact and the **turn** diverged from its
|
||||
> continuation form. That is the interesting failure and it is not one the resolution anticipated;
|
||||
> it would mean a load boundary changes turn 39's outcome, and it is a resolver case, not a lane
|
||||
> result.
|
||||
> - P1b holds **and** P1b-aux fails ⇒ the resave is not byte-exact but is behaviourally equivalent;
|
||||
> the pair is certified and `determinism-oracle.md`'s round-trip section needs a note.
|
||||
|
||||
### 1.3 Part 1 — the exposure test
|
||||
|
||||
**Procedure.** `ar-oracle-A-post.sav` (Frame 39, sha256 `7a8b3d5e…`), **two fresh processes**,
|
||||
`hooks=off`, **one End Turn each**, any encounter query resolved with **`Auto Resolve Peacefully` in
|
||||
both**.
|
||||
|
||||
> **P1 — committed.** The two `(Autosave).sav` files **differ**, and the difference is confined to
|
||||
> `Player[32]`'s `TechTree/*`, `ResTNm`, `otch`, `Events`, `turnstats/…/tch` and `Summary/Checksum`,
|
||||
> while `/Sim/RNG`, `/Sim/trdmgr`, **every** `Player[16]` leaf and **every** player-0 fleet are
|
||||
> identical.
|
||||
|
||||
The reasoning, and it is the predicate speaking: `ar-oracle-A-post.sav` carries `ResTNm == ''` for
|
||||
Player[32] (§2). By the AS precedent (`as-turn15 → 16`, 22 leaves, entered with `ResTNm == ''`) and
|
||||
the row-326 precedent on `turn1-state`, that is a research-pick turn. So the predicate says, **in
|
||||
advance**, that lane AR's pair must not be extended by a turn — and this run is what makes that a
|
||||
measurement rather than an inference.
|
||||
|
||||
**How P1 can be wrong, and the symptom of each way** (rule 2):
|
||||
|
||||
| way it could be wrong | symptom |
|
||||
|---|---|
|
||||
| a producer supplied the target, so the pick had an outcome set of size 1 (as for player 32 on `turn1-state`) | the two files **agree** byte-for-byte; the predicate survives but needs a **producer gate**, and lane L4's `airesearch=on` dump names which producer returned non-null |
|
||||
| something else on turn 40 is exposed as well as the pick | the files differ, but **outside** the named leaf set — e.g. in fleets, `trdmgr`, or `Player[16]` |
|
||||
| the pick is exposed but its outcome-set is 1 for a different reason (only one affordable node) | files agree; same follow-up as the producer case, and `otch`/`TechTree` at turn 40 says which node was taken |
|
||||
| VM145 is not byte-faithful to the lineage | **P1b fails** as well, and part 1b is the guard against reading part 1 off a guest that cannot reproduce anything |
|
||||
|
||||
**A negative here is a result, not a null.** If the two files agree, the honest statement is *"no
|
||||
exposed decision was reached on turn 40 either, and the pick is therefore producer-supplied on this
|
||||
state"* — never *"the AI is deterministic here"* (rule 26 (c)).
|
||||
|
||||
### 1.4 A false-positive class in the predicate, named before the run
|
||||
|
||||
Read off the two saves (§2), and stated here because it is a *pre-run* correction to the predicate
|
||||
as the resolution words it:
|
||||
|
||||
**`ResTNm == '' at turn start` is true of four players on `ar-oracle-A-pre.sav` — the turn whose
|
||||
control agreed byte-for-byte.** Players 528 (`Alien Menace`), 544 (`Peacekeeper Enforcer`), 560
|
||||
(`Von Neumann`) and 576 (`Independent Colony`) all carry `ResTNm == ''` on turn 38 **and** turn 39,
|
||||
and player 16 (the human) does too. They have `NumOwn == 0`: no colonies, no research income, no
|
||||
pick to make. So the raw predicate has a known false-positive class already sitting inside the very
|
||||
state that falsified AR's P7.
|
||||
|
||||
The sharp form the next lane should use is therefore:
|
||||
|
||||
> `ResTNm == ''` **at turn start, for a non-eliminated AI player with `NumOwn > 0`**, names a
|
||||
> research-pick turn.
|
||||
|
||||
On `ar-oracle-A-post.sav` exactly one player satisfies that: **Player[32]**, `NumOwn 18`. That is
|
||||
the whole basis of P1, and it is why P1 names Player[32]'s leaves and no one else's.
|
||||
|
||||
*(Note for honesty: players 496 and 512 — the two `Spengler` NPCs — hold non-empty `ResTNm` and also
|
||||
have `NumOwn == 0`. They are not evidence either way; they are listed in §2 for completeness.)*
|
||||
|
||||
### 1.5 What this lane will not settle (rule 15)
|
||||
|
||||
- **Two processes, not three**, for part 1 — rule 26's bar, matching AR's.
|
||||
- **One state.** Neither part says anything about `ad-turn27`, which is probe 2's job on VM146.
|
||||
- **The producer gate is not run here** unless part 1 comes out as agreement and time allows; if it
|
||||
does not, this document names it as the next step rather than guessing at it.
|
||||
- **`0x0069dbb0`'s 3–40-turn fuse cannot fire** in a one-turn-from-load run, by construction — so
|
||||
neither part can say anything about it, in either direction.
|
||||
- **No instrument.** `hooks=off` throughout, so this lane measures behaviour and never attributes it
|
||||
to a draw site. The consumer identification is probe 3's job.
|
||||
|
||||
---
|
||||
|
||||
## 2. The exposure facts, read off the saves before the runs (rule 26 (c))
|
||||
|
||||
`uv run python3 verify/save-reader/save_reader.py --json`, three saves on the AD/AR lineage.
|
||||
`NumDes` = the `designs` list length, `NumOwn` = the `owners` list length (both are the on-wire count
|
||||
prefixes; verified against the `--dump` tree at `NumOwn`/`NumDes`). "ships +" is the per-owner
|
||||
`ShipID` set delta from the previous save in the lineage.
|
||||
|
||||
### 2.1 `ar-oracle-A-pre.sav` — Frame 38, `ModCount 2108`, the input to part 1b
|
||||
|
||||
| PID | PlyrIdx | name | species | NPC | `ResTNm` | `NumDes` | `NumOwn` | ships | fleets |
|
||||
|---|---|---|---|---|---|---|---|---|---|
|
||||
| 16 | 0 | `re` (human) | 0 | no | `''` | 6 | 3 | 5 | 5 |
|
||||
| **32** | **1** | **The Eternal Empire** | 2 | no | **`BIO_EnvTail`** | **47** | **18** | 243 | 59 |
|
||||
| 496 | 2 | Spengler | 0 | yes | `DRV_PlsFiss` | 0 | 0 | 0 | 0 |
|
||||
| 512 | 3 | Spengler | 2 | yes | `XNC_TrnsMorr2` | 0 | 0 | 0 | 0 |
|
||||
| 528 | 4 | Alien Menace | 4 | yes | `''` | 19 | 0 | 0 | 0 |
|
||||
| 544 | 5 | Peacekeeper Enforcer | 4 | yes | `''` | 1 | 0 | 0 | 0 |
|
||||
| 560 | 6 | Von Neumann | 4 | yes | `''` | 6 | 0 | 0 | 0 |
|
||||
| 576 | 7 | Independent Colony | 4 | yes | `''` | 1 | 0 | 0 | 0 |
|
||||
|
||||
**Predicate reading for turn 38→39:** the only player that can research holds a target
|
||||
(`BIO_EnvTail`), `NumDes` is constant at 47, `NumOwn` constant at 18. **No exposed decision
|
||||
predicted** — which is exactly what AR measured (three processes agreed). Part 1b is therefore a
|
||||
*re-run of an agreeing turn from a load*, and its only open question is the load boundary itself.
|
||||
|
||||
### 2.2 `ar-oracle-A-post.sav` — Frame 39, `ModCount 2147`, the input to part 1
|
||||
|
||||
| PID | PlyrIdx | name | species | NPC | `ResTNm` | `NumDes` | `NumOwn` | ships | fleets |
|
||||
|---|---|---|---|---|---|---|---|---|---|
|
||||
| 16 | 0 | `re` (human) | 0 | no | `''` | 6 | 3 | 5 | 5 |
|
||||
| **32** | **1** | **The Eternal Empire** | 2 | no | **`''`** ← **pick signature** | **47** | **18** | 245 | 59 |
|
||||
| 496 | 2 | Spengler | 0 | yes | `DRV_PlsFiss` | 0 | 0 | 0 | 0 |
|
||||
| 512 | 3 | Spengler | 2 | yes | `XNC_TrnsMorr2` | 0 | 0 | 0 | 0 |
|
||||
| 528 | 4 | Alien Menace | 4 | yes | `''` | 19 | 0 | 0 | 0 |
|
||||
| 544 | 5 | Peacekeeper Enforcer | 4 | yes | `''` | 1 | 0 | 0 | 0 |
|
||||
| 560 | 6 | Von Neumann | 4 | yes | `''` | 6 | 0 | 0 | 0 |
|
||||
| 576 | 7 | Independent Colony | 4 | yes | `''` | 1 | 0 | 0 | 0 |
|
||||
|
||||
**Predicate reading for turn 39→40: EXPOSED.** Player[32] enters with `ResTNm == ''` and `NumOwn 18`.
|
||||
`otch` moved 46 → 47 across turn 39 (`BIO_EnvTail` completed), which is the same shape AS recorded.
|
||||
|
||||
### 2.3 Ship completions on the lineage, for the fleet-assignment half of the predicate
|
||||
|
||||
| transition | `ModCount` | PID 16 ships | PID 32 ships | reading |
|
||||
|---|---|---|---|---|
|
||||
| turn 37 → 38 | 2057 → 2108 | **−7408** (`Zeta Fleet`'s destroyer, lost in the encounter) | **+8784, +8800** | 2 completions, into existing fleets — not a batch |
|
||||
| turn 38 → 39 | 2108 → 2147 | none | **+8816, +8832** | 2 completions, into existing fleets — not a batch |
|
||||
|
||||
Two ships a turn into existing `Freighters` fleets is the *quiet* fleet consumer, not the
|
||||
thirteen-into-five-new-fleets batch that AD's turn 28 carried. `designIds` is constant at 95 and
|
||||
`fleetIds` at 64 across both transitions, corroborating "no design turn, no fleet creation".
|
||||
|
||||
**So: on the input to part 1b the predicate says NOT exposed; on the input to part 1 it says
|
||||
EXPOSED, via the research pick, for exactly one player.**
|
||||
|
||||
---
|
||||
|
||||
## 3. Procedure and configuration
|
||||
|
||||
`hooks=off` throughout, no build (rule 24 is satisfied trivially — nothing is compiled).
|
||||
|
||||
| item | value |
|
||||
|---|---|
|
||||
| guest | VM145 `sots-re-win10-145`, 192.168.10.145 |
|
||||
| shim build | `C:\SOTS\shimdist-l4\binkw32.dll`, `BUILD_ID l4r-20260908T2208Z` |
|
||||
| config | `C:\SOTS\shimdist-l4\shim.cfg.l4off`, **unmodified** — `hooks=off`, installs nothing |
|
||||
| why this build | lane L4 proved *on this guest, with this exact DLL and this exact config* that VM145 reproduces the campaign's published autosave oracle byte-identically (`ai-order-capture.md` §3: `bb4fd9ac89f41e3b` / `978041acd168b56e`). It is the only hooks=off pair on VM145 with a published byte-fidelity result behind it |
|
||||
| `SavedGames` | reset to **exactly one file** — the run's input save — before every launch, so the Load dialog has one row and its position is re-derived from a screenshot anyway |
|
||||
| main menu | verified from a `qm monitor` screendump (`tools/vmshot.py --one 145`), never by sleeping |
|
||||
| encounter query | detected by sampling the `Done` pixel at (233, 673): ≈(183,18,0) query up, ≈(8,8,8) map. `Auto Resolve Peacefully` (667,641), `Done` (233,673) |
|
||||
|
||||
**VM145 as found**, recorded so it can be put back (§8):
|
||||
|
||||
```
|
||||
binkw32.dll 15,527,327 B sha256 903527f4a698eea9fbe25f3a6236657c7d8348f994eef394696f187e5e554b97
|
||||
(= shimdist-recap, BUILD_ID recap-7584bad-20260908T0615Z)
|
||||
shim.cfg sha256 0ae410cc72fe155837d711c78543e14b1f5743310cd023298eb1e5bbd5457e71 (hooks=trace, lane R recapture)
|
||||
SavedGames 9 files, saved to C:\SOTS\ui\preBQ\
|
||||
game not running
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Results
|
||||
|
||||
*(added after the runs; nothing above this line is edited)*
|
||||
|
||||
---
|
||||
|
||||
## 5. Verdicts on the committed predictions
|
||||
|
||||
*(added after the runs)*
|
||||
|
||||
---
|
||||
|
||||
## Proposed board rows
|
||||
|
||||
*(added after the runs)*
|
||||
|
|
@ -299,655 +299,3 @@ From `as-turn14-predeploy.sav`, one Deploy Spy order, one End Turn, `probes=8`:
|
|||
---
|
||||
|
||||
*(End of the pre-registered section. Everything below is measurement.)*
|
||||
|
||||
---
|
||||
|
||||
## 4. What was run
|
||||
|
||||
Shim build **`ap-989c692-20260909T0425Z`**, cross-built on CT111 in this lane's own directory
|
||||
`/srv/re-lab/build/sots-engine-ap` after `rm -rf` of the whole tree, from a lane-private
|
||||
`git worktree` at `~/sots-engine-ap` with no local `build*` shipped (rules 21 and 24). `binkw32.dll`
|
||||
sha256 `ae084ed4774caf24ea7927fcb012d1999633f10556c7c99f0209f66067416a17`. Staged to
|
||||
`/srv/re-lab/shim/dist-ap`, deployed to `C:\SOTS\shimdist-ap` on VM144. **This lane wrote no engine
|
||||
code**; `shim.cfg.hp8` and `shim.cfg.hoff` were used unmodified.
|
||||
|
||||
| run | config | input | End Turns | purpose |
|
||||
|---|---|---|---|---|
|
||||
| **W** | `shim.cfg.hp8` (`probes=8`) | `MyGameas1spydep.sav` (Frame 15) | **11** (15 → 26) | target 1 |
|
||||
| **D** | `shim.cfg.hp8` | `MyGameas1predeploy.sav` (Frame 14) + one `Deploy Spy` order | 1 | target 2 |
|
||||
| **OA / OB** | `shim.cfg.hoff` | `MyGameas1spydep.sav` | 1 each, two fresh processes | control (§7) |
|
||||
|
||||
**Instrument armed and verified from `shim.log`, not assumed** (rule 1). Both instrumented runs:
|
||||
seven `drawsite:` detours `create=MH_OK enable=MH_OK`; `config: probes=8 -> 8 lane-H entry probes`
|
||||
and all eight `create=MH_OK enable=MH_OK`; **zero** `COVERAGE:` lines; **zero**
|
||||
`config: ignoring unknown key` lines; `draw_site_overflow = 0` on every turn. Probe indices 8–11
|
||||
report **NOT INSTALLED**, never 0. The one `MH_ERROR_ALREADY_CREATED` line is the `fpu` module
|
||||
losing the race for `BeginProcessTurn` to the ledger; it is present verbatim in lanes AC, AD, AR and
|
||||
AS's logs, so this is the same instrument those lanes ran.
|
||||
|
||||
**`probes=11` was not used anywhere in this lane.** No number here is comparable to lane AC's turn
|
||||
totals.
|
||||
|
||||
### 4.1 The wait cost eleven minutes, not an evening
|
||||
|
||||
The brief budgeted "~20 End Turns, expensive in wall-clock". On this state an End Turn under
|
||||
`probes=8` completes in **6 seconds**; the eleven turns took **11 minutes** including the load. The
|
||||
expensive part is the launch (~2 min through the intro movies) and the load (~3 min). Turn 27 hit a
|
||||
Von Neumann encounter dialog at Rigel and the driver stopped on it exactly as designed; by then the
|
||||
question was answered and the run was ended there rather than clicked through.
|
||||
|
||||
The driver is worth carrying forward: a scheduled task (`SOTSAP`) running an in-guest loop that
|
||||
clicks End Turn, then **polls the autosave's mtime** — never a button colour, which is lane AS's
|
||||
lesson — snapshots `(Autosave).sav` per turn, and stops on the first stall with a screenshot. It is
|
||||
left at `C:\SOTS\ui\ap\ap_loop.ps1`.
|
||||
|
||||
---
|
||||
|
||||
## 5. Target 1 — the wait, measured turn by turn
|
||||
|
||||
Detection landed on **Frame 22**, seven turns in. `P` therefore ran on **Frame 25**.
|
||||
|
||||
### 5.1 The per-turn ledger
|
||||
|
||||
Every row is `draw_sites` at the post-turn autosave marker, which the shim resets at the pre-turn
|
||||
marker — so these are **per-turn** figures, not cumulative.
|
||||
|
||||
| Frame | `0x00887c8a` spy 13 | `0x0088dc43` spy 14 | `0x00840a3c` `P` B1 | `0x00820e1d` trade raid | tail bracket | probe `vslot13` | probe `Slot13RngCallee` |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| 16 | **1** | — | — | — | **1** | 1 | 0 |
|
||||
| 17 | **1** | — | — | — | **1** | 1 | 0 |
|
||||
| 18 | **1** | — | — | — | **1** | 1 | 0 |
|
||||
| 19 | **1** | **1** ← first ever | — | — | **2** | 1 | 0 |
|
||||
| 20 | **1** | **1** | — | 2 | **4** | 1 | 0 |
|
||||
| 21 | **1** | **1** | — | 4 | **6** | 1 | 0 |
|
||||
| **22** | **1** ← succeeds, `sdet := 22` | **1** | — | 7 | **9** | 1 | 0 |
|
||||
| 23 | **—** | **1** | — | 7 | **8** | **1** | 0 |
|
||||
| 24 | **—** | **1** | — | 8 | **9** | **1** | 0 |
|
||||
| **25** | **—** | **—** | **1** ← first ever | 7 | **8** | **1** | **1** ← first ever |
|
||||
| 26 | — | — | — | 8 | **8** | 1 | 0 |
|
||||
|
||||
Every cell is `calls = words`, `no_draw_calls = 0`, `strategic = true`. **The tail bracket equals the
|
||||
sum of its rows on all eleven turns: residual 0 every turn**, and `draw_site_overflow = 0`.
|
||||
|
||||
Three lines of that table are the lane:
|
||||
|
||||
> **Frame 25:** `entry = Chance`, `ret_rva = 0x0044_0a41` (VA `0x00840a41`, the instruction after
|
||||
> `call 0x8e6dd0` at `0x00840a3c`), `calls = 1`, `words = 1`, `no_draw_calls = 0`,
|
||||
> `strategic = true`. **`0x00840a3c` had never fired in this campaign.**
|
||||
>
|
||||
> **Frames 23 and 24:** no row at `0x0048_7c8f` at all, while the entry probe on
|
||||
> `ServerSpyManager::vslot13` reads **1** on both. That is "entered and gated", not "did not run" —
|
||||
> rule 28 practice 1, in a third distinct arm of the same function.
|
||||
>
|
||||
> **Frame 25, the probe column:** `Game::SpyManager::Slot13RngCallee 0x008408e0` reads **1**. Lane AS
|
||||
> demonstrated that this probe's **zero** said nothing about the subtree. This is the other half:
|
||||
> the same probe, on the one turn the callee is actually entered, reads one.
|
||||
|
||||
### 5.2 `0x00840929` and `0x008409c7` did not fire, and could not have
|
||||
|
||||
Neither site appears in any of the eleven turns, including Frame 25 — the one turn `P` ran. **PA1
|
||||
held.** The reason is not a state we failed to build: `P`'s first instruction pair is
|
||||
`cmp [spyOwner+0x5c], 6` / `jne`, the spy's owner is player 16 `re` with `Species = 0` (Human), and
|
||||
the launch card confirms it in the UI. Branch A is a **Morrigi-only** path.
|
||||
|
||||
> The brief that created this lane, lane AS's §6, board row 207 and lane AG's §6 all list
|
||||
> `0x00840929` / `0x008409c7` / `0x00840a3c` as three sites behind one gate. They are **two
|
||||
> mutually exclusive branches selected by species**, and no workload can fire more than one of them
|
||||
> per call. To reach the other two, a lane must play a **Morrigi** empire, deploy a spy, and lose it.
|
||||
|
||||
### 5.3 `sdo` — the accumulator, exact to the float32
|
||||
|
||||
Read from the eleven autosaves. Prediction PB1 was `sdo(f) = 0.0084 × (f − 14)` as a float32.
|
||||
|
||||
| Frame | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
|
||||
|---|---|---|---|---|---|---|---|---|---|
|
||||
| `sdo` | 0.016800 | 0.025200 | 0.033600 | 0.042000 | 0.050400 | 0.058800 | 0.067200 | 0.067200 | 0.067200 |
|
||||
| bits | `3c89a027` | `3cce703a` | `3d09a027` | `3d2c0831` | `3d4e703b` | `3d70d845` | `3d89a027` | frozen | frozen |
|
||||
|
||||
Seven consecutive exact steps of 0.0084, then **frozen** the moment `sdet` stamps — because branch D
|
||||
is the only writer of `sdo` and `sdet != -1` skips it. The freeze is a second, save-side proof that
|
||||
the branch stopped running on Frames 23 and 24, independent of the ledger's zero.
|
||||
|
||||
Lane AS measured two points of this line (0 → 0.0084 → 0.0168) and derived the rest. **Nine points
|
||||
now lie on it**, and `countC` stayed at 2 for the whole window, so `sdo`'s per-turn increment is a
|
||||
constant on this state rather than a fitted one.
|
||||
|
||||
### 5.4 The counter-mission machine, measured for the first time
|
||||
|
||||
`0x0088dc43` (lane AG §3.2) had **corpus count 0 of 22** and had never fired. It fires here from
|
||||
Frame 19, one call and one word per turn, and the save-side state machine is fully visible:
|
||||
|
||||
| Frame | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| `spyon` | **32** | 32 | 32 | 32 | 32 | 32 | 32 | — |
|
||||
| `cm` | **1** | 1 | **2** | 2 | **3** | 3 | **4** | — |
|
||||
| `cmo` | 0.2 | 0.4 | 0.2 | 0.4 | 0.2 | 0.4 | 0.2 | — |
|
||||
| `ncp` | 0 | 0 | **1** | 1 | **2** | 2 | **3** | — |
|
||||
| words at `0x0088dc43` | **0** | 1 | 1 | 1 | 1 | 1 | 1 | **0** |
|
||||
|
||||
Everything AG decoded statically is confirmed, and four things are added:
|
||||
|
||||
1. **The bootstrap turn costs nothing.** Frame 18 is `Frame − tdep == 3`; `vslot14` sets `spyon`,
|
||||
runs the stage machine `cm: 0 → 1` and `cmo := 0.2f`, and **does not draw**. The first draw is
|
||||
Frame 19. PB3 predicted exactly this and it held.
|
||||
2. **`cmo` steps by `0.2f` on failure and resets to `0.2f` on success**, as decoded. The stage
|
||||
advanced on Frames 20, 22 and 24 — always on the second try, at `p = 0.4`. Six rolls, three
|
||||
successes; expectation at (0.2, 0.4) alternating is 2.4. Consistent, not validated.
|
||||
3. **`ncp` is a scalar counter of completed stages, not a container.** It is a plain `int` item in
|
||||
the stream and it increments by exactly 1 on each stage completion (0,0,1,1,2,2,3), in lock-step
|
||||
with `cm`. AG's decode reads the `cm == 0` branch as gated on "`ncp` non-empty"; that gate was
|
||||
**never reached** here, because `cm` never returned to 0 before the spy was destroyed. It stays a
|
||||
rule-6 hypothesis — and a sharper one now that `ncp`'s values are known.
|
||||
4. **The `CnTrd` the stage machine consults is the TARGET's, not the spy owner's.** AG's caution to
|
||||
lane AS was that a spy program run without FTL Economics takes the `1 → 3` arm. This run took
|
||||
`1 → 2`, and in the save **my player (16) has `CnTrd = False` while Kepler's owner (32) has
|
||||
`CnTrd = True`**. So `owner->+0xff` at that branch is the **victim** empire's FTL Economics. The
|
||||
caution as written would have mispredicted this run.
|
||||
|
||||
`cm`, `cmo`, `spyon` and `ncp` are four of the 234 fields the value-domain census lists as having
|
||||
only ever held one value. **All four are now off zero**, with a measured trajectory each.
|
||||
|
||||
### 5.5 The spy is destroyed at `sdet + 3`, and `vslot13` does it
|
||||
|
||||
`nspy` goes **1 → 0** between the Frame-24 and Frame-25 autosaves, `spies2` at Kepler returns to
|
||||
`count = 0`, and the `spymgr` record loses its only `spy` child. That is `vslot13`'s drain loop at
|
||||
`0x00887eb0` calling manager vtable slot 10 `0x00838480`, which calls `ServerSystem::RemoveSpy
|
||||
0x0074f550`. **PA4 held.**
|
||||
|
||||
It also settles the ordering question in §1.4 behaviourally: `0x0088dc43` costs **0** on Frame 25
|
||||
although `vslot14`'s entry probe still reads 1. Phase 23 destroys the spy before phase 33 walks the
|
||||
list.
|
||||
|
||||
---
|
||||
|
||||
## 6. Target 2 — `0x0078c97f`, the site in no inventory, measured
|
||||
|
||||
Run D: `MyGameas1predeploy.sav` (Frame 14) in a fresh process under `probes=8`; Kepler selected on
|
||||
the map; `Special → Deploy Spy → OK`; one End Turn.
|
||||
|
||||
```
|
||||
draw_sites, post-turn autosave marker, the row verbatim:
|
||||
|
||||
entry = NextFloat
|
||||
ret_rva = 0x0038_c984 (VA 0x0078c984 -- after `call 0x47d830` at 0x0078c97f)
|
||||
calls = 1
|
||||
words = 1
|
||||
no_draw_calls = 0
|
||||
strategic = true
|
||||
|
||||
boundary ledger, same turn:
|
||||
|
||||
BeginProcessTurn 326 -> 326 0
|
||||
ProcessTurn 326 -> 344 18 <-- the deploy draw is in here
|
||||
OnAllCombatDone_Tail 344 -> 345 1 <-- the first detection roll, sdo = 0.0084
|
||||
Autosave 345 -> 345 0
|
||||
```
|
||||
|
||||
**PC1, PC2 and PC3 all held exactly.** The site fires once per applied `SHIPACTION_DEPLOYSPY`
|
||||
command, for one word, on the strategic generator, inside the `ProcessTurn` bracket — and the same
|
||||
turn's tail costs exactly 1, because `ApplyAllTurnCommands` runs before `OnAllCombatDone_Tail` and
|
||||
the freshly deployed spy is immediately eligible for its first detection roll.
|
||||
|
||||
It appears in **no other turn of this lane**: eleven turns of run W carry no row at `0x0038c984`.
|
||||
That is the stream predicate showing its shape — the site's cost is not a function of the save at
|
||||
all, it is a function of what the player ordered.
|
||||
|
||||
### 6.1 The sharpest prediction held: the deploy draw is reproducible across processes
|
||||
|
||||
**PC4.** Lane AS's `as-turn15-spydeployed.sav` was written by a different process, on a different
|
||||
day, from a different build. This lane's Frame-15 autosave was written by run D.
|
||||
|
||||
```
|
||||
lane AS spy.cbh = 5.033599376678467 (float32 0x40A11333)
|
||||
lane AP spy.cbh = 5.033599376678467 identical
|
||||
cbh / 2pi = 0.8011222000
|
||||
```
|
||||
|
||||
The same input state plus the same order drew the same word, in two processes separated by hours and
|
||||
by a rebuild. Together with `deat = 400`, `tdep = 15`, `sdo = 0.0084`, `sdet = -1` and `spies2 = [1]`
|
||||
at Kepler reproducing exactly (**PC5**), this says the **strategic** generator's consumption up to
|
||||
`ApplyAllTurnCommands` is deterministic given the save — the per-process AI client seed does not
|
||||
reach it. It is a much stronger statement than a whole-file hash comparison, because it isolates one
|
||||
word to one site.
|
||||
|
||||
### 6.2 A correction to lane AS's reading of the same bytes
|
||||
|
||||
AS gives the site as `cbh = NextFloat() * 2*pi`. The value is right; the expression is the
|
||||
campaign's standard range idiom with `LO` supplied by an `fldz`:
|
||||
|
||||
```
|
||||
0078c984 fld qword [0x009e21b0] ; HI = 6.2831854820251465
|
||||
0078c98a fldz ; LO = 0.0
|
||||
0078c994 fsub st(1),st ; HI - LO
|
||||
0078c99b fmulp st(1),st ; (HI - LO) * r
|
||||
0078c99d fstp [ebp+8] ; through a FLOAT32 temp
|
||||
0078c9a0 fadd [ebp+8] ; LO + that
|
||||
```
|
||||
|
||||
so it is `lerp(0.0, 2*pi, r)` **rounded to float32 mid-expression**, not a `double` multiply. A
|
||||
reimplementation that computes `r * 6.2831854820251465` in double and stores at the end can differ in
|
||||
the last bit.
|
||||
|
||||
The other half of the sequence is worth writing down because it reads wrong at first glance:
|
||||
|
||||
```
|
||||
0078c998 push ecx ; reserve DeploySpy's SECOND argument slot
|
||||
0078c9a9 fstp [esp] ; slot := the angle
|
||||
0078c9ac call 0x0080c860 ; __thiscall getter, `mov eax,[ecx+0xa8]; ret` -- NO stack args,
|
||||
; so it leaves the angle slot untouched. eax = the spy's id.
|
||||
0078c9ba push eax ; the FIRST argument
|
||||
0078c9bb call edx ; ServerSpyManager::DeploySpy(spyId, angle)
|
||||
```
|
||||
|
||||
`0x0080c860` looks like it consumes the float and does not; the compiler built the argument list out
|
||||
of order and called a zero-argument getter across the half-built frame. **`DeploySpy` takes two
|
||||
arguments**, and `0x008874b0 fld [ebp+0xc]` / `0x008874c0 fstp [esi+0x18]` is where `cbh` is
|
||||
written. Lane AS's *"`spy->cbh (+0x18) := <the float argument>`"* is exactly right; this only names
|
||||
which argument and shows why an eye following `eax` misses it.
|
||||
|
||||
---
|
||||
|
||||
## 7. The control — a truthful non-pair, and the exposure predicate checked against it
|
||||
|
||||
Two fresh `hooks=off` processes (**OA**, **OB**) on the same input, one End Turn each, plus this
|
||||
lane's instrumented run **W** and lane AS's three runs from the day before. Six processes, one
|
||||
input, one End Turn.
|
||||
|
||||
### 7.1 The hashes
|
||||
|
||||
```
|
||||
input MyGameas1spydep.sav 854a10fa1ea602f0f7909f9bf9154942e56ea5fa1db4cce47d6d32bf53952e08
|
||||
```
|
||||
|
||||
| run | lane | config | pre-turn `(Autosave EndTurn).sav` | post-turn `(Autosave).sav` | size |
|
||||
|---|---|---|---|---|---|
|
||||
| A | AS | `hoff` | `98e45d3745b91450…` | `262f8bda97c9511d…` | 77,685 |
|
||||
| B | AS | `hoff` | `98e45d3745b91450…` | `e34775a757e6fb3d…` | 77,649 |
|
||||
| M | AS | `probes=8` | `98e45d3745b91450…` | `262f8bda97c9511d…` | 77,685 |
|
||||
| **W** | **AP** | `probes=8` | — | **`262f8bda97c9511d…`** | 77,685 |
|
||||
| **OA** | **AP** | `hoff` | **`98e45d3745b91450…`** | **`e296394f578b3a56…`** | 77,677 |
|
||||
| **OB** | **AP** | `hoff` | *(§7.4)* | *(§7.4)* | |
|
||||
|
||||
**The pre-turn save is byte-identical across four processes, two lanes and two builds** — including
|
||||
this lane's own, which is not lane AS's binary. That is the strongest statement available about the
|
||||
input, and it is what makes the post-turn comparison meaningful.
|
||||
|
||||
**The post-turn saves are not.** Five processes have produced **three** distinct outcomes:
|
||||
`262f8bda` (three times: AS's A, AS's M, this lane's W), `e34775a7` (once: AS's B), `e296394f`
|
||||
(once: this lane's OA).
|
||||
|
||||
> **This is not a calibration pair and must not enter `determinism-hashes.txt`.** Said in advance as
|
||||
> PD3, and it is the honest verdict rather than a post-hoc excuse.
|
||||
|
||||
### 7.2 What varies, localised by sub-tree
|
||||
|
||||
`state_checksum --no-audit --floats bits --mask none`, OA against W:
|
||||
|
||||
```
|
||||
DIVERGED: 15 leaf difference(s)
|
||||
/Summary/Checksum 985948923 -> 985948837
|
||||
/Sim/turnstats/history/hist[1]/stats[15]/tch 45 -> 46
|
||||
/Sim/players/Player[32 "Revenge Fleet"]/TechTree/St[60] 3 -> 2
|
||||
/Sim/players/Player[32 "Revenge Fleet"]/TechTree/TResDone[60] 22469 -> 0
|
||||
/Sim/players/Player[32 "Revenge Fleet"]/TechTree/Tbd[60] 2 -> 1
|
||||
/Sim/players/Player[32 "Revenge Fleet"]/TechTree/St[64] 2 -> 4
|
||||
/Sim/players/Player[32 "Revenge Fleet"]/TechTree/TResDone[64] 0 -> 22469
|
||||
/Sim/players/Player[32 "Revenge Fleet"]/TechTree/TAcq[64] -1 -> 16
|
||||
/Sim/players/Player[32 "Revenge Fleet"]/TechTree/TiAcq[64] -1 -> 45
|
||||
/Sim/players/Player[32]/Events/…/EvDsc 'Research Over Budget' -> 'Research Complete'
|
||||
/Sim/players/Player[32]/Events/…/EvMsg 'Research for Micro-Fusion Drives has gone overbudget.'
|
||||
-> 'Tech Overthrusting has been acquired'
|
||||
/Sim/players/Player[32]/Events/…/EvImg 'EVENT_RESEARCH_OVERBUDGET' -> 'EVENT_RESEARCH_COMPLETE'
|
||||
/Sim/players/Player[32 "Revenge Fleet"]/ResTNm 'DRV_McroFus' -> ''
|
||||
/Sim/players/Player[32 "Revenge Fleet"]/otch/.[34] only-in-B
|
||||
/Sim/players/Player[32 "Revenge Fleet"]/otch/.[0] 33 -> 34
|
||||
```
|
||||
|
||||
**And the sub-tree digests say which halves of the save are affected**, which is the form the claim
|
||||
should take (PD4):
|
||||
|
||||
| sub-tree | OA | W | |
|
||||
|---|---|---|---|
|
||||
| `Sim/spymgr` | `9c3f224cf954aa54` | `9c3f224cf954aa54` | **identical** |
|
||||
| `Sim/systems` | `3227b08124339fe2` | `3227b08124339fe2` | **identical** |
|
||||
| `Sim/fleets` | `26a640cdfc597869` | `26a640cdfc597869` | **identical** |
|
||||
| `Sim/trdmgr` | `ed99071bdc121694` | `ed99071bdc121694` | **identical** |
|
||||
| `Sim/players` | `2d1c0cad92679606` | `46ddf6778ef36e0b` | differs |
|
||||
| `Summary` | `66db5e1055c9fe37` | `cb8a4c8e22480af0` | differs (the derived checksum) |
|
||||
|
||||
> **Every leaf this lane's numbers depend on reproduces across the pair. `spymgr` — the spy's
|
||||
> `deat`, `sdet`, `sdo`, `cm`, `cmo`, `ncp`, `cbh` — is byte-identical between an instrumented run
|
||||
> and an un-instrumented one, as is every system's `spies2`.** What does not reproduce is one AI
|
||||
> empire's research pick and the two derived values downstream of it.
|
||||
|
||||
**Three distinct picks across five processes** is worth stating plainly, because it is the first
|
||||
time this outcome set has been sampled more than twice: A/M/W completed `Overthrusting` (tech 64),
|
||||
B was part-way through `DRV_NodFoc`, OA went over budget on `DRV_McroFus`. AS observed A and M
|
||||
agreeing and correctly flagged it as a `1/k` coincidence rather than evidence about the instrument.
|
||||
With five samples the set has at least three members and the modal outcome took 3 of 5 — so the
|
||||
coincidence AS refused to lean on was about a 1-in-3 event, not a 1-in-2 one, and refusing to lean
|
||||
on it was right.
|
||||
|
||||
### 7.3 The seed-exposure predicate, checked (rule 26 corollary (c))
|
||||
|
||||
The coordinator's instruction is to record the exposure fields next to every control hash. Here they
|
||||
are for the **pre-turn** save of the control pair, and for every turn this lane played, so the
|
||||
predicate can be checked rather than asserted. `Species = 4` (NPC) players are omitted; they never
|
||||
decide. Net ids: player 16 is `re` (human), 32 is `Revenge Fleet` (the AI), 48 is `Spengler`.
|
||||
|
||||
| pre-turn save | Frame | Player[32] `ResTNm` | `NDes` | `NOwn` | ships | exposure |
|
||||
|---|---|---|---|---|---|---|
|
||||
| `as-turn14-predeploy` | 14 | **`''`** | 15 | 10 | 146 | **pick** |
|
||||
| **`as-turn15-spydeployed`** (the control input) | **15** | **`''`** | **15** | **10** | **146→148** | **pick + colonise + 2 ships** |
|
||||
| `w-16` | 16 | `''` | 15 | 11 | 157 | pick + 9 ships |
|
||||
| `w-17` | 17 | `''` | 16 | 12 | 161 | pick + design + colonise + 4 ships |
|
||||
| `w-18` | 18 | `''` | 20 | 12 | 169 | pick + 4 designs + 8 ships |
|
||||
| `w-19` | 19 | `''` | 20 | 12 | 181 | pick + 12 ships |
|
||||
| `w-20` | 20 | `'WEP_AmWhd'` | 20 | 12 | 185 | 4 ships |
|
||||
| `w-21` | 21 | `'WEP_AmWhd'` | 23 | 12 | 201 | 3 designs + 16 ships |
|
||||
| `w-22` | 22 | `'WEP_AmWhd'` | 27 | 12 | 218 | 4 designs + 17 ships |
|
||||
| `w-23` | 23 | `'WEP_AmWhd'` | 27 | 12 | 236 | 18 ships |
|
||||
| `w-24` | 24 | `'WEP_AmWhd'` | 27 | 14 | 235 | colonise ×2 |
|
||||
| `w-25` | 25 | `''` | 28 | 15 | 244 | pick + design + colonise + 9 ships |
|
||||
| `w-26` | 26 | `''` | 28 | 15 | 251 | pick + 7 ships |
|
||||
|
||||
**The predicate held, and it held in its strong direction.** The control input carries
|
||||
`Player[32].ResTNm == ''` — a pick turn — and the control varied, in exactly the research-pick leaves
|
||||
the predicate names and nothing else. Two independent lanes have now produced that signature on this
|
||||
input.
|
||||
|
||||
**And the state says something the predicate did not anticipate: on this map exposure is
|
||||
*saturated*.** Every one of the thirteen pre-turn states above carries at least one exposure
|
||||
signature; nine of thirteen carry a research pick, and every single turn adds ships. There is **no
|
||||
quiet turn anywhere in this lineage** to attempt an agreeing control on — so no rung-A oracle pair is
|
||||
obtainable from `as-turn15-spydeployed.sav` at any horizon by waiting, and a lane that wants one on
|
||||
this map must pin the client seeds instead. That is a fact about a 2-empire game where the AI runs a
|
||||
146 → 251-ship war economy, and it is the opposite end of the same axis from lane AR's quiet
|
||||
turns 38–39.
|
||||
|
||||
**One nuance that cuts against a naive reading of the predicate.** Exposure is necessary for
|
||||
variation, not sufficient *per process pair*: W (`probes=8`) and AS's A and M (two different
|
||||
configurations, two different builds, three different processes) landed on the **same** post-turn
|
||||
bytes on this exposed pick turn. A single agreeing pair on an exposed turn therefore proves nothing —
|
||||
which is rule 26's original point, now with a measured outcome-set size behind it.
|
||||
|
||||
### 7.4 OB, and the verdict
|
||||
|
||||
```
|
||||
OB (Autosave EndTurn).sav 98e45d3745b914506fc4c409ad5a5ad0938a2003ab4c845421a99a8065149c3a 76,706
|
||||
OB (Autosave).sav 262f8bda97c9511d8d2b41e6a8a0582d6f5364c2b01b1caf99e639d0e4f53ebe 77,685
|
||||
```
|
||||
|
||||
* **OA ≠ OB.** The two `hooks=off` processes of *this* lane's own control disagree, in **15 leaves,
|
||||
all of them** `Player[32]`'s research pick plus `/Summary/Checksum` and the `turnstats` `tch` cell.
|
||||
Nothing of my empire, the spy, `deat`, `sdet`, `sdo`, `cm`, `cmo`, `ncp`, `spies2`, the systems,
|
||||
the fleets or `trdmgr` moved between them.
|
||||
* **OB is byte-identical to W**, the instrumented run: `state_checksum` prints **IDENTICAL** over
|
||||
**44,438 leaves**. Both are `fc85c4228b9973fa159c1ed6aa851ae0`.
|
||||
|
||||
So the honest three-part statement, which is all the evidence supports:
|
||||
|
||||
1. **Not a calibration pair.** Two fresh un-instrumented processes on this input do not agree, so
|
||||
nothing here may enter `determinism-hashes.txt` as a rung-A pair. **PD1 and PD3 held.**
|
||||
2. **The instrument is neutral on everything this lane measured.** `probes=8` reproduced an
|
||||
un-instrumented run leaf for leaf, and the sub-trees carrying the spy state are identical across
|
||||
all three of this lane's processes. **PD4 held.** That is a stronger neutrality statement than
|
||||
lane AS could make, because AS's instrumented run agreed with only one of two controls; here it
|
||||
agrees with one control *exactly and completely* while the two controls differ from each other in
|
||||
a leaf class the instrument provably does not touch.
|
||||
3. **The divergence is the known one, and it was predicted.** **PD2 held**, and it held with the
|
||||
pre-turn exposure fields recorded in advance (§7.3) rather than diagnosed afterwards.
|
||||
|
||||
**A note for whoever certifies pairs.** Lane AS reported A ≠ B and called the class "one AI player's
|
||||
research pick plus the derived checksum". Two more processes, taken independently, land in the same
|
||||
class and add a third member to the outcome set. That is a second lane reproducing the *class* while
|
||||
failing to reproduce the *value* — which is exactly what a per-process seed feeding a small
|
||||
discrete choice should look like, and it is now measured rather than asserted.
|
||||
|
||||
---
|
||||
|
||||
## 8. Predictions scored — including the one that was wrong
|
||||
|
||||
| | prediction | verdict |
|
||||
|---|---|---|
|
||||
| **PA1** | `P` reaches at most one draw site per call, selected by `Species == 6`; only `0x00840a3c` from this save | **HELD.** No row at `0x0044092e` or `0x004409cc` on any of the twelve measured turns, including the turn `P` ran |
|
||||
| **PA2** | species table `0 Human … 4 _NPC, 5 Zuul, 6 Morrigi`; `0.75f` is Zuul, `0.5f` is Morrigi | **HELD** (corpus-wide; the launch card independently shows `re` = Human) |
|
||||
| **PA3** | `0x00840a3c` is `Chance` on a widened `0.25f` | **HELD** — `0x009e5ac0` is `00 00 80 3e` |
|
||||
| **PA4** | the spy is destroyed at the end of `vslot13` on the `P` turn | **HELD** — `nspy` 1 → 0, `spies2` emptied, no `spy` record at Frame 25 |
|
||||
| **PB1** | `sdo(f) = 0.0084 × (f − 14)` exactly, until detection | **HELD** — seven exact float32 steps, then frozen |
|
||||
| **PB2** | tail costs 1 on Frames 16, 17, 18 | **HELD** |
|
||||
| **PB3** | `0x0088dc43` first fires on Frame 19; Frame 18 bootstraps without drawing | **HELD exactly** |
|
||||
| **PB4** | **the tail costs 2 words/turn from Frame 19** | **WRONG.** It costs 2 on Frame 19 and then 4, 6, 9, 8, 9, 8, 8 |
|
||||
| **PB5** | `cm`, `spyon` move on Frame 18; `cmo` steps by `0.2f` | **HELD** |
|
||||
| **PB6** | on the detection turn `vslot13` still costs 1 and `sdet := T` | **HELD** — Frame 22 |
|
||||
| **PB7** | `vslot13` costs **zero** on `T+1`, `T+2` while still being entered | **HELD** — Frames 23, 24: no row, probe reads 1 |
|
||||
| **PB8** | `T+3`: one row at `0x0044_0a41`, 1/1/0/strategic; no `0x0048_7c8f`; `vslot14` contributes 0 | **HELD in all three parts** |
|
||||
| **PB9** | the `Slot13RngCallee` probe reads 1 on `T+3` | **HELD** — its first non-zero in the campaign |
|
||||
| **PB10** | 11 % by +4, 43 % by +10, 70 % by +15, 87 % by +20 | **not tested.** Detection landed at +7, where the model says 26 %. One sample is consistent with the model and does not test it |
|
||||
| **PB11** | residual 0 on every turn | **HELD** on all eleven turns of W and on run D |
|
||||
| **PB12** | the +20 tail case | **not reached** |
|
||||
| **PC1** | `0x0038c984`, `NextFloat`, 1/1/0, strategic | **HELD exactly** |
|
||||
| **PC2** | in the `ProcessTurn` bracket | **HELD** |
|
||||
| **PC3** | the same turn's tail costs exactly 1 | **HELD** |
|
||||
| **PC4** | `cbh` reproduces `5.033599376678467` exactly | **HELD** |
|
||||
| **PC5** | `spies2` 0 → `[1]`, `deat` → 400, `tdep := 15`, `sdo := 0.0084` | **HELD** |
|
||||
| **PD1** | the control pair's pre-turn saves agree, post-turn saves differ | **HELD** |
|
||||
| **PD2** | the divergence is one AI's research pick + checksum + `tch`, and nothing of mine | **HELD** — 15 leaves, localised |
|
||||
| **PD3** | not a calibration pair; must not enter `determinism-hashes.txt` | **HELD**, and stated in advance |
|
||||
| **PD4** | the sub-trees this lane's numbers depend on reproduce | **HELD** — `spymgr`, `systems`, `fleets`, `trdmgr` digests identical; and W is byte-identical to OB over 44,438 leaves |
|
||||
|
||||
### 8.1 PB4, the one that was wrong, and why it was wrong
|
||||
|
||||
I predicted the **tail bracket** would cost 2 words per turn from Frame 19, on the reasoning that
|
||||
`vslot13` contributes 1 and `vslot14` contributes 1. Both halves of that were right on every single
|
||||
turn. The prediction was still wrong, because **the tail has a third contributor and I treated it as
|
||||
a constant zero.**
|
||||
|
||||
```
|
||||
Frame 16 17 18 19 20 21 22 23 24 25 26
|
||||
vslot13 1 1 1 1 1 1 1 0 0 0 0 <- predicted exactly
|
||||
vslot14 0 0 0 1 1 1 1 1 1 0 0 <- predicted exactly
|
||||
0x00820e1d 0 0 0 0 2 4 7 7 8 7 8 <- NOT PREDICTED
|
||||
tail bracket 1 1 1 2 4 6 9 8 9 8 8
|
||||
```
|
||||
|
||||
`0x00820e1d` is the **trade-raid roll** in `TradeManager::Slot13RngCalleeA` — lane AC's site, priced
|
||||
per fleet by lane AD. It was at zero on Frames 16–19 and entered the tail on Frame 20, growing to 8.
|
||||
That is the AI's raider fleets arriving on trade-sector nodes as its navy went from 157 to 251
|
||||
ships: **`calls == words == the number of qualifying fleets`, exactly lane AD's per-fleet model**,
|
||||
now reproduced on a different map, a different lineage and an AI-owned fleet rather than a
|
||||
player-owned one. AD measured 2; this run measured 2, 4, 7, 7, 8, 7, 8 on seven consecutive turns.
|
||||
|
||||
The lesson is rule 20's, in the direction nobody watches: I checked that my *sites* were priced, and
|
||||
then quoted a *bracket* total as if the bracket contained only my sites. A bracket is a sum over
|
||||
subsystems, and predicting one requires predicting all of them. The correct form of PB4 was "the
|
||||
**spy** contribution to the tail is 2 words per turn from Frame 19", which is what was measured and
|
||||
what should have been written.
|
||||
|
||||
**It is also the most useful failure available**, because a wrong bracket prediction that decomposes
|
||||
cleanly into "my model was right, an unmodelled neighbour moved" is a free confirmation of the
|
||||
neighbour's model. The residual was 0 on every turn, so nothing is unaccounted for.
|
||||
|
||||
---
|
||||
|
||||
## 9. Coverage — what this did not touch, said as loudly as what it did
|
||||
|
||||
* **`0x00840929` and `0x008409c7` remain unfired, and are now known to need a Morrigi empire.**
|
||||
That is a *stronger* negative than "not reached in the states measured": the gate is decoded, the
|
||||
branch was taken twelve times in the other direction, and the predicate is a single field on the
|
||||
spy's owner. **The workload that closes them, named from the failed conjunct:** a Morrigi
|
||||
single-player game, four spy techs, a spy deployed at a foreign colony with a belt, and ~7 turns of
|
||||
waiting. `0x008409c7` needs one more thing on top — the roll at `0x00840929` must *succeed* (75 %)
|
||||
**and** the candidate list must be non-empty, which needs a **third** non-eliminated empire that is
|
||||
neither the spy's owner nor the target's. This map has one (`Spengler`), so a 3-empire Morrigi game
|
||||
reaches both.
|
||||
* **`P` ran exactly once.** Everything about its cost is a single observation. The loop is over the
|
||||
spy vector, so two spies detected three turns apart should give two calls on different turns and
|
||||
two spies detected on the *same* turn should give two calls on one turn — **that is a reading, not
|
||||
a measurement** (rule 20: do not fit a constant to one observation).
|
||||
* **The `sdo` arithmetic is still validated only in its first and third terms.** `countA`, `countB`
|
||||
and the species multiplier were 0 / 0 / 1.0 for all eleven turns. `countC` held at 2 throughout,
|
||||
which is why the line is straight; nothing here identifies *what* `countC` counts, only that it did
|
||||
not change while one fleet of one ship sat at Kepler.
|
||||
* **The auto-detect arm `(TerrFl & 1) == 0` was never taken.** Lane AS flagged it as the most
|
||||
load-bearing unmeasured branch in the chain and it still is. Nothing in this lane touched it.
|
||||
* **The `ncp`-blocks-rebootstrap gate was never reached** (§5.4 item 3). `cm` never wrapped 4 → 0
|
||||
because the spy was destroyed at Frame 25 with `cm = 4`. Two more turns of survival would have
|
||||
tested it; a second spy deployed later than the first would too.
|
||||
* **`P`'s return value was not traced.** The Frame-25 roll's outcome (whether `re` was named in
|
||||
Kepler's `EVENT_SPY_DESTROYED` event, a 25 % chance) was not read out of the event text. The
|
||||
ledger prices the site; the semantics in §1.2 are from the instruction stream.
|
||||
* **One turn, one process for the eleven-turn series.** W is a single process. The control pair
|
||||
covers only its **first** turn. Frames 17–26 have no two-process control at all, and by §7.3 every
|
||||
one of them is an exposed turn, so they should not be assumed reproducible.
|
||||
* **Turn 27 was not played.** The driver stopped on a Von Neumann encounter dialog at Rigel, which is
|
||||
where the series ends. Nothing after Frame 26 is measured.
|
||||
* **`probes=11` was not used anywhere in this lane**, and no number here is comparable to lane AC's
|
||||
turn totals.
|
||||
* **No `Guard` region is declared by any hook in this family** — the same gap lanes Z, H, AS and AR
|
||||
reported. `undeclared = 0` in these traces is vacuous.
|
||||
* **The species table is read from the save's own `ISsp` list**, cross-checked on one Zuul save and
|
||||
one hook report. No Morrigi, Hiver, Liir or Tarka save exists in the corpus, so indices 1, 2, 3 and
|
||||
6 are named but not exercised.
|
||||
|
||||
---
|
||||
|
||||
## 10. Corrections to earlier findings (rule 11)
|
||||
|
||||
* **Lane AS §6, board row 207, lane AG §6 and this lane's own brief: "`P`'s three draws".**
|
||||
`0x00840929`, `0x008409c7` and `0x00840a3c` are **not three sites behind one gate**. They are two
|
||||
mutually exclusive branches selected by `spyOwner->Species == 6`, and no call can reach more than
|
||||
one of them. Every inventory that lists them as a group of three should say so. §1.2.
|
||||
* **Lane AG §3.2's caution to lane AS: "a spy program run without FTL Economics takes a different
|
||||
branch of the machine".** The `CnTrd` the stage machine consults at `cm 1 → 2/3` is the **target
|
||||
system owner's**, not the spy owner's. My empire has `CnTrd = False` and the machine still took the
|
||||
`1 → 2` arm, because Kepler's owner has `CnTrd = True`. §5.4 item 4.
|
||||
* **Lane AG §3.2's `ncp` reading.** `ncp` is a scalar `int` in the stream, and it behaves as a
|
||||
**counter of completed counter-mission stages** (0,0,1,1,2,2,3 in lock-step with `cm`). "Non-empty"
|
||||
is therefore `!= 0`, and the branch that consults it was never reached here. §5.4 item 3.
|
||||
* **Lane AS §1.4 / §6.1: "`cbh = NextFloat() * 2*pi`".** Correct in value; the code is
|
||||
`lerp(0.0, 2*pi, r)` with a float32 round in the middle, and the angle is `DeploySpy`'s **second**
|
||||
argument, set up before `0x0080c860` (a zero-argument getter) is called across the half-built
|
||||
frame. AS's "`spy->cbh := <the float argument>`" is right; §6.2 only names which argument.
|
||||
* **Lane AS §6's detection-probability table** (38 % / 65 % / 85 % at +10 / +15 / +20) is the right
|
||||
model evaluated one turn late. `AccumulateDetectionOdds` runs *before* the gate, so the roll on the
|
||||
End Turn producing Frame `f` uses `sdo = 0.0084 × (f − 14)`, not `0.0084 × (f − 15)`. The corrected
|
||||
figures are 43 % / 70 % / 87 %. Measured `sdo` (§5.3) settles it: the Frame-16 autosave already
|
||||
holds 0.0168, so the Frame-16 roll was at 0.0168.
|
||||
* **Lane AG's audit and lane V2's inventory have a column they need.** `0x0078c97f`'s predicate is
|
||||
*"a `SHIPACTION_DEPLOYSPY` command in this turn's command stream"*. It is now **measured**, so the
|
||||
gate-indexed audit's two cell kinds (a firing, or a save predicate) become three: a firing, a save
|
||||
predicate, or a **stream** predicate. This is the first entry in that column.
|
||||
|
||||
---
|
||||
|
||||
## 11. Artifacts
|
||||
|
||||
| what | where |
|
||||
|---|---|
|
||||
| the instrumented eleven-turn trace (per-turn `draw_sites` + `probe_entries` + brackets) | `verify/traces/ap-probes8-turn16-turn26.jsonl.gz` |
|
||||
| the deploy-turn trace | `verify/traces/ap-probes8-deploy-turn15.jsonl.gz` |
|
||||
| shim log for the eleven-turn run | `verify/results/shim/ap/ap-probes8-w.shim.log` |
|
||||
| shim log for the deploy run | `verify/results/shim/ap/ap-probes8-d.shim.log` |
|
||||
| **the detected-spy save** — first `sdet != -1`, first non-zero `cm`/`cmo`/`ncp`/`spyon` in the corpus | `verify/results/saves/ap-turn22-spydetected.sav` (83,188 B, `--strict` 0 errors / 0 warnings) |
|
||||
| **the post-`P` save** — the spy destroyed, `nspy` back to 0, `spies2` emptied | `verify/results/saves/ap-turn25-spydestroyed.sav` (84,487 B, `--strict` clean) |
|
||||
| the deploy run's Frame-15 autosave (`cbh` reproduced) | `verify/results/saves/ap-deploy-turn15.sav` |
|
||||
| the two control post-turn saves | `verify/results/saves/ap-oa-turn16.sav`, `ap-ob-turn16.sav` |
|
||||
| addresses this lane mints | `ghidra/addresses.d/ap.json` |
|
||||
| predictions, committed before the build | this file §0–§3, commit `f8ff1b6` |
|
||||
| instrument | `sots-engine` `src/shim/shim.cfg.hp8` and `shim.cfg.hoff`, **both unchanged** — this lane wrote no engine code |
|
||||
|
||||
### 11.1 The hashes, for the record
|
||||
|
||||
```
|
||||
input MyGameas1spydep.sav 854a10fa1ea602f0f7909f9bf9154942e56ea5fa1db4cce47d6d32bf53952e08
|
||||
A/B/M/OA/OB (Autosave EndTurn).sav 98e45d3745b914506fc4c409ad5a5ad0938a2003ab4c845421a99a8065149c3a
|
||||
W (probes=8) turn 16 262f8bda97c9511d8d2b41e6a8a0582d6f5364c2b01b1caf99e639d0e4f53ebe
|
||||
OB (hooks=off) turn 16 262f8bda97c9511d8d2b41e6a8a0582d6f5364c2b01b1caf99e639d0e4f53ebe
|
||||
OA (hooks=off) turn 16 e296394f578b3a5668e5934b9eec8d6c4638ca7411200078f97de1abd346f4c5
|
||||
turn 22 (detection) 91381bd7e722ac3847795a402d78ebb31d74dbb5d2909f33d243aec3ef8abaf8
|
||||
turn 25 (P ran; spy destroyed) 46380fcf4498d67507e4471eb9ee3762647c53ee5473be142fe5c34e37344bc3
|
||||
deploy run, turn 15 844f2b746060dc2c4e2099cdc6ceffd5f55ef858c9e347df28c8aca3041f7165
|
||||
shim binkw32.dll ap-989c692-… ae084ed4774caf24ea7927fcb012d1999633f10556c7c99f0209f66067416a17
|
||||
```
|
||||
|
||||
**None of these is a calibration pair.** §7.
|
||||
|
||||
---
|
||||
|
||||
## 12. VM144 as left
|
||||
|
||||
**Restored and verified by screenshot at the main menu**, profile `re`, 2026-09-09.
|
||||
|
||||
* `C:\SOTS\binkw32.dll` restored to lane L3's build from `C:\SOTS\shimdist-l3\binkw32.dll`
|
||||
(sha256 `479B8614D2417603…`, byte-identical to what this lane found in place).
|
||||
* `C:\SOTS\shim.cfg` restored from `C:\SOTS\ui\preAS-shim.cfg` (L3's `shim.cfg.l3probe`,
|
||||
`probes=11`).
|
||||
* The three autosaves restored **byte-identical** from `C:\SOTS\ui\preAS-SavedGames`
|
||||
(`1985E6F4…` / `24B2E072…` / `5EC80C1E…`). This lane's eleven turns had overwritten their contents;
|
||||
lane AS's snapshot is what made the restore possible and it is worth keeping.
|
||||
* `C:\SOTS\shim.trace.jsonl` and `shim.log` removed before the relaunch.
|
||||
|
||||
**`SavedGames` is still 15 files** — this lane added none and removed none, so **lane AS's row
|
||||
positions still hold**: `MyGameas1predeploy` at **(400, 347)**, `MyGameas1spydep` at **(400, 376)**,
|
||||
`OK` at (682, 624). Verified by screenshot twice this session. All fifteen files hash as AS left
|
||||
them.
|
||||
|
||||
Left in place, all harmless: `C:\SOTS\shimdist-ap\` (build `ap-989c692-20260909T0425Z`, 63 files),
|
||||
`C:\SOTS\ui\apgo.ps1`, `C:\SOTS\ui\aphash.ps1`, `C:\SOTS\ui\ap\` (the End-Turn driver, its per-turn
|
||||
saves and screenshots), and the scheduled task **`SOTSAP`**. `click_helper.ps1` was **not touched** —
|
||||
this lane needed no new verbs either.
|
||||
|
||||
### 12.1 Guest notes worth carrying forward
|
||||
|
||||
* **The End-Turn driver is the reusable part.** `C:\SOTS\ui\ap\ap_loop.ps1`, run through the
|
||||
`SOTSAP` scheduled task (an `InteractiveToken` clone of `SOTSUI`), reads `C:\SOTS\ui\ap\job.txt`
|
||||
(`turns=`, `tag=`, `first=`, `maxwait=`), clicks End Turn, **polls the autosave's mtime** until it
|
||||
moves, snapshots `(Autosave).sav` to `ap\saves\<tag>-<NN>.sav`, and **stops on the first stall with
|
||||
a screenshot**. Eleven turns cost 11 minutes unattended. Set `job.txt`, `schtasks /Run /TN SOTSAP`,
|
||||
then watch `ap\loop.log` from outside.
|
||||
* **Nine minutes of this lane went into a screenshot-lag artefact, and the lesson is general.**
|
||||
Four consecutive clicks appeared to select the wrong Load-dialog rows, which read exactly like a
|
||||
coordinate offset and nearly produced a "the click helper is 87 px out on this guest" note. It was
|
||||
not: the click task takes ~3 s to start and ~3 s to run, and a screenshot taken 4 s after
|
||||
`schtasks /Run` shows the state **before** the click. **Wait ≥ 9 s between triggering the click
|
||||
task and screenshotting.** Every documented coordinate on this guest is correct.
|
||||
* **The first click after `fg` is swallowed** by the focus activation. Send `fg`, then `move`, then
|
||||
`sleep`, then `click` — or spend a throwaway click.
|
||||
* **A `wheel` zoom on the star map separates systems that overlap at the default zoom.** Lane AS lost
|
||||
a run to Kepler and Midway sharing a hit test; six notches at the cluster centre and then eight more
|
||||
at the target spread them to ~120 px apart, and the labels render. No affine fit was needed.
|
||||
* **Selecting the system, not the fleet, is what enables `Special`.** With Kepler selected the left
|
||||
panel grows a `Fleets at Kepler` list and `Manage Fleets` / `Move` / `Special` light up;
|
||||
`Special → Deploy Spy` then opens a ship picker whose ship is already selected, so `OK` is the only
|
||||
further click. The whole deploy is four clicks once the right star is under the cursor.
|
||||
* **The pixel test for "is the main menu up" must sample the button, not its label.** (511, 536) is
|
||||
inside the white text of `Load Game` and reads ~(195,191,191) on a bright frame; (470, 530) is the
|
||||
button itself and reads (184, 0, 0). A test on the first point passes only by luck on a dark frame.
|
||||
* **An End Turn on this state costs 6 seconds** under `probes=8` with ~150–250 AI ships. The
|
||||
campaign's "30–45 s per End Turn" figure is from a different guest and a different config.
|
||||
* Turn 27 raised a **Von Neumann encounter at Rigel** ("No ships available", `Done` at (233, 673)).
|
||||
A driver that polls the autosave rather than the screen stalls on it cleanly instead of clicking
|
||||
through something it cannot see.
|
||||
|
||||
---
|
||||
|
||||
## Proposed board rows
|
||||
|
||||
New row:
|
||||
|
||||
```
|
||||
| THE SPY ATTRIBUTION ROLL FIRES - and P's "three draws" are TWO SPECIES BRANCHES, only one reachable per game | verify | verified | high | 100% | 2026-09-09 | **Lane AP, VM144, build `ap-989c692-20260909T0425Z`, `probes=8` (never 11), own build dir /srv/re-lab/build/sots-engine-ap rm -rf'd first.** Continues lane AS from `as-turn15-spydeployed.sav`: **11 End Turns, 6 SECONDS EACH** (the brief budgeted an evening; the cost is the launch and the load, not the turns). **DETECTION AT FRAME 22, `P` RAN AT FRAME 25.** `Mars::RNG::Chance` at **0x00840a3c** fired **1 call / 1 word / no_draw_calls=0 / strategic=true** at `ret_rva 0x00840a41` - a site that had never fired. **CORRECTION TO EVERY INVENTORY (row 207, lane AG 6, lane AS 6, and this lane's own brief): 0x00840929 / 0x008409c7 / 0x00840a3c ARE NOT THREE SITES BEHIND ONE GATE.** `SpyManager::Slot13RngCallee 0x008408e0` opens `cmp [spyOwner+0x5c], 6; jne` - `Species == 6` (MORRIGI) takes `Chance(0.75f)` at 0x00840929 and then `NextInt` at 0x008409c7 to blame a RANDOM THIRD EMPIRE (a false flag; the true owner is never named); every other species takes `Chance(0.25f)` at 0x00840a3c and on success returns the TRUE owner. **No call can reach more than one.** Species table decoded from the save's own ISsp list and cross-checked on lane V's Zuul save: **0 Human, 1 Hiver, 2 Tarkas, 3 Liir, 4 _NPC, 5 Zuul, 6 Morrigi** - which also NAMES lane AS's two unexplained multipliers in `AccumulateDetectionOdds` (0.75f = ZUUL, 0.5f = MORRIGI). Constants read as the four bytes (rule 23): 0x009e5ac0 = 0.25f, 0x009e5ac4 = 0.75f (the same word AS read as the Zuul multiplier). **0x008409c7 needs BOTH the 0.75f roll to succeed AND a third non-eliminated empire** that is neither the spy's owner nor the target's. **SECOND SITE CLOSED: 0x0088dc43** (the counter-mission roll, lane AG 3.2, corpus 0 of 22, never fired) fires 1 word/turn from **Frame 19**; the bootstrap turn (Frame == tdep+3) sets spyon/cm:=1/cmo:=0.2f and DRAWS NOTHING. `cm`, `cmo`, `spyon`, `ncp` - four of the value-domain census's 234 single-valued fields - are all OFF ZERO with a measured trajectory. **TWO CORRECTIONS TO AG 3.2:** the `CnTrd` the stage machine consults at cm 1->2/3 is the TARGET OWNER's not the spy owner's (my player has CnTrd=False and it still took 1->2, because Kepler's owner has CnTrd=True), and `ncp` is a SCALAR COUNTER of completed stages (0,0,1,1,2,2,3 in lock-step with cm), not a container. **THIRD SITE CLOSED: 0x0078c97f**, the deploy `NextFloat` in the SHIPACTION_DEPLOYSPY handler that is in NO inventory - 1 call / 1 word / strategic, in the **ProcessTurn** bracket, and **spy.cbh came out 5.033599376678467 BIT-IDENTICAL to lane AS's** from a different process, build and session. **Its predicate is on the COMMAND STREAM, and this is the first measured entry in a column the gate-indexed audit does not have.** THE POLARITY CASE, MEASURED: on Frames 23 and 24 (sdet+1, sdet+2) `vslot13` is ENTERED (probe = 1) and costs **ZERO** - a third arm of the same function, and `sdo` FREEZES at 0.0672 in the save, proving branch D stopped independently of the ledger. On Frame 25 the entry probe on `SpyManager::Slot13RngCallee 0x008408e0` reads **1** - ITS FIRST NON-ZERO EVER, the complement of lane AS's demonstration that its zero said nothing about the subtree. The spy is DESTROYED at the end of phase 23 on sdet+3 by manager vtable slot 10 `0x00838480` -> `ServerSystem::RemoveSpy`, so vslot14 costs 0 that turn: nspy 1->0, spies2 emptied. `sdo` measured on NINE points, exactly `0.0084*(f-14)` as float32 (`3c89a027 3cce703a 3d09a027 3d2c0831 3d4e703b 3d70d845 3d89a027`), which also corrects AS's detection-probability table by one turn: **43%/70%/87%** at +10/+15/+20, not 38/65/85. Residual **0 on all 12 measured turns**, overflow 0. **ONE PREDICTION WRONG AND NAMED: PB4** said the tail costs 2 words/turn from Frame 19; it costs 2,4,6,9,8,9,8,8 because the TRADE-RAID roll 0x00820e1d entered the tail at Frame 20 and grew 2,4,7,7,8,7,8 as the AI's navy went 157->251 ships - an independent live re-confirmation of lane AD's per-fleet model on a different map and an AI-owned fleet. The spy halves were predicted exactly; quoting a BRACKET total requires modelling every subsystem in it. Saves `ap-turn22-spydetected.sav`, `ap-turn25-spydestroyed.sav`, `ap-deploy-turn15.sav`; findings `findings/subsystems/spy-program-draws.md` |
|
||||
```
|
||||
|
||||
```
|
||||
| CONTROL ON as-turn15: THREE OUTCOMES IN SIX PROCESSES, and exposure is SATURATED on this map | verify | verified | high | 100% | 2026-09-09 | Lane AP, VM144. Two fresh `hooks=off` processes (OA, OB) on `MyGameas1spydep.sav` + 1 End Turn, added to lane AS's A/B/M and this lane's `probes=8` run W. **Pre-turn `(Autosave EndTurn).sav` is byte-identical across four processes, two lanes and TWO DIFFERENT BUILDS** (`98e45d3745b91450...`). Post-turn: **three distinct outcomes in six processes** - `262f8bda` x4 (AS's A and M, AP's W and OB), `e34775a7` x1 (AS's B), `e296394f` x1 (AP's OA). **OA != OB, so this is NOT a calibration pair and must not enter `determinism-hashes.txt`** - stated in advance as PD3. OA vs OB diverge in **15 leaves, ALL of them Player[32]'s research pick plus /Summary/Checksum and one turnstats `tch` cell**; three distinct picks were sampled (Overthrusting completed / DRV_NodFoc in progress / DRV_McroFus over budget). **`probes=8` IS BYTE-NEUTRAL, PROVEN PROPERLY THIS TIME: W is IDENTICAL to OB over 44,438 leaves** (`state_checksum --floats bits --mask none`), while the two un-instrumented controls differ from each other - so the instrument agrees exactly with a control in a leaf class it provably does not touch. Sub-tree digests: `Sim/spymgr`, `Sim/systems`, `Sim/fleets`, `Sim/trdmgr` all IDENTICAL across the pair; only `Sim/players` and the derived `Summary` move. **RULE 26(c) EXPOSURE FIELDS RECORDED NEXT TO THE HASHES** (coordinator's request): the control input carries `Player[32].ResTNm == ''` - a pick turn - and it varied in exactly the leaves the predicate names. **AND THE PREDICATE IS SATURATED ON THIS MAP: all 13 pre-turn states from Frame 14 to Frame 26 carry at least one exposure signature** (9 of 13 a research pick, every single one a batch of ship completions, four a design, four a colonisation; Player[32]'s navy goes 146 -> 251 ships in twelve turns). **There is NO quiet turn anywhere in this lineage**, so no rung-A pair is obtainable from `as-turn15-spydeployed.sav` by waiting - the opposite end of the axis from lane AR's turns 38-39, and a lane that wants a pair on this map must pin the client seeds. Counter-nuance: exposure is necessary for variation, not sufficient per pair - W, A and M (three processes, two configurations, two builds) landed on the SAME bytes on this exposed turn, so a single agreeing pair on an exposed turn proves nothing. Saves `ap-oa-turn16.sav`, `ap-ob-turn16.sav` |
|
||||
```
|
||||
|
||||
Edits to existing rows:
|
||||
|
||||
- **Row 62** (guest holders) — `VM144 = FREE (lane AP released 2026-09-09; restored to L3's build 479B8614… + L3's shim.cfg (probes=11) + the three pre-AS autosaves BYTE-IDENTICAL from ui\preAS-SavedGames, main menu verified by screenshot). SavedGames is STILL 15 FILES and lane AS's row positions STILL HOLD - MyGameas1predeploy (400,347), MyGameas1spydep (400,376), OK (682,624), verified by screenshot twice. AP added C:\SOTS\shimdist-ap, ui\ap{go,hash}.ps1, ui\ap\ (an END-TURN DRIVER worth reusing: ap_loop.ps1 + the SOTSAP scheduled task clicks End Turn, POLLS THE AUTOSAVE MTIME, snapshots (Autosave).sav per turn and stops on the first stall with a screenshot - 11 turns unattended in 11 minutes). click_helper.ps1 untouched. GOTCHA THAT COST THIS LANE NINE MINUTES: the click task takes ~6 s end to end, so a screenshot taken 4 s after `schtasks /Run /TN SOTSUI` shows the state BEFORE the click - four such shots read exactly like an 87 px coordinate offset and nearly became a false gotcha. WAIT >= 9 s. GOTCHA: the first click after `fg` is swallowed by the focus activation. GOTCHA: the main-menu pixel test must sample the BUTTON (470,530) = (184,0,0), not the white label at (511,536). TIP: `wheel` zoom separates stars that share a hit test at the default zoom (Kepler vs Midway, which cost lane AS a run) - no affine fit needed. An End Turn on this state costs 6 SECONDS under probes=8.`
|
||||
- **Row 207** (V2's eight sites) — append: `CORRECTED AND ADVANCED 2026-09-09 by lane AP. 0x00840a3c FIRED (1 word, Frame sdet+3 from as-turn15-spydeployed.sav). 0x00840929 and 0x008409c7 are NOT two more sites behind the same gate - they are the MORRIGI branch of SpyManager::Slot13RngCallee (`cmp [spyOwner+0x5c],6`), mutually exclusive with 0x00840a3c, and unreachable in any Human/Hiver/Tarka/Liir/Zuul game. Closing them needs a MORRIGI empire (and, for 0x008409c7, a third surviving empire). Of V2's eight, only 0x0082cdb8 (trade 15) is now both reachable and unfired.`
|
||||
- **Row 418** (lane AS's detection-roll row) — append: `EXTENDED 2026-09-09 by lane AP: the roll fired on seven consecutive turns and SUCCEEDED on Frame 22; `sdo` is exactly 0.0084*(f-14) as float32 over NINE points and FREEZES the moment sdet stamps. AS's probability table is one turn late - the corrected figures are 43%/70%/87% at +10/+15/+20. AS's 0x0078c97f is now MEASURED (1 word, ProcessTurn bracket) and `cbh` reproduced bit-identically across processes and builds.`
|
||||
- **The `0x0088dc43` row of lane AG's audit (§3.2)** — `FIRED 2026-09-09 by lane AP, 1 word/turn from Frame 19 (= tdep + 4). The bootstrap turn draws nothing. TWO CORRECTIONS: the CnTrd consulted at cm 1->2/3 is the TARGET OWNER's, and `ncp` is a scalar counter of completed stages, not a container.`
|
||||
- **The gate-indexed audit's cell taxonomy** — `A THIRD CELL KIND EXISTS AND NOW HAS ITS FIRST MEASURED ENTRY: a STREAM predicate. 0x0078c97f fires once per SHIPACTION_DEPLOYSPY command applied; no predicate over the save can express it, and no call-graph sweep can find it (stack-built ship-action table, lane B6's class).`
|
||||
|
|
|
|||
|
|
@ -1,69 +0,0 @@
|
|||
{
|
||||
"_note": "Lane AP (2026-09-09). The rest of the spy program's draw sites, read from the instruction stream of dumps/sots.exe (disassembled to the NEXT FUNCTION START, rule 17 -- no Ghidra size is used below) and then MEASURED live on VM144 under probes=8, build ap-989c692-20260909T0425Z. Evidence: findings/subsystems/spy-program-draws.md. The headline is that SpyManager_Slot13RngCallee 0x008408e0 (already named in lane-h.json, not re-minted here) contains TWO MUTUALLY EXCLUSIVE BRANCHES selected by the spy owner's Species, so its three draw sites can never all be reached: 0x00840929 + 0x008409c7 are Morrigi-only and 0x00840a3c is everyone else. NOT minted here because other fragments already have them: SpyManager_Slot13RngCallee 0x008408e0 (lane H), ServerSpyManager_vslot13 0x008877b0 and vslot14 0x0088db80 (lane V2), ServerSpyManager_DeploySpy 0x00887410 and ServerSystem_AddSpy/RemoveSpy (lane AS), Mars_RNG_NextFloat/NextInt/Chance (addresses.json).",
|
||||
"entries": [
|
||||
{
|
||||
"name": "SpyManager_ShipActionDeploySpyHandler",
|
||||
"addr": "0x0078c930",
|
||||
"convention": "__thiscall",
|
||||
"prototype": "bool (Game::StrategyServer* this, Game::Ship* ship) /* body 0x0078c930..0x0078c9e0 (next function start), `ret 4`. Entry of the STACK-BUILT SHIP-ACTION TABLE (lane B6's indirection class): no direct callers, no vtable slot, invisible to every call-graph sweep this campaign has run. One gate -- a 12-byte stack query object (vtable 0x00a09648) built at 0x0078c93d and asked about the ship at 0x0078c964; false => return with NO DRAW. Past it: `mov ecx,[esi+0x16c]; add ecx,4; call Mars_RNG_NextFloat` at 0x0078c97f -- ONE STRATEGIC-GENERATOR WORD PER APPLIED Deploy Spy ORDER, inside ApplyAllTurnCommands, i.e. the ProcessTurn bracket and NOT the tail's. The angle is lerp(0.0, 2*pi, r) computed through a FLOAT32 temp at [ebp+8] (fldz supplies LO; HI is the double 6.2831854820251465 at 0x009e21b0), stored to the stack slot pushed at 0x0078c998, which is DeploySpy's SECOND argument. 0x0080c860 is then called ACROSS that half-built frame and does not touch it. MEASURED lane AP 2026-09-09: 1 call / 1 word / no_draw_calls=0 / strategic=true at ret_rva 0x0078c984, and spy.cbh came out 5.033599376678467 -- BIT-IDENTICAL to lane AS's value from a different process, build and session, so this draw is reproducible from the save. ITS PREDICATE IS ON THE COMMAND STREAM, not on save fields: `a SHIPACTION_DEPLOYSPY command in this turn's command stream`. The gate-indexed audit has no column for that and should grow one */",
|
||||
"status": "verified",
|
||||
"source": "findings/subsystems/spy-program-draws.md (lane AP 2026-09-09)"
|
||||
},
|
||||
{
|
||||
"name": "Ship_GetAttachedSpyId",
|
||||
"addr": "0x0080c860",
|
||||
"convention": "__thiscall",
|
||||
"prototype": "int (Game::Ship* this) /* 7 bytes, complete: `mov eax,[ecx+0xa8]; ret`. A zero-argument getter for the ship's attached-spy id -- the same field ServerSpyManager_DeploySpy clears when it detaches the craft from its tender. Recorded because at its ONE call site (0x0078c9ac, in the SHIPACTION_DEPLOYSPY handler) it looks like it takes a float: the caller has already pushed DeploySpy's second argument and stored the deploy angle into it, and this call runs across that half-built frame without disturbing it. An eye following eax there misses where the angle goes */",
|
||||
"status": "verified",
|
||||
"source": "findings/subsystems/spy-program-draws.md (lane AP 2026-09-09)"
|
||||
},
|
||||
{
|
||||
"name": "SpyManager_DestroySpyById",
|
||||
"addr": "0x00838480",
|
||||
"convention": "__thiscall",
|
||||
"prototype": "void (Game::ServerSpyManager* this, int sid) /* Game::ServerSpyManager vftable 0x00a3073c SLOT 10. Looks the SpyCraft up by id through vtable slot 5, then: if spy->deat(+0x10) != 0, registry_lookup(server+0x84, deat) and ServerSystem_RemoveSpy 0x0074f550 on that system (which clears deat and erases sid from spies2); if spy->atto(+0xc) != 0, clear the tender's ship->[+0xa8] and spy->atto; erase the craft from the manager's vector at this+0x10 via 0x0059ec00; then the scalar deleting destructor with flag 1. CALLED FROM ServerSpyManager_vslot13's drain loop at 0x00887eb0, back to front over the local vector<int> of sids collected at 0x008878a1 -- so a spy detected on turn T is DESTROYED at the end of phase 23 on turn T+3, BEFORE vslot14 runs at phase 33. MEASURED lane AP 2026-09-09: nspy 1 -> 0 and spies2 emptied between the Frame-24 and Frame-25 autosaves, and 0x0088dc43 cost 0 on Frame 25 although vslot14 was still entered */",
|
||||
"status": "verified",
|
||||
"source": "findings/subsystems/spy-program-draws.md (lane AP 2026-09-09)"
|
||||
},
|
||||
{
|
||||
"name": "SpyManager_AttributionRoll_MorrigiBranch",
|
||||
"addr": "0x00840929",
|
||||
"convention": "site",
|
||||
"prototype": "/* NOT A FUNCTION -- the `call Mars_RNG_Chance 0x008e6dd0` at 0x00840929 inside SpyManager_Slot13RngCallee 0x008408e0, return address 0x0084092e. Reached ONLY when the destroyed spy's owner has ServerPlayer.Species (+0x5c) == 6, i.e. MORRIGI (species table read from the save's own ISsp list: 0 Human, 1 Hiver, 2 Tarkas, 3 Liir, 4 _NPC, 5 Zuul, 6 Morrigi). Probability is the WIDENED FLOAT at 0x009e5ac4 = 0.75f -- the same four bytes SpyCraft_AccumulateDetectionOdds uses as its species-5 multiplier. Generator: `mov ecx,[eax+0x16c]` -- the STRATEGIC generator OBJECT (not the +4 sub-object). One word at 0 < p < 1. On success the function walks StrategyServer+0x54..+0x58 collecting every player with [+0xfb]==0 and [+0xf8]==0 that is neither the spy's owner nor the target system's owner, and picks one -- a FALSE FLAG; the true owner is never returned for a Morrigi spy. UNFIRED: lane AP measured twelve turns including the one turn the function ran and this branch was never taken, because its Species was 0. THE WORKLOAD THAT CLOSES IT is a Morrigi empire, not a different save of a Human one */",
|
||||
"status": "verified",
|
||||
"source": "findings/subsystems/spy-program-draws.md (lane AP 2026-09-09)"
|
||||
},
|
||||
{
|
||||
"name": "SpyManager_AttributionRoll_MorrigiPick",
|
||||
"addr": "0x008409c7",
|
||||
"convention": "site",
|
||||
"prototype": "/* NOT A FUNCTION -- the `call Mars_RNG_NextInt 0x004271c0` at 0x008409c7 inside SpyManager_Slot13RngCallee 0x008408e0, return address 0x008409cc. Generator: `mov ecx,[...+0x16c]; add ecx,4` -- the +4 SUB-OBJECT. Bound is `count - 1` passed BY POINTER at [ebp+8] (inclusive), so the index is uniform over the candidate list. TWO conditions past the Morrigi branch: the 0.75f roll at 0x00840929 must SUCCEED, and the candidate list must be NON-EMPTY -- `cmp ecx,eax; je 0x840a07` at 0x008409ac returns NULL with no draw when it is empty, which needs a third non-eliminated empire that is neither the spy's owner nor the target's. UNFIRED for the same reason as 0x00840929 */",
|
||||
"status": "verified",
|
||||
"source": "findings/subsystems/spy-program-draws.md (lane AP 2026-09-09)"
|
||||
},
|
||||
{
|
||||
"name": "SpyManager_AttributionRoll_DefaultBranch",
|
||||
"addr": "0x00840a3c",
|
||||
"convention": "site",
|
||||
"prototype": "/* NOT A FUNCTION -- the `call Mars_RNG_Chance 0x008e6dd0` at 0x00840a3c inside SpyManager_Slot13RngCallee 0x008408e0, return address 0x00840a41. Taken for EVERY species except 6 (Morrigi), i.e. the `jne 0x840a29` at 0x00840910. Probability is the WIDENED FLOAT at 0x009e5ac0 = 0.25f. Generator: `mov ecx,[edx+0x16c]` -- the STRATEGIC generator object. One word. On success the function returns arg1, the spy's OWN owner: the victim correctly identifies who sent the spy, 25% of the time; otherwise NULL and the event names no empire. FIRED FOR THE FIRST TIME IN THIS CAMPAIGN, lane AP 2026-09-09: 1 call / 1 word / no_draw_calls=0 / strategic=true at ret_rva 0x00840a41, on the End Turn producing Frame sdet+3 (sdet=22, so Frame 25), from verify/results/saves/as-turn15-spydeployed.sav after seven End Turns. On that same turn the ENTRY PROBE on SpyManager_Slot13RngCallee 0x008408e0 read 1 -- its first non-zero ever, the complement of lane AS's demonstration that its zero said nothing about the subtree */",
|
||||
"status": "verified",
|
||||
"source": "findings/subsystems/spy-program-draws.md (lane AP 2026-09-09)"
|
||||
},
|
||||
{
|
||||
"name": "SpyManager_CounterMissionRollSite",
|
||||
"addr": "0x0088dc43",
|
||||
"convention": "site",
|
||||
"prototype": "/* NOT A FUNCTION -- the `call Mars_RNG_Chance 0x008e6dd0` at 0x0088dc43 inside ServerSpyManager_vslot14 0x0088db80 (phase 33), return address 0x0088dc48. Decoded statically by lane AG (gate-indexed-rng-audit.md 3.2) with CORPUS COUNT 0 OF 22; FIRED FOR THE FIRST TIME lane AP 2026-09-09, 1 call / 1 word / strategic=true on each of Frames 19..24. Probability is spy.cmo (+0x28). MEASURED BEHAVIOUR: the bootstrap turn (Frame == tdep + 3, here Frame 18) sets spyon, runs the stage machine cm 0 -> 1 and cmo := 0.2f and DOES NOT DRAW; from the next turn the site costs one word until cmo reaches 1.0. cmo steps +0.2f per failure and resets to 0.2f on success. TWO CORRECTIONS TO LANE AG 3.2: (a) the CnTrd (+0xff) the stage machine consults at cm 1 -> 2/3 is the TARGET SYSTEM OWNER's, not the spy owner's -- measured, my player has CnTrd=False and the machine still took 1 -> 2 because Kepler's owner has CnTrd=True; (b) `ncp` is a scalar int counter of COMPLETED counter-mission stages (measured 0,0,1,1,2,2,3 in lock-step with cm), so the cm==0 branch's `ncp non-empty` test is `ncp != 0` -- and that branch was never reached, because vslot13 destroyed the spy at cm==4 */",
|
||||
"status": "verified",
|
||||
"source": "findings/subsystems/spy-program-draws.md (lane AP 2026-09-09)"
|
||||
},
|
||||
{
|
||||
"name": "SpyManager_DeploySpyDrawSite",
|
||||
"addr": "0x0078c97f",
|
||||
"convention": "site",
|
||||
"prototype": "/* NOT A FUNCTION -- the `call Mars_RNG_NextFloat 0x0047d830` at 0x0078c97f inside SpyManager_ShipActionDeploySpyHandler 0x0078c930, return address 0x0078c984, ECX = GetGame()->RNG(+0x16c) + 4. ONE STRATEGIC-GENERATOR WORD PER APPLIED Deploy Spy ORDER, in the ProcessTurn bracket. Decoded but not measured by lane AS; MEASURED lane AP 2026-09-09 (1 call / 1 word / no_draw_calls=0 / strategic=true) and the resulting spy.cbh reproduced lane AS's 5.033599376678467 bit for bit across processes, builds and sessions. IN NO EARLIER INVENTORY -- not lane V2's eight, not lane I's 22, not lane AG's audit -- because it hangs off the stack-built ship-action table and leaves no static call edge. Its predicate is on the COMMAND STREAM, not on save fields */",
|
||||
"status": "verified",
|
||||
"source": "findings/subsystems/spy-program-draws.md (lane AP 2026-09-09)"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -290,15 +290,6 @@ exactly, an empty container.
|
|||
**A float literal in this image is a widened `float`, not a `double`.** It has now bitten the money
|
||||
chain, the bankruptcy divisor and the gate constant. Read the four bytes; do not assume the decimal.
|
||||
|
||||
> **Corollary (2026-09-09).** *Predict at the site, not at the bracket.* Lane AP predicted every
|
||||
> spy-half draw exactly and still got its headline prediction wrong: it had forecast the whole
|
||||
> `OnAllCombatDone_Tail` total, and the total moved because an **unrelated subsystem entered the
|
||||
> bracket** — the trade-raid roll, growing 2 → 8 words as the AI's navy went 157 → 251 ships. A
|
||||
> bracket total is a sum over every subsystem inside it, so quoting one commits you to modelling all
|
||||
> of them. Predict and report **per site, by return address**; let the bracket total be the check on
|
||||
> your arithmetic rather than the claim. (The consolation is that the surprise was itself a result:
|
||||
> an independent live re-confirmation of another lane's per-fleet model, on a different map.)
|
||||
|
||||
## 24. Never reuse a build directory across trees — a stale binary measures cleanly
|
||||
|
||||
The integrator's gate rsync excludes `build*` to save transfer time, so the remote build directory
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,114 +0,0 @@
|
|||
00:48:28.253 [tid 10144] ==== sots-engine shim (binkw32 proxy) build ap-989c692-20260909T0425Z ====
|
||||
00:48:28.253 [tid 10144] exe: C:\SOTS\Sword of the Stars.exe
|
||||
00:48:28.253 [tid 10144] exe base=0x006b0000 (link-time image base 0x00400000, ASLR delta +2818048) pid=7108 shim=72b60000
|
||||
00:48:28.253 [tid 10144] addresses: Source: sots-re ghidra/addresses.json @ 48db3cc, generated 2026-09-08 by tools/gen_addresses.py
|
||||
00:48:28.268 [tid 10144] config: hooks=trace
|
||||
00:48:28.268 [tid 10144] config: hook.Shim::SelfTest::Fill=off
|
||||
00:48:28.268 [tid 10144] config: hook.Mars::GlobalConsts::LoadFile=off
|
||||
00:48:28.268 [tid 10144] config: hook.Game::WeaponDictionary::Init=off
|
||||
00:48:28.268 [tid 10144] config: hook.Game::SectionDictionary::SectionDictionary=off
|
||||
00:48:28.268 [tid 10144] config: hook.Game::ServerPlayer::ComputeBudget=off
|
||||
00:48:28.268 [tid 10144] config: hook.Game::TechTree::ProcessResearch=off
|
||||
00:48:28.268 [tid 10144] config: hook.Game::ServerPlayer::OnTechResearched=off
|
||||
00:48:28.268 [tid 10144] config: hook.Game::ServerSystem::ProcessTurn=off
|
||||
00:48:28.268 [tid 10144] config: hook.Game::ServerPlayer::ProcessTurn=off
|
||||
00:48:28.268 [tid 10144] config: hook.Game::ServerSystem::GroupOutput=off
|
||||
00:48:28.268 [tid 10144] config: hook.Game::ServerSystem::ComputeTotalOutput=off
|
||||
00:48:28.268 [tid 10144] config: hook.Game::StrategyServer::MoveFleet=off
|
||||
00:48:28.268 [tid 10144] config: hook.Game::StrategyServer::ProcessFleetMovement=off
|
||||
00:48:28.268 [tid 10144] config: hook.Game::StrategyHost::Autosave=trace
|
||||
00:48:28.268 [tid 10144] config: hook.Game::StrategyServer::ProcessTurn=trace
|
||||
00:48:28.268 [tid 10144] config: hook.Game::StrategyServer::OnAllCombatDone_Tail=trace
|
||||
00:48:28.268 [tid 10144] config: hook.Game::StrategyServer::ApplyEncounterResult=trace
|
||||
00:48:28.268 [tid 10144] config: hook.Game::StrategyServer::NodeLineDecay=trace
|
||||
00:48:28.268 [tid 10144] config: hook.Game::StrategyServer::ProcessNodeSpaceTravel=trace
|
||||
00:48:28.268 [tid 10144] config: hook.Game::EncounterDetect::AssignContacts=trace
|
||||
00:48:28.268 [tid 10144] config: hook.Game::EncounterDetect::ProcessTeamRecord=trace
|
||||
00:48:28.268 [tid 10144] config: fpu.sample_turn=off
|
||||
00:48:28.268 [tid 10144] config: fpu.sample_ticks=off
|
||||
00:48:28.268 [tid 10144] config: trace.inline_max=64
|
||||
00:48:28.268 [tid 10144] config: trace.path=C:\SOTS\shim.trace.jsonl
|
||||
00:48:28.268 [tid 10144] config: trace.flush=always
|
||||
00:48:28.268 [tid 10144] config: probes=8 -> 8 lane-H entry probes
|
||||
00:48:28.331 [tid 10144] trace: C:\SOTS\shim.trace.jsonl (default mode trace, inline_max 64, flush always)
|
||||
00:48:28.331 [tid 10144] hook: Mars_Application_Initialize rva=0x004a0e50 -> va=00b50e50
|
||||
00:48:28.331 [tid 10144] hook: MH_Initialize -> MH_OK
|
||||
00:48:28.331 [tid 10144] hook: MH_CreateHook -> MH_OK (trampoline=030e0fe0)
|
||||
00:48:28.346 [tid 10144] hook: MH_EnableHook -> MH_OK
|
||||
00:48:28.346 [tid 10144] cfg: GlobalConsts hook ready (scale constant 0.017453292519943295)
|
||||
00:48:28.346 [tid 10144] hook: Mars::GlobalConsts::LoadFile rva=0x004b73c0 mode=off (not installed)
|
||||
00:48:28.346 [tid 10144] dict: dictionaries hook ready (crt new=74c4232b delete=74c40174)
|
||||
00:48:28.346 [tid 10144] hook: Game::WeaponDictionary::Init rva=0x0019a4c0 mode=off (not installed)
|
||||
00:48:28.346 [tid 10144] hook: Game::SectionDictionary::SectionDictionary rva=0x00176f40 mode=off (not installed)
|
||||
00:48:28.346 [tid 10144] research: ProcessResearch hook ready (Cost=0082da00, node=0x34, rng=0x9cc, fpu_cw=0x027f)
|
||||
00:48:28.346 [tid 10144] hook: Game::TechTree::ProcessResearch rva=0x001876c0 mode=off (not installed)
|
||||
00:48:28.346 [tid 10144] techfx: OnTechResearched hook ready (regions=15, gate=0/0, fpu_cw=0x027f)
|
||||
00:48:28.346 [tid 10144] hook: Game::ServerPlayer::OnTechResearched rva=0x00491790 mode=off (not installed)
|
||||
00:48:28.346 [tid 10144] hook: Game::ServerPlayer::ComputeBudget rva=0x00463030 mode=off (not installed)
|
||||
00:48:28.346 [tid 10144] hook: Game::ServerSystem::ProcessTurn rva=0x003598e0 mode=off (not installed)
|
||||
00:48:28.346 [tid 10144] hook: Game::ServerSystem::GroupOutput rva=0x0034b7a0 mode=off (not installed)
|
||||
00:48:28.346 [tid 10144] hook: Game::ServerSystem::ComputeTotalOutput rva=0x00350480 mode=off (not installed)
|
||||
00:48:28.346 [tid 10144] player_turn: ServerPlayer::ProcessTurn hook armed (ratio helper at 0082e950)
|
||||
00:48:28.346 [tid 10144] hook: Game::ServerPlayer::ProcessTurn rva=0x00491340 mode=off (not installed)
|
||||
00:48:28.346 [tid 10144] hook: Game::StrategyServer::MoveFleet rva=0x003d9ee0 mode=off (not installed)
|
||||
00:48:28.346 [tid 10144] hook: Game::StrategyServer::ProcessFleetMovement rva=0x003da9a0 mode=off (not installed)
|
||||
00:48:28.346 [tid 10144] hook: Game::StrategyHost::Autosave rva=0x00495210 -> va=00b45210 MH_CreateHook -> MH_OK (trampoline=030e0fc0)
|
||||
00:48:28.362 [tid 10144] hook: Game::StrategyHost::Autosave MH_EnableHook -> MH_OK mode=trace
|
||||
00:48:28.362 [tid 10144] hook: Game::StrategyServer::ProcessTurn rva=0x003dc6c0 -> va=00a8c6c0 MH_CreateHook -> MH_OK (trampoline=030e0fa0)
|
||||
00:48:28.378 [tid 10144] hook: Game::StrategyServer::ProcessTurn MH_EnableHook -> MH_OK mode=trace
|
||||
00:48:28.378 [tid 10144] hook: Game::StrategyServer::OnAllCombatDone_Tail rva=0x003d92a0 -> va=00a892a0 MH_CreateHook -> MH_OK (trampoline=030e0f80)
|
||||
00:48:28.393 [tid 10144] hook: Game::StrategyServer::OnAllCombatDone_Tail MH_EnableHook -> MH_OK mode=trace
|
||||
00:48:28.393 [tid 10144] hook: Game::StrategyServer::ApplyEncounterResult rva=0x003d8920 -> va=00a88920 MH_CreateHook -> MH_OK (trampoline=030e0f60)
|
||||
00:48:28.409 [tid 10144] hook: Game::StrategyServer::ApplyEncounterResult MH_EnableHook -> MH_OK mode=trace
|
||||
00:48:28.409 [tid 10144] hook: Game::StrategyServer::NodeLineDecay rva=0x003ae010 -> va=00a5e010 MH_CreateHook -> MH_OK (trampoline=030e0f40)
|
||||
00:48:28.409 [tid 10144] hook: Game::StrategyServer::NodeLineDecay MH_EnableHook -> MH_OK mode=trace
|
||||
00:48:28.409 [tid 10144] hook: Game::StrategyServer::ProcessNodeSpaceTravel rva=0x003a0e20 -> va=00a50e20 MH_CreateHook -> MH_OK (trampoline=030e0f20)
|
||||
00:48:28.424 [tid 10144] hook: Game::StrategyServer::ProcessNodeSpaceTravel MH_EnableHook -> MH_OK mode=trace
|
||||
00:48:28.424 [tid 10144] hook: Game::EncounterDetect::AssignContacts rva=0x003aa240 -> va=00a5a240 MH_CreateHook -> MH_OK (trampoline=030e0f00)
|
||||
00:48:28.440 [tid 10144] hook: Game::EncounterDetect::AssignContacts MH_EnableHook -> MH_OK mode=trace
|
||||
00:48:28.440 [tid 10144] hook: Game::EncounterDetect::ProcessTeamRecord rva=0x003ca640 -> va=00a7a640 MH_CreateHook -> MH_OK (trampoline=030e0ee0)
|
||||
00:48:28.456 [tid 10144] hook: Game::EncounterDetect::ProcessTeamRecord MH_EnableHook -> MH_OK mode=trace
|
||||
00:48:28.456 [tid 10144] hook: Game::StrategyServer::BeginProcessTurn rva=0x003d98e0 -> va=00a898e0 MH_CreateHook -> MH_OK (trampoline=030e0ec0)
|
||||
00:48:28.471 [tid 10144] hook: Game::StrategyServer::BeginProcessTurn MH_EnableHook -> MH_OK mode=trace
|
||||
00:48:28.471 [tid 10144] hook: Game::SVSOSwarmQueen::OnTurnBegin rva=0x00129930 -> va=007d9930 MH_CreateHook -> MH_OK (trampoline=030e0ea0)
|
||||
00:48:28.487 [tid 10144] hook: Game::SVSOSwarmQueen::OnTurnBegin MH_EnableHook -> MH_OK mode=trace
|
||||
00:48:28.487 [tid 10144] hook: Game::SVSOSwarmQueen::RegisterHives rva=0x00127630 -> va=007d7630 MH_CreateHook -> MH_OK (trampoline=030e0e80)
|
||||
00:48:28.503 [tid 10144] hook: Game::SVSOSwarmQueen::RegisterHives MH_EnableHook -> MH_OK mode=trace
|
||||
00:48:28.503 [tid 10144] hook: Game::SVSOSwarmQueen::TickHives rva=0x00127770 -> va=007d7770 MH_CreateHook -> MH_OK (trampoline=030e0e60)
|
||||
00:48:28.518 [tid 10144] hook: Game::SVSOSwarmQueen::TickHives MH_EnableHook -> MH_OK mode=trace
|
||||
00:48:28.518 [tid 10144] hook: Game::SVSOSlaversRefuel::UpdateDifficultyTier rva=0x00115820 -> va=007c5820 MH_CreateHook -> MH_OK (trampoline=030e0e40)
|
||||
00:48:28.534 [tid 10144] hook: Game::SVSOSlaversRefuel::UpdateDifficultyTier MH_EnableHook -> MH_OK mode=trace
|
||||
00:48:28.534 [tid 10144] hook: Mars::RNG::Seed rva=0x0009fdf0 -> va=0074fdf0 MH_CreateHook -> MH_OK (trampoline=030e0e20)
|
||||
00:48:28.534 [tid 10144] hook: Mars::RNG::Seed MH_EnableHook -> MH_OK mode=trace
|
||||
00:48:28.534 [tid 10144] hook: Game::StrategyApp::RunAI rva=0x004706f0 -> va=00b206f0 MH_CreateHook -> MH_OK (trampoline=030e0e00)
|
||||
00:48:28.549 [tid 10144] hook: Game::StrategyApp::RunAI MH_EnableHook -> MH_OK mode=trace
|
||||
00:48:28.565 [tid 10144] drawsite: Mars::RNG::NextFloat rva=0x0007d830 -> va=0072d830 create=MH_OK enable=MH_OK
|
||||
00:48:28.581 [tid 10144] drawsite: Mars::RNG::NextInt rva=0x000271c0 -> va=006d71c0 create=MH_OK enable=MH_OK
|
||||
00:48:28.596 [tid 10144] drawsite: Mars::RNG::Chance rva=0x004e6dd0 -> va=00b96dd0 create=MH_OK enable=MH_OK
|
||||
00:48:28.612 [tid 10144] drawsite: Mars::RNG::NextUInt rva=0x000f7670 -> va=007a7670 create=MH_OK enable=MH_OK
|
||||
00:48:28.628 [tid 10144] drawsite: Mars::RNG::FloatRange rva=0x0007d8a0 -> va=0072d8a0 create=MH_OK enable=MH_OK
|
||||
00:48:28.628 [tid 10144] drawsite: Mars::RNG::IntRangeBell rva=0x004e6d80 -> va=00b96d80 create=MH_OK enable=MH_OK
|
||||
00:48:28.643 [tid 10144] drawsite: Mars::RNG::GaussianRange rva=0x004e6e30 -> va=00b96e30 create=MH_OK enable=MH_OK
|
||||
00:48:28.643 [tid 10144] probe: installing 8 of 12 (probes= in shim.cfg)
|
||||
00:48:28.659 [tid 10144] probe: Game::ServerSpyManager::vslot13 rva=0x004877b0 -> va=00b377b0 create=MH_OK enable=MH_OK
|
||||
00:48:28.674 [tid 10144] probe: Game::ServerSpyManager::vslot14 rva=0x0048db80 -> va=00b3db80 create=MH_OK enable=MH_OK
|
||||
00:48:28.690 [tid 10144] probe: Game::ServerTradeManagerImpl::vslot13 rva=0x0048ef80 -> va=00b3ef80 create=MH_OK enable=MH_OK
|
||||
00:48:28.706 [tid 10144] probe: Game::ServerTradeManagerImpl::vslot15 rva=0x0042cca0 -> va=00adcca0 create=MH_OK enable=MH_OK
|
||||
00:48:28.706 [tid 10144] probe: Game::SpyManager::Slot13RngCallee rva=0x004408e0 -> va=00af08e0 create=MH_OK enable=MH_OK
|
||||
00:48:28.721 [tid 10144] probe: Game::TradeManager::Slot13RngCalleeA rva=0x00420ca0 -> va=00ad0ca0 create=MH_OK enable=MH_OK
|
||||
00:48:28.737 [tid 10144] probe: Game::TradeManager::Slot13RngCalleeB rva=0x0048b440 -> va=00b3b440 create=MH_OK enable=MH_OK
|
||||
00:48:28.753 [tid 10144] probe: Game::ServerTradeManager::CreateRaidEncounter rva=0x004938a0 -> va=00b438a0 create=MH_OK enable=MH_OK
|
||||
00:48:28.753 [tid 10144] watch: disabled (watch=off)
|
||||
00:48:28.753 [tid 10144] aiorders: disabled (aiorders=off)
|
||||
00:48:28.753 [tid 10144] fpu: module init, entry cw=0x027f 53bit-double/nearest; force=off value=0x0000 sample_ticks=off
|
||||
00:48:28.753 [tid 10144] fpu: sample_turn=off (off releases StrategyServer::ProcessTurn for another hook)
|
||||
00:48:28.753 [tid 10144] fpu: StrategyClient::EndTurn rva=0x00383be0 -> va=00a33be0 MH_CreateHook -> MH_OK (trampoline=030e0c00)
|
||||
00:48:28.768 [tid 10144] fpu: StrategyClient::EndTurn MH_EnableHook -> MH_OK
|
||||
00:48:28.768 [tid 10144] fpu: StrategyServer::BeginProcessTurn rva=0x003d98e0 -> va=00a898e0 MH_CreateHook -> MH_ERROR_ALREADY_CREATED (trampoline=00000000)
|
||||
00:48:28.768 [tid 10144] fpu: StrategyServer::ProcessTurn rva=0x003dc6c0 not installed (sampler off)
|
||||
00:48:28.768 [tid 10144] fpu: DemoApp::OnTick rva=0x0049a640 not installed (sampler off)
|
||||
00:48:28.768 [tid 10144] selftest: Shim::SelfTest::Fill mode=off checksum=075ef0c3 records=0
|
||||
00:48:28.768 [tid 10144] Application::Initialize called (this=033a8128)
|
||||
00:59:06.468 [tid 10144] fpu: sample at StrategyClient::EndTurn (this=0d69f600): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:59:09.765 [tid 10144] fpu: sample at StrategyClient::EndTurn (this=330dbd58): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:59:09.827 [tid 10144] fpu: sample at StrategyClient::EndTurn (this=330e0628): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
00:32:14.211 [tid 8036] ==== sots-engine shim (binkw32 proxy) build ap-989c692-20260909T0425Z ====
|
||||
00:32:14.211 [tid 8036] exe: C:\SOTS\Sword of the Stars.exe
|
||||
00:32:14.211 [tid 8036] exe base=0x006b0000 (link-time image base 0x00400000, ASLR delta +2818048) pid=8872 shim=72b60000
|
||||
00:32:14.211 [tid 8036] addresses: Source: sots-re ghidra/addresses.json @ 48db3cc, generated 2026-09-08 by tools/gen_addresses.py
|
||||
00:32:14.211 [tid 8036] config: hooks=trace
|
||||
00:32:14.211 [tid 8036] config: hook.Shim::SelfTest::Fill=off
|
||||
00:32:14.211 [tid 8036] config: hook.Mars::GlobalConsts::LoadFile=off
|
||||
00:32:14.211 [tid 8036] config: hook.Game::WeaponDictionary::Init=off
|
||||
00:32:14.211 [tid 8036] config: hook.Game::SectionDictionary::SectionDictionary=off
|
||||
00:32:14.211 [tid 8036] config: hook.Game::ServerPlayer::ComputeBudget=off
|
||||
00:32:14.211 [tid 8036] config: hook.Game::TechTree::ProcessResearch=off
|
||||
00:32:14.211 [tid 8036] config: hook.Game::ServerPlayer::OnTechResearched=off
|
||||
00:32:14.211 [tid 8036] config: hook.Game::ServerSystem::ProcessTurn=off
|
||||
00:32:14.211 [tid 8036] config: hook.Game::ServerPlayer::ProcessTurn=off
|
||||
00:32:14.211 [tid 8036] config: hook.Game::ServerSystem::GroupOutput=off
|
||||
00:32:14.211 [tid 8036] config: hook.Game::ServerSystem::ComputeTotalOutput=off
|
||||
00:32:14.211 [tid 8036] config: hook.Game::StrategyServer::MoveFleet=off
|
||||
00:32:14.211 [tid 8036] config: hook.Game::StrategyServer::ProcessFleetMovement=off
|
||||
00:32:14.211 [tid 8036] config: hook.Game::StrategyHost::Autosave=trace
|
||||
00:32:14.211 [tid 8036] config: hook.Game::StrategyServer::ProcessTurn=trace
|
||||
00:32:14.211 [tid 8036] config: hook.Game::StrategyServer::OnAllCombatDone_Tail=trace
|
||||
00:32:14.211 [tid 8036] config: hook.Game::StrategyServer::ApplyEncounterResult=trace
|
||||
00:32:14.211 [tid 8036] config: hook.Game::StrategyServer::NodeLineDecay=trace
|
||||
00:32:14.211 [tid 8036] config: hook.Game::StrategyServer::ProcessNodeSpaceTravel=trace
|
||||
00:32:14.211 [tid 8036] config: hook.Game::EncounterDetect::AssignContacts=trace
|
||||
00:32:14.211 [tid 8036] config: hook.Game::EncounterDetect::ProcessTeamRecord=trace
|
||||
00:32:14.211 [tid 8036] config: fpu.sample_turn=off
|
||||
00:32:14.211 [tid 8036] config: fpu.sample_ticks=off
|
||||
00:32:14.211 [tid 8036] config: trace.inline_max=64
|
||||
00:32:14.211 [tid 8036] config: trace.path=C:\SOTS\shim.trace.jsonl
|
||||
00:32:14.211 [tid 8036] config: trace.flush=always
|
||||
00:32:14.211 [tid 8036] config: probes=8 -> 8 lane-H entry probes
|
||||
00:32:14.274 [tid 8036] trace: C:\SOTS\shim.trace.jsonl (default mode trace, inline_max 64, flush always)
|
||||
00:32:14.274 [tid 8036] hook: Mars_Application_Initialize rva=0x004a0e50 -> va=00b50e50
|
||||
00:32:14.274 [tid 8036] hook: MH_Initialize -> MH_OK
|
||||
00:32:14.274 [tid 8036] hook: MH_CreateHook -> MH_OK (trampoline=013f0fe0)
|
||||
00:32:14.305 [tid 8036] hook: MH_EnableHook -> MH_OK
|
||||
00:32:14.305 [tid 8036] cfg: GlobalConsts hook ready (scale constant 0.017453292519943295)
|
||||
00:32:14.305 [tid 8036] hook: Mars::GlobalConsts::LoadFile rva=0x004b73c0 mode=off (not installed)
|
||||
00:32:14.305 [tid 8036] dict: dictionaries hook ready (crt new=74c4232b delete=74c40174)
|
||||
00:32:14.305 [tid 8036] hook: Game::WeaponDictionary::Init rva=0x0019a4c0 mode=off (not installed)
|
||||
00:32:14.305 [tid 8036] hook: Game::SectionDictionary::SectionDictionary rva=0x00176f40 mode=off (not installed)
|
||||
00:32:14.305 [tid 8036] research: ProcessResearch hook ready (Cost=0082da00, node=0x34, rng=0x9cc, fpu_cw=0x027f)
|
||||
00:32:14.305 [tid 8036] hook: Game::TechTree::ProcessResearch rva=0x001876c0 mode=off (not installed)
|
||||
00:32:14.305 [tid 8036] techfx: OnTechResearched hook ready (regions=15, gate=0/0, fpu_cw=0x027f)
|
||||
00:32:14.305 [tid 8036] hook: Game::ServerPlayer::OnTechResearched rva=0x00491790 mode=off (not installed)
|
||||
00:32:14.305 [tid 8036] hook: Game::ServerPlayer::ComputeBudget rva=0x00463030 mode=off (not installed)
|
||||
00:32:14.305 [tid 8036] hook: Game::ServerSystem::ProcessTurn rva=0x003598e0 mode=off (not installed)
|
||||
00:32:14.305 [tid 8036] hook: Game::ServerSystem::GroupOutput rva=0x0034b7a0 mode=off (not installed)
|
||||
00:32:14.305 [tid 8036] hook: Game::ServerSystem::ComputeTotalOutput rva=0x00350480 mode=off (not installed)
|
||||
00:32:14.305 [tid 8036] player_turn: ServerPlayer::ProcessTurn hook armed (ratio helper at 0082e950)
|
||||
00:32:14.305 [tid 8036] hook: Game::ServerPlayer::ProcessTurn rva=0x00491340 mode=off (not installed)
|
||||
00:32:14.305 [tid 8036] hook: Game::StrategyServer::MoveFleet rva=0x003d9ee0 mode=off (not installed)
|
||||
00:32:14.305 [tid 8036] hook: Game::StrategyServer::ProcessFleetMovement rva=0x003da9a0 mode=off (not installed)
|
||||
00:32:14.305 [tid 8036] hook: Game::StrategyHost::Autosave rva=0x00495210 -> va=00b45210 MH_CreateHook -> MH_OK (trampoline=013f0fc0)
|
||||
00:32:14.321 [tid 8036] hook: Game::StrategyHost::Autosave MH_EnableHook -> MH_OK mode=trace
|
||||
00:32:14.321 [tid 8036] hook: Game::StrategyServer::ProcessTurn rva=0x003dc6c0 -> va=00a8c6c0 MH_CreateHook -> MH_OK (trampoline=013f0fa0)
|
||||
00:32:14.336 [tid 8036] hook: Game::StrategyServer::ProcessTurn MH_EnableHook -> MH_OK mode=trace
|
||||
00:32:14.336 [tid 8036] hook: Game::StrategyServer::OnAllCombatDone_Tail rva=0x003d92a0 -> va=00a892a0 MH_CreateHook -> MH_OK (trampoline=013f0f80)
|
||||
00:32:14.336 [tid 8036] hook: Game::StrategyServer::OnAllCombatDone_Tail MH_EnableHook -> MH_OK mode=trace
|
||||
00:32:14.336 [tid 8036] hook: Game::StrategyServer::ApplyEncounterResult rva=0x003d8920 -> va=00a88920 MH_CreateHook -> MH_OK (trampoline=013f0f60)
|
||||
00:32:14.352 [tid 8036] hook: Game::StrategyServer::ApplyEncounterResult MH_EnableHook -> MH_OK mode=trace
|
||||
00:32:14.352 [tid 8036] hook: Game::StrategyServer::NodeLineDecay rva=0x003ae010 -> va=00a5e010 MH_CreateHook -> MH_OK (trampoline=013f0f40)
|
||||
00:32:14.367 [tid 8036] hook: Game::StrategyServer::NodeLineDecay MH_EnableHook -> MH_OK mode=trace
|
||||
00:32:14.367 [tid 8036] hook: Game::StrategyServer::ProcessNodeSpaceTravel rva=0x003a0e20 -> va=00a50e20 MH_CreateHook -> MH_OK (trampoline=013f0f20)
|
||||
00:32:14.383 [tid 8036] hook: Game::StrategyServer::ProcessNodeSpaceTravel MH_EnableHook -> MH_OK mode=trace
|
||||
00:32:14.383 [tid 8036] hook: Game::EncounterDetect::AssignContacts rva=0x003aa240 -> va=00a5a240 MH_CreateHook -> MH_OK (trampoline=013f0f00)
|
||||
00:32:14.399 [tid 8036] hook: Game::EncounterDetect::AssignContacts MH_EnableHook -> MH_OK mode=trace
|
||||
00:32:14.399 [tid 8036] hook: Game::EncounterDetect::ProcessTeamRecord rva=0x003ca640 -> va=00a7a640 MH_CreateHook -> MH_OK (trampoline=013f0ee0)
|
||||
00:32:14.414 [tid 8036] hook: Game::EncounterDetect::ProcessTeamRecord MH_EnableHook -> MH_OK mode=trace
|
||||
00:32:14.414 [tid 8036] hook: Game::StrategyServer::BeginProcessTurn rva=0x003d98e0 -> va=00a898e0 MH_CreateHook -> MH_OK (trampoline=013f0ec0)
|
||||
00:32:14.430 [tid 8036] hook: Game::StrategyServer::BeginProcessTurn MH_EnableHook -> MH_OK mode=trace
|
||||
00:32:14.430 [tid 8036] hook: Game::SVSOSwarmQueen::OnTurnBegin rva=0x00129930 -> va=007d9930 MH_CreateHook -> MH_OK (trampoline=013f0ea0)
|
||||
00:32:14.446 [tid 8036] hook: Game::SVSOSwarmQueen::OnTurnBegin MH_EnableHook -> MH_OK mode=trace
|
||||
00:32:14.446 [tid 8036] hook: Game::SVSOSwarmQueen::RegisterHives rva=0x00127630 -> va=007d7630 MH_CreateHook -> MH_OK (trampoline=013f0e80)
|
||||
00:32:14.461 [tid 8036] hook: Game::SVSOSwarmQueen::RegisterHives MH_EnableHook -> MH_OK mode=trace
|
||||
00:32:14.461 [tid 8036] hook: Game::SVSOSwarmQueen::TickHives rva=0x00127770 -> va=007d7770 MH_CreateHook -> MH_OK (trampoline=013f0e60)
|
||||
00:32:14.477 [tid 8036] hook: Game::SVSOSwarmQueen::TickHives MH_EnableHook -> MH_OK mode=trace
|
||||
00:32:14.477 [tid 8036] hook: Game::SVSOSlaversRefuel::UpdateDifficultyTier rva=0x00115820 -> va=007c5820 MH_CreateHook -> MH_OK (trampoline=013f0e40)
|
||||
00:32:14.492 [tid 8036] hook: Game::SVSOSlaversRefuel::UpdateDifficultyTier MH_EnableHook -> MH_OK mode=trace
|
||||
00:32:14.492 [tid 8036] hook: Mars::RNG::Seed rva=0x0009fdf0 -> va=0074fdf0 MH_CreateHook -> MH_OK (trampoline=013f0e20)
|
||||
00:32:14.508 [tid 8036] hook: Mars::RNG::Seed MH_EnableHook -> MH_OK mode=trace
|
||||
00:32:14.508 [tid 8036] hook: Game::StrategyApp::RunAI rva=0x004706f0 -> va=00b206f0 MH_CreateHook -> MH_OK (trampoline=013f0e00)
|
||||
00:32:14.524 [tid 8036] hook: Game::StrategyApp::RunAI MH_EnableHook -> MH_OK mode=trace
|
||||
00:32:14.524 [tid 8036] drawsite: Mars::RNG::NextFloat rva=0x0007d830 -> va=0072d830 create=MH_OK enable=MH_OK
|
||||
00:32:14.539 [tid 8036] drawsite: Mars::RNG::NextInt rva=0x000271c0 -> va=006d71c0 create=MH_OK enable=MH_OK
|
||||
00:32:14.555 [tid 8036] drawsite: Mars::RNG::Chance rva=0x004e6dd0 -> va=00b96dd0 create=MH_OK enable=MH_OK
|
||||
00:32:14.571 [tid 8036] drawsite: Mars::RNG::NextUInt rva=0x000f7670 -> va=007a7670 create=MH_OK enable=MH_OK
|
||||
00:32:14.586 [tid 8036] drawsite: Mars::RNG::FloatRange rva=0x0007d8a0 -> va=0072d8a0 create=MH_OK enable=MH_OK
|
||||
00:32:14.602 [tid 8036] drawsite: Mars::RNG::IntRangeBell rva=0x004e6d80 -> va=00b96d80 create=MH_OK enable=MH_OK
|
||||
00:32:14.617 [tid 8036] drawsite: Mars::RNG::GaussianRange rva=0x004e6e30 -> va=00b96e30 create=MH_OK enable=MH_OK
|
||||
00:32:14.617 [tid 8036] probe: installing 8 of 12 (probes= in shim.cfg)
|
||||
00:32:14.633 [tid 8036] probe: Game::ServerSpyManager::vslot13 rva=0x004877b0 -> va=00b377b0 create=MH_OK enable=MH_OK
|
||||
00:32:14.649 [tid 8036] probe: Game::ServerSpyManager::vslot14 rva=0x0048db80 -> va=00b3db80 create=MH_OK enable=MH_OK
|
||||
00:32:14.664 [tid 8036] probe: Game::ServerTradeManagerImpl::vslot13 rva=0x0048ef80 -> va=00b3ef80 create=MH_OK enable=MH_OK
|
||||
00:32:14.680 [tid 8036] probe: Game::ServerTradeManagerImpl::vslot15 rva=0x0042cca0 -> va=00adcca0 create=MH_OK enable=MH_OK
|
||||
00:32:14.696 [tid 8036] probe: Game::SpyManager::Slot13RngCallee rva=0x004408e0 -> va=00af08e0 create=MH_OK enable=MH_OK
|
||||
00:32:14.711 [tid 8036] probe: Game::TradeManager::Slot13RngCalleeA rva=0x00420ca0 -> va=00ad0ca0 create=MH_OK enable=MH_OK
|
||||
00:32:14.727 [tid 8036] probe: Game::TradeManager::Slot13RngCalleeB rva=0x0048b440 -> va=00b3b440 create=MH_OK enable=MH_OK
|
||||
00:32:14.742 [tid 8036] probe: Game::ServerTradeManager::CreateRaidEncounter rva=0x004938a0 -> va=00b438a0 create=MH_OK enable=MH_OK
|
||||
00:32:14.742 [tid 8036] watch: disabled (watch=off)
|
||||
00:32:14.742 [tid 8036] aiorders: disabled (aiorders=off)
|
||||
00:32:14.742 [tid 8036] fpu: module init, entry cw=0x027f 53bit-double/nearest; force=off value=0x0000 sample_ticks=off
|
||||
00:32:14.742 [tid 8036] fpu: sample_turn=off (off releases StrategyServer::ProcessTurn for another hook)
|
||||
00:32:14.742 [tid 8036] fpu: StrategyClient::EndTurn rva=0x00383be0 -> va=00a33be0 MH_CreateHook -> MH_OK (trampoline=013f0c00)
|
||||
00:32:14.758 [tid 8036] fpu: StrategyClient::EndTurn MH_EnableHook -> MH_OK
|
||||
00:32:14.758 [tid 8036] fpu: StrategyServer::BeginProcessTurn rva=0x003d98e0 -> va=00a898e0 MH_CreateHook -> MH_ERROR_ALREADY_CREATED (trampoline=00000000)
|
||||
00:32:14.758 [tid 8036] fpu: StrategyServer::ProcessTurn rva=0x003dc6c0 not installed (sampler off)
|
||||
00:32:14.758 [tid 8036] fpu: DemoApp::OnTick rva=0x0049a640 not installed (sampler off)
|
||||
00:32:14.758 [tid 8036] selftest: Shim::SelfTest::Fill mode=off checksum=075ef0c3 records=0
|
||||
00:32:14.758 [tid 8036] Application::Initialize called (this=03438128)
|
||||
00:40:12.096 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=0d67e8f0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:40:15.284 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e7ee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:40:15.284 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e8d70): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:40:25.878 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=0d67e8f0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:40:29.081 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e7ee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:40:29.096 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e8d70): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:40:39.299 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=0d67e8f0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:40:42.503 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e7ee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:40:42.503 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e8d70): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:40:52.768 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=0d67e8f0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:40:55.956 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e7ee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:40:55.971 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e8d70): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:41:06.237 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=0d67e8f0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:41:09.471 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e7ee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:41:09.471 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e8d70): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:41:19.690 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=0d67e8f0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:41:22.893 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e7ee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:41:22.893 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e8d70): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:41:33.096 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=0d67e8f0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:41:36.331 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e7ee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:41:36.331 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e8d70): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:41:46.549 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=0d67e8f0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:41:49.799 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e7ee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:41:49.799 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e8d70): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:42:00.018 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=0d67e8f0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:42:03.237 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e7ee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:42:03.237 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e8d70): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:42:13.503 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=0d67e8f0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:42:16.706 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e7ee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:42:16.706 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e8d70): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:42:26.956 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=0d67e8f0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:42:30.174 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e7ee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:42:30.190 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e8d70): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:42:40.378 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=0d67e8f0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:42:43.549 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e7ee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
00:42:43.549 [tid 8036] fpu: sample at StrategyClient::EndTurn (this=341e8d70): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||
Binary file not shown.
Binary file not shown.
Loading…
Add table
Reference in a new issue