Compare commits
5 commits
5e4c27772d
...
e935ec5880
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e935ec5880 | ||
|
|
c37eb0e79b | ||
|
|
db4fda269f | ||
|
|
df9431be64 | ||
|
|
f8ff1b6fa9 |
19 changed files with 1692 additions and 20 deletions
|
|
@ -1,16 +1,16 @@
|
||||||
# SotS RE campaign — coverage dashboard
|
# SotS RE campaign — coverage dashboard
|
||||||
|
|
||||||
Generated 2026-09-09 04:14 UTC · `sots-re` @ aef3d48,2026-09-09 · `sots-engine` @ 989c692,2026-09-08 (240 commits) · regenerate with `tools/dashboard.py`
|
Generated 2026-09-09 04:39 UTC · `sots-re` @ c37eb0e,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
|
> **North star:** A functional reimplementation of the engine — behavior-equivalent, NOT byte-for-byte
|
||||||
|
|
||||||
## 1. Map coverage (campaign/board.md)
|
## 1. Map coverage (campaign/board.md)
|
||||||
|
|
||||||
414 targets · mapped-or-better **367/414** `[█████████░] 89%` · verified **325/414** `[████████░░] 79%`
|
418 targets · mapped-or-better **371/418** `[█████████░] 89%` · verified **329/418** `[████████░░] 79%`
|
||||||
|
|
||||||
| Status | Count | % |
|
| Status | Count | % |
|
||||||
|---|---:|---:|
|
|---|---:|---:|
|
||||||
| verified | 325 | 79% |
|
| verified | 329 | 79% |
|
||||||
| mapped | 42 | 10% |
|
| mapped | 42 | 10% |
|
||||||
| in-progress | 4 | 1% |
|
| in-progress | 4 | 1% |
|
||||||
| backlog | 41 | 10% |
|
| backlog | 41 | 10% |
|
||||||
|
|
@ -19,26 +19,26 @@ Generated 2026-09-09 04:14 UTC · `sots-re` @ aef3d48,2026-09-09 · `sots-engine
|
||||||
| Type | verified | mapped | in-progress | backlog | blocked | total |
|
| Type | verified | mapped | in-progress | backlog | blocked | total |
|
||||||
|---|---:|---:|---:|---:|---:|---:|
|
|---|---:|---:|---:|---:|---:|---:|
|
||||||
| objects | 46 | 6 | 0 | 3 | 1 | 56 |
|
| objects | 46 | 6 | 0 | 3 | 1 | 56 |
|
||||||
| control-flow | 29 | 2 | 0 | 0 | 0 | 31 |
|
| control-flow | 32 | 2 | 0 | 0 | 0 | 34 |
|
||||||
| subsystems | 4 | 8 | 0 | 2 | 1 | 15 |
|
| subsystems | 4 | 8 | 0 | 2 | 1 | 15 |
|
||||||
| engine | 30 | 0 | 0 | 0 | 0 | 30 |
|
| engine | 30 | 0 | 0 | 0 | 0 | 30 |
|
||||||
| verify | 102 | 15 | 3 | 35 | 0 | 155 |
|
| verify | 102 | 15 | 3 | 35 | 0 | 155 |
|
||||||
| phase2 | 13 | 3 | 1 | 0 | 0 | 17 |
|
| phase2 | 13 | 3 | 1 | 0 | 0 | 17 |
|
||||||
| meta | 82 | 6 | 0 | 1 | 0 | 89 |
|
| meta | 83 | 6 | 0 | 1 | 0 | 90 |
|
||||||
| other | 19 | 2 | 0 | 0 | 0 | 21 |
|
| other | 19 | 2 | 0 | 0 | 0 | 21 |
|
||||||
|
|
||||||
## 2. Binary understanding
|
## 2. Binary understanding
|
||||||
|
|
||||||
- RTTI type descriptors: **1,924** (`Game::` 1,404, `Mars::` 194; serializable types 179)
|
- 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
|
- 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): **1283**, verified **1152** `[█████████░] 90%`
|
- Functions: **41,411** (parsed from `01-fingerprint.md`); named/annotated in the **address contract** (`ghidra/addresses.json`, not Ghidra's full rename count): **1282**, verified **1151** `[█████████░] 90%`
|
||||||
|
|
||||||
## 3. Data layer
|
## 3. Data layer
|
||||||
|
|
||||||
- Catalogs: **1,595/1,595** files parsed (91 block kinds in `schema_stats.json`), dangling cross-refs **0** (`crosslink.json`)
|
- 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-parse`: **1,531/1,531** files agree `[██████████] 100%`
|
||||||
- Oracle `mars-text`: **64/64** files agree `[██████████] 100%`
|
- Oracle `mars-text`: **64/64** files agree `[██████████] 100%`
|
||||||
- Saves: **29/29** real saves strict-clean — strict exit 0, 0 errors, 0 warnings
|
- Saves: **33/33** real saves strict-clean — strict exit 0, 0 errors, 0 warnings
|
||||||
- Design rules: **127/127** stock designs pass `[██████████] 100%`
|
- 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`)
|
- 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
|
## 7. Verification ledger
|
||||||
|
|
||||||
- ✅ Saves strict: 29/29 (strict exit 0, 0 errors, 0 warnings)
|
- ✅ Saves strict: 33/33 (strict exit 0, 0 errors, 0 warnings)
|
||||||
- ✅ Design rules: 127/127
|
- ✅ Design rules: 127/127
|
||||||
- ✅ oracle mars-parse 1531/1531 · ✅ oracle mars-text 64/64
|
- ✅ oracle mars-parse 1531/1531 · ✅ oracle mars-text 64/64
|
||||||
- ✅ Compare harness present (`verify/harness/compare/`)
|
- ✅ Compare harness present (`verify/harness/compare/`)
|
||||||
|
|
@ -133,11 +133,11 @@ Most recent open:
|
||||||
|
|
||||||
## 9. Delta since previous dashboard
|
## 9. Delta since previous dashboard
|
||||||
|
|
||||||
- verified targets: 321 → 325 (+4) · mapped-or-better: 363 → 367 (+4)
|
- verified targets: 325 → 329 (+4) · mapped-or-better: 367 → 371 (+4)
|
||||||
- engine LOC: 58,647 → 58,647 (+0) · test files: 122 → 122 (+0) · checks: 4,257 → 4,257 (+0)
|
- engine LOC: 58,647 → 58,647 (+0) · test files: 122 → 122 (+0) · checks: 4,257 → 4,257 (+0)
|
||||||
- addresses verified: 1,145 → 1,152 (+7) · recovered layouts: 384 → 384 (+0) · open questions: 26 → 26 (+0)
|
- addresses verified: 1,152 → 1,151 (-1) · recovered layouts: 384 → 384 (+0) · open questions: 26 → 26 (+0)
|
||||||
- standalone leaves closed: 45 → 45 (+0) · leaves still diverging: 63 → 63 (+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
|
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": 325, "mapped_plus": 367, "targets": 414, "loc": 58647, "tests": 122, "checks": 4257, "addr_verified": 1152, "addr_total": 1283, "layouts": 384, "open_q": 26, "sa_closed": 45, "sa_left": 63} -->
|
<!-- dashboard-metrics {"verified": 329, "mapped_plus": 371, "targets": 418, "loc": 58647, "tests": 122, "checks": 4257, "addr_verified": 1151, "addr_total": 1282, "layouts": 384, "open_q": 26, "sa_closed": 45, "sa_left": 63} -->
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,8 +1,10 @@
|
||||||
# The raid target pick — a verdict on `TradeManager+0x0c`
|
# The raid target pick — a verdict on `TradeManager+0x0c`
|
||||||
|
|
||||||
- **Type:** control-flow (static decode of the writer + live measurement)
|
- **Type:** control-flow (static decode of the writer + live measurement)
|
||||||
- **Owner / date:** lane AR · 2026-09-08 · guest **VM141** (`sots-re-win10-b`, 192.168.10.143) —
|
- **Owner / date:** lane AR · 2026-09-08 → 2026-09-09 · guest **VM141** (`sots-re-win10-b`,
|
||||||
**held from the time this file was committed**
|
192.168.10.143) — held from the time the predictions were committed, **released** (§10)
|
||||||
|
- **Status:** **verified** for the verdict, for `A`'s per-fleet cost and for the oracle pair;
|
||||||
|
**one observation** of the pick itself, and the coverage limits are listed in §7
|
||||||
- **Decides:** lane AG's `gate-indexed-rng-audit.md` §3.3 final paragraph — *per-system containing-sector
|
- **Decides:** lane AG's `gate-indexed-rng-audit.md` §3.3 final paragraph — *per-system containing-sector
|
||||||
table* versus *sector-indexed vector of six* — which lane AD (`raid-gate-multiplicity.md` §4) measured
|
table* versus *sector-indexed vector of six* — which lane AD (`raid-gate-multiplicity.md` §4) measured
|
||||||
and correctly reported it could not separate on sector `TradeID 832`
|
and correctly reported it could not separate on sector `TradeID 832`
|
||||||
|
|
@ -196,3 +198,496 @@ from its usual direction.
|
||||||
---
|
---
|
||||||
|
|
||||||
*Results, and the verdict, follow below. Nothing above this line is edited after the run.*
|
*Results, and the verdict, follow below. Nothing above this line is edited after the run.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. The verdict
|
||||||
|
|
||||||
|
> ### `TradeManager+0x0c` is the **per-system containing-trade-sector table**. Lane AG's §3.3 reading is **correct**; the sector-indexed-vector-of-six reading is **dead**.
|
||||||
|
>
|
||||||
|
> Two independent instruments agree, and they are the two rule 3 names.
|
||||||
|
>
|
||||||
|
> **Static.** The writer AG's §7 lists as not found is `FUN_00841700`. It resizes the `+0x0c` vector
|
||||||
|
> to the length of the *systems* vector — the same container `FUN_00841cd0` indexes with `rt->trfr` —
|
||||||
|
> and fills it with `containingSector[system.Idx] = sector`. `G_B1a` cannot reject a valid `trfr`.
|
||||||
|
>
|
||||||
|
> **Behavioural.** On turn 42 of the instrumented run, with a raider parked on sector `TradeID 816`
|
||||||
|
> and `Pos` bit-equal, `TradeManager::Slot13RngCalleeB` was entered once and the return-address ledger
|
||||||
|
> priced it: **`NextInt` at call `0x0088b613`, calls = 1, words = 1.** `OnAllCombatDone_Tail` cost
|
||||||
|
> **5** words on that turn against **4** on every other turn of the same run. Bracket residual **0**.
|
||||||
|
>
|
||||||
|
> **And the same run carries its own control.** On turns 38 and 40 `Slot13RngCalleeB` was entered
|
||||||
|
> once each — by a cruiser parked on sector `TradeID 832` — and cost **0 words**, exactly as lane AC
|
||||||
|
> and lane AD measured. **Same process, same build, same instrument, same function, same turn
|
||||||
|
> structure; the only difference is which sector the raider stands on.** That is the cleanest
|
||||||
|
> available demonstration that AC's and AD's proof-carrying zero is a fact about the *sector*, and
|
||||||
|
> that the code path itself is live.
|
||||||
|
|
||||||
|
`0x0088b613` had never fired in this campaign. It has now.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. What was run
|
||||||
|
|
||||||
|
Four fresh processes on VM141, all on the same guest with the same dist
|
||||||
|
(`C:\SOTS\shimdist-ar`, `BUILD_ID ar-989c692-20260909T0313Z`, built in
|
||||||
|
`/srv/re-lab/build/sots-engine-ar` after `ssh spicy 'rm -rf …'` of the whole tree, from a lane-private
|
||||||
|
`git worktree` at `~/sots-engine-ar` with no local `build*` shipped — rules 21 and 24) and the same
|
||||||
|
input save.
|
||||||
|
|
||||||
|
| run | config | End Turns | purpose |
|
||||||
|
|---|---|---|---|
|
||||||
|
| play-forward | `shim.cfg.hoff` | 10 (turn 27 → 37) | build the workload |
|
||||||
|
| **R1** | `shim.cfg.hp8` (`probes=8`) | 6 (turn 37 → 43) | the measurement |
|
||||||
|
| **OA** | `shim.cfg.hoff` | 1 (turn 37 → 38) | control |
|
||||||
|
| **OB** | `shim.cfg.hoff` | 1 (turn 37 → 38) | control, second fresh process |
|
||||||
|
|
||||||
|
**Instrument armed and verified from `shim.log`, not assumed** (rule 1): all 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** `config: ignoring unknown key` lines. Probe indices 8–11 report
|
||||||
|
**NOT INSTALLED**, never 0 — index 8 is `GenerateTradeRaidEncounters`, the detour lane H bisected as
|
||||||
|
*not* byte-neutral, excluded by construction. `shim.cfg.hp8` was used **unmodified**.
|
||||||
|
|
||||||
|
### 3.1 The workload, and what it cost
|
||||||
|
|
||||||
|
From `ad-turn27-two-raiders.sav`: five stock `Extended Range` destroyers queued at Epsilon Eridani
|
||||||
|
(Build screen confirms `Range 27.0`, `Construction Cost 2,252`, `Speed (Node Speed) 0.2 (4.0)` —
|
||||||
|
lane AD's costing is exact), completed over turns 28–31, then **split into four separate fleets** and
|
||||||
|
each ordered to sector 5's node. They arrived on turn 35; the state was saved on turn 37 as
|
||||||
|
`verify/results/saves/ar-turn37-816raiders.sav`
|
||||||
|
(sha256 `b6f4e05ff226eabd1695003b36293553642553cea96ef417364393e2332a7094`).
|
||||||
|
|
||||||
|
**Three UI facts the next lane should have, because each cost this lane time.**
|
||||||
|
|
||||||
|
1. **A new ship joins an existing fleet at the colony, and a fleet's `Range` is the minimum over its
|
||||||
|
ships.** The five 27-ly destroyers landed in `Gamma Fleet` alongside AD's 9-ly `Repair and Salvage`
|
||||||
|
cruiser and the fleet read `Range: 9.0 (9.0)` — sector 816 is 15.66 ly away and was not a legal
|
||||||
|
destination until the cruiser was split out. **Split the cruiser off first, then read the range.**
|
||||||
|
2. **Splitting is a right-click context menu on a *ship row* in the map's fleet panel**, not the
|
||||||
|
Manage Fleets screen (which offers only `Rename Fleet` and "Fleet Layout Not Available" here). The
|
||||||
|
menu is `Add To New Fleet` / `Split Ships` / `Add Note`, and its first item sits **+15 px** below
|
||||||
|
the click. The click helper has no right-click verb, but **`rdrag x y x y` — a right-drag of zero
|
||||||
|
length — works as one**, and that is how every split in this run was made.
|
||||||
|
3. **A trade-sector node is a legal move target even when its cube is not drawn.** Lane AD reported
|
||||||
|
that only sector 6's cube renders at any zoom, and that is still true. It does **not** mean the
|
||||||
|
other nodes are unreachable: in Move mode the hover readout names them
|
||||||
|
(`Sector 5 / Range: 15.7 / ETA: 4 Turns`) and a plain click commits. Two known screen points are
|
||||||
|
enough to fit `screen = (A·wx + B·wz + C, D·wx + E·wz + F)` from the save's world coordinates and
|
||||||
|
land the cursor on any node first try; this run fitted it from Epsilon Eridani and sector 800 and
|
||||||
|
hit sector 816 at (825, 444) on the first probe. **Hovering near a sector also makes its cube
|
||||||
|
appear**, which is the confirmation that the aim was right.
|
||||||
|
|
||||||
|
### 3.2 The gate, read from the save for the measured turns (rule 28)
|
||||||
|
|
||||||
|
`ar-turn37-816raiders.sav`, player 0 = `PlyrIdx 0` = `PID 16`, `CnRad true`:
|
||||||
|
|
||||||
|
| fleet | id | `LocID` | `Pos` vs sector `Pos` | rolls `A`? |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| `Alpha Fleet` (1 CR) | 3744 | **832** | `[0, 0, 8.0]` — **bit-identical** | yes |
|
||||||
|
| `Beta Fleet` (1 CR) | 6544 | **832** | `[0, 0, 8.0]` — **bit-identical** | yes |
|
||||||
|
| `Epsilon Fleet` (1 DE) | 49 | **816** | `[8.307682991027832, 0.05633879080414772, 0.4591276943683624]` — **bit-identical** | yes |
|
||||||
|
| `Eta Fleet` (1 DE) | 81 | **816** | same three floats — **bit-identical** | yes |
|
||||||
|
| `Zeta Fleet` (1 DE) | 65 | 816 | `[9.2771635055542, 0.03959554061293602, 1.8529905080795288]` — **not** the node | **no** (G4 fails) |
|
||||||
|
| `Delta Fleet` (1 CR) | 33 | 48 | home | no |
|
||||||
|
|
||||||
|
`Trade[816]`: `tsct 2`, `tscr 253`, `tsnumflt 5`, `tsflt 49, 65, 81, 8752, 8768` — my three plus the
|
||||||
|
AI's. `tsct = 2` is the AI's bit, so `TradeSector_PlayerTradesHere` is false for player 0 and **no
|
||||||
|
`FtFlg & 0x800` is required**, exactly as lane AD read it; every fleet above carries `FtFlg 4`.
|
||||||
|
|
||||||
|
**Four qualifying fleets, and `Slot13RngCalleeA` was entered exactly four times on every turn** —
|
||||||
|
which is both the confirmation of lane AD's per-fleet result on a new sector and a new hull, and the
|
||||||
|
proof that the two 816 destroyers clear G0–G4.
|
||||||
|
|
||||||
|
**`trfr` re-read on the state actually built, as instructed.** `trdmgr` at turn 37 holds **eight**
|
||||||
|
`rt` records — not lane AG's four at turn 22 and not lane AD's three at turn 27 — with
|
||||||
|
`trfr = 18, 16, 14, 20, 14, 20, 14, 25`, `tro = 32` and `trfrs = trtos = 0` on all eight. Mapping
|
||||||
|
each through the sector membership lists: **sector 816 sources two of them (`trfr` 18 and 16)**,
|
||||||
|
768 sources three, 752 two, 784 one, and 832 still sources none. So the candidate list on 816 has
|
||||||
|
`n = 2`, `bound = n − 1 = 1`, the mask is 1 and **no rejection is possible** — the site costs exactly
|
||||||
|
one word, which is what it cost.
|
||||||
|
|
||||||
|
**Correction to lane AD (rule 11).** `raid-gate-multiplicity.md` §4 reports *"three route records,
|
||||||
|
`trfr = 18, 14, 14"* in `ad-turn27-two-raiders.sav`. That save holds **five**, `trfr = 18, 16, 14,
|
||||||
|
20, 14`. Read directly with `save_reader.py --dump` before this lane touched the guest. The
|
||||||
|
consequence matters: **sector 816 already sourced two routes at turn 27**, not one.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. The numbers
|
||||||
|
|
||||||
|
### 4.1 Per turn, all three instruments side by side
|
||||||
|
|
||||||
|
`A` = `TradeManager::Slot13RngCalleeA` (probe 5) · `B` = `Slot13RngCalleeB` (probe 6) ·
|
||||||
|
"tail" = `OnAllCombatDone_Tail`'s word delta from the boundary ledger ·
|
||||||
|
`0x0088b613` = the raid target pick, from `draw_sites` return-address attribution.
|
||||||
|
|
||||||
|
| turn | `A` entries | `0x00820e18` calls/words | `B` entries | **`0x0088b613`** | **tail words** | bracket residual |
|
||||||
|
|---|---|---|---|---|---|---|
|
||||||
|
| 38 | 4 | 4 / 4 | **1** | — | 4 | 0 |
|
||||||
|
| 39 | 4 | 4 / 4 | 0 | — | 4 | 0 |
|
||||||
|
| 40 | 4 | 4 / 4 | **1** | — | 4 | 0 |
|
||||||
|
| 41 | 4 | 4 / 4 | 0 | — | 4 | 0 |
|
||||||
|
| **42** | 4 | 4 / 4 | **1** | **calls = 1, words = 1** | **5** | 0 |
|
||||||
|
| 43 | 3 | 3 / 3 | 0 | — | 3 | 0 |
|
||||||
|
|
||||||
|
**Read the two rows that matter together.** Turns 38 and 40: `B` entered, tail 4 — `B` cost **0**.
|
||||||
|
Turn 42: `B` entered, tail **5** — `B` cost **1**, and the ledger names the site. The difference is
|
||||||
|
which sector the successful raider stood on, and nothing else moved: `A`'s row is `calls = words = 4`
|
||||||
|
on all five of those turns and the bracket residual is 0 on every one.
|
||||||
|
|
||||||
|
Turn 43's `A = 3` is not a defect: `Epsilon Fleet` had been displaced off the node by its own
|
||||||
|
successful raid on turn 42 (§4.3), so only three fleets satisfied G4.
|
||||||
|
|
||||||
|
### 4.2 `B` costs **one** word on a success, not two — and why
|
||||||
|
|
||||||
|
**No `0x00820c1b` row appears on turn 42.** `FUN_00820af0` was called (it always is, immediately
|
||||||
|
after the pick) and returned without drawing. That is the species short-circuit, and this lane pinned
|
||||||
|
which disjunct fires, from the image:
|
||||||
|
|
||||||
|
```
|
||||||
|
FUN_00820af0:
|
||||||
|
if (routeOwner->Species == 1) frac = 1.0 ; AI here is Species 2 -- no
|
||||||
|
if (StarFleet_GetCrewSpeciesForIntercept(fleet) == 1) frac = 1.0 ; raider is Species 0 -- no
|
||||||
|
if (SpeciesDef_HasInterceptFlag(Get(that same species))) frac = 1.0 ; <-- THIS ONE
|
||||||
|
else frac = NextFloat() ; 0x00820c1b, 1 word
|
||||||
|
```
|
||||||
|
|
||||||
|
`Get` `0x00545cc0` returns `0x00b10a00 + k*0x184`; `InitTable` `0x005453a0` fills element `k` at that
|
||||||
|
same address and, at `0x0054562f`/`0x00545638`, sets `elem->+0x144 |= 1` when `k == 0` and `|= 2`
|
||||||
|
when `k == 5` — **and for no other species**. (Both of those addresses were **already named** in
|
||||||
|
`ghidra/addresses.json` as `SpeciesDef_Get` and `g_SpeciesDefTable`, from `handoff/tech-effects.md`.
|
||||||
|
This lane derived them independently from the `FUN_00820af0` call chain and the generator's
|
||||||
|
duplicate-name check is what surfaced the agreement — rule 14 working as designed. Only the `+0x144`
|
||||||
|
flag word is new, and it is the fragment's one data entry.) `SpeciesDef_HasInterceptFlag` `0x0053baf0` is twelve
|
||||||
|
bytes: `xor eax,eax; cmp [ecx+0x144],eax; setne al; ret`. So the flag is set for **Human (0) and Zuul
|
||||||
|
(5)** and clear for the other five.
|
||||||
|
|
||||||
|
> **A Human or Zuul raider intercepts at `frac = 1.0` and draws nothing; every other species draws a
|
||||||
|
> `NextFloat` at `0x00820c1b`.**
|
||||||
|
|
||||||
|
**This corrects two committed numbers, and the corrections point the same way** (rule 11):
|
||||||
|
|
||||||
|
- lane AG §5.2, *"`B`'s cost on success is `1 (NextInt) + 1 (NextFloat)`"* — true for five of the
|
||||||
|
seven species, false for the two whose flag is set, and the player in this lineage is one of them;
|
||||||
|
- lane AG §3.3's committed prediction, *"**3 words** on a turn it succeeds (`A` 1 + `B`'s `NextInt` 1
|
||||||
|
+ `FUN_00820af0`'s `NextFloat` 1)"* — the measured figure for one raider is **2**. My own P3/P4
|
||||||
|
carried the same error with a hedge on it; the hedge was the right half.
|
||||||
|
|
||||||
|
The general model, then, and it is a model of the *state*, not a constant (rule 20):
|
||||||
|
|
||||||
|
> **`OnAllCombatDone_Tail` costs `k + s + z` words**, where `k` is the number of permitted raiders
|
||||||
|
> parked on a trade-sector node with `Pos` bit-equal, `s` is how many of their raid rolls succeeded
|
||||||
|
> **on a sector that sources at least one raidable route**, and `z` is `s` again for a raider whose
|
||||||
|
> species does not set `SpeciesDef+0x144`. Measured here at `k + s` with `k` = 4, 4, 4, 4, 4, 3 and
|
||||||
|
> `s` = 0, 0, 0, 0, 1, 0.
|
||||||
|
|
||||||
|
### 4.3 A success moves the raider off the node — so a fleet raids at most once per parking
|
||||||
|
|
||||||
|
`Slot13RngCalleeB` writes `fleet->Pos = out` at `0x0088b672`, *after* the pick. G4 then fails for that
|
||||||
|
fleet on the following turn, because `Pos` is no longer bit-equal to the sector's. This is visible in
|
||||||
|
the saves and it explains turn 43's `A = 3`:
|
||||||
|
|
||||||
|
| fleet | `Pos` at turn 37 | `Pos` at turn 43 |
|
||||||
|
|---|---|---|
|
||||||
|
| `Eta Fleet` (81) | the node, bit-equal | the node, **still bit-equal** |
|
||||||
|
| `Epsilon Fleet` (49) | the node, bit-equal | `[7.13520622253418, 5.090692520141602, -2.1875174045562744]` — **displaced**, `LocID` still 816 |
|
||||||
|
| `Alpha`/`Beta` (832) | the node, bit-equal | the node, **still bit-equal** |
|
||||||
|
|
||||||
|
The 832 raiders are **never** displaced, because on 832 `B` returns at `G_B4` *before* the `Pos`
|
||||||
|
write. So the within-run control is durable by construction and the 816 arm exhausts itself — which
|
||||||
|
is a real constraint on this workload and the reason the run has one firing of the pick and not six.
|
||||||
|
|
||||||
|
### 4.4 Two more of lane AG's unread gates opened, on turn 43
|
||||||
|
|
||||||
|
```
|
||||||
|
turn 43 * STRAT NextInt call 0x008939ee FUN_008938a0+0x14e calls= 1 words= 1
|
||||||
|
* STRAT NextFloat call 0x00820c1b FUN_00820af0+0x12b calls= 1 words= 1
|
||||||
|
probe: ServerTradeManager::CreateRaidEncounter calls=3
|
||||||
|
```
|
||||||
|
|
||||||
|
- **`0x008939ee` fired.** That is the site behind `CreateRaidEncounter`'s empty-candidate-list gate —
|
||||||
|
lane H's measurement of it (*entered 2× on Zuul turn 24, 1× on turn 25, 0 words every time*) is the
|
||||||
|
campaign's case study for rule 20, and `tail-rng-ledger.md` has carried it as a zero ever since.
|
||||||
|
**The candidate list is not always empty**, and the first non-zero reading of that site is in this
|
||||||
|
trace.
|
||||||
|
- **`0x00820c1b` fired**, and **not** through `Slot13RngCalleeB` — `B` was entered 0 times on turn 43.
|
||||||
|
It came through the other caller, `0x0082cf65` inside the `CreateRaidEncounter` subtree, i.e. lane
|
||||||
|
AG's §5.1 chain `CreateRaidEncounter → 0x00892640 → 0x0082ce00 → FUN_00820af0`. Both of AG's §5.1
|
||||||
|
and §5.2 readings of that function's two call sites are therefore confirmed live, from opposite
|
||||||
|
directions.
|
||||||
|
|
||||||
|
### 4.5 The odds arithmetic — consistency, not validation (rule 15)
|
||||||
|
|
||||||
|
| arm | hull | odds per fleet-turn | rolls | expected | observed |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
| sector 832 | 1 CR | `(double)0.2f + (double)0.01f` = 0.21000000275671482, no freighter | 12 | 2.52 | **2** |
|
||||||
|
| sector 816 | 1 DE | `(double)0.05f + (double)0.01f` = 0.06, **doubled to 0.12** if the AI's `Freighters` fleet (id 7072, `LocID 816`) satisfies `param_2` | 11 | 0.66 / 1.32 | **1** |
|
||||||
|
|
||||||
|
**The freighter doubling is still not decided and I said in advance it would not be.** One success in
|
||||||
|
eleven rolls sits comfortably inside both hypotheses; separating 0.06 from 0.12 needs on the order of
|
||||||
|
a hundred rolls, and a fleet retires itself from the 816 arm the moment it succeeds (§4.3), which is
|
||||||
|
the structural reason this workload cannot cheaply accumulate them. The honest statement is that the
|
||||||
|
observed rate is consistent with the read constants and validates neither.
|
||||||
|
|
||||||
|
### 4.6 The news event `B` posts, named
|
||||||
|
|
||||||
|
`Slot13RngCalleeB`'s tail loop formats two strings held at `ds:0x00af0b5c` and `ds:0x00af0b64`.
|
||||||
|
Resolving their `GlobalConst` registrations in `FUN_009bf960` (`0x009bfcf0`, `0x009bfd10`) names them
|
||||||
|
**`EVENTSUM_SECTOR_RAIDERS_DETECTED`** and **`EVENTMSG_SECTOR_RAIDERS_DETECTED`**, and **each of those
|
||||||
|
two globals is referenced from exactly one function in the whole image — `0x0088b440`, `B` itself.**
|
||||||
|
So that event pair is a signature of the raid target pick having fired, visible in the news feed
|
||||||
|
without any instrument at all. It is posted to every player whose bit is in `sector->tssec`, which is
|
||||||
|
why the *raider* does not see it.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Verdicts on the committed predictions
|
||||||
|
|
||||||
|
| # | prediction | verdict |
|
||||||
|
|---|---|---|
|
||||||
|
| **P0** | `+0x0c` is the per-system containing-sector table; AG's reading right, sector-indexed reading dead | **CONFIRMED**, by the writer statically and by `0x0088b613` firing live |
|
||||||
|
| **P1** | `A` entered once per parked permitted fleet, 1 word each | **CONFIRMED** — 4/4 on five turns and 3/3 on the sixth, `0x00820e18` `calls == words` every turn |
|
||||||
|
| **P2** | `B` reaches `0x0088b613` and costs ≥ 1 word on an 816 success | **CONFIRMED** — calls = 1, words = 1 |
|
||||||
|
| **P3** | `B` costs 2 words (`NextInt` + `NextFloat`), *unless the species short-circuit fires* | **HALF WRONG, and the hedge was the right half.** It costs **1**. The short-circuit fires, and §4.2 names the disjunct: `SpeciesDef[Human]+0x144` bit 0, set by `InitTable` for species 0 and 5 only |
|
||||||
|
| **P4** | tail = `k + 2s`; 1 word on a failing turn and 3 on a succeeding one for one raider | **CORRECTED to `k + s`** — 4, 4, 4, 4, **5**, 3 against `k` = 4, 4, 4, 4, 4, 3. Lane AG's committed "3 words on a success" is **2** for this species |
|
||||||
|
| **P5** | a `draw_sites` row at `0x0088b613` with `calls == words == s`, and one at `0x00820c1b` | **CONFIRMED for `0x0088b613`** (calls = words = 1). **FALSIFIED for `0x00820c1b` via `B`** — no such row on turn 42; the site did fire on turn 43 but through `CreateRaidEncounter`, not through `B` |
|
||||||
|
| **P6** | `0x00820e18` shows `calls == words == k`, reproducing AD's per-fleet pricing on a new hull and sector | **CONFIRMED** on all six turns |
|
||||||
|
| **P7** | the `hooks=off` control will not agree with itself; the variation will be the AI's decisions; `/Sim/RNG` and `/Sim/trdmgr` bit-identical | §6 |
|
||||||
|
| **P8** | if `A` fires but `B` never does, report the binomial probability rather than "unremarkable" | **not triggered** — `B` fired three times and the pick once |
|
||||||
|
|
||||||
|
**The prediction that was wrong is the useful one.** P3/P4 were written from lane AG's §5.2 and they
|
||||||
|
are wrong for exactly the reason rule 23 exists: the deciding value is a **flag word set by a
|
||||||
|
constructor for two species out of seven**, and no amount of reading `FUN_00820af0` alone reveals it.
|
||||||
|
The measurement found it because the word count came out one short.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. The control — and it is an oracle pair (rules 19 and 26)
|
||||||
|
|
||||||
|
**P7 predicted the `hooks=off` control would fail to agree with itself, as lane AD's did on
|
||||||
|
`ad-turn27-two-raiders.sav`. P7 is FALSIFIED. The control agrees, byte for byte.**
|
||||||
|
|
||||||
|
Two fresh processes, same guest, same build, same `shim.cfg.hoff`, the same input save and the same
|
||||||
|
procedure — load, End Turn, resolve the one encounter query with `Auto Resolve Peacefully`, End Turn:
|
||||||
|
|
||||||
|
```
|
||||||
|
input ar-turn37-816raiders.sav b6f4e05ff226eabd1695003b36293553642553cea96ef417364393e2332a7094
|
||||||
|
|
||||||
|
OA (Autosave EndTurn).sav Frame 38 15b99255e1f03dab3e35ab8c1ac64f221cb5aa9321f113c7a6e3d1263c3f34ca
|
||||||
|
(Autosave).sav Frame 39 7a8b3d5eb3a60ebac9f40646d3e4b15768a24a0af047a439ce090c7cf38e8b38
|
||||||
|
|
||||||
|
OB (Autosave EndTurn).sav Frame 38 15b99255e1f03dab3e35ab8c1ac64f221cb5aa9321f113c7a6e3d1263c3f34ca
|
||||||
|
(Autosave).sav Frame 39 7a8b3d5eb3a60ebac9f40646d3e4b15768a24a0af047a439ce090c7cf38e8b38
|
||||||
|
```
|
||||||
|
|
||||||
|
`state_checksum.py --floats bits --mask none` on the two post-turn saves prints **`IDENTICAL`**, root
|
||||||
|
`237020deca931f5a180289592cece7ae`, `coverage: PROVED` (1,173,884 bytes rebuilt == inflated; 67,239
|
||||||
|
leaves), `0 error, 0 warn`.
|
||||||
|
|
||||||
|
> **This is a rung-A oracle pair, from a lineage that did not have one.** Lane AD ran the same check
|
||||||
|
> on `ad-turn27-two-raiders.sav` and got 94 differing leaves — all of them the AI empire's designs,
|
||||||
|
> build queues and fleet ids — and correctly refused to call that state calibration data. Ten turns
|
||||||
|
> later on the same lineage, the same check comes out byte-identical.
|
||||||
|
|
||||||
|
**I do not have an explanation for the difference and I am not going to invent one.** What can be
|
||||||
|
said precisely: AD's variation was confined to `Player[32]`'s decision sub-tree, and on this state
|
||||||
|
that sub-tree does not vary across processes. Whether that is because the AI's choices are forced
|
||||||
|
here, or because the per-process seed AD pinned enters somewhere this workload does not reach, is
|
||||||
|
**not settled by anything I measured**. The load-bearing consequence for the campaign is narrower and
|
||||||
|
solid: **AD's rule-26 result is a fact about that state, not about the lineage or the engine**, and a
|
||||||
|
lane that treats "the AI varies per process" as a general property of this game will be wrong at
|
||||||
|
least once.
|
||||||
|
|
||||||
|
Two honest limits on this pair, stated rather than glossed:
|
||||||
|
|
||||||
|
* **Two processes, not three.** Rule 26's bar is "reproduced in two fresh processes and agrees with
|
||||||
|
itself", which this clears; lane AD's `turn1-state` episode needed three to expose the variation,
|
||||||
|
and a third run here would be cheap for whoever wants it.
|
||||||
|
* **One workload.** Both runs took the same two End Turns and resolved the same encounter query the
|
||||||
|
same way. A pair is a statement about that procedure.
|
||||||
|
|
||||||
|
### 6.1 Rule 19 — the same two turns with the instrument installed
|
||||||
|
|
||||||
|
Run **R2**: a fourth fresh process, `shim.cfg.hp8` (`probes=8` + the seven `draw_sites` detours + the
|
||||||
|
boundary-ledger template hooks), same save, same two End Turns, same encounter resolution.
|
||||||
|
|
||||||
|
```
|
||||||
|
input ar-turn37-816raiders.sav b6f4e05ff226eabd1695003b36293553642553cea96ef417364393e2332a7094
|
||||||
|
|
||||||
|
OA hooks=off Frame 38 15b99255e1f03dab3e35ab8c1ac64f221cb5aa9321f113c7a6e3d1263c3f34ca
|
||||||
|
Frame 39 7a8b3d5eb3a60ebac9f40646d3e4b15768a24a0af047a439ce090c7cf38e8b38
|
||||||
|
OB hooks=off Frame 38 15b99255e1f03dab3e35ab8c1ac64f221cb5aa9321f113c7a6e3d1263c3f34ca
|
||||||
|
Frame 39 7a8b3d5eb3a60ebac9f40646d3e4b15768a24a0af047a439ce090c7cf38e8b38
|
||||||
|
R2 probes=8 Frame 38 15b99255e1f03dab3e35ab8c1ac64f221cb5aa9321f113c7a6e3d1263c3f34ca
|
||||||
|
Frame 39 7a8b3d5eb3a60ebac9f40646d3e4b15768a24a0af047a439ce090c7cf38e8b38
|
||||||
|
```
|
||||||
|
|
||||||
|
> **All three processes are byte-identical at both snapshot points, instrumented and not.** The
|
||||||
|
> `probes=8` + `draw_sites` + boundary-ledger instrument is **behaviour-neutral on this state, at
|
||||||
|
> whole-save byte granularity** — not "neutral on the sub-tree the measurement reads", which is the
|
||||||
|
> weaker statement lane AD could make, but neutral outright.
|
||||||
|
|
||||||
|
Rule 26's coincidence caveat does not apply here and it is worth saying why. AD warns that one
|
||||||
|
instrumented run agreeing with one control is a `1/k` coincidence when the control has an outcome set
|
||||||
|
of size `k`. **Here `k = 1`: the control was reproduced first and shown to be a single outcome, and
|
||||||
|
only then did the instrumented run match it.** That is the order the rule requires.
|
||||||
|
|
||||||
|
R2's own counters reproduce R1's turn 38 line for line — `A` `calls = words = 4`, `B` entered once at
|
||||||
|
**0 words**, `OnAllCombatDone_Tail` **4**, bracket total 24, **residual 0**, all seven `drawsite:` and
|
||||||
|
all eight `probe:` detours `create=MH_OK enable=MH_OK`, zero `ignoring unknown key`. So the
|
||||||
|
measurement is reproducible across processes as well as neutral.
|
||||||
|
|
||||||
|
**What this licenses, and what it does not.** It licenses treating
|
||||||
|
`ar-turn37-816raiders.sav` + two End Turns as a **rung-A calibration pair** for the standalone, which
|
||||||
|
is the first one this lineage has produced. It does **not** license the six-turn R1 sequence as one:
|
||||||
|
R1 resolved encounter queries on turns its own play produced, and that path was exercised once here,
|
||||||
|
not twice.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Coverage, and what was not done (rule 15)
|
||||||
|
|
||||||
|
* **Six instrumented turns, one process, four qualifying fleets, two sectors, two hull classes, one
|
||||||
|
species.** The pick fired **once**. One firing is enough to decide reachability — that was the
|
||||||
|
question — and it is **not** enough to price the site as a constant. The word count 1 is
|
||||||
|
corroborated by the static read of `RNG_NextInt` (mask smear, `bound = 1` ⇒ mask 1 ⇒ no rejection
|
||||||
|
possible), which is why I am willing to state it; if the candidate list on 816 ever exceeds two,
|
||||||
|
the rejection loop becomes live and the cost stops being 1 (rule 20 — do not fit a constant to one
|
||||||
|
observation).
|
||||||
|
* **The `k + s + z` model is fitted to `s ∈ {0, 1}` and `z = 0`.** `z` — the `FUN_00820af0` `NextFloat`
|
||||||
|
charged to `B` — has **never been observed through `B`**, in this lane or any other, because the
|
||||||
|
only species that has ever raided in this campaign is one of the two whose short-circuit flag is
|
||||||
|
set. **A non-Human, non-Zuul raider is now the cheapest unexercised state in the trade half**, and
|
||||||
|
it is one save away: the same workload played as Tarka, Liir, Hiver or Morrigi.
|
||||||
|
* **The freighter doubling is still untested** (§4.5), and the structure of the workload is why: a
|
||||||
|
successful raider leaves the node (§4.3), so the 816 arm cannot accumulate rolls without re-issuing
|
||||||
|
move orders every time.
|
||||||
|
* **`bestScale` was not read.** `0x009f8d48 = 0.33f` applies when `ship+0x18 & 0x100000`; that flag is
|
||||||
|
not obviously on the wire and this lane did not chase it. `A` cost exactly one word per fleet on
|
||||||
|
every turn regardless, which is independent of the scale.
|
||||||
|
* **The `design+0x12c > 1` short-circuit is still unpriced**, as it was for lane AD — the Dreadnought
|
||||||
|
category is empty in this game.
|
||||||
|
* **The spy half is untouched.**
|
||||||
|
* **No probe wanted `probes=11`.** Indices 8–11 are reported as NOT INSTALLED, never as zeros.
|
||||||
|
* **One accidental loss, disclosed.** `Gamma Fleet` (2 destroyers) and later `Zeta Fleet` (1) were
|
||||||
|
destroyed resolving encounters during the play-forward and the measured run. Both losses are inside
|
||||||
|
the workload, not the measurement: the input save is on disk and every number in §4 is read off the
|
||||||
|
trace of a run that loaded it.
|
||||||
|
* **What no lane has yet done on this state: a Rung B capture.** `--turn-commands` replay runs no AI,
|
||||||
|
and this state now has an *unconditional* rung-A pair, which makes it the obvious candidate for the
|
||||||
|
standalone's first trade-raid comparison.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Corrections to earlier findings (rule 11)
|
||||||
|
|
||||||
|
1. **Lane AG `gate-indexed-rng-audit.md` §7** — *"`ServerTradeManager+0x0c`'s writer was not found.
|
||||||
|
This is the one load-bearing inference in the document and it is flagged as one."* **Found:
|
||||||
|
`FUN_00841700`** (§1.0). AG's §3.3 reading is upheld and the alternative it offered is dead. The
|
||||||
|
flagging discipline is what made this a one-lane job, and it is worth saying so.
|
||||||
|
2. **Lane AG §3.3's committed prediction** — *"**3 words** on a turn `A` succeeds"* — is **2** for a
|
||||||
|
Human or Zuul raider, because `FUN_00820af0`'s third short-circuit fires
|
||||||
|
(`SpeciesDef[k]+0x144`, set by `InitTable` only for species 0 and 5). §4.2.
|
||||||
|
3. **Lane AG §5.2** — *"`B`'s cost on success is `1 (NextInt) + 1 (NextFloat)`, minus the species
|
||||||
|
short-circuit"* — right about the code, and the subtraction applies to the only species that has
|
||||||
|
ever raided in this campaign. `B` costs **1**.
|
||||||
|
4. **Lane AG's row-186 correction and `tail-rng-ledger.md` §11.1** — *"a success costs 0 or 1 further
|
||||||
|
word"* was corrected by AG to "at least six draws". Both sentences are now measured on the same
|
||||||
|
turn: `CreateRaidEncounter` entered 3× on turn 43 and drew **two** words in its subtree
|
||||||
|
(`0x008939ee` and `0x00820c1b`, one each). The correct statement is that the cost is **unbounded
|
||||||
|
above and state-dependent**, and the first non-zero observation is 2.
|
||||||
|
5. **Lane AD `raid-gate-multiplicity.md` §4** — *"three route records, `trfr = 18, 14, 14"* in
|
||||||
|
`ad-turn27-two-raiders.sav`. It is **five**, `trfr = 18, 16, 14, 20, 14`. §3.2.
|
||||||
|
6. **Lane AD §5 and its board row** — *"there is no oracle pair for this state"*. True of
|
||||||
|
`ad-turn27-two-raiders.sav`; **not** true of the same lineage ten turns later. §6.
|
||||||
|
7. **Lane H's `CreateRaidEncounter` zero** (`tail-rng-ledger.md`, rule 20's case study) — the
|
||||||
|
candidate list is **not** always empty. First non-zero reading of `0x008939ee` is in
|
||||||
|
`verify/traces/ar-r1-turn38-turn43.jsonl`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Artefacts
|
||||||
|
|
||||||
|
| what | where |
|
||||||
|
|---|---|
|
||||||
|
| this document | `findings/control-flow/raid-target-pick-verdict.md` |
|
||||||
|
| **input state — 4 raiders on two sectors, turn 37** | `verify/results/saves/ar-turn37-816raiders.sav` (`b6f4e05f…`) |
|
||||||
|
| `probes=8` trace, six instrumented End Turns (the pick fires on turn 42) | `verify/traces/ar-r1-turn38-turn43.jsonl` |
|
||||||
|
| `probes=8` trace, the two control turns | `verify/traces/ar-r2-control-turn38-turn39.jsonl` |
|
||||||
|
| site / ledger / probe reports for R1 | `verify/results/shim/ar/ar-r1-{sites,ledger,probes}.txt` |
|
||||||
|
| shim logs (detour + probe install status) | `verify/results/shim/ar/ar-r{1,2}-shim.log` |
|
||||||
|
| **oracle pair**, two fresh `hooks=off` processes | `verify/results/saves/ar-oracle-{A,B}-post.sav` (both `7a8b3d5e…`) |
|
||||||
|
| pre-turn half of the pair | `verify/results/saves/ar-oracle-A-pre.sav` (`15b99255…`) |
|
||||||
|
| the instrumented run's post-turn autosave, byte-identical to both | `verify/results/saves/ar-r2-probes8-post.sav` (`7a8b3d5e…`) |
|
||||||
|
| R1's final state, turn 43 | `verify/results/saves/ar-r1-turn43-post.sav` |
|
||||||
|
| new addresses (7 entries, no name collides) | `ghidra/addresses.d/ar.json` |
|
||||||
|
| instrument | `sots-engine` `src/shim/shim.cfg.hp8`, **unchanged**; build `ar-989c692-20260909T0313Z` |
|
||||||
|
| build tree | lane worktree `~/sots-engine-ar` (branch `wip/ar`) → CT111 `/srv/re-lab/build/sots-engine-ar`, `rm -rf`'d before the build; dist `/srv/re-lab/shim/dist-ar` |
|
||||||
|
|
||||||
|
**New content for the coverage ratchet (rule 27):** `ar-turn37-816raiders.sav` carries a
|
||||||
|
`TradeSector` with **`tsnumflt 5`** and five `tsflt` entries mixing both empires' fleets; a `trdmgr`
|
||||||
|
with **eight** `rt` records where the corpus maximum was four; and — the first in the corpus — a
|
||||||
|
`StarFleet` whose `LocID` is a `TradeSector` id **while its `Pos` is not the sector node's**, which is
|
||||||
|
the serialised signature of a raider displaced to an interception point. Nothing here is a new *kind*
|
||||||
|
of item, so the ratchet should hold.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. VM141 as left
|
||||||
|
|
||||||
|
Guest **restored**, hold **released**. Game stopped; `C:\SOTS\shim.cfg` is `shim.cfg.hoff`;
|
||||||
|
`C:\SOTS\binkw32.dll` is this lane's build (`ar-989c692-20260909T0313Z`), with the original still at
|
||||||
|
`binkw32_real.dll`. `C:\SOTS\SavedGames` is lane AD's set **plus `ar-turn37-816raiders.sav`**, so
|
||||||
|
**Load-dialog row positions have moved again — screenshot the dialog.** With the three autosaves
|
||||||
|
deleted the list is 12 rows from y = 260 at 29 px pitch, and `ar-turn37-816raiders` is **row 3 at
|
||||||
|
(400, 318)**.
|
||||||
|
|
||||||
|
Left in place, all additive: `C:\SOTS\shimdist-ar` (4 files) and `C:\SOTS\ui\ar-*.ps1`
|
||||||
|
(`ar-go.ps1` takes `-Cfg`, `ar-ui.ps1` writes `cmd.txt` and runs the helper once, plus three
|
||||||
|
one-shot copy helpers). **`click_helper.ps1` is unmodified** from lane AC's version.
|
||||||
|
|
||||||
|
**Four things that cost this lane time, for the next holder.**
|
||||||
|
|
||||||
|
* **Startup is faster than the board says if you drive it.** `fg` + `key {ESC}` three times spaced
|
||||||
|
~2.5 s, then ~90 s, put the main menu up in about **two minutes**, not four and a half. Loading a
|
||||||
|
turn-37 save is a further **3–4 minutes** and that part is not compressible. Verify both from a
|
||||||
|
screendump.
|
||||||
|
* **`rdrag x y x y` is a right-click.** The click helper has no right-click verb and the fleet panel's
|
||||||
|
`Add To New Fleet` / `Split Ships` menu is right-click-only. A zero-length right-drag opens it.
|
||||||
|
* **A trade-sector node is a legal move target even when its cube is not drawn** (§3.1), and its
|
||||||
|
screen position is computable from the save. Do not conclude a sector is unreachable because you
|
||||||
|
cannot see it.
|
||||||
|
* **The encounter query blocks the End Turn**, so a scripted turn loop must detect it. This lane
|
||||||
|
detected it by sampling **one pixel**: the `Done` button at (233, 673) reads ≈ `(183, 18, 0)` when a
|
||||||
|
query is up and ≈ `(8, 8, 8)` on the map. `Auto Resolve Peacefully` is the fourth icon at
|
||||||
|
(667, 641) and `Done` at (233, 673).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Proposed board rows
|
||||||
|
|
||||||
|
New rows:
|
||||||
|
|
||||||
|
```
|
||||||
|
| VERDICT: `TradeManager+0x0c` IS the per-system containing-sector table - the writer is found and the raid target pick FIRES | control-flow | verified | high | 100% | 2026-09-09 | **Lane AR**, VM141, `findings/control-flow/raid-target-pick-verdict.md`. Decides lane AG's §3.3 final paragraph, the one load-bearing inference AG flagged as unproven, and lane AD correctly reported it could not separate on sector 832. **BOTH INSTRUMENTS AGREE (rule 3).** STATIC: the writer AG's §7 lists as NOT FOUND is **`FUN_00841700`** (214 B, 0x00841700-0x008417d5) - it clears the +0x0c vector, RESIZES it to `count(([this+4])+0x40..+0x44)` (the SYSTEMS vector, the very container `FUN_00841cd0` indexes with `rt->trfr` at 0x00841d36), then walks the SECTOR vector x each sector's MEMBER SYSTEM vector executing `mov [this->+0x0c + m->+0x5c * 4], sector` at 0x008417a8. `ServerSystem+0x5c` is the serialised **`Idx`** field (objects/layouts.md, grade verified), so this is literally `containingSector[system.Idx] = sector` and **G_B1a cannot reject a valid trfr, BY CONSTRUCTION**. It is called from the DESERIALISER `FUN_00858a10` at 0x00858f07, so a loaded save has the table populated. LIVE: with 4 raiders parked (2 CR on sector 832, 2 DE on sector **816**, all `Pos` bit-equal), `Slot13RngCalleeA` is entered **4x/turn, 4 words**, every turn - and on turn 42 `Slot13RngCalleeB` reached its target pick: **`NextInt` at call `0x0088b613`, calls=1 words=1**, the FIRST firing of that site in the campaign. `OnAllCombatDone_Tail` cost **5** words that turn against **4** on every other turn; bracket residual **0** on all six turns. **THE SAME RUN CARRIES ITS OWN CONTROL**: on turns 38 and 40 `B` was entered by a cruiser on sector 832 and cost **0 words** - same process, same build, same instrument, same function, only the sector differs. AC's and AD's proof-carrying zero is a fact about the SECTOR, not the code path. Instrument `probes=8` (NOT 11), shim `ar-989c692-20260909T0313Z`, cfg `shim.cfg.hp8` unmodified, lane worktree + own build dir `/srv/re-lab/build/sots-engine-ar` rm -rf'd first (rules 21, 24) |
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
| `B` costs ONE word on a success, not two - and the deciding value is a SPECIES FLAG set by a constructor for exactly two species | control-flow | verified | high | 100% | 2026-09-09 | Lane AR. Lane AG's committed §3.3 prediction was **3 words on a succeeding turn** (`A` 1 + `B`'s NextInt 1 + `FUN_00820af0`'s NextFloat 1) and §5.2 says `B` costs 2 on success. **MEASURED: the tail cost 5 with k=4 raiders and one success, i.e. `B` cost 1, and there is NO `0x00820c1b` row on that turn.** Why: `FUN_00820af0`'s third short-circuit is `SpeciesDef_HasInterceptFlag 0x0053baf0` - twelve bytes, `cmp [ecx+0x144],0; setne al` - and `InitTable 0x005453a0` sets that flag word at 0x0054562f/0x00545638 for **species 0 (HUMAN) bit 0 and species 5 (ZUUL) bit 1 ONLY**. `Get 0x00545cc0` returns `0x00b10a00 + k*0x184`, the same table InitTable fills. So **a Human or Zuul raider intercepts at frac=1.0 and draws nothing; the other five species draw a NextFloat at 0x00820c1b**. The general tail model is **`k + s + z`** words: k = permitted raiders parked with `Pos` bit-equal, s = their successes ON A SECTOR THAT SOURCES A ROUTE, z = s again unless the raider's species sets the flag. Measured at k+s with k = 4,4,4,4,4,3 and s = 0,0,0,0,1,0. THE CHEAPEST UNEXERCISED STATE IN THE TRADE HALF IS NOW A NON-HUMAN, NON-ZUUL RAIDER - z has never been observed through `B` by anyone. Rule 23's lesson pointing a new way: the deciding value was not a float literal but a FLAG WORD SET BY A CONSTRUCTOR, invisible to any amount of reading `FUN_00820af0` alone |
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
| ORACLE PAIR on the turn-37 raider state - and the probes=8 instrument is BYTE-NEUTRAL, whole-save | meta | verified | high | 100% | 2026-09-09 | Lane AR (rules 19, 26). Two fresh `hooks=off` processes loading `ar-turn37-816raiders.sav` and running the same two End Turns produced **BYTE-IDENTICAL** autosaves at both snapshot points: Frame 38 `15b99255e1f03dab…` and Frame 39 `7a8b3d5eb3a60eba…`; `state_checksum --floats bits --mask none` prints **IDENTICAL**, root `237020deca931f5a180289592cece7ae`, coverage PROVED (1,173,884 B rebuilt, 67,239 leaves), 0 error 0 warn. **THEN** a fourth process with `shim.cfg.hp8` installed produced the SAME TWO HASHES. So the instrument is behaviour-neutral **at whole-save byte granularity**, not merely on the sub-tree the measurement reads - the stronger form of what lane AD could show. Order matters and it was the right order: the control was reproduced FIRST and shown to be a single outcome, so rule 26's `1/k` coincidence caveat does not apply (k=1). **THIS CORRECTS THE SCOPE OF LANE AD'S ROW**: "no oracle pair for this state / the AI varies per process" is true of `ad-turn27-two-raiders.sav` and NOT true of the same lineage ten turns later, so it is a fact about that state, not about the engine. No explanation for the difference is offered and none should be inferred. `ar-turn37-816raiders.sav` + 2 End Turns is the first RUNG-A CALIBRATION PAIR from this lineage and the obvious candidate for the standalone's first trade-raid comparison |
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
| `CreateRaidEncounter`'s candidate list is NOT always empty - 0x008939ee fires, and rule 20's case study gets its positive | control-flow | verified | high | 100% | 2026-09-09 | Lane AR, turn 43 of `verify/traces/ar-r1-turn38-turn43.jsonl`. `ServerTradeManager::CreateRaidEncounter` entered **3x** and its subtree drew **two** words: `NextInt 0x008939ee calls=1 words=1` - the site lane H measured at 0 on every turn and that `tail-rng-ledger.md` has carried as a zero ever since, the campaign's own case study for rule 20 - and `NextFloat 0x00820c1b calls=1 words=1` through the OTHER caller `0x0082cf65`, i.e. lane AG §5.1's chain `CreateRaidEncounter -> 0x00892640 -> 0x0082ce00 -> FUN_00820af0`. `Slot13RngCalleeB` was entered **0** times that turn, so neither word is `B`'s. **Two of AG's §5.1/§5.2 unread gates are now read from opposite directions.** The honest form of the cost claim is neither "0 or 1 further word" nor "at least six draws" but **unbounded above and state-dependent**; the first non-zero observation is 2 |
|
||||||
|
```
|
||||||
|
|
||||||
|
Edits to existing rows:
|
||||||
|
|
||||||
|
- **Row 62** (guest holders) — `VM141 = FREE (lane AR released 2026-09-09; guest restored, `shim.cfg.hoff`, this lane's binkw32.dll, SavedGames = lane AD's set PLUS `ar-turn37-816raiders.sav`, so Load-dialog rows have MOVED AGAIN - with the autosaves deleted the list is 12 rows from y=260 at 29 px pitch and `ar-turn37-816raiders` is row 3 at (400,318)).` Lane AR left `C:\SOTS\shimdist-ar` + `C:\SOTS\ui\ar-*.ps1`; `click_helper.ps1` unmodified. **GOTCHA (corrects the startup figure): `fg` + `key {ESC}` x3 spaced ~2.5 s then ~90 s puts the main menu up in about TWO minutes, not 4.5** - the 4.5 figure is what you get by waiting the movies out. Loading a turn-37 save is a further 3-4 min and that part is not compressible. **GOTCHA: `rdrag x y x y` (a zero-length right-drag) IS A RIGHT-CLICK** - the fleet panel's `Add To New Fleet` / `Split Ships` menu is right-click-only and the helper has no right-click verb. **GOTCHA: a trade-sector node is a legal move target EVEN WHEN ITS CUBE IS NOT DRAWN** - in Move mode the hover readout names it (`Sector 5 / Range: 15.7 / ETA: 4 Turns`); fit `screen = (A*wx + B*wz + C, D*wx + E*wz + F)` from two known points in the save and you land on any node first try. **GOTCHA: the encounter query BLOCKS the End Turn** - detect it by sampling the `Done` button pixel at (233,673): ~(183,18,0) when a query is up, ~(8,8,8) on the map; `Auto Resolve Peacefully` is (667,641), `Done` (233,673).`
|
||||||
|
- **Row 399 / the AC-AD raid rows** — append: `RESOLVED 2026-09-09 (lane AR): AD's "my data does NOT distinguish AG's per-system vs sector-indexed reading" is now decided BOTH WAYS - `FUN_00841700` is the writer and the pick fired live at 0x0088b613 with the raider on sector 816. AD's zero on 832 stands and is reproduced inside lane AR's own run as the within-run control.`
|
||||||
|
- **Row 207** — append: `0x0088b613 IS NO LONGER UNFIRED (lane AR 2026-09-09): calls=1 words=1 on turn 42 of ar-r1-turn38-turn43.jsonl, with the raider on sector 816. 0x00820c1b also fired, but through CreateRaidEncounter's caller, never through B - the species short-circuit blocks B's second draw for Human and Zuul raiders.`
|
||||||
|
- **Row 186** (`RNG LEDGER CLOSED`) — append: `Lane AR 2026-09-09: the tail's cost is `k + s + z` - one word per parked permitted raider, PLUS one per success on a route-sourcing sector, PLUS one more per success unless the raider's species sets SpeciesDef+0x144 (Human and Zuul only). Measured 4,4,4,4,5,3 over six turns with k = 4,4,4,4,4,3.`
|
||||||
|
- **Lane AD's "Sector 816 is UNREACHABLE" row** — append: `REACHED 2026-09-09 (lane AR) exactly as costed: five stock Extended Range destroyers (Range 27.0, 2,252 each) built at Epsilon Eridani over turns 28-31, split into four fleets, ETA 4 turns, parked on sector 5's node turn 35. AD's geometry table and its build costing are exact. TWO THINGS AD's recipe did not say: a new ship JOINS an existing fleet and a fleet's Range is the MINIMUM over its ships, so the 9-ly cruiser has to be split off before the node is a legal target; and the sector node is clickable even though its cube is not drawn.`
|
||||||
|
|
|
||||||
301
findings/subsystems/spy-program-draws.md
Normal file
301
findings/subsystems/spy-program-draws.md
Normal file
|
|
@ -0,0 +1,301 @@
|
||||||
|
# The spy program's remaining draws — `P`'s branch split, the counter-mission roll, and the deploy's own `NextFloat`
|
||||||
|
|
||||||
|
- **Type:** subsystem (static decode + live measurement)
|
||||||
|
- **Owner / date:** lane AP · 2026-09-09 · guest **VM144** (`sots-re-win10-144`, `re@192.168.10.144`)
|
||||||
|
- **Instrument:** lane Z's `draw_sites` return-address ledger at **`probes=8`** (the byte-neutral set;
|
||||||
|
never `probes=11` — lane H bisected 11 as not byte-neutral)
|
||||||
|
- **Continues:** lane AS's `findings/subsystems/spy-detection-roll.md`, whose §6 named this workload
|
||||||
|
from its own failed conjunct; lane AG's `findings/control-flow/gate-indexed-rng-audit.md` §3.2
|
||||||
|
- **Inputs:** `verify/results/saves/as-turn15-spydeployed.sav` (target 1),
|
||||||
|
`verify/results/saves/as-turn14-predeploy.sav` (target 2)
|
||||||
|
|
||||||
|
*(Sections 0–3 were written and committed **before** the build and before any measurement, in their
|
||||||
|
own commit. Sections 4 onward are the measurement. Rule 2.)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 0. Headline of the predictions
|
||||||
|
|
||||||
|
> **The brief that created this lane asks for "`P`'s three draws". There are three sites but they are
|
||||||
|
> two mutually exclusive branches, and the branch selector is the spy owner's *species*.** From
|
||||||
|
> `as-turn15-spydeployed.sav` **exactly one** of the three can ever fire — `0x00840a3c` — because the
|
||||||
|
> spy's owner is player 0 (`re`), `Species = 0` (Human). `0x00840929` and `0x008409c7` are gated on
|
||||||
|
> `spyOwner->Species == 6`, i.e. **Morrigi**, and are unreachable from this save, from every save in
|
||||||
|
> the 22-save corpus, and from any workload that does not start a *Morrigi* empire.
|
||||||
|
>
|
||||||
|
> Predicted, before the run: `0x00840a3c` fires once, for one word, on the End Turn that produces
|
||||||
|
> `Frame == sdet + 3`; and two sites nobody expected fire on the way — the spy **counter-mission**
|
||||||
|
> roll `0x0088dc43` (lane AG §3.2, corpus 0 of 22, never fired) starting at **Frame 19**, and the
|
||||||
|
> deploy's own `NextFloat` `0x0078c97f` on a separate one-turn run.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. `P` decoded — `SpyManager::Slot13RngCallee` `0x008408e0`, complete
|
||||||
|
|
||||||
|
Program `sots` / "Sword of the Stars.exe", ImageBase `0x00400000`, all addresses VAs. Body
|
||||||
|
disassembled from its start **to the next function start** (rule 17): `0x008408e0 .. 0x00840a5a`,
|
||||||
|
followed by `int3` padding. The ReVa MCP server is down (`CONNECTION_CLOSED`) for this lane too, so
|
||||||
|
this is instruction stream only.
|
||||||
|
|
||||||
|
### 1.1 How `P` is reached, and that there is no further gate
|
||||||
|
|
||||||
|
The chain in `ServerSpyManager::vslot13` `0x008877b0` from lane AS's §1, extended past the point AS
|
||||||
|
stopped at. **Between the last gate and the call to `P` there is no branch at all** — the whole span
|
||||||
|
`0x00887897 .. 0x00887af2` is two `EVENT_SPY_DESTROYED_OWNER`-shaped string builds, a `push_back`,
|
||||||
|
and an event post:
|
||||||
|
|
||||||
|
```
|
||||||
|
0088781d je 0x887e92 G1 spy.deat (+0x10) == 0 -> next spy
|
||||||
|
00887856 je 0x887c5b G2 spy.sdet (+0x40) == -1 -> BRANCH D (the detection roll)
|
||||||
|
00887867 jl 0x887e92 G3 (server.Frame - sdet) < 3 -> next spy
|
||||||
|
0088787a je 0x887c4f G4 ServerSystem_GetOwner(sysA) == NULL -> sdet := -1, next spy
|
||||||
|
00887891 je 0x887c4f G5 ServerSystem_GetOwner(sysA) == ownerO -> sdet := -1, next spy
|
||||||
|
008878a1 call 0x59f1a0 push_back spy.sid into a LOCAL vector<int> at [ebp-0xdc]
|
||||||
|
008879dd call 0x8862b0 PostEvent "EVENT_SPY_DESTROYED_OWNER"
|
||||||
|
00887ae3 call 0x7437e0 eax = ServerSystem_GetOwner(sysA)
|
||||||
|
00887aee push eax ; arg2 = the TARGET system's owner
|
||||||
|
00887aef push edx ; arg1 = ownerO, the SPY's owner ([ebp-0xc0])
|
||||||
|
00887af0 mov ecx,edi ; this = the spy manager
|
||||||
|
00887af2 call 0x8408e0 P <-- the false-flag draw
|
||||||
|
00887af7 ...
|
||||||
|
00887b07 cmp eax,ebx
|
||||||
|
00887b09 je 0x887b5b ; P returned NULL -> the "unknown empire" event string
|
||||||
|
```
|
||||||
|
|
||||||
|
so **once `sdet` is stamped and three turns have passed, `P` is called unconditionally** (given a
|
||||||
|
target system that is owned and not owned by the spy's own empire). `P`'s arguments are two
|
||||||
|
`Game::ServerPlayer*`, not ids — `P` compares them by pointer against entries of the player vector.
|
||||||
|
|
||||||
|
### 1.2 The species branch — and why "three draws" is one draw
|
||||||
|
|
||||||
|
```
|
||||||
|
00840909 mov esi,[ebp+8] ; esi = arg1 = the SPY'S OWNER (a ServerPlayer*)
|
||||||
|
0084090c cmp dword ptr [esi+0x5c], 0x6 ; +0x5c = ServerPlayer::Species
|
||||||
|
00840910 jne 0x840a29 ; NOT species 6 -> BRANCH B
|
||||||
|
|
||||||
|
; ---- BRANCH A, species == 6 only --------------------------------------------------------------
|
||||||
|
00840919 fld dword ptr ds:0x9e5ac4 ; 0.75f (bytes 00 00 40 3f)
|
||||||
|
0084091f mov ecx,[eax+0x16c] ; THE STRATEGIC GENERATOR (the object, not +4)
|
||||||
|
00840929 call 0x8e6dd0 A1 ; Mars::RNG::Chance(strategic, 0.75f) ret 0x0084092e
|
||||||
|
00840930 je 0x840a45 ; roll failed -> return NULL
|
||||||
|
; build a candidate list over StrategyServer +0x54..+0x58 (the player vector):
|
||||||
|
; skip p if p->+0xfb != 0, p->+0xf8 != 0, p == arg1, or p == arg2
|
||||||
|
008409ac je 0x840a07 ; list EMPTY -> free it, return NULL (no NextInt)
|
||||||
|
008409ae eax = count - 1
|
||||||
|
008409b0 mov ecx,[...+0x16c]; add ecx,4 ; the +4 SUB-OBJECT (the NextInt convention)
|
||||||
|
008409c7 call 0x4271c0 A2 ; Mars::RNG::NextInt(&(count-1)) ret 0x008409cc
|
||||||
|
008409cf esi = list[eax] ; the blamed empire
|
||||||
|
return esi
|
||||||
|
|
||||||
|
; ---- BRANCH B, every other species ------------------------------------------------------------
|
||||||
|
00840a2c fld dword ptr ds:0x9e5ac0 ; 0.25f (bytes 00 00 80 3e)
|
||||||
|
00840a32 mov ecx,[edx+0x16c] ; the strategic generator
|
||||||
|
00840a3c call 0x8e6dd0 B1 ; Mars::RNG::Chance(strategic, 0.25f) ret 0x00840a41
|
||||||
|
00840a43 jne 0x8409f2 ; roll SUCCEEDED -> return esi == arg1 (the true owner)
|
||||||
|
00840a45 xor eax,eax ; else return NULL
|
||||||
|
```
|
||||||
|
|
||||||
|
Both float constants were read as the **four bytes in the image** (rule 23): `0x009e5ac0` is
|
||||||
|
`00 00 80 3e` = `0.25f` and `0x009e5ac4` is `00 00 40 3f` = `0.75f`. `0x009e5ac4` is the *same* word
|
||||||
|
lane AS read as the species-5 multiplier in `SpyCraft_AccumulateDetectionOdds` — one constant, two
|
||||||
|
uses.
|
||||||
|
|
||||||
|
**So `P` is the attribution roll for a destroyed spy, and it has two completely different shapes:**
|
||||||
|
|
||||||
|
| spy owner | draw sites reached | semantics |
|
||||||
|
|---|---|---|
|
||||||
|
| `Species == 6` | `0x00840929` (`Chance` 0.75f), then `0x008409c7` (`NextInt`) **only if the roll succeeds and the candidate list is non-empty** | 75 % of the time a **random third empire** is blamed — a false flag. The true owner is *never* returned. |
|
||||||
|
| every other species | `0x00840a3c` (`Chance` 0.25f) | 25 % of the time the **true owner** is returned; otherwise nobody is blamed. |
|
||||||
|
|
||||||
|
### 1.3 The species table, decoded from the corpus
|
||||||
|
|
||||||
|
`Game::ServerPlayer +0x5c` is the field `objects/layouts.md` names **`Species`** (Write
|
||||||
|
`0x008563e0`). The `sim/species` node lists seven `ISsp` names in index order, identical in every
|
||||||
|
save read:
|
||||||
|
|
||||||
|
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
|
||||||
|
|---|---|---|---|---|---|---|
|
||||||
|
| Human | Hiver | Tarkas | Liir | **_NPC** | Zuul | **Morrigi** |
|
||||||
|
|
||||||
|
Cross-checked against lane V's `zuul-turn5-species5.sav`, whose three real players all carry
|
||||||
|
`Species = 5` — and lane V's hook independently reported `species=5` on the Zuul double-roll. The
|
||||||
|
four NPC empires (`Alien Menace`, `Peacekeeper Enforcer`, `Von Neumann`, `Independent Colony`) carry
|
||||||
|
`Species = 4` in every save.
|
||||||
|
|
||||||
|
That also **names lane AS's two unexplained multipliers**: `SpyCraft_AccumulateDetectionOdds`
|
||||||
|
multiplies the per-turn detection odds by `0.75f` for **Zuul** and `0.5f` for **Morrigi**, and by
|
||||||
|
`1.0f` for everyone else. Morrigi are the stealth species on both sites — half the detection odds,
|
||||||
|
and a false flag when they are caught.
|
||||||
|
|
||||||
|
### 1.4 What happens to the spy on that turn
|
||||||
|
|
||||||
|
The local `vector<int>` filled at `0x008878a1` is drained after the spy loop:
|
||||||
|
|
||||||
|
```
|
||||||
|
00887eb0..00887ee8 for each collected sid, back to front:
|
||||||
|
[[manager]+0x28](sid) ; vtable slot 10 = 0x00838480
|
||||||
|
```
|
||||||
|
|
||||||
|
and `0x00838480` looks the `SpyCraft` up by `sid`, calls **`ServerSystem::RemoveSpy 0x0074f550`** on
|
||||||
|
the `deat` system (which clears `spy.deat` and erases `sid` from `spies2`), clears the tender's
|
||||||
|
`atto` back-pointer (`spy+0xc`, `ship+0xa8`), erases the craft from the manager's vector at `+0x10`,
|
||||||
|
and invokes the scalar deleting destructor. **The spy is gone at the end of `vslot13`**, which is
|
||||||
|
phase 23 — *before* `vslot14` runs at phase 33.
|
||||||
|
|
||||||
|
### 1.5 The deploy's `NextFloat` — `0x0078c97f`, re-read
|
||||||
|
|
||||||
|
`SHIPACTION_DEPLOYSPY` handler `0x0078c930`, body to the next function start `0x0078c9e0`. One gate,
|
||||||
|
then the draw, with no branch between them:
|
||||||
|
|
||||||
|
```
|
||||||
|
0078c93d..0078c964 build a 12-byte stack query object (vtable 0x00a09648) and ask it about the ship
|
||||||
|
0078c969 test al,al
|
||||||
|
0078c96b jne 0x78c975 ; FALSE -> return 0 with NO DRAW
|
||||||
|
0078c975 mov ecx,[esi+0x16c]; add ecx,4 ; the strategic generator's +4 sub-object
|
||||||
|
0078c97f call 0x47d830 ; Mars::RNG::NextFloat ret 0x0078c984 <-- THE DRAW
|
||||||
|
0078c984 fld qword [0x009e21b0] ; 6.2831854820251465 == 2*pi
|
||||||
|
0078c98a fldz ; LO = 0.0
|
||||||
|
angle = LO + (HI - LO) * r ; the float-range idiom, stored through a float32 temp
|
||||||
|
0078c9ac call 0x0080c860 ; (ship, angle) -> eax
|
||||||
|
0078c9bb call edx ; [[esi+0x15c]+0x1c] = ServerSpyManager::DeploySpy slot 7
|
||||||
|
```
|
||||||
|
|
||||||
|
Lane AS read this as `cbh = NextFloat() * 2pi`; that is right in value (`LO` is literally `fldz`) and
|
||||||
|
the expanded form is worth recording because it is the campaign's standard `lerp(LO, HI, r)` shape,
|
||||||
|
not a bare multiply. **The draw is unconditional once the validator passes, so it is exactly one
|
||||||
|
strategic word per applied Deploy Spy order**, in the `ProcessTurn` bracket
|
||||||
|
(`ApplyAllTurnCommands`), not the tail's.
|
||||||
|
|
||||||
|
**Its predicate is on the command stream**, not on save fields: *"a `SHIPACTION_DEPLOYSPY` command in
|
||||||
|
this turn's command stream"*. Lane AG's gate-indexed audit has two kinds of cell — a measured firing,
|
||||||
|
or a predicate over the save — and this is neither.
|
||||||
|
|
||||||
|
### 1.6 A complete RNG scan of all four bodies
|
||||||
|
|
||||||
|
Every `call`/`jmp` in each body decoded to a real instruction boundary and matched against the seven
|
||||||
|
RNG entry points (`NextFloat 0x0047d830`, `NextInt 0x004271c0`, `Chance 0x008e6dd0`,
|
||||||
|
`Twist 0x00426e00`, `Seed 0x0049fdf0`, `0x005876c0`, `0x0057da00`):
|
||||||
|
|
||||||
|
| body | range | RNG sites |
|
||||||
|
|---|---|---|
|
||||||
|
| `ServerSpyManager::vslot13` | `0x008877b0 .. 0x00887f30` | `0x00887c8a` only |
|
||||||
|
| `SpyManager::Slot13RngCallee` (`P`) | `0x008408e0 .. 0x00840a5a` | `0x00840929`, `0x008409c7`, `0x00840a3c` |
|
||||||
|
| `SHIPACTION_DEPLOYSPY` handler | `0x0078c930 .. 0x0078c9e0` | `0x0078c97f` only |
|
||||||
|
| `ServerSpyManager::vslot14` | `0x0088db80 .. 0x0088dd2c` | `0x0088dc43` only |
|
||||||
|
|
||||||
|
No inlined draw is present in any of them (rule 16's tempering immediates do not appear).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. The corpus and the state, counted before building (rule 28 practice 5)
|
||||||
|
|
||||||
|
`as-turn15-spydeployed.sav`, read with `verify/save-reader/save_reader.py`:
|
||||||
|
|
||||||
|
| field | value | consequence |
|
||||||
|
|---|---|---|
|
||||||
|
| `sim/Frame` | 15 | |
|
||||||
|
| spy `sid` | 1 | |
|
||||||
|
| spy `sown` | 16 | player 0, `re` |
|
||||||
|
| **`re`'s `Species`** | **0 (Human)** | **`P` takes branch B; `0x00840929` and `0x008409c7` are unreachable** |
|
||||||
|
| spy `deat` | 400 (Kepler) | G1 satisfied — lane AS's contribution |
|
||||||
|
| spy `sdet` | **−1** | **the failed conjunct; G2 sends us to branch D every turn** |
|
||||||
|
| spy `sdo` | 0.00839999970048666 | |
|
||||||
|
| spy `tdep` | **15** | `vslot14`'s `Frame − tdep ≥ 3` first holds at **Frame 18** |
|
||||||
|
| spy `cm`, `cmo`, `spyon`, `ncp` | all 0 | `vslot14` G4 fails today; it bootstraps itself at Frame 18 |
|
||||||
|
| spy `cbh` | 5.033599376678467 | `= 2π × 0.8011207…`, i.e. `0x0078c97f` already fired once, unmeasured |
|
||||||
|
| players | 7 — `re`(0), `Revenge Fleet`(0), `Spengler`(0), 4 × `_NPC`(4) | branch A's candidate list would be non-empty, if it were reachable |
|
||||||
|
|
||||||
|
**Corpus count for `P`, on the predicate `∃ spy with deat != 0 && sdet != -1 && Frame − sdet ≥ 3`:
|
||||||
|
0 of 22 before this lane, and 0 of 23 including `as-turn15-spydeployed.sav`.** The failed conjunct is
|
||||||
|
`sdet == -1`, exactly as lane AS handed it over — and it is not a conjunct any amount of clicking can
|
||||||
|
satisfy directly. It is satisfied by *waiting*, at a probability the code fixes.
|
||||||
|
|
||||||
|
**Corpus count for `0x0078c97f`:** not expressible over save fields at all (§1.5). The nearest
|
||||||
|
save-side witness is `cbh != 0`, which holds in **1 of 23** saves — `as-turn15-spydeployed.sav`,
|
||||||
|
because the site fired on the turn that produced it.
|
||||||
|
|
||||||
|
**No save needs to be manufactured for either target.** Lane AS built both states. This lane
|
||||||
|
generates no map and plays no new game.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Predictions
|
||||||
|
|
||||||
|
Committed before the build, before the deploy of any binary to VM144, and before any End Turn.
|
||||||
|
|
||||||
|
### 3.1 The static claims
|
||||||
|
|
||||||
|
| | prediction | how it is wrong |
|
||||||
|
|---|---|---|
|
||||||
|
| **PA1** | `P` reaches **at most one** draw site per call, selected by `spyOwner->Species (+0x5c) == 6`. From this save, only `0x00840a3c`. | a `draw_sites` row at `ret_rva 0x0044092e` or `0x004409cc` on any turn of this workload falsifies it outright |
|
||||||
|
| **PA2** | Species indices are `0 Human, 1 Hiver, 2 Tarkas, 3 Liir, 4 _NPC, 5 Zuul, 6 Morrigi`; therefore `AccumulateDetectionOdds`'s `0.75f` is **Zuul** and its `0.5f` is **Morrigi** | a save whose `sim/species` list is ordered differently, or a Zuul save with `Species != 5` |
|
||||||
|
| **PA3** | `0x00840a3c` is `Chance(0.25f)` — a widened `float`, not the decimal 0.25 read from a decompiler | the four bytes at `0x009e5ac0` are not `00 00 80 3e` |
|
||||||
|
| **PA4** | the spy is **destroyed** at the end of `vslot13` on the turn `P` runs: `nspy` 1 → 0, `spies2` at Kepler 1 → 0, and no spy record survives in the autosave | the post-`P` autosave still carries a `spy` record |
|
||||||
|
|
||||||
|
### 3.2 Target 1 — the wait, and the per-turn word trajectory
|
||||||
|
|
||||||
|
Let `T` be the `Frame` on which `sdet` is stamped. `sdo` grows by **0.0084 per turn** and the roll on
|
||||||
|
the End Turn producing `Frame f` uses `sdo = 0.0084 × (f − 14)`, because `AccumulateDetectionOdds`
|
||||||
|
runs *before* the gate. `Chance` costs one word for `0 < p < 1` (board row 367).
|
||||||
|
|
||||||
|
| | prediction |
|
||||||
|
|---|---|
|
||||||
|
| **PB1** | `sdo` in the autosave after the End Turn producing `Frame f` is exactly `0.0084 × (f − 14)` as a float32, for every `f` until detection: 0.0168, 0.0252, 0.0336, 0.0420, 0.0504, … |
|
||||||
|
| **PB2** | `OnAllCombatDone_Tail` costs **1** word on Frames 16, 17, 18 (`vslot13`'s detection roll alone) |
|
||||||
|
| **PB3** | **`0x0088dc43` fires for the first time in this campaign on Frame 19**, one call, one word, `ret_rva 0x0048dc48`, `strategic = true` — because `vslot14` bootstraps its counter-mission at Frame 18 (`Frame − tdep = 3`, `ncp` empty), setting `spyon`, `cm := 1`, `cmo := 0.2f`, **without drawing on Frame 18 itself** |
|
||||||
|
| **PB4** | from Frame 19 the tail costs **2** words per turn (`vslot13` 1 + `vslot14` 1), and drops to 1 on any turn where `cmo` has accumulated to ≥ 1.0 or where `cm` has just cycled back to 0 |
|
||||||
|
| **PB5** | save-side: `cm` moves off its corpus-constant 0 on **Frame 18**, `spyon` moves to the Kepler owner's id on Frame 18, and `cmo` starts stepping by `0.2f` per failed counter-mission roll from Frame 19 |
|
||||||
|
| **PB6** | on the detection turn `T`: `vslot13` still costs 1 word (the roll that *succeeds*), `sdet := T` |
|
||||||
|
| **PB7** | on `T+1` and `T+2`: **`vslot13` costs ZERO words** — `sdet != -1` skips branch D, and `Frame − sdet < 3` skips the destruction path. A zero at `0x00487c8f` on those two turns is a *positive* result about a third arm and must not be read as "the roll did not fire" (rule 28 practice 6) |
|
||||||
|
| **PB8** | on `T+3`: one row at `ret_rva 0x00440a41`, `entry = Chance`, `calls = 1`, `words = 1`, `no_draw_calls = 0`, `strategic = true`; `vslot13`'s own `0x00487c8f` row **absent**; `vslot14` contributes **0** because the spy was destroyed at the end of phase 23 |
|
||||||
|
| **PB9** | the entry probe on **`Game::SpyManager::Slot13RngCallee 0x008408e0` reads 1** on Frame `T+3` — its first non-zero in the campaign, and the complement of lane AS's demonstration that its zero said nothing about the subtree |
|
||||||
|
| **PB10** | cumulative detection probability: **11 % by +4 turns, 43 % by +10, 70 % by +15, 87 % by +20** — computed from `p_k = 0.0084(k+1)`. *(Lane AS's brief quoted 38/65/85; that is the same model evaluated one turn late, using `p_k = 0.0084k`. Minor, and stated so the difference is on the record before the run.)* |
|
||||||
|
| **PB11** | the tail bracket total over the whole run equals the per-site sum: **residual 0** on every turn |
|
||||||
|
|
||||||
|
**PB12 — the tail case, stated in advance.** At +20 turns there is a 13 % chance `sdet` is still −1.
|
||||||
|
If that happens, the result reported is the **`sdo` trajectory against PB1** plus the `0x0088dc43`
|
||||||
|
series, and `P` stays a decoded-not-measured site. That is a real measurement of the accumulator and
|
||||||
|
it will be reported as such rather than ground out.
|
||||||
|
|
||||||
|
### 3.3 Target 2 — the deploy order
|
||||||
|
|
||||||
|
From `as-turn14-predeploy.sav`, one Deploy Spy order, one End Turn, `probes=8`:
|
||||||
|
|
||||||
|
| | prediction |
|
||||||
|
|---|---|
|
||||||
|
| **PC1** | one `draw_sites` row at `ret_rva 0x0038c984`, `entry = NextFloat`, `calls = 1`, `words = 1`, `no_draw_calls = 0`, `strategic = true` |
|
||||||
|
| **PC2** | it lands in the **`ProcessTurn`** bracket, not `OnAllCombatDone_Tail`'s, because `ApplyAllTurnCommands` runs first |
|
||||||
|
| **PC3** | the same turn's `OnAllCombatDone_Tail` costs **exactly 1** — the first detection roll at `sdo = 0.0084` |
|
||||||
|
| **PC4** | the resulting `spy.cbh` reproduces lane AS's value **exactly**: `5.033599376678467`, i.e. `2π × 0.80112…`. The strategic generator is seeded from the save and the per-process AI client seed does not feed it, so the same input plus the same order must draw the same word. **This is the sharpest single prediction in the document**: it says the deploy draw is reproducible across processes, sessions and lanes |
|
||||||
|
| **PC5** | `spies2` at Kepler goes 0 → `[1]`, `deat` 0 → 400, `tdep := 15`, `sdo := 0` then `0.0084` — reproducing lane AS's §4.2 from a different process |
|
||||||
|
|
||||||
|
### 3.4 The control
|
||||||
|
|
||||||
|
| | prediction |
|
||||||
|
|---|---|
|
||||||
|
| **PD1** | two fresh `hooks=off` processes on the **same** input will produce a byte-identical *pre*-turn `(Autosave EndTurn).sav` and **differing** post-turn autosaves |
|
||||||
|
| **PD2** | the differences localise to **one AI player's research pick plus `Summary/Checksum` and the `turnstats` `tch` cell** — the per-process `StrategyClient` seed of `2026-09-08-ai-seed-per-process.md`. Nothing of my empire, the spy, `deat`, `sdet`, `sdo`, `cm`, `cmo` or `spies2` moves |
|
||||||
|
| **PD3** | therefore **this is not a calibration pair and must not enter `determinism-hashes.txt`** — stated in advance so it cannot be a post-hoc excuse (rule 26) |
|
||||||
|
| **PD4** | the leaves this lane's numbers depend on — the `spymgr` sub-tree and the `systems` sub-tree — **do** reproduce across the control pair, and that is the claim that will be checked by sub-tree rather than by whole-file hash |
|
||||||
|
|
||||||
|
### 3.5 How the whole model could be wrong
|
||||||
|
|
||||||
|
* **`countC` is not stable.** `sdo`'s per-turn increment is `0.7 × (0.01 + 0.001 × countC)` with
|
||||||
|
`countC = 2` inferred, not observed. If a fleet moves in or out of Kepler the increment changes and
|
||||||
|
PB1 breaks — **and that would be the most interesting failure available**, because it would
|
||||||
|
identify `countC` from the delta. Symptom: an `sdo` step that is not 0.0084.
|
||||||
|
* **`vslot14` might not bootstrap.** AG's `ncp` check is on a container this lane has only seen as
|
||||||
|
the integer 0. If `ncp` is a count and non-empty means something else, PB3 fires late or not at
|
||||||
|
all. Symptom: Frame 19 tail costs 1, not 2, and `cm` stays 0.
|
||||||
|
* **The stage machine consults `owner->+0xff` (`CnTrd`, FTL Economics) at 1 → 2/3.** This game has no
|
||||||
|
FTL Economics, so the 1 → 3 arm is the one that runs; that changes which stage sequence is
|
||||||
|
exercised but not any word count.
|
||||||
|
* **PB7's two zero turns are the polarity trap in a new place.** `vslot13` will be *entered* on
|
||||||
|
`T+1`/`T+2` (the probe reads 1) and cost 0. If this lane reported that as "the roll stopped
|
||||||
|
working", it would repeat exactly the mistake rule 28 exists for.
|
||||||
|
* **PC4 can fail benignly.** If AI orders applied before mine consume strategic words, `cbh` differs
|
||||||
|
and the deploy draw is still 1 word. That falsifies *reproducibility*, not the site.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*(End of the pre-registered section. Everything below is measurement.)*
|
||||||
52
ghidra/addresses.d/ar.json
Normal file
52
ghidra/addresses.d/ar.json
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
{
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"name": "TradeManager_RebuildSystemToSectorTable",
|
||||||
|
"addr": "0x00841700",
|
||||||
|
"convention": "thiscall",
|
||||||
|
"prototype": "void __thiscall (TradeManager* this) // 214 B, 0x00841700-0x008417d5, decoded to the next function start. THE WRITER OF TradeManager+0x0c that lane AG's gate-indexed audit section 7 lists as NOT FOUND, and it settles AG section 3.3: (1) `lea ecx,[this+0x0c]; push 0; call 0x00459f70` clears the vector; (2) resizes it to `count(([this+4])+0x40 .. +0x44)` -- the SYSTEMS vector, the very container FUN_00841cd0 indexes with rt->trfr at 0x00841d36 -- growing with vector::_Insert_n 0x0050e6a0 (fill value NULL) or shrinking with erase 0x004ddfc0; (3) walks this->+0x1c (the SECTOR vector) x sector->+0x78 (that sector's MEMBER SYSTEM vector) and executes `mov [this->+0x0c + m->+0x5c * 4], sector` at 0x008417a8. ServerSystem+0x5c is the serialised `Idx` field (objects/layouts.md, grade verified), so this is literally `containingSector[system.Idx] = sector`. CONSEQUENCE: TradeManager+0x0c is a PER-SYSTEM table whose length is BY CONSTRUCTION the length of the container trfr indexes, so Slot13RngCalleeB's bounds check G_B1a can never reject a valid trfr and 0x0088b613 is reachable. Five callers; FUN_00858a10 is the DESERIALISER (ReadInt/ReadFloat throughout, calls this at 0x00858f07), so the table is rebuilt on load",
|
||||||
|
"status": "verified",
|
||||||
|
"source": "findings/control-flow/raid-target-pick-verdict.md (lane AR 2026-09-09); disassembled from dumps/sots.exe to the next function start"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "TradeManager_GetSectorForSystem",
|
||||||
|
"addr": "0x00841c70",
|
||||||
|
"convention": "thiscall",
|
||||||
|
"prototype": "void __thiscall (TradeManager* this, ServerSystem* sys) // 83 B, RET 4. Reads TradeManager+0x0c back the same way the writer fills it: bounds-checks `sys->+0x5c` (= the `Idx` tag) against `(this->+0x10 - this->+0x0c)/4` and indexes `((TradeSector**)this->+0x0c)[sys->Idx]`, then passes `sector + 0x78` -- the sector's MEMBER SYSTEM vector, the same vector the writer iterates -- to FUN_0059ec00 with the system. Independent confirmation that +0x5c on the indexing object and +0x78 on the table element are the two halves of one relation. Tail-calls TradeManager_RebuildSystemToSectorTable 0x00841700",
|
||||||
|
"status": "verified",
|
||||||
|
"source": "findings/control-flow/raid-target-pick-verdict.md (lane AR 2026-09-09)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Vector_ResizePtr",
|
||||||
|
"addr": "0x00459f70",
|
||||||
|
"convention": "thiscall",
|
||||||
|
"prototype": "void __thiscall (std::vector<void*>* this, size_t n) // RET 4. resize(n): when size > n it moves _Mylast down to _Myfirst + n (the shrink arm the trade manager uses with n = 0, i.e. clear); when size < n it calls 0x00538180 to grow",
|
||||||
|
"status": "verified",
|
||||||
|
"source": "findings/control-flow/raid-target-pick-verdict.md (lane AR 2026-09-09)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "SpeciesDef_InterceptFlagWord",
|
||||||
|
"addr": "0x00b10b44",
|
||||||
|
"convention": "data",
|
||||||
|
"prototype": "int, at g_SpeciesDefTable + 0*0x184 + 0x144 -- i.e. the +0x144 slot of SpeciesDef[0]. The SAME slot in every element is written ONLY by SpeciesDef_InitTable 0x005453a0 at 0x0054562f (`or [ebx+0x144],2` when the element's species index is 5) and 0x00545638 (`or [ebx+0x144],1` when it is 0). So the word is 1 for HUMAN, 2 for ZUUL and 0 for the other five species, and SpeciesDef_HasInterceptFlag 0x0053baf0 tests it. This is the value that decides whether TradeManager's raid interception draws a NextFloat at 0x00820c1b; the table base g_SpeciesDefTable 0x00b10a00 and accessor SpeciesDef_Get 0x00545cc0 were already named in addresses.json and this lane's independent derivation reproduced both",
|
||||||
|
"status": "verified",
|
||||||
|
"source": "findings/control-flow/raid-target-pick-verdict.md (lane AR 2026-09-09)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "SpeciesDef_HasInterceptFlag",
|
||||||
|
"addr": "0x0053baf0",
|
||||||
|
"convention": "thiscall",
|
||||||
|
"prototype": "bool __thiscall (SpeciesDef* this) // 12 B: `xor eax,eax; cmp [ecx+0x144],eax; setne al; ret`. TRUE for HUMAN (species 0) and ZUUL (species 5) only. This is the third disjunct of FUN_00820af0's short-circuit, so a HUMAN raider intercepts at frac = 1.0 and the NextFloat at 0x00820c1b IS NOT DRAWN -- correcting lane AG section 3.3's committed `3 words on a success` and section 5.2's `B costs 2 on a success`, both of which hold only for a raider whose species does not set this flag",
|
||||||
|
"status": "verified",
|
||||||
|
"source": "findings/control-flow/raid-target-pick-verdict.md (lane AR 2026-09-09)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "StarFleet_GetCrewSpeciesForIntercept",
|
||||||
|
"addr": "0x0081a2d0",
|
||||||
|
"convention": "cdecl",
|
||||||
|
"prototype": "int __cdecl (StarFleet* fleet) // returns the fleet owner's species (FUN_0071e280(fleet)->+0x5c) on the default path; only when that species is 4 does it scan the fleet's ship vector (+0xa4..+0xa8) for a ship whose design->+0x14->+0xac..+0xb4 slot is non-null and return THAT record's +0x4 instead. Called TWICE from FUN_00820af0 (0x00820bcf, 0x00820bdd) -- once compared against 1, once used as the index into g_SpeciesDefTable via SpeciesDef_Get",
|
||||||
|
"status": "verified",
|
||||||
|
"source": "findings/control-flow/raid-target-pick-verdict.md (lane AR 2026-09-09)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// GENERATED — do not edit. Facts about Sword of the Stars.exe (GOG 1.8.1).
|
// GENERATED — do not edit. Facts about Sword of the Stars.exe (GOG 1.8.1).
|
||||||
// Source: sots-re ghidra/addresses.json @ 712d184, generated 2026-09-08 by tools/gen_addresses.py
|
// Source: sots-re ghidra/addresses.json @ db4fda2, generated 2026-09-09 by tools/gen_addresses.py
|
||||||
// Runtime address = (uintptr_t)GetModuleHandle(NULL) + RVA (the exe is ASLR-relocated).
|
// Runtime address = (uintptr_t)GetModuleHandle(NULL) + RVA (the exe is ASLR-relocated).
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
@ -1281,6 +1281,18 @@ constexpr uint32_t RaidEncounter_Helper848e50 = 0x00448e50;
|
||||||
constexpr uint32_t RaidEncounter_Helper848e50_DrawSite = 0x00448fd9;
|
constexpr uint32_t RaidEncounter_Helper848e50_DrawSite = 0x00448fd9;
|
||||||
// thiscall Called only from TradeManager_BuildRaidEncounter at 0x00892700; calls TradeManager_ComputeRaidInterceptPoint at 0x0082cf65, which is where the NextFloat at 0x00820c1b is spent on this path. Body not read [mapped]
|
// thiscall Called only from TradeManager_BuildRaidEncounter at 0x00892700; calls TradeManager_ComputeRaidInterceptPoint at 0x0082cf65, which is where the NextFloat at 0x00820c1b is spent on this path. Body not read [mapped]
|
||||||
constexpr uint32_t RaidEncounter_Helper82ce00 = 0x0042ce00;
|
constexpr uint32_t RaidEncounter_Helper82ce00 = 0x0042ce00;
|
||||||
|
// thiscall void __thiscall (TradeManager* this) // 214 B, 0x00841700-0x008417d5, decoded to the next function start. THE WRITER OF TradeManager+0x0c that lane AG's gate-indexed audit section 7 lists as NOT FOUND, and it settles AG section 3.3: (1) `lea ecx,[this+0x0c]; push 0; call 0x00459f70` clears the vector; (2) resizes it to `count(([this+4])+0x40 .. +0x44)` -- the SYSTEMS vector, the very container FUN_00841cd0 indexes with rt->trfr at 0x00841d36 -- growing with vector::_Insert_n 0x0050e6a0 (fill value NULL) or shrinking with erase 0x004ddfc0; (3) walks this->+0x1c (the SECTOR vector) x sector->+0x78 (that sector's MEMBER SYSTEM vector) and executes `mov [this->+0x0c + m->+0x5c * 4], sector` at 0x008417a8. ServerSystem+0x5c is the serialised `Idx` field (objects/layouts.md, grade verified), so this is literally `containingSector[system.Idx] = sector`. CONSEQUENCE: TradeManager+0x0c is a PER-SYSTEM table whose length is BY CONSTRUCTION the length of the container trfr indexes, so Slot13RngCalleeB's bounds check G_B1a can never reject a valid trfr and 0x0088b613 is reachable. Five callers; FUN_00858a10 is the DESERIALISER (ReadInt/ReadFloat throughout, calls this at 0x00858f07), so the table is rebuilt on load [verified]
|
||||||
|
constexpr uint32_t TradeManager_RebuildSystemToSectorTable = 0x00441700;
|
||||||
|
// thiscall void __thiscall (TradeManager* this, ServerSystem* sys) // 83 B, RET 4. Reads TradeManager+0x0c back the same way the writer fills it: bounds-checks `sys->+0x5c` (= the `Idx` tag) against `(this->+0x10 - this->+0x0c)/4` and indexes `((TradeSector**)this->+0x0c)[sys->Idx]`, then passes `sector + 0x78` -- the sector's MEMBER SYSTEM vector, the same vector the writer iterates -- to FUN_0059ec00 with the system. Independent confirmation that +0x5c on the indexing object and +0x78 on the table element are the two halves of one relation. Tail-calls TradeManager_RebuildSystemToSectorTable 0x00841700 [verified]
|
||||||
|
constexpr uint32_t TradeManager_GetSectorForSystem = 0x00441c70;
|
||||||
|
// thiscall void __thiscall (std::vector<void*>* this, size_t n) // RET 4. resize(n): when size > n it moves _Mylast down to _Myfirst + n (the shrink arm the trade manager uses with n = 0, i.e. clear); when size < n it calls 0x00538180 to grow [verified]
|
||||||
|
constexpr uint32_t Vector_ResizePtr = 0x00059f70;
|
||||||
|
// data int, at g_SpeciesDefTable + 0*0x184 + 0x144 -- i.e. the +0x144 slot of SpeciesDef[0]. The SAME slot in every element is written ONLY by SpeciesDef_InitTable 0x005453a0 at 0x0054562f (`or [ebx+0x144],2` when the element's species index is 5) and 0x00545638 (`or [ebx+0x144],1` when it is 0). So the word is 1 for HUMAN, 2 for ZUUL and 0 for the other five species, and SpeciesDef_HasInterceptFlag 0x0053baf0 tests it. This is the value that decides whether TradeManager's raid interception draws a NextFloat at 0x00820c1b; the table base g_SpeciesDefTable 0x00b10a00 and accessor SpeciesDef_Get 0x00545cc0 were already named in addresses.json and this lane's independent derivation reproduced both [verified]
|
||||||
|
constexpr uint32_t SpeciesDef_InterceptFlagWord = 0x00710b44;
|
||||||
|
// thiscall bool __thiscall (SpeciesDef* this) // 12 B: `xor eax,eax; cmp [ecx+0x144],eax; setne al; ret`. TRUE for HUMAN (species 0) and ZUUL (species 5) only. This is the third disjunct of FUN_00820af0's short-circuit, so a HUMAN raider intercepts at frac = 1.0 and the NextFloat at 0x00820c1b IS NOT DRAWN -- correcting lane AG section 3.3's committed `3 words on a success` and section 5.2's `B costs 2 on a success`, both of which hold only for a raider whose species does not set this flag [verified]
|
||||||
|
constexpr uint32_t SpeciesDef_HasInterceptFlag = 0x0013baf0;
|
||||||
|
// cdecl int __cdecl (StarFleet* fleet) // returns the fleet owner's species (FUN_0071e280(fleet)->+0x5c) on the default path; only when that species is 4 does it scan the fleet's ship vector (+0xa4..+0xa8) for a ship whose design->+0x14->+0xac..+0xb4 slot is non-null and return THAT record's +0x4 instead. Called TWICE from FUN_00820af0 (0x00820bcf, 0x00820bdd) -- once compared against 1, once used as the index into g_SpeciesDefTable via SpeciesDef_Get [verified]
|
||||||
|
constexpr uint32_t StarFleet_GetCrewSpeciesForIntercept = 0x0041a2d0;
|
||||||
// __thiscall void (Game::ServerSystem* this, Game::SpyCraft* spy) /* 48 B, complete: `if (!spy) return; spy->deat(+0x10) = this ? this->[+4] : 0; push_back(&this->spies2(+0x1cc), &spy->sid(+0x4))` via lane AI3's 0x0059f1a0. THE ONLY WRITER THAT EVER MAKES `deat` NON-ZERO AT RUNTIME (the other stores to SpyCraft+0x10 are the zero-init in CreateSpyCraft, the deserializer, and three field copies). Exactly one caller, 0x008874d4 inside ServerSpyManager_DeploySpy, and no vtable slot. THIS SETTLES `spies2`: ServerSystem+0x1cc is the per-system vector of DEPLOYED spy ids, written in the same two instructions as `deat`, which is why it is 0 in every save whose only spy is docked to its tender */ [verified]
|
// __thiscall void (Game::ServerSystem* this, Game::SpyCraft* spy) /* 48 B, complete: `if (!spy) return; spy->deat(+0x10) = this ? this->[+4] : 0; push_back(&this->spies2(+0x1cc), &spy->sid(+0x4))` via lane AI3's 0x0059f1a0. THE ONLY WRITER THAT EVER MAKES `deat` NON-ZERO AT RUNTIME (the other stores to SpyCraft+0x10 are the zero-init in CreateSpyCraft, the deserializer, and three field copies). Exactly one caller, 0x008874d4 inside ServerSpyManager_DeploySpy, and no vtable slot. THIS SETTLES `spies2`: ServerSystem+0x1cc is the per-system vector of DEPLOYED spy ids, written in the same two instructions as `deat`, which is why it is 0 in every save whose only spy is docked to its tender */ [verified]
|
||||||
constexpr uint32_t ServerSystem_AddSpy = 0x003514c0;
|
constexpr uint32_t ServerSystem_AddSpy = 0x003514c0;
|
||||||
// __thiscall void (Game::ServerSystem* this, Game::SpyCraft* spy) /* 48 B, complete: `if (!spy) return; spy->deat(+0x10) = 0; erase(&this->spies2(+0x1cc), &spy->sid(+0x4))` via 0x0059ec00. The exact mirror of ServerSystem_AddSpy; the two together are the whole life cycle of `deat` and of `spies2` */ [verified]
|
// __thiscall void (Game::ServerSystem* this, Game::SpyCraft* spy) /* 48 B, complete: `if (!spy) return; spy->deat(+0x10) = 0; erase(&this->spies2(+0x1cc), &spy->sid(+0x4))` via 0x0059ec00. The exact mirror of ServerSystem_AddSpy; the two together are the whole life cycle of `deat` and of `spies2` */ [verified]
|
||||||
|
|
|
||||||
BIN
verify/results/saves/ar-oracle-A-post.sav
Normal file
BIN
verify/results/saves/ar-oracle-A-post.sav
Normal file
Binary file not shown.
BIN
verify/results/saves/ar-oracle-A-pre.sav
Normal file
BIN
verify/results/saves/ar-oracle-A-pre.sav
Normal file
Binary file not shown.
BIN
verify/results/saves/ar-oracle-B-post.sav
Normal file
BIN
verify/results/saves/ar-oracle-B-post.sav
Normal file
Binary file not shown.
BIN
verify/results/saves/ar-r1-turn43-post.sav
Normal file
BIN
verify/results/saves/ar-r1-turn43-post.sav
Normal file
Binary file not shown.
BIN
verify/results/saves/ar-r2-probes8-post.sav
Normal file
BIN
verify/results/saves/ar-r2-probes8-post.sav
Normal file
Binary file not shown.
BIN
verify/results/saves/ar-turn37-816raiders.sav
Normal file
BIN
verify/results/saves/ar-turn37-816raiders.sav
Normal file
Binary file not shown.
163
verify/results/shim/ar/ar-r1-ledger.txt
Normal file
163
verify/results/shim/ar/ar-r1-ledger.txt
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
cid d hook turn S+8 enc paths pred w_in w_out WORDS left
|
||||||
|
-------------------------------------------------------------------------------------------------
|
||||||
|
0 0 Seed None None None None None None None None None->None
|
||||||
|
1 0 Seed None None None None None None None None None->None
|
||||||
|
3 1 Seed None None None None None None None None None->None
|
||||||
|
2 0 RunAI None None None None None None None None None->None
|
||||||
|
5 1 Seed None None None None None None None None None->None
|
||||||
|
4 0 RunAI None None None None None None None None None->None
|
||||||
|
7 1 Seed None None None None None None None None None->None
|
||||||
|
6 0 RunAI None None None None None None None None None->None
|
||||||
|
8 0 Autosave None None None None None None None None None->None
|
||||||
|
11 2 RegisterHives None None None None None 190 190 0 434->434
|
||||||
|
12 2 TickHives None None None None 0 190 190 0 434->434
|
||||||
|
10 1 OnTurnBegin None None None None None 190 190 0 434->434
|
||||||
|
9 0 BeginProcessTurn 37 2057 -1 None None 190 190 0 434->434
|
||||||
|
14 1 ProcessNodeSpaceTravel 38 2106 -1 None None 190 190 0 434->434
|
||||||
|
15 1 ProcessTeamRecord None None None None None 207 207 0 417->417
|
||||||
|
13 0 ProcessTurn 38 2105 -1 None None 190 207 17 434->417
|
||||||
|
17 1 ApplyEncounterResult 38 2107 1 None None 207 207 0 417->417
|
||||||
|
18 1 ProcessNodeSpaceTravel 38 2108 0 None None 207 207 0 417->417
|
||||||
|
19 1 NodeLineDecay 38 2108 0 51 0 207 207 0 417->417
|
||||||
|
20 1 UpdateDifficultyTier None None None None 0 207 207 0 417->417
|
||||||
|
16 0 OnAllCombatDone_Tail 38 2106 1 51 0 207 211 4 417->413
|
||||||
|
21 0 Autosave None None None None None 211 211 0 413->413
|
||||||
|
22 0 Autosave None None None None None 211 211 0 413->413
|
||||||
|
25 2 RegisterHives None None None None None 211 211 0 413->413
|
||||||
|
26 2 TickHives None None None None 0 211 211 0 413->413
|
||||||
|
24 1 OnTurnBegin None None None None None 211 211 0 413->413
|
||||||
|
23 0 BeginProcessTurn 38 2108 0 None None 211 211 0 413->413
|
||||||
|
28 1 ProcessNodeSpaceTravel 39 2146 0 None None 211 211 0 413->413
|
||||||
|
27 0 ProcessTurn 39 2145 0 None None 211 231 20 413->393
|
||||||
|
30 1 ApplyEncounterResult 39 2147 1 None None 231 231 0 393->393
|
||||||
|
31 1 ProcessNodeSpaceTravel 39 2147 0 None None 231 231 0 393->393
|
||||||
|
32 1 NodeLineDecay 39 2147 0 51 0 231 231 0 393->393
|
||||||
|
33 1 UpdateDifficultyTier None None None None 0 231 231 0 393->393
|
||||||
|
29 0 OnAllCombatDone_Tail 39 2146 1 51 0 231 235 4 393->389
|
||||||
|
34 0 Autosave None None None None None 235 235 0 389->389
|
||||||
|
35 0 Autosave None None None None None 235 235 0 389->389
|
||||||
|
38 2 RegisterHives None None None None None 235 235 0 389->389
|
||||||
|
39 2 TickHives None None None None 0 235 235 0 389->389
|
||||||
|
37 1 OnTurnBegin None None None None None 235 235 0 389->389
|
||||||
|
36 0 BeginProcessTurn 39 2147 0 None None 235 235 0 389->389
|
||||||
|
41 1 ProcessNodeSpaceTravel 40 2185 0 None None 235 235 0 389->389
|
||||||
|
42 1 ProcessTeamRecord None None None None None 252 252 0 372->372
|
||||||
|
40 0 ProcessTurn 40 2184 0 None None 235 252 17 389->372
|
||||||
|
44 1 ApplyEncounterResult 40 2186 1 None None 252 252 0 372->372
|
||||||
|
45 1 ProcessNodeSpaceTravel 40 2186 0 None None 252 252 0 372->372
|
||||||
|
46 1 NodeLineDecay 40 2186 0 51 0 252 252 0 372->372
|
||||||
|
47 1 UpdateDifficultyTier None None None None 0 252 252 0 372->372
|
||||||
|
43 0 OnAllCombatDone_Tail 40 2185 1 51 0 252 256 4 372->368
|
||||||
|
48 0 Autosave None None None None None 256 256 0 368->368
|
||||||
|
49 0 Autosave None None None None None 256 256 0 368->368
|
||||||
|
52 2 RegisterHives None None None None None 256 256 0 368->368
|
||||||
|
53 2 TickHives None None None None 0 256 256 0 368->368
|
||||||
|
51 1 OnTurnBegin None None None None None 256 256 0 368->368
|
||||||
|
50 0 BeginProcessTurn 40 2186 0 None None 256 256 0 368->368
|
||||||
|
55 1 ProcessNodeSpaceTravel 41 2247 0 None None 256 256 0 368->368
|
||||||
|
56 1 ProcessTeamRecord None None None None None 273 273 0 351->351
|
||||||
|
54 0 ProcessTurn 41 2246 0 None None 256 273 17 368->351
|
||||||
|
58 1 ApplyEncounterResult 41 2250 1 None None 273 273 0 351->351
|
||||||
|
59 1 ProcessNodeSpaceTravel 41 2251 0 None None 273 273 0 351->351
|
||||||
|
60 1 NodeLineDecay 41 2251 0 51 0 273 273 0 351->351
|
||||||
|
61 1 UpdateDifficultyTier None None None None 0 273 273 0 351->351
|
||||||
|
57 0 OnAllCombatDone_Tail 41 2249 1 51 0 273 277 4 351->347
|
||||||
|
62 0 Autosave None None None None None 277 277 0 347->347
|
||||||
|
63 0 Autosave None None None None None 277 277 0 347->347
|
||||||
|
66 2 RegisterHives None None None None None 277 277 0 347->347
|
||||||
|
67 2 TickHives None None None None 0 277 277 0 347->347
|
||||||
|
65 1 OnTurnBegin None None None None None 277 277 0 347->347
|
||||||
|
64 0 BeginProcessTurn 41 2251 0 None None 277 277 0 347->347
|
||||||
|
69 1 ProcessNodeSpaceTravel 42 2302 0 None None 277 277 0 347->347
|
||||||
|
68 0 ProcessTurn 42 2301 0 None None 277 297 20 347->327
|
||||||
|
71 1 ApplyEncounterResult 42 2303 1 None None 297 297 0 327->327
|
||||||
|
72 1 ProcessNodeSpaceTravel 42 2303 0 None None 297 297 0 327->327
|
||||||
|
73 1 NodeLineDecay 42 2303 0 51 0 297 297 0 327->327
|
||||||
|
74 1 UpdateDifficultyTier None None None None 0 297 297 0 327->327
|
||||||
|
70 0 OnAllCombatDone_Tail 42 2302 1 51 0 297 301 4 327->323
|
||||||
|
75 0 Autosave None None None None None 301 301 0 323->323
|
||||||
|
76 0 Autosave None None None None None 301 301 0 323->323
|
||||||
|
79 2 RegisterHives None None None None None 301 301 0 323->323
|
||||||
|
80 2 TickHives None None None None 0 301 301 0 323->323
|
||||||
|
78 1 OnTurnBegin None None None None None 301 301 0 323->323
|
||||||
|
77 0 BeginProcessTurn 42 2303 0 None None 301 301 0 323->323
|
||||||
|
82 1 ProcessNodeSpaceTravel 43 2378 0 None None 301 301 0 323->323
|
||||||
|
81 0 ProcessTurn 43 2377 0 None None 301 320 19 323->304
|
||||||
|
84 1 ApplyEncounterResult 43 2379 1 None None 320 320 0 304->304
|
||||||
|
85 1 ProcessNodeSpaceTravel 43 2379 0 None None 320 320 0 304->304
|
||||||
|
86 1 NodeLineDecay 43 2379 0 51 0 320 320 0 304->304
|
||||||
|
87 1 UpdateDifficultyTier None None None None 0 320 320 0 304->304
|
||||||
|
83 0 OnAllCombatDone_Tail 43 2378 1 51 0 320 325 5 304->299
|
||||||
|
88 0 Autosave None None None None None 325 325 0 299->299
|
||||||
|
89 0 Autosave None None None None None 325 325 0 299->299
|
||||||
|
92 2 RegisterHives None None None None None 325 325 0 299->299
|
||||||
|
93 2 TickHives None None None None 0 325 325 0 299->299
|
||||||
|
91 1 OnTurnBegin None None None None None 325 325 0 299->299
|
||||||
|
90 0 BeginProcessTurn 43 2379 0 None None 325 325 0 299->299
|
||||||
|
95 1 ProcessNodeSpaceTravel 44 2434 0 None None 325 325 0 299->299
|
||||||
|
96 1 ProcessTeamRecord None None None None None 352 352 0 272->272
|
||||||
|
97 1 ProcessTeamRecord None None None None None 352 352 0 272->272
|
||||||
|
94 0 ProcessTurn 44 2433 0 None None 325 352 27 299->272
|
||||||
|
99 1 ApplyEncounterResult 44 2437 2 None None 352 352 0 272->272
|
||||||
|
100 1 ApplyEncounterResult 44 2437 2 None None 352 352 0 272->272
|
||||||
|
101 1 ProcessNodeSpaceTravel 44 2437 0 None None 352 352 0 272->272
|
||||||
|
102 1 NodeLineDecay 44 2437 0 51 0 352 352 0 272->272
|
||||||
|
103 1 UpdateDifficultyTier None None None None 0 352 352 0 272->272
|
||||||
|
98 0 OnAllCombatDone_Tail 44 2436 2 51 0 352 355 3 272->269
|
||||||
|
104 0 Autosave None None None None None 355 355 0 269->269
|
||||||
|
105 0 Autosave None None None None None 355 355 0 269->269
|
||||||
|
108 2 RegisterHives None None None None None 355 355 0 269->269
|
||||||
|
109 2 TickHives None None None None 0 355 355 0 269->269
|
||||||
|
107 1 OnTurnBegin None None None None None 355 355 0 269->269
|
||||||
|
106 0 BeginProcessTurn 44 2437 0 None None 355 355 0 269->269
|
||||||
|
111 1 ProcessNodeSpaceTravel 45 2502 0 None None 355 355 0 269->269
|
||||||
|
112 1 ProcessTeamRecord None None None None None 372 372 0 252->252
|
||||||
|
113 1 ProcessTeamRecord None None None None None 372 372 0 252->252
|
||||||
|
110 0 ProcessTurn 45 2501 0 None None 355 372 17 269->252
|
||||||
|
114 0 Seed None None None None None None None None None->None
|
||||||
|
115 0 Seed None None None None None None None None None->None
|
||||||
|
|
||||||
|
node-line population (phase 11's draw is one word per EXPIRED line):
|
||||||
|
turn paths permanent immortal mortal min_life <=5 expired words
|
||||||
|
38 51 51 0 0 -1 0 0 0
|
||||||
|
39 51 51 0 0 -1 0 0 0
|
||||||
|
40 51 51 0 0 -1 0 0 0
|
||||||
|
41 51 51 0 0 -1 0 0 0
|
||||||
|
42 51 51 0 0 -1 0 0 0
|
||||||
|
43 51 51 0 0 -1 0 0 0
|
||||||
|
44 51 51 0 0 -1 0 0 0
|
||||||
|
|
||||||
|
tail invocations (P1: does it run on every End Turn?):
|
||||||
|
turn 38: encounters=1 words=4
|
||||||
|
turn 39: encounters=1 words=4
|
||||||
|
turn 40: encounters=1 words=4
|
||||||
|
turn 41: encounters=1 words=4
|
||||||
|
turn 42: encounters=1 words=4
|
||||||
|
turn 43: encounters=1 words=5
|
||||||
|
turn 44: encounters=2 words=3
|
||||||
|
|
||||||
|
bracket 0: INCOMPLETE (pre-turn marker has no ledger position)
|
||||||
|
BRACKET turn 38: total=24 words attributed=24 residual=0
|
||||||
|
BeginProcessTurn 0
|
||||||
|
ProcessTurn 20
|
||||||
|
OnAllCombatDone_Tail 4
|
||||||
|
BRACKET turn 39: total=21 words attributed=21 residual=0
|
||||||
|
BeginProcessTurn 0
|
||||||
|
ProcessTurn 17
|
||||||
|
OnAllCombatDone_Tail 4
|
||||||
|
BRACKET turn 40: total=21 words attributed=21 residual=0
|
||||||
|
BeginProcessTurn 0
|
||||||
|
ProcessTurn 17
|
||||||
|
OnAllCombatDone_Tail 4
|
||||||
|
BRACKET turn 41: total=24 words attributed=24 residual=0
|
||||||
|
BeginProcessTurn 0
|
||||||
|
ProcessTurn 20
|
||||||
|
OnAllCombatDone_Tail 4
|
||||||
|
BRACKET turn 42: total=24 words attributed=24 residual=0
|
||||||
|
BeginProcessTurn 0
|
||||||
|
ProcessTurn 19
|
||||||
|
OnAllCombatDone_Tail 5
|
||||||
|
BRACKET turn 43: total=30 words attributed=30 residual=0
|
||||||
|
BeginProcessTurn 0
|
||||||
|
ProcessTurn 27
|
||||||
|
OnAllCombatDone_Tail 3
|
||||||
112
verify/results/shim/ar/ar-r1-probes.txt
Normal file
112
verify/results/shim/ar/ar-r1-probes.txt
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
[ProcessTeamRecord] call 15 depth 1: entries=2 gate=False contacts=0 detectors=2 neither=0 max_trials=-1 fc_byte_vs_dword_disagreements=2 WORDS=0
|
||||||
|
entry flags (fb, fc, fc_dword): (0,0,0x1010100), (0,0,0x1010100)
|
||||||
|
|
||||||
|
=== post-turn autosave #1 (call 21) ===
|
||||||
|
0x008877b0 Game::ServerSpyManager::vslot13 calls=1 since_launch=1
|
||||||
|
0x0088db80 Game::ServerSpyManager::vslot14 calls=1 since_launch=1
|
||||||
|
0x0088ef80 Game::ServerTradeManagerImpl::vslot13 calls=1 since_launch=1
|
||||||
|
0x0082cca0 Game::ServerTradeManagerImpl::vslot15 calls=1 since_launch=1
|
||||||
|
0x008408e0 Game::SpyManager::Slot13RngCallee calls=0 since_launch=0
|
||||||
|
0x00820ca0 Game::TradeManager::Slot13RngCalleeA calls=4 since_launch=4
|
||||||
|
0x0088b440 Game::TradeManager::Slot13RngCalleeB calls=0 since_launch=0
|
||||||
|
0x008938a0 Game::ServerTradeManager::CreateRaidEncounter calls=0 since_launch=0
|
||||||
|
0x00893290 Game::ServerTradeManager::GenerateTradeRaidEncounters **NOT INSTALLED**
|
||||||
|
0x00887f30 Game::ServerSpyManager::vslot15 [control] **NOT INSTALLED**
|
||||||
|
0x008590d0 Game::ServerTradeManagerImpl::vslot14 [control] **NOT INSTALLED**
|
||||||
|
0x007cb080 Game::EncounterDetect::Run [control] **NOT INSTALLED**
|
||||||
|
|
||||||
|
=== post-turn autosave #2 (call 34) ===
|
||||||
|
0x008877b0 Game::ServerSpyManager::vslot13 calls=1 since_launch=2
|
||||||
|
0x0088db80 Game::ServerSpyManager::vslot14 calls=1 since_launch=2
|
||||||
|
0x0088ef80 Game::ServerTradeManagerImpl::vslot13 calls=1 since_launch=2
|
||||||
|
0x0082cca0 Game::ServerTradeManagerImpl::vslot15 calls=1 since_launch=2
|
||||||
|
0x008408e0 Game::SpyManager::Slot13RngCallee calls=0 since_launch=0
|
||||||
|
0x00820ca0 Game::TradeManager::Slot13RngCalleeA calls=4 since_launch=8
|
||||||
|
0x0088b440 Game::TradeManager::Slot13RngCalleeB calls=1 since_launch=1
|
||||||
|
0x008938a0 Game::ServerTradeManager::CreateRaidEncounter calls=0 since_launch=0
|
||||||
|
0x00893290 Game::ServerTradeManager::GenerateTradeRaidEncounters **NOT INSTALLED**
|
||||||
|
0x00887f30 Game::ServerSpyManager::vslot15 [control] **NOT INSTALLED**
|
||||||
|
0x008590d0 Game::ServerTradeManagerImpl::vslot14 [control] **NOT INSTALLED**
|
||||||
|
0x007cb080 Game::EncounterDetect::Run [control] **NOT INSTALLED**
|
||||||
|
[ProcessTeamRecord] call 42 depth 1: entries=2 gate=False contacts=0 detectors=2 neither=0 max_trials=-1 fc_byte_vs_dword_disagreements=2 WORDS=0
|
||||||
|
entry flags (fb, fc, fc_dword): (0,0,0x1010100), (0,0,0x1010100)
|
||||||
|
|
||||||
|
=== post-turn autosave #3 (call 48) ===
|
||||||
|
0x008877b0 Game::ServerSpyManager::vslot13 calls=1 since_launch=3
|
||||||
|
0x0088db80 Game::ServerSpyManager::vslot14 calls=1 since_launch=3
|
||||||
|
0x0088ef80 Game::ServerTradeManagerImpl::vslot13 calls=1 since_launch=3
|
||||||
|
0x0082cca0 Game::ServerTradeManagerImpl::vslot15 calls=1 since_launch=3
|
||||||
|
0x008408e0 Game::SpyManager::Slot13RngCallee calls=0 since_launch=0
|
||||||
|
0x00820ca0 Game::TradeManager::Slot13RngCalleeA calls=4 since_launch=12
|
||||||
|
0x0088b440 Game::TradeManager::Slot13RngCalleeB calls=0 since_launch=1
|
||||||
|
0x008938a0 Game::ServerTradeManager::CreateRaidEncounter calls=0 since_launch=0
|
||||||
|
0x00893290 Game::ServerTradeManager::GenerateTradeRaidEncounters **NOT INSTALLED**
|
||||||
|
0x00887f30 Game::ServerSpyManager::vslot15 [control] **NOT INSTALLED**
|
||||||
|
0x008590d0 Game::ServerTradeManagerImpl::vslot14 [control] **NOT INSTALLED**
|
||||||
|
0x007cb080 Game::EncounterDetect::Run [control] **NOT INSTALLED**
|
||||||
|
[ProcessTeamRecord] call 56 depth 1: entries=2 gate=False contacts=0 detectors=2 neither=0 max_trials=-1 fc_byte_vs_dword_disagreements=2 WORDS=0
|
||||||
|
entry flags (fb, fc, fc_dword): (0,0,0x1010100), (0,0,0x1010100)
|
||||||
|
|
||||||
|
=== post-turn autosave #4 (call 62) ===
|
||||||
|
0x008877b0 Game::ServerSpyManager::vslot13 calls=1 since_launch=4
|
||||||
|
0x0088db80 Game::ServerSpyManager::vslot14 calls=1 since_launch=4
|
||||||
|
0x0088ef80 Game::ServerTradeManagerImpl::vslot13 calls=1 since_launch=4
|
||||||
|
0x0082cca0 Game::ServerTradeManagerImpl::vslot15 calls=1 since_launch=4
|
||||||
|
0x008408e0 Game::SpyManager::Slot13RngCallee calls=0 since_launch=0
|
||||||
|
0x00820ca0 Game::TradeManager::Slot13RngCalleeA calls=4 since_launch=16
|
||||||
|
0x0088b440 Game::TradeManager::Slot13RngCalleeB calls=1 since_launch=2
|
||||||
|
0x008938a0 Game::ServerTradeManager::CreateRaidEncounter calls=1 since_launch=1
|
||||||
|
0x00893290 Game::ServerTradeManager::GenerateTradeRaidEncounters **NOT INSTALLED**
|
||||||
|
0x00887f30 Game::ServerSpyManager::vslot15 [control] **NOT INSTALLED**
|
||||||
|
0x008590d0 Game::ServerTradeManagerImpl::vslot14 [control] **NOT INSTALLED**
|
||||||
|
0x007cb080 Game::EncounterDetect::Run [control] **NOT INSTALLED**
|
||||||
|
|
||||||
|
=== post-turn autosave #5 (call 75) ===
|
||||||
|
0x008877b0 Game::ServerSpyManager::vslot13 calls=1 since_launch=5
|
||||||
|
0x0088db80 Game::ServerSpyManager::vslot14 calls=1 since_launch=5
|
||||||
|
0x0088ef80 Game::ServerTradeManagerImpl::vslot13 calls=1 since_launch=5
|
||||||
|
0x0082cca0 Game::ServerTradeManagerImpl::vslot15 calls=1 since_launch=5
|
||||||
|
0x008408e0 Game::SpyManager::Slot13RngCallee calls=0 since_launch=0
|
||||||
|
0x00820ca0 Game::TradeManager::Slot13RngCalleeA calls=4 since_launch=20
|
||||||
|
0x0088b440 Game::TradeManager::Slot13RngCalleeB calls=0 since_launch=2
|
||||||
|
0x008938a0 Game::ServerTradeManager::CreateRaidEncounter calls=0 since_launch=1
|
||||||
|
0x00893290 Game::ServerTradeManager::GenerateTradeRaidEncounters **NOT INSTALLED**
|
||||||
|
0x00887f30 Game::ServerSpyManager::vslot15 [control] **NOT INSTALLED**
|
||||||
|
0x008590d0 Game::ServerTradeManagerImpl::vslot14 [control] **NOT INSTALLED**
|
||||||
|
0x007cb080 Game::EncounterDetect::Run [control] **NOT INSTALLED**
|
||||||
|
|
||||||
|
=== post-turn autosave #6 (call 88) ===
|
||||||
|
0x008877b0 Game::ServerSpyManager::vslot13 calls=1 since_launch=6
|
||||||
|
0x0088db80 Game::ServerSpyManager::vslot14 calls=1 since_launch=6
|
||||||
|
0x0088ef80 Game::ServerTradeManagerImpl::vslot13 calls=1 since_launch=6
|
||||||
|
0x0082cca0 Game::ServerTradeManagerImpl::vslot15 calls=1 since_launch=6
|
||||||
|
0x008408e0 Game::SpyManager::Slot13RngCallee calls=0 since_launch=0
|
||||||
|
0x00820ca0 Game::TradeManager::Slot13RngCalleeA calls=4 since_launch=24
|
||||||
|
0x0088b440 Game::TradeManager::Slot13RngCalleeB calls=1 since_launch=3
|
||||||
|
0x008938a0 Game::ServerTradeManager::CreateRaidEncounter calls=0 since_launch=1
|
||||||
|
0x00893290 Game::ServerTradeManager::GenerateTradeRaidEncounters **NOT INSTALLED**
|
||||||
|
0x00887f30 Game::ServerSpyManager::vslot15 [control] **NOT INSTALLED**
|
||||||
|
0x008590d0 Game::ServerTradeManagerImpl::vslot14 [control] **NOT INSTALLED**
|
||||||
|
0x007cb080 Game::EncounterDetect::Run [control] **NOT INSTALLED**
|
||||||
|
[ProcessTeamRecord] call 96 depth 1: entries=2 gate=False contacts=0 detectors=2 neither=0 max_trials=-1 fc_byte_vs_dword_disagreements=2 WORDS=0
|
||||||
|
entry flags (fb, fc, fc_dword): (0,0,0x1010100), (0,0,0x1010100)
|
||||||
|
[ProcessTeamRecord] call 97 depth 1: entries=2 gate=False contacts=0 detectors=1 neither=1 max_trials=-1 fc_byte_vs_dword_disagreements=2 WORDS=0
|
||||||
|
entry flags (fb, fc, fc_dword): (0,0,0x1010100), (1,0,0x1010000)
|
||||||
|
|
||||||
|
=== post-turn autosave #7 (call 104) ===
|
||||||
|
0x008877b0 Game::ServerSpyManager::vslot13 calls=1 since_launch=7
|
||||||
|
0x0088db80 Game::ServerSpyManager::vslot14 calls=1 since_launch=7
|
||||||
|
0x0088ef80 Game::ServerTradeManagerImpl::vslot13 calls=1 since_launch=7
|
||||||
|
0x0082cca0 Game::ServerTradeManagerImpl::vslot15 calls=1 since_launch=7
|
||||||
|
0x008408e0 Game::SpyManager::Slot13RngCallee calls=0 since_launch=0
|
||||||
|
0x00820ca0 Game::TradeManager::Slot13RngCalleeA calls=3 since_launch=27
|
||||||
|
0x0088b440 Game::TradeManager::Slot13RngCalleeB calls=0 since_launch=3
|
||||||
|
0x008938a0 Game::ServerTradeManager::CreateRaidEncounter calls=3 since_launch=4
|
||||||
|
0x00893290 Game::ServerTradeManager::GenerateTradeRaidEncounters **NOT INSTALLED**
|
||||||
|
0x00887f30 Game::ServerSpyManager::vslot15 [control] **NOT INSTALLED**
|
||||||
|
0x008590d0 Game::ServerTradeManagerImpl::vslot14 [control] **NOT INSTALLED**
|
||||||
|
0x007cb080 Game::EncounterDetect::Run [control] **NOT INSTALLED**
|
||||||
|
[ProcessTeamRecord] call 112 depth 1: entries=2 gate=False contacts=0 detectors=2 neither=0 max_trials=-1 fc_byte_vs_dword_disagreements=2 WORDS=0
|
||||||
|
entry flags (fb, fc, fc_dword): (0,0,0x1010100), (0,0,0x1010100)
|
||||||
|
[ProcessTeamRecord] call 113 depth 1: entries=2 gate=False contacts=0 detectors=2 neither=0 max_trials=-1 fc_byte_vs_dword_disagreements=2 WORDS=0
|
||||||
|
entry flags (fb, fc, fc_dword): (0,0,0x1010100), (0,0,0x1010100)
|
||||||
143
verify/results/shim/ar/ar-r1-shim.log
Normal file
143
verify/results/shim/ar/ar-r1-shim.log
Normal file
|
|
@ -0,0 +1,143 @@
|
||||||
|
23:47:48.211 [tid 5640] ==== sots-engine shim (binkw32 proxy) build ar-989c692-20260909T0313Z ====
|
||||||
|
23:47:48.211 [tid 5640] exe: C:\SOTS\Sword of the Stars.exe
|
||||||
|
23:47:48.211 [tid 5640] exe base=0x00210000 (link-time image base 0x00400000, ASLR delta -2031616) pid=8632 shim=72a50000
|
||||||
|
23:47:48.211 [tid 5640] addresses: Source: sots-re ghidra/addresses.json @ 48db3cc, generated 2026-09-08 by tools/gen_addresses.py
|
||||||
|
23:47:48.211 [tid 5640] config: hooks=trace
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Shim::SelfTest::Fill=off
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Mars::GlobalConsts::LoadFile=off
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Game::WeaponDictionary::Init=off
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Game::SectionDictionary::SectionDictionary=off
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Game::ServerPlayer::ComputeBudget=off
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Game::TechTree::ProcessResearch=off
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Game::ServerPlayer::OnTechResearched=off
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Game::ServerSystem::ProcessTurn=off
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Game::ServerPlayer::ProcessTurn=off
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Game::ServerSystem::GroupOutput=off
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Game::ServerSystem::ComputeTotalOutput=off
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Game::StrategyServer::MoveFleet=off
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Game::StrategyServer::ProcessFleetMovement=off
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Game::StrategyHost::Autosave=trace
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Game::StrategyServer::ProcessTurn=trace
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Game::StrategyServer::OnAllCombatDone_Tail=trace
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Game::StrategyServer::ApplyEncounterResult=trace
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Game::StrategyServer::NodeLineDecay=trace
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Game::StrategyServer::ProcessNodeSpaceTravel=trace
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Game::EncounterDetect::AssignContacts=trace
|
||||||
|
23:47:48.211 [tid 5640] config: hook.Game::EncounterDetect::ProcessTeamRecord=trace
|
||||||
|
23:47:48.211 [tid 5640] config: fpu.sample_turn=off
|
||||||
|
23:47:48.211 [tid 5640] config: fpu.sample_ticks=off
|
||||||
|
23:47:48.211 [tid 5640] config: trace.inline_max=64
|
||||||
|
23:47:48.211 [tid 5640] config: trace.path=C:\SOTS\shim.trace.jsonl
|
||||||
|
23:47:48.211 [tid 5640] config: trace.flush=always
|
||||||
|
23:47:48.211 [tid 5640] config: probes=8 -> 8 lane-H entry probes
|
||||||
|
23:47:48.273 [tid 5640] trace: C:\SOTS\shim.trace.jsonl (default mode trace, inline_max 64, flush always)
|
||||||
|
23:47:48.273 [tid 5640] hook: Mars_Application_Initialize rva=0x004a0e50 -> va=006b0e50
|
||||||
|
23:47:48.273 [tid 5640] hook: MH_Initialize -> MH_OK
|
||||||
|
23:47:48.273 [tid 5640] hook: MH_CreateHook -> MH_OK (trampoline=00f00fe0)
|
||||||
|
23:47:48.289 [tid 5640] hook: MH_EnableHook -> MH_OK
|
||||||
|
23:47:48.289 [tid 5640] cfg: GlobalConsts hook ready (scale constant 0.017453292519943295)
|
||||||
|
23:47:48.289 [tid 5640] hook: Mars::GlobalConsts::LoadFile rva=0x004b73c0 mode=off (not installed)
|
||||||
|
23:47:48.289 [tid 5640] dict: dictionaries hook ready (crt new=74b3232b delete=74b30174)
|
||||||
|
23:47:48.289 [tid 5640] hook: Game::WeaponDictionary::Init rva=0x0019a4c0 mode=off (not installed)
|
||||||
|
23:47:48.289 [tid 5640] hook: Game::SectionDictionary::SectionDictionary rva=0x00176f40 mode=off (not installed)
|
||||||
|
23:47:48.289 [tid 5640] research: ProcessResearch hook ready (Cost=0038da00, node=0x34, rng=0x9cc, fpu_cw=0x027f)
|
||||||
|
23:47:48.289 [tid 5640] hook: Game::TechTree::ProcessResearch rva=0x001876c0 mode=off (not installed)
|
||||||
|
23:47:48.289 [tid 5640] techfx: OnTechResearched hook ready (regions=15, gate=0/0, fpu_cw=0x027f)
|
||||||
|
23:47:48.289 [tid 5640] hook: Game::ServerPlayer::OnTechResearched rva=0x00491790 mode=off (not installed)
|
||||||
|
23:47:48.289 [tid 5640] hook: Game::ServerPlayer::ComputeBudget rva=0x00463030 mode=off (not installed)
|
||||||
|
23:47:48.289 [tid 5640] hook: Game::ServerSystem::ProcessTurn rva=0x003598e0 mode=off (not installed)
|
||||||
|
23:47:48.289 [tid 5640] hook: Game::ServerSystem::GroupOutput rva=0x0034b7a0 mode=off (not installed)
|
||||||
|
23:47:48.289 [tid 5640] hook: Game::ServerSystem::ComputeTotalOutput rva=0x00350480 mode=off (not installed)
|
||||||
|
23:47:48.289 [tid 5640] player_turn: ServerPlayer::ProcessTurn hook armed (ratio helper at 0038e950)
|
||||||
|
23:47:48.289 [tid 5640] hook: Game::ServerPlayer::ProcessTurn rva=0x00491340 mode=off (not installed)
|
||||||
|
23:47:48.289 [tid 5640] hook: Game::StrategyServer::MoveFleet rva=0x003d9ee0 mode=off (not installed)
|
||||||
|
23:47:48.289 [tid 5640] hook: Game::StrategyServer::ProcessFleetMovement rva=0x003da9a0 mode=off (not installed)
|
||||||
|
23:47:48.289 [tid 5640] hook: Game::StrategyHost::Autosave rva=0x00495210 -> va=006a5210 MH_CreateHook -> MH_OK (trampoline=00f00fc0)
|
||||||
|
23:47:48.305 [tid 5640] hook: Game::StrategyHost::Autosave MH_EnableHook -> MH_OK mode=trace
|
||||||
|
23:47:48.305 [tid 5640] hook: Game::StrategyServer::ProcessTurn rva=0x003dc6c0 -> va=005ec6c0 MH_CreateHook -> MH_OK (trampoline=00f00fa0)
|
||||||
|
23:47:48.336 [tid 5640] hook: Game::StrategyServer::ProcessTurn MH_EnableHook -> MH_OK mode=trace
|
||||||
|
23:47:48.336 [tid 5640] hook: Game::StrategyServer::OnAllCombatDone_Tail rva=0x003d92a0 -> va=005e92a0 MH_CreateHook -> MH_OK (trampoline=00f00f80)
|
||||||
|
23:47:48.351 [tid 5640] hook: Game::StrategyServer::OnAllCombatDone_Tail MH_EnableHook -> MH_OK mode=trace
|
||||||
|
23:47:48.351 [tid 5640] hook: Game::StrategyServer::ApplyEncounterResult rva=0x003d8920 -> va=005e8920 MH_CreateHook -> MH_OK (trampoline=00f00f60)
|
||||||
|
23:47:48.367 [tid 5640] hook: Game::StrategyServer::ApplyEncounterResult MH_EnableHook -> MH_OK mode=trace
|
||||||
|
23:47:48.367 [tid 5640] hook: Game::StrategyServer::NodeLineDecay rva=0x003ae010 -> va=005be010 MH_CreateHook -> MH_OK (trampoline=00f00f40)
|
||||||
|
23:47:48.383 [tid 5640] hook: Game::StrategyServer::NodeLineDecay MH_EnableHook -> MH_OK mode=trace
|
||||||
|
23:47:48.383 [tid 5640] hook: Game::StrategyServer::ProcessNodeSpaceTravel rva=0x003a0e20 -> va=005b0e20 MH_CreateHook -> MH_OK (trampoline=00f00f20)
|
||||||
|
23:47:48.398 [tid 5640] hook: Game::StrategyServer::ProcessNodeSpaceTravel MH_EnableHook -> MH_OK mode=trace
|
||||||
|
23:47:48.398 [tid 5640] hook: Game::EncounterDetect::AssignContacts rva=0x003aa240 -> va=005ba240 MH_CreateHook -> MH_OK (trampoline=00f00f00)
|
||||||
|
23:47:48.414 [tid 5640] hook: Game::EncounterDetect::AssignContacts MH_EnableHook -> MH_OK mode=trace
|
||||||
|
23:47:48.414 [tid 5640] hook: Game::EncounterDetect::ProcessTeamRecord rva=0x003ca640 -> va=005da640 MH_CreateHook -> MH_OK (trampoline=00f00ee0)
|
||||||
|
23:47:48.430 [tid 5640] hook: Game::EncounterDetect::ProcessTeamRecord MH_EnableHook -> MH_OK mode=trace
|
||||||
|
23:47:48.430 [tid 5640] hook: Game::StrategyServer::BeginProcessTurn rva=0x003d98e0 -> va=005e98e0 MH_CreateHook -> MH_OK (trampoline=00f00ec0)
|
||||||
|
23:47:48.445 [tid 5640] hook: Game::StrategyServer::BeginProcessTurn MH_EnableHook -> MH_OK mode=trace
|
||||||
|
23:47:48.445 [tid 5640] hook: Game::SVSOSwarmQueen::OnTurnBegin rva=0x00129930 -> va=00339930 MH_CreateHook -> MH_OK (trampoline=00f00ea0)
|
||||||
|
23:47:48.461 [tid 5640] hook: Game::SVSOSwarmQueen::OnTurnBegin MH_EnableHook -> MH_OK mode=trace
|
||||||
|
23:47:48.461 [tid 5640] hook: Game::SVSOSwarmQueen::RegisterHives rva=0x00127630 -> va=00337630 MH_CreateHook -> MH_OK (trampoline=00f00e80)
|
||||||
|
23:47:48.476 [tid 5640] hook: Game::SVSOSwarmQueen::RegisterHives MH_EnableHook -> MH_OK mode=trace
|
||||||
|
23:47:48.476 [tid 5640] hook: Game::SVSOSwarmQueen::TickHives rva=0x00127770 -> va=00337770 MH_CreateHook -> MH_OK (trampoline=00f00e60)
|
||||||
|
23:47:48.492 [tid 5640] hook: Game::SVSOSwarmQueen::TickHives MH_EnableHook -> MH_OK mode=trace
|
||||||
|
23:47:48.492 [tid 5640] hook: Game::SVSOSlaversRefuel::UpdateDifficultyTier rva=0x00115820 -> va=00325820 MH_CreateHook -> MH_OK (trampoline=00f00e40)
|
||||||
|
23:47:48.508 [tid 5640] hook: Game::SVSOSlaversRefuel::UpdateDifficultyTier MH_EnableHook -> MH_OK mode=trace
|
||||||
|
23:47:48.508 [tid 5640] hook: Mars::RNG::Seed rva=0x0009fdf0 -> va=002afdf0 MH_CreateHook -> MH_OK (trampoline=00f00e20)
|
||||||
|
23:47:48.523 [tid 5640] hook: Mars::RNG::Seed MH_EnableHook -> MH_OK mode=trace
|
||||||
|
23:47:48.523 [tid 5640] hook: Game::StrategyApp::RunAI rva=0x004706f0 -> va=006806f0 MH_CreateHook -> MH_OK (trampoline=00f00e00)
|
||||||
|
23:47:48.539 [tid 5640] hook: Game::StrategyApp::RunAI MH_EnableHook -> MH_OK mode=trace
|
||||||
|
23:47:48.555 [tid 5640] drawsite: Mars::RNG::NextFloat rva=0x0007d830 -> va=0028d830 create=MH_OK enable=MH_OK
|
||||||
|
23:47:48.570 [tid 5640] drawsite: Mars::RNG::NextInt rva=0x000271c0 -> va=002371c0 create=MH_OK enable=MH_OK
|
||||||
|
23:47:48.586 [tid 5640] drawsite: Mars::RNG::Chance rva=0x004e6dd0 -> va=006f6dd0 create=MH_OK enable=MH_OK
|
||||||
|
23:47:48.601 [tid 5640] drawsite: Mars::RNG::NextUInt rva=0x000f7670 -> va=00307670 create=MH_OK enable=MH_OK
|
||||||
|
23:47:48.617 [tid 5640] drawsite: Mars::RNG::FloatRange rva=0x0007d8a0 -> va=0028d8a0 create=MH_OK enable=MH_OK
|
||||||
|
23:47:48.648 [tid 5640] drawsite: Mars::RNG::IntRangeBell rva=0x004e6d80 -> va=006f6d80 create=MH_OK enable=MH_OK
|
||||||
|
23:47:48.664 [tid 5640] drawsite: Mars::RNG::GaussianRange rva=0x004e6e30 -> va=006f6e30 create=MH_OK enable=MH_OK
|
||||||
|
23:47:48.664 [tid 5640] probe: installing 8 of 12 (probes= in shim.cfg)
|
||||||
|
23:47:48.680 [tid 5640] probe: Game::ServerSpyManager::vslot13 rva=0x004877b0 -> va=006977b0 create=MH_OK enable=MH_OK
|
||||||
|
23:47:48.695 [tid 5640] probe: Game::ServerSpyManager::vslot14 rva=0x0048db80 -> va=0069db80 create=MH_OK enable=MH_OK
|
||||||
|
23:47:48.711 [tid 5640] probe: Game::ServerTradeManagerImpl::vslot13 rva=0x0048ef80 -> va=0069ef80 create=MH_OK enable=MH_OK
|
||||||
|
23:47:48.726 [tid 5640] probe: Game::ServerTradeManagerImpl::vslot15 rva=0x0042cca0 -> va=0063cca0 create=MH_OK enable=MH_OK
|
||||||
|
23:47:48.742 [tid 5640] probe: Game::SpyManager::Slot13RngCallee rva=0x004408e0 -> va=006508e0 create=MH_OK enable=MH_OK
|
||||||
|
23:47:48.758 [tid 5640] probe: Game::TradeManager::Slot13RngCalleeA rva=0x00420ca0 -> va=00630ca0 create=MH_OK enable=MH_OK
|
||||||
|
23:47:48.789 [tid 5640] probe: Game::TradeManager::Slot13RngCalleeB rva=0x0048b440 -> va=0069b440 create=MH_OK enable=MH_OK
|
||||||
|
23:47:48.805 [tid 5640] probe: Game::ServerTradeManager::CreateRaidEncounter rva=0x004938a0 -> va=006a38a0 create=MH_OK enable=MH_OK
|
||||||
|
23:47:48.805 [tid 5640] watch: disabled (watch=off)
|
||||||
|
23:47:48.805 [tid 5640] aiorders: disabled (aiorders=off)
|
||||||
|
23:47:48.805 [tid 5640] fpu: module init, entry cw=0x027f 53bit-double/nearest; force=off value=0x0000 sample_ticks=off
|
||||||
|
23:47:48.805 [tid 5640] fpu: sample_turn=off (off releases StrategyServer::ProcessTurn for another hook)
|
||||||
|
23:47:48.805 [tid 5640] fpu: StrategyClient::EndTurn rva=0x00383be0 -> va=00593be0 MH_CreateHook -> MH_OK (trampoline=00f00c00)
|
||||||
|
23:47:48.820 [tid 5640] fpu: StrategyClient::EndTurn MH_EnableHook -> MH_OK
|
||||||
|
23:47:48.820 [tid 5640] fpu: StrategyServer::BeginProcessTurn rva=0x003d98e0 -> va=005e98e0 MH_CreateHook -> MH_ERROR_ALREADY_CREATED (trampoline=00000000)
|
||||||
|
23:47:48.820 [tid 5640] fpu: StrategyServer::ProcessTurn rva=0x003dc6c0 not installed (sampler off)
|
||||||
|
23:47:48.820 [tid 5640] fpu: DemoApp::OnTick rva=0x0049a640 not installed (sampler off)
|
||||||
|
23:47:48.820 [tid 5640] selftest: Shim::SelfTest::Fill mode=off checksum=075ef0c3 records=0
|
||||||
|
23:47:48.836 [tid 5640] Application::Initialize called (this=02fb8128)
|
||||||
|
23:53:02.045 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=1f876370): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:53:05.171 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a69610): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:53:05.186 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a6dee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:53:05.233 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a6a4a0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:56:01.702 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=1f876370): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:56:04.842 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a69610): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:56:04.874 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a6dee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:56:04.920 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a6a4a0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:56:46.827 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=1f876370): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:56:49.952 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a69610): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:56:49.999 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a6dee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:56:50.045 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a6a4a0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:57:51.061 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=1f876370): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:57:54.217 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a69610): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:57:54.233 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a6dee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:57:54.295 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a6a4a0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:59:04.858 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=1f876370): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:59:08.014 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a69610): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:59:08.030 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a6dee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:59:08.077 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a6a4a0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:59:50.061 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=1f876370): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:59:53.233 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a69610): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:59:53.249 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a6dee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
23:59:53.295 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a6a4a0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
00:00:35.264 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=1f876370): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
00:00:38.452 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a69610): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
00:00:38.467 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a6dee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
00:00:38.530 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a6a4a0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
00:01:39.780 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=1f876370): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
00:01:42.889 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a69610): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
00:01:42.905 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a6dee0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
00:01:42.952 [tid 5640] fpu: sample at StrategyClient::EndTurn (this=33a6a4a0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
118
verify/results/shim/ar/ar-r1-sites.txt
Normal file
118
verify/results/shim/ar/ar-r1-sites.txt
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
turn: strategic 37 words / 52 calls; other generators 174 words / 172 calls; overflow 0
|
||||||
|
* STRAT NextFloat call 0x00587888 ProcessResearch+0x1c8 calls= 1 words= 1
|
||||||
|
* STRAT Chance call 0x00753d87 FUN_00753c60+0x127 calls= 15 words= 0
|
||||||
|
* STRAT NextFloat call 0x00820e18 FUN_00820ca0+0x178 calls= 4 words= 4
|
||||||
|
* STRAT Chance call 0x00893426 FUN_00893290+0x196 calls= 8 words= 8
|
||||||
|
* STRAT Chance call 0x00893513 FUN_00893290+0x283 calls= 8 words= 8
|
||||||
|
STRAT NextFloat call 0x008e6e04 FUN_008e6dd0+0x34 calls= 16 words= 16 [internal to Chance: already counted on that row]
|
||||||
|
other Chance call 0x00578d10 FUN_00578cf0+0x20 calls= 1 words= 1
|
||||||
|
other NextInt call 0x00579910 FUN_005798e0+0x30 calls= 3 words= 5
|
||||||
|
other NextInt call 0x0069dc29 FUN_0069dbb0+0x79 calls= 3 words= 3
|
||||||
|
other NextInt call 0x006f3512 FUN_006f3450+0xc2 calls= 2 words= 2
|
||||||
|
other Chance call 0x006fb69c FUN_006fb1a0+0x4fc calls= 80 words= 80
|
||||||
|
other NextInt call 0x008622a5 FUN_00861ca0+0x605 calls= 2 words= 2
|
||||||
|
other NextFloat call 0x008e6e04 FUN_008e6dd0+0x34 calls= 81 words= 81 [internal to Chance: already counted on that row]
|
||||||
|
=> attributed strategic words: 21
|
||||||
|
turn: strategic 40 words / 53 calls; other generators 17 words / 8 calls; overflow 0
|
||||||
|
* STRAT NextFloat call 0x0050329d FUN_00503200+0x9d calls= 1 words= 1
|
||||||
|
* STRAT Chance call 0x00753d87 FUN_00753c60+0x127 calls= 15 words= 0
|
||||||
|
* STRAT NextInt call 0x007929a4 FUN_00792750+0x254 calls= 1 words= 3
|
||||||
|
* STRAT NextFloat call 0x00820e18 FUN_00820ca0+0x178 calls= 4 words= 4
|
||||||
|
* STRAT Chance call 0x00893426 FUN_00893290+0x196 calls= 8 words= 8
|
||||||
|
* STRAT Chance call 0x00893513 FUN_00893290+0x283 calls= 8 words= 8
|
||||||
|
STRAT NextFloat call 0x008e6e04 FUN_008e6dd0+0x34 calls= 16 words= 16 [internal to Chance: already counted on that row]
|
||||||
|
other Chance call 0x00578d10 FUN_00578cf0+0x20 calls= 1 words= 1
|
||||||
|
other NextInt call 0x00579910 FUN_005798e0+0x30 calls= 3 words= 12
|
||||||
|
other NextInt call 0x0069dc29 FUN_0069dbb0+0x79 calls= 3 words= 3
|
||||||
|
other NextFloat call 0x008e6e04 FUN_008e6dd0+0x34 calls= 1 words= 1 [internal to Chance: already counted on that row]
|
||||||
|
=> attributed strategic words: 24
|
||||||
|
turn: strategic 37 words / 52 calls; other generators 522 words / 509 calls; overflow 0
|
||||||
|
* STRAT NextFloat call 0x00587888 ProcessResearch+0x1c8 calls= 1 words= 1
|
||||||
|
* STRAT Chance call 0x00753d87 FUN_00753c60+0x127 calls= 15 words= 0
|
||||||
|
* STRAT NextFloat call 0x00820e18 FUN_00820ca0+0x178 calls= 4 words= 4
|
||||||
|
* STRAT Chance call 0x00893426 FUN_00893290+0x196 calls= 8 words= 8
|
||||||
|
* STRAT Chance call 0x00893513 FUN_00893290+0x283 calls= 8 words= 8
|
||||||
|
STRAT NextFloat call 0x008e6e04 FUN_008e6dd0+0x34 calls= 16 words= 16 [internal to Chance: already counted on that row]
|
||||||
|
other Chance call 0x00536a60 FUN_00536a10+0x50 calls= 1 words= 1
|
||||||
|
other Chance call 0x00578d10 FUN_00578cf0+0x20 calls= 1 words= 1
|
||||||
|
other NextInt call 0x00579910 FUN_005798e0+0x30 calls= 3 words= 9
|
||||||
|
other NextInt call 0x0069dc29 FUN_0069dbb0+0x79 calls= 3 words= 3
|
||||||
|
other NextFloat call 0x006e9753 FUN_006e96e0+0x73 calls=113 words=113
|
||||||
|
other NextInt call 0x006f3512 FUN_006f3450+0xc2 calls= 7 words= 13
|
||||||
|
other Chance call 0x006fb69c FUN_006fb1a0+0x4fc calls=186 words=186
|
||||||
|
other NextInt call 0x008622a5 FUN_00861ca0+0x605 calls= 7 words= 8
|
||||||
|
other NextFloat call 0x008e6e04 FUN_008e6dd0+0x34 calls=188 words=188 [internal to Chance: already counted on that row]
|
||||||
|
=> attributed strategic words: 21
|
||||||
|
turn: strategic 37 words / 53 calls; other generators 1159 words / 1150 calls; overflow 0
|
||||||
|
* STRAT NextFloat call 0x00587888 ProcessResearch+0x1c8 calls= 1 words= 1
|
||||||
|
* STRAT Chance call 0x00753d87 FUN_00753c60+0x127 calls= 16 words= 0
|
||||||
|
* STRAT NextFloat call 0x00820e18 FUN_00820ca0+0x178 calls= 4 words= 4
|
||||||
|
* STRAT Chance call 0x00893426 FUN_00893290+0x196 calls= 8 words= 8
|
||||||
|
* STRAT Chance call 0x00893513 FUN_00893290+0x283 calls= 8 words= 8
|
||||||
|
STRAT NextFloat call 0x008e6e04 FUN_008e6dd0+0x34 calls= 16 words= 16 [internal to Chance: already counted on that row]
|
||||||
|
other Chance call 0x00578d10 FUN_00578cf0+0x20 calls= 1 words= 1
|
||||||
|
other NextInt call 0x00579910 FUN_005798e0+0x30 calls= 3 words= 6
|
||||||
|
other NextInt call 0x0069dc29 FUN_0069dbb0+0x79 calls= 3 words= 3
|
||||||
|
other NextFloat call 0x006e9753 FUN_006e96e0+0x73 calls=259 words=259
|
||||||
|
other NextInt call 0x006f3512 FUN_006f3450+0xc2 calls= 15 words= 21
|
||||||
|
other Chance call 0x006fb69c FUN_006fb1a0+0x4fc calls=434 words=434
|
||||||
|
other NextFloat call 0x008e6e04 FUN_008e6dd0+0x34 calls=435 words=435 [internal to Chance: already counted on that row]
|
||||||
|
=> attributed strategic words: 21
|
||||||
|
turn: strategic 40 words / 55 calls; other generators 10 words / 8 calls; overflow 0
|
||||||
|
* STRAT NextFloat call 0x0050329d FUN_00503200+0x9d calls= 1 words= 1
|
||||||
|
* STRAT NextFloat call 0x00587888 ProcessResearch+0x1c8 calls= 1 words= 1
|
||||||
|
* STRAT Chance call 0x00753d87 FUN_00753c60+0x127 calls= 15 words= 0
|
||||||
|
* STRAT NextInt call 0x007929a4 FUN_00792750+0x254 calls= 1 words= 1
|
||||||
|
* STRAT NextFloat call 0x00820e18 FUN_00820ca0+0x178 calls= 4 words= 4
|
||||||
|
* STRAT NextFloat call 0x0088df4f FUN_0088df20+0x2f calls= 1 words= 1
|
||||||
|
* STRAT Chance call 0x00893426 FUN_00893290+0x196 calls= 8 words= 8
|
||||||
|
* STRAT Chance call 0x00893513 FUN_00893290+0x283 calls= 8 words= 8
|
||||||
|
STRAT NextFloat call 0x008e6e04 FUN_008e6dd0+0x34 calls= 16 words= 16 [internal to Chance: already counted on that row]
|
||||||
|
other Chance call 0x00578d10 FUN_00578cf0+0x20 calls= 1 words= 1
|
||||||
|
other NextInt call 0x00579910 FUN_005798e0+0x30 calls= 3 words= 5
|
||||||
|
other NextInt call 0x0069dc29 FUN_0069dbb0+0x79 calls= 3 words= 3
|
||||||
|
other NextFloat call 0x008e6e04 FUN_008e6dd0+0x34 calls= 1 words= 1 [internal to Chance: already counted on that row]
|
||||||
|
=> attributed strategic words: 24
|
||||||
|
turn: strategic 40 words / 55 calls; other generators 10 words / 8 calls; overflow 0
|
||||||
|
* STRAT NextFloat call 0x0050329d FUN_00503200+0x9d calls= 1 words= 1
|
||||||
|
* STRAT NextFloat call 0x00587888 ProcessResearch+0x1c8 calls= 1 words= 1
|
||||||
|
* STRAT Chance call 0x00753d87 FUN_00753c60+0x127 calls= 15 words= 0
|
||||||
|
* STRAT NextInt call 0x007929a4 FUN_00792750+0x254 calls= 1 words= 1
|
||||||
|
* STRAT NextFloat call 0x00820e18 FUN_00820ca0+0x178 calls= 4 words= 4
|
||||||
|
* STRAT NextInt call 0x0088b613 FUN_0088b440+0x1d3 calls= 1 words= 1
|
||||||
|
* STRAT Chance call 0x00893426 FUN_00893290+0x196 calls= 8 words= 8
|
||||||
|
* STRAT Chance call 0x00893513 FUN_00893290+0x283 calls= 8 words= 8
|
||||||
|
STRAT NextFloat call 0x008e6e04 FUN_008e6dd0+0x34 calls= 16 words= 16 [internal to Chance: already counted on that row]
|
||||||
|
other Chance call 0x00578d10 FUN_00578cf0+0x20 calls= 1 words= 1
|
||||||
|
other NextInt call 0x00579910 FUN_005798e0+0x30 calls= 3 words= 5
|
||||||
|
other NextInt call 0x0069dc29 FUN_0069dbb0+0x79 calls= 3 words= 3
|
||||||
|
other NextFloat call 0x008e6e04 FUN_008e6dd0+0x34 calls= 1 words= 1 [internal to Chance: already counted on that row]
|
||||||
|
=> attributed strategic words: 24
|
||||||
|
turn: strategic 44 words / 55 calls; other generators 2121 words / 2077 calls; overflow 0
|
||||||
|
* STRAT NextFloat call 0x00587888 ProcessResearch+0x1c8 calls= 1 words= 1
|
||||||
|
* STRAT Chance call 0x00753d87 FUN_00753c60+0x127 calls= 15 words= 0
|
||||||
|
* STRAT NextFloat call 0x00820c1b FUN_00820af0+0x12b calls= 1 words= 1
|
||||||
|
* STRAT NextFloat call 0x00820e18 FUN_00820ca0+0x178 calls= 3 words= 3
|
||||||
|
* STRAT NextInt call 0x0083abc4 FUN_0083aa30+0x194 calls= 1 words= 1
|
||||||
|
* STRAT NextInt call 0x0083ac18 FUN_0083aa30+0x1e8 calls= 1 words= 1
|
||||||
|
* STRAT NextInt call 0x0083af44 FUN_0083ace0+0x264 calls= 1 words= 1
|
||||||
|
* STRAT NextInt call 0x0083b460 FUN_0083b1e0+0x280 calls= 1 words= 1
|
||||||
|
* STRAT NextInt call 0x0088f1eb FUN_0088f070+0x17b calls= 1 words= 5
|
||||||
|
* STRAT NextInt call 0x0088f356 FUN_0088f070+0x2e6 calls= 1 words= 1
|
||||||
|
* STRAT Chance call 0x00893426 FUN_00893290+0x196 calls= 7 words= 7
|
||||||
|
* STRAT Chance call 0x00893513 FUN_00893290+0x283 calls= 7 words= 7
|
||||||
|
* STRAT NextInt call 0x008939ee FUN_008938a0+0x14e calls= 1 words= 1
|
||||||
|
STRAT NextFloat call 0x008e6e04 FUN_008e6dd0+0x34 calls= 14 words= 14 [internal to Chance: already counted on that row]
|
||||||
|
other Chance call 0x00536a60 FUN_00536a10+0x50 calls= 1 words= 1
|
||||||
|
other Chance call 0x00578d10 FUN_00578cf0+0x20 calls= 1 words= 1
|
||||||
|
other NextInt call 0x00579910 FUN_005798e0+0x30 calls= 3 words= 6
|
||||||
|
other NextInt call 0x0069dc29 FUN_0069dbb0+0x79 calls= 3 words= 3
|
||||||
|
other NextInt call 0x006e87cd FUN_006e86b0+0x11d calls=129 words=160
|
||||||
|
other NextFloat call 0x006e9753 FUN_006e96e0+0x73 calls=324 words=324
|
||||||
|
other NextInt call 0x006eeb1c FUN_006ee960+0x1bc calls= 2 words= 3
|
||||||
|
other Chance call 0x006f0b73 FUN_006f0a40+0x133 calls= 39 words= 39
|
||||||
|
other NextInt call 0x006f3512 FUN_006f3450+0xc2 calls= 32 words= 41
|
||||||
|
other Chance call 0x006fb69c FUN_006fb1a0+0x4fc calls=746 words=746
|
||||||
|
other NextInt call 0x008622a5 FUN_00861ca0+0x605 calls= 10 words= 10
|
||||||
|
other NextFloat call 0x008e6e04 FUN_008e6dd0+0x34 calls=787 words=787 [internal to Chance: already counted on that row]
|
||||||
|
=> attributed strategic words: 30
|
||||||
119
verify/results/shim/ar/ar-r2-shim.log
Normal file
119
verify/results/shim/ar/ar-r2-shim.log
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
00:23:29.854 [tid 6236] ==== sots-engine shim (binkw32 proxy) build ar-989c692-20260909T0313Z ====
|
||||||
|
00:23:29.854 [tid 6236] exe: C:\SOTS\Sword of the Stars.exe
|
||||||
|
00:23:29.854 [tid 6236] exe base=0x00210000 (link-time image base 0x00400000, ASLR delta -2031616) pid=7128 shim=72a50000
|
||||||
|
00:23:29.854 [tid 6236] addresses: Source: sots-re ghidra/addresses.json @ 48db3cc, generated 2026-09-08 by tools/gen_addresses.py
|
||||||
|
00:23:29.854 [tid 6236] config: hooks=trace
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Shim::SelfTest::Fill=off
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Mars::GlobalConsts::LoadFile=off
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Game::WeaponDictionary::Init=off
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Game::SectionDictionary::SectionDictionary=off
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Game::ServerPlayer::ComputeBudget=off
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Game::TechTree::ProcessResearch=off
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Game::ServerPlayer::OnTechResearched=off
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Game::ServerSystem::ProcessTurn=off
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Game::ServerPlayer::ProcessTurn=off
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Game::ServerSystem::GroupOutput=off
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Game::ServerSystem::ComputeTotalOutput=off
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Game::StrategyServer::MoveFleet=off
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Game::StrategyServer::ProcessFleetMovement=off
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Game::StrategyHost::Autosave=trace
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Game::StrategyServer::ProcessTurn=trace
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Game::StrategyServer::OnAllCombatDone_Tail=trace
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Game::StrategyServer::ApplyEncounterResult=trace
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Game::StrategyServer::NodeLineDecay=trace
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Game::StrategyServer::ProcessNodeSpaceTravel=trace
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Game::EncounterDetect::AssignContacts=trace
|
||||||
|
00:23:29.854 [tid 6236] config: hook.Game::EncounterDetect::ProcessTeamRecord=trace
|
||||||
|
00:23:29.854 [tid 6236] config: fpu.sample_turn=off
|
||||||
|
00:23:29.854 [tid 6236] config: fpu.sample_ticks=off
|
||||||
|
00:23:29.854 [tid 6236] config: trace.inline_max=64
|
||||||
|
00:23:29.854 [tid 6236] config: trace.path=C:\SOTS\shim.trace.jsonl
|
||||||
|
00:23:29.854 [tid 6236] config: trace.flush=always
|
||||||
|
00:23:29.854 [tid 6236] config: probes=8 -> 8 lane-H entry probes
|
||||||
|
00:23:29.916 [tid 6236] trace: C:\SOTS\shim.trace.jsonl (default mode trace, inline_max 64, flush always)
|
||||||
|
00:23:29.916 [tid 6236] hook: Mars_Application_Initialize rva=0x004a0e50 -> va=006b0e50
|
||||||
|
00:23:29.916 [tid 6236] hook: MH_Initialize -> MH_OK
|
||||||
|
00:23:29.916 [tid 6236] hook: MH_CreateHook -> MH_OK (trampoline=01170fe0)
|
||||||
|
00:23:29.947 [tid 6236] hook: MH_EnableHook -> MH_OK
|
||||||
|
00:23:29.947 [tid 6236] cfg: GlobalConsts hook ready (scale constant 0.017453292519943295)
|
||||||
|
00:23:29.947 [tid 6236] hook: Mars::GlobalConsts::LoadFile rva=0x004b73c0 mode=off (not installed)
|
||||||
|
00:23:29.947 [tid 6236] dict: dictionaries hook ready (crt new=74b3232b delete=74b30174)
|
||||||
|
00:23:29.947 [tid 6236] hook: Game::WeaponDictionary::Init rva=0x0019a4c0 mode=off (not installed)
|
||||||
|
00:23:29.947 [tid 6236] hook: Game::SectionDictionary::SectionDictionary rva=0x00176f40 mode=off (not installed)
|
||||||
|
00:23:29.947 [tid 6236] research: ProcessResearch hook ready (Cost=0038da00, node=0x34, rng=0x9cc, fpu_cw=0x027f)
|
||||||
|
00:23:29.947 [tid 6236] hook: Game::TechTree::ProcessResearch rva=0x001876c0 mode=off (not installed)
|
||||||
|
00:23:29.947 [tid 6236] techfx: OnTechResearched hook ready (regions=15, gate=0/0, fpu_cw=0x027f)
|
||||||
|
00:23:29.947 [tid 6236] hook: Game::ServerPlayer::OnTechResearched rva=0x00491790 mode=off (not installed)
|
||||||
|
00:23:29.947 [tid 6236] hook: Game::ServerPlayer::ComputeBudget rva=0x00463030 mode=off (not installed)
|
||||||
|
00:23:29.947 [tid 6236] hook: Game::ServerSystem::ProcessTurn rva=0x003598e0 mode=off (not installed)
|
||||||
|
00:23:29.947 [tid 6236] hook: Game::ServerSystem::GroupOutput rva=0x0034b7a0 mode=off (not installed)
|
||||||
|
00:23:29.947 [tid 6236] hook: Game::ServerSystem::ComputeTotalOutput rva=0x00350480 mode=off (not installed)
|
||||||
|
00:23:29.947 [tid 6236] player_turn: ServerPlayer::ProcessTurn hook armed (ratio helper at 0038e950)
|
||||||
|
00:23:29.947 [tid 6236] hook: Game::ServerPlayer::ProcessTurn rva=0x00491340 mode=off (not installed)
|
||||||
|
00:23:29.947 [tid 6236] hook: Game::StrategyServer::MoveFleet rva=0x003d9ee0 mode=off (not installed)
|
||||||
|
00:23:29.947 [tid 6236] hook: Game::StrategyServer::ProcessFleetMovement rva=0x003da9a0 mode=off (not installed)
|
||||||
|
00:23:29.947 [tid 6236] hook: Game::StrategyHost::Autosave rva=0x00495210 -> va=006a5210 MH_CreateHook -> MH_OK (trampoline=01170fc0)
|
||||||
|
00:23:29.963 [tid 6236] hook: Game::StrategyHost::Autosave MH_EnableHook -> MH_OK mode=trace
|
||||||
|
00:23:29.963 [tid 6236] hook: Game::StrategyServer::ProcessTurn rva=0x003dc6c0 -> va=005ec6c0 MH_CreateHook -> MH_OK (trampoline=01170fa0)
|
||||||
|
00:23:29.979 [tid 6236] hook: Game::StrategyServer::ProcessTurn MH_EnableHook -> MH_OK mode=trace
|
||||||
|
00:23:29.979 [tid 6236] hook: Game::StrategyServer::OnAllCombatDone_Tail rva=0x003d92a0 -> va=005e92a0 MH_CreateHook -> MH_OK (trampoline=01170f80)
|
||||||
|
00:23:29.994 [tid 6236] hook: Game::StrategyServer::OnAllCombatDone_Tail MH_EnableHook -> MH_OK mode=trace
|
||||||
|
00:23:29.994 [tid 6236] hook: Game::StrategyServer::ApplyEncounterResult rva=0x003d8920 -> va=005e8920 MH_CreateHook -> MH_OK (trampoline=01170f60)
|
||||||
|
00:23:30.010 [tid 6236] hook: Game::StrategyServer::ApplyEncounterResult MH_EnableHook -> MH_OK mode=trace
|
||||||
|
00:23:30.010 [tid 6236] hook: Game::StrategyServer::NodeLineDecay rva=0x003ae010 -> va=005be010 MH_CreateHook -> MH_OK (trampoline=01170f40)
|
||||||
|
00:23:30.025 [tid 6236] hook: Game::StrategyServer::NodeLineDecay MH_EnableHook -> MH_OK mode=trace
|
||||||
|
00:23:30.025 [tid 6236] hook: Game::StrategyServer::ProcessNodeSpaceTravel rva=0x003a0e20 -> va=005b0e20 MH_CreateHook -> MH_OK (trampoline=01170f20)
|
||||||
|
00:23:30.057 [tid 6236] hook: Game::StrategyServer::ProcessNodeSpaceTravel MH_EnableHook -> MH_OK mode=trace
|
||||||
|
00:23:30.057 [tid 6236] hook: Game::EncounterDetect::AssignContacts rva=0x003aa240 -> va=005ba240 MH_CreateHook -> MH_OK (trampoline=01170f00)
|
||||||
|
00:23:30.072 [tid 6236] hook: Game::EncounterDetect::AssignContacts MH_EnableHook -> MH_OK mode=trace
|
||||||
|
00:23:30.072 [tid 6236] hook: Game::EncounterDetect::ProcessTeamRecord rva=0x003ca640 -> va=005da640 MH_CreateHook -> MH_OK (trampoline=01170ee0)
|
||||||
|
00:23:30.088 [tid 6236] hook: Game::EncounterDetect::ProcessTeamRecord MH_EnableHook -> MH_OK mode=trace
|
||||||
|
00:23:30.088 [tid 6236] hook: Game::StrategyServer::BeginProcessTurn rva=0x003d98e0 -> va=005e98e0 MH_CreateHook -> MH_OK (trampoline=01170ec0)
|
||||||
|
00:23:30.119 [tid 6236] hook: Game::StrategyServer::BeginProcessTurn MH_EnableHook -> MH_OK mode=trace
|
||||||
|
00:23:30.119 [tid 6236] hook: Game::SVSOSwarmQueen::OnTurnBegin rva=0x00129930 -> va=00339930 MH_CreateHook -> MH_OK (trampoline=01170ea0)
|
||||||
|
00:23:30.135 [tid 6236] hook: Game::SVSOSwarmQueen::OnTurnBegin MH_EnableHook -> MH_OK mode=trace
|
||||||
|
00:23:30.135 [tid 6236] hook: Game::SVSOSwarmQueen::RegisterHives rva=0x00127630 -> va=00337630 MH_CreateHook -> MH_OK (trampoline=01170e80)
|
||||||
|
00:23:30.151 [tid 6236] hook: Game::SVSOSwarmQueen::RegisterHives MH_EnableHook -> MH_OK mode=trace
|
||||||
|
00:23:30.151 [tid 6236] hook: Game::SVSOSwarmQueen::TickHives rva=0x00127770 -> va=00337770 MH_CreateHook -> MH_OK (trampoline=01170e60)
|
||||||
|
00:23:30.166 [tid 6236] hook: Game::SVSOSwarmQueen::TickHives MH_EnableHook -> MH_OK mode=trace
|
||||||
|
00:23:30.166 [tid 6236] hook: Game::SVSOSlaversRefuel::UpdateDifficultyTier rva=0x00115820 -> va=00325820 MH_CreateHook -> MH_OK (trampoline=01170e40)
|
||||||
|
00:23:30.182 [tid 6236] hook: Game::SVSOSlaversRefuel::UpdateDifficultyTier MH_EnableHook -> MH_OK mode=trace
|
||||||
|
00:23:30.182 [tid 6236] hook: Mars::RNG::Seed rva=0x0009fdf0 -> va=002afdf0 MH_CreateHook -> MH_OK (trampoline=01170e20)
|
||||||
|
00:23:30.197 [tid 6236] hook: Mars::RNG::Seed MH_EnableHook -> MH_OK mode=trace
|
||||||
|
00:23:30.197 [tid 6236] hook: Game::StrategyApp::RunAI rva=0x004706f0 -> va=006806f0 MH_CreateHook -> MH_OK (trampoline=01170e00)
|
||||||
|
00:23:30.229 [tid 6236] hook: Game::StrategyApp::RunAI MH_EnableHook -> MH_OK mode=trace
|
||||||
|
00:23:30.244 [tid 6236] drawsite: Mars::RNG::NextFloat rva=0x0007d830 -> va=0028d830 create=MH_OK enable=MH_OK
|
||||||
|
00:23:30.260 [tid 6236] drawsite: Mars::RNG::NextInt rva=0x000271c0 -> va=002371c0 create=MH_OK enable=MH_OK
|
||||||
|
00:23:30.276 [tid 6236] drawsite: Mars::RNG::Chance rva=0x004e6dd0 -> va=006f6dd0 create=MH_OK enable=MH_OK
|
||||||
|
00:23:30.291 [tid 6236] drawsite: Mars::RNG::NextUInt rva=0x000f7670 -> va=00307670 create=MH_OK enable=MH_OK
|
||||||
|
00:23:30.307 [tid 6236] drawsite: Mars::RNG::FloatRange rva=0x0007d8a0 -> va=0028d8a0 create=MH_OK enable=MH_OK
|
||||||
|
00:23:30.338 [tid 6236] drawsite: Mars::RNG::IntRangeBell rva=0x004e6d80 -> va=006f6d80 create=MH_OK enable=MH_OK
|
||||||
|
00:23:30.354 [tid 6236] drawsite: Mars::RNG::GaussianRange rva=0x004e6e30 -> va=006f6e30 create=MH_OK enable=MH_OK
|
||||||
|
00:23:30.354 [tid 6236] probe: installing 8 of 12 (probes= in shim.cfg)
|
||||||
|
00:23:30.369 [tid 6236] probe: Game::ServerSpyManager::vslot13 rva=0x004877b0 -> va=006977b0 create=MH_OK enable=MH_OK
|
||||||
|
00:23:30.385 [tid 6236] probe: Game::ServerSpyManager::vslot14 rva=0x0048db80 -> va=0069db80 create=MH_OK enable=MH_OK
|
||||||
|
00:23:30.401 [tid 6236] probe: Game::ServerTradeManagerImpl::vslot13 rva=0x0048ef80 -> va=0069ef80 create=MH_OK enable=MH_OK
|
||||||
|
00:23:30.416 [tid 6236] probe: Game::ServerTradeManagerImpl::vslot15 rva=0x0042cca0 -> va=0063cca0 create=MH_OK enable=MH_OK
|
||||||
|
00:23:30.432 [tid 6236] probe: Game::SpyManager::Slot13RngCallee rva=0x004408e0 -> va=006508e0 create=MH_OK enable=MH_OK
|
||||||
|
00:23:30.463 [tid 6236] probe: Game::TradeManager::Slot13RngCalleeA rva=0x00420ca0 -> va=00630ca0 create=MH_OK enable=MH_OK
|
||||||
|
00:23:30.479 [tid 6236] probe: Game::TradeManager::Slot13RngCalleeB rva=0x0048b440 -> va=0069b440 create=MH_OK enable=MH_OK
|
||||||
|
00:23:30.494 [tid 6236] probe: Game::ServerTradeManager::CreateRaidEncounter rva=0x004938a0 -> va=006a38a0 create=MH_OK enable=MH_OK
|
||||||
|
00:23:30.494 [tid 6236] watch: disabled (watch=off)
|
||||||
|
00:23:30.494 [tid 6236] aiorders: disabled (aiorders=off)
|
||||||
|
00:23:30.494 [tid 6236] fpu: module init, entry cw=0x027f 53bit-double/nearest; force=off value=0x0000 sample_ticks=off
|
||||||
|
00:23:30.494 [tid 6236] fpu: sample_turn=off (off releases StrategyServer::ProcessTurn for another hook)
|
||||||
|
00:23:30.494 [tid 6236] fpu: StrategyClient::EndTurn rva=0x00383be0 -> va=00593be0 MH_CreateHook -> MH_OK (trampoline=01170c00)
|
||||||
|
00:23:30.510 [tid 6236] fpu: StrategyClient::EndTurn MH_EnableHook -> MH_OK
|
||||||
|
00:23:30.510 [tid 6236] fpu: StrategyServer::BeginProcessTurn rva=0x003d98e0 -> va=005e98e0 MH_CreateHook -> MH_ERROR_ALREADY_CREATED (trampoline=00000000)
|
||||||
|
00:23:30.510 [tid 6236] fpu: StrategyServer::ProcessTurn rva=0x003dc6c0 not installed (sampler off)
|
||||||
|
00:23:30.510 [tid 6236] fpu: DemoApp::OnTick rva=0x0049a640 not installed (sampler off)
|
||||||
|
00:23:30.510 [tid 6236] selftest: Shim::SelfTest::Fill mode=off checksum=075ef0c3 records=0
|
||||||
|
00:23:30.526 [tid 6236] Application::Initialize called (this=03348128)
|
||||||
|
00:27:45.137 [tid 6236] fpu: sample at StrategyClient::EndTurn (this=0e23f478): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
00:27:48.309 [tid 6236] fpu: sample at StrategyClient::EndTurn (this=34e00038): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
00:27:48.325 [tid 6236] fpu: sample at StrategyClient::EndTurn (this=34e074b8): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
00:27:48.387 [tid 6236] fpu: sample at StrategyClient::EndTurn (this=34e00780): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
00:29:38.215 [tid 6236] fpu: sample at StrategyClient::EndTurn (this=0e23f478): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
00:29:41.340 [tid 6236] fpu: sample at StrategyClient::EndTurn (this=34e00038): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
00:29:41.387 [tid 6236] fpu: sample at StrategyClient::EndTurn (this=34e074b8): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
|
00:29:41.434 [tid 6236] fpu: sample at StrategyClient::EndTurn (this=34e00780): cw=0x127f 53bit-double/nearest [no fpu.force configured]
|
||||||
117
verify/traces/ar-r1-turn38-turn43.jsonl
Normal file
117
verify/traces/ar-r1-turn38-turn43.jsonl
Normal file
File diff suppressed because one or more lines are too long
36
verify/traces/ar-r2-control-turn38-turn39.jsonl
Normal file
36
verify/traces/ar-r2-control-turn38-turn39.jsonl
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue