CB: the turn-command stream, captured and bound to the autosave it produced
Canonical pair turn2->turn3: the complete block set, the three heap payloads no previous capture could read (route [272], list-10 [1728], the 24-byte Population body), the three AI client seeds, and both output autosaves -- byte-identical to the published oracle AND to this lane's own hooks=off control, so the stream and the save come from the same run and the instrument did not change the turn it recorded. Creation turn turn1->turn2: three runs. Pinning the AI client seeds to the values an earlier run observed made a DIFFERENT process reproduce that run's block -- including the research pick that varies -- and its autosave byte for byte. The workload three lanes could not reproduce is reproducible given the seeds. Two corrections to lane L4's list-23 reading (no trailing int; the body is not turn-dependent) and one to my own list-5 record, the latter found by lane RB while consuming this capture. Format: JSON (raw words are ground truth, decoded is a typing) plus lane RB's own .tcb grammar with the heap payloads filled in, so RB's reader consumes it unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ARBgSooAfokKUy6wKUKEyZ
This commit is contained in:
parent
f0aee296fe
commit
954f3cec63
21 changed files with 3259 additions and 14 deletions
310
findings/subsystems/turncommands-capture.md
Normal file
310
findings/subsystems/turncommands-capture.md
Normal file
|
|
@ -0,0 +1,310 @@
|
|||
# The command stream, captured and bound to the autosave it produced
|
||||
|
||||
Lane CB, 2026-09-08. Guest **VM146** (`sots-re-win10-146`, 192.168.10.146), build
|
||||
`cb2-20260908T2251Z`, worktree `wip/cb` off `main` `4f25f1e`. Predictions committed before the
|
||||
instrument changed: `sots-engine` `docs/CB-predictions.md` (commit `4457249`, before
|
||||
`ai_orders.cpp` was touched; the seed addendum at `c3d95dd`, before the turn-1 runs).
|
||||
|
||||
Paired with lane **RB**, which builds `sots_turn --turn-commands <blocks>`. This document is the
|
||||
input side. Captures live in `verify/results/turncommands/`; raw logs in
|
||||
`verify/results/shim/aiorders/cb-*.txt`.
|
||||
|
||||
---
|
||||
|
||||
## 0. Lead
|
||||
|
||||
**The canonical pair is captured and it binds.** `ref-turn2.sav` + one End Turn, with the block
|
||||
dump installed, wrote `(Autosave EndTurn).sav` = `bb4fd9ac89f41e3b…` (66,732 B) and
|
||||
`(Autosave).sav` = `978041acd168b56e…` (67,219 B) — **both byte-identical to the published
|
||||
determinism oracle and to this lane's own `hooks=off` control taken on the same guest through the
|
||||
same click path**. So the stream and the autosave come from the same run, and the instrument did
|
||||
not change the turn it recorded. `(Autosave).sav` is byte-identical to `turn3-state.sav`, which is
|
||||
the file lane RB's replay has to reproduce.
|
||||
|
||||
`verify/results/turncommands/cb-turn2to3.json` carries, for that one run:
|
||||
|
||||
* the **complete block set** — 8 block slots, 6 gates and all 27 lists each, with every element;
|
||||
* the **three heap payloads no previous capture could read** — list 8's route, list 10's counted
|
||||
vector, list 23's `Population` body;
|
||||
* the **three AI client seeds** (lane L1's per-process words), `0x9dfad635` / `0xb482b2d8` /
|
||||
`0xfb81e993` for net ids 32 / 496 / 512;
|
||||
* the **input save and both output autosaves**, with sizes, sha256s, and the oracle comparison.
|
||||
|
||||
Two things this lane did not expect to produce and did:
|
||||
|
||||
1. **The creation turn made reproducible.** `turn1-state → turn2` is the workload three lanes ran
|
||||
and got three different files from. With the AI client seeds **pinned** to the values an earlier
|
||||
run observed, a *different process* reproduced that run's command block — including the research
|
||||
pick that varies — and its autosave **byte for byte**. Lane L1's mechanism confirmed from the
|
||||
other end; details in §4.
|
||||
2. **An independent, empirical measurement of every element's size**, from two runs on two guests
|
||||
that wrote byte-identical autosaves. Any element word that differs between them cannot be a word
|
||||
the applier reads. The measured sizes agree with the record sizes read from the writer's
|
||||
instruction stream on all six lists — two methods, no disagreement.
|
||||
3. **Two corrections to lane L4's list-23 reading**, and one to my own list-5 record — the latter
|
||||
found by lane RB while consuming this capture, which is the pairing working as intended.
|
||||
|
||||
---
|
||||
|
||||
## 1. What the canonical stream is
|
||||
|
||||
`turn2-state.sav` (`ab4ac2d7…`, 66,739 B) → one End Turn → `turn3-state.sav` (`978041ac…`).
|
||||
|
||||
Batch `seq=2`, `n=8` blocks at stride 0x1b4. Slots 0–3 carry player ids **16, 32, 496, 512**; slots
|
||||
4–7 carry `playerId = 0` with uninitialised gate payloads (lane L4's P1 falsifier, reproduced).
|
||||
**Every one of the four real players has the research-rate gate set** and no other gate; no
|
||||
research-target gate is set on this turn by anybody.
|
||||
|
||||
Only player 32 emits commands:
|
||||
|
||||
| list | n | wire record, as captured |
|
||||
|---|---:|---|
|
||||
| 3 build | 1 | `{ordinal 2, designId 18, systemId 288, 0}` |
|
||||
| 5 system rates | 1 | `{systemId 288, 0, 1.0f, 0, 0, 0, 0, 0}` |
|
||||
| 8 fleet move | 1 | `{fleetId 34, nHops 1, [272]}` |
|
||||
| 10 | 1 | `{systemId 288, fleetId 34, count 1, [1728]}` |
|
||||
| 14 fleet task | 2 | `{34, 0, true}` and `{34, 1, true}` |
|
||||
| 23 population | 1 | `{systemId 288, vptr, 24-byte body}` |
|
||||
|
||||
The three rows in bold type below are new; everything else reproduces lane L4 exactly, from a
|
||||
different guest and a different build, which is worth stating as the corroboration it is.
|
||||
|
||||
**P3a held. The route is system 272.** Lane L4 could not read it and recorded that
|
||||
`turn3-state.sav`'s waypoint says 272 without being able to prove the command said so. It does.
|
||||
The waypoint in the output save and the route in the input command are the same id, so a replayer
|
||||
needs to carry only one.
|
||||
|
||||
**P3b half-held, and the falsified half is the useful one.** List 10's counted vector holds one
|
||||
value, **1728** — a *master-counter* id (a multiple of 16), **not** a small client-allocated one in
|
||||
the 18/34 space. So the client allocates the fleet (34) and the design (18) out of its own small
|
||||
counter but names the ship out of the server's. Lane L4's open question — "the client id counter is
|
||||
not located, and 18 and 34 differ by 16, the master stride" — now has a boundary: **the two id
|
||||
spaces coexist inside a single element**, and whatever the client counter is, it is not what names
|
||||
ships. That is a sharper statement of the hole than the one L4 left, and it is still a hole.
|
||||
|
||||
**P3c half-held, and the falsified half is a better answer.** List 23's body is 24 bytes, as
|
||||
predicted: `[0x00bd8d50, 1, 2, <ptr>, 1000000000, 0]`. The first word is a vftable pointer in the
|
||||
same neighbourhood as the element's own, so this is **one 24-byte polymorphic object**, not six
|
||||
ints, and the `1000000000` is population-shaped.
|
||||
|
||||
I predicted it would **differ between the turn-1 and turn-2 workloads**, on the strength of lane
|
||||
L4's `+1` / `−1` trailing. It does not. Captured on both turns, **five of the six words are
|
||||
identical** and the only one that moves is word 3, a heap pointer:
|
||||
|
||||
```
|
||||
turn2 -> 3 [12422480, 1, 2, 0x3369f4c8, 1000000000, 0]
|
||||
turn1 -> 2 [12422480, 1, 2, 0x343ba3e8, 1000000000, 0]
|
||||
```
|
||||
|
||||
So the `+1`/`−1` that made it look turn-dependent was the noise word outside the element (§2), and
|
||||
the payload itself is the same on every turn anyone has captured. It is still **not named** — this
|
||||
lane says what bytes it carries and nothing more (rule 6) — but a replayer is not going to be
|
||||
caught out by it on these two workloads.
|
||||
|
||||
---
|
||||
|
||||
## 2. The element sizes, measured rather than read
|
||||
|
||||
Lane L4 dumped a fixed 12-word window; this lane's is configurable and was run at 32. A wide window
|
||||
runs off the end of a small heap node into the next one, and the words past the record are
|
||||
**neighbouring heap**, not zero. That is a nuisance and it is also an instrument:
|
||||
|
||||
**Two runs of the same turn, on two different guests, both of which wrote byte-identical autosaves
|
||||
(`bb4fd9ac` / `978041ac`). Any element word that differs between them cannot be a word the applier
|
||||
reads.**
|
||||
|
||||
| list | stable prefix, L4 (VM145) vs CB (VM146) | record size from the writer | agree? |
|
||||
|---|---:|---:|---|
|
||||
| 3 build | 4 words | 4 | yes |
|
||||
| 5 system rates | 8 words | 8 | yes |
|
||||
| 8 fleet move | 1 + vector | 1 + 3 | yes |
|
||||
| 10 | 2 + vector | 2 + 3 | yes |
|
||||
| 14 fleet task | 2 words + **one byte** | 2 + bool | yes |
|
||||
| 23 population | 1 + vptr + vector | 1 + 1 + 3 | yes |
|
||||
|
||||
Two consequences worth having:
|
||||
|
||||
**List 14's third field is one byte, and the other three bytes of its word are garbage.** The two
|
||||
runs read `0x00B5B601` and `0x01138601` — same low byte, different upper three, which look like the
|
||||
low bytes of a heap pointer. A replayer that compares the whole word will find a difference that is
|
||||
not there.
|
||||
|
||||
**Correction to `ai-order-capture.md` §0: list 23's element has no trailing int.** Lane L4 recorded
|
||||
`Population{vptr, vector(24 B), −1}` on turn 2→3 and `{…, 1}` on turn 1→2, and read those as a
|
||||
field. This lane's turn-2 run reads **`0x0035765f`** in that slot — a value that also appears
|
||||
mid-element in list 8 in L4's own log, i.e. an allocator cookie. Two runs, byte-identical outputs,
|
||||
different value: it is not a field. The `+1`/`−1` L4 saw was heap noise that happened to look like
|
||||
a signed flag, which is exactly why a wide window is worth having and exactly why the campaign
|
||||
types elements offline instead of in the instrument.
|
||||
|
||||
---
|
||||
|
||||
## 3. The seeds
|
||||
|
||||
Lane L1 found each AI client's generator is seeded with a fresh per-process 32-bit word. This lane
|
||||
records them next to the block, because **the seeds are part of the stream**: with them, the capture
|
||||
is a reproducible pair; without them it is the AI's answer with no record of its input.
|
||||
|
||||
`Game::StrategyApp::RunAI` is entered **three times per process on a save load**, once per AI
|
||||
client, and the fourth stack argument is the seed. On the canonical run:
|
||||
|
||||
| call | net id | seed |
|
||||
|---:|---:|---|
|
||||
| 1 | 32 | `0x9dfad635` |
|
||||
| 2 | 496 | `0xb482b2d8` |
|
||||
| 3 | 512 | `0xfb81e993` |
|
||||
|
||||
The net ids are the same four-value set the block slots carry (16 is the human and gets no client),
|
||||
so a seed binds to a block by net id with no ambiguity.
|
||||
|
||||
### 3.1 One instrument defect, caught by its own coverage line
|
||||
|
||||
The first attempt reported `MH_ERROR_ALREADY_CREATED`: the trace framework installs **its own**
|
||||
template hook on `RunAI` (that is L1's probe), and MinHook refuses a second detour on one target.
|
||||
The module printed
|
||||
|
||||
```
|
||||
COVERAGE: aiseed hook NOT INSTALLED -- the capture will carry NO seeds, and an absent seed list
|
||||
means the instrument failed, not that the clients were unseeded
|
||||
```
|
||||
|
||||
and that line is the only reason the run was not published with a silently empty seed list. It is
|
||||
method rule 1 doing exactly the job it was written for. The fix is a config line
|
||||
(`hook.Game::StrategyApp::RunAI=off`), and the detour count is unchanged: one instrument on that
|
||||
function, not two.
|
||||
|
||||
---
|
||||
|
||||
## 4. The creation turn, and the control that had to be built
|
||||
|
||||
`turn1-state.sav` + one End Turn is the turn three AI players each **choose** a research target.
|
||||
Three lanes have run it and got three different autosaves; the campaign's oracle does not extend to
|
||||
it. This lane ran it three times.
|
||||
|
||||
### 4.1 Run C3, unpinned — and a fifth value for the tie set
|
||||
|
||||
The block reproduces lane L4's turn-1 block exactly: player 32 emits lists `{1:1, 3:1, 5:1, 23:1}`
|
||||
with `{ordinal 1, designId 18, systemId 288, 0}`, and the three AI players set research-target
|
||||
gates. **The design's name is read directly for the first time** — `"Honor Lance"`, short-string
|
||||
optimised inside the list-1 element, recovered by the string scanner at word 2.
|
||||
|
||||
The targets are **144 / 90 / 282** for players 32 / 496 / 512. The first two are lane L4's values.
|
||||
**282 is new.** L4 measured 288 for player 512; lane L5 named four outcomes by tech name. So the
|
||||
outcome set for that one decision has at least one more member than anyone has enumerated, and
|
||||
Rung C's "k = 6, all six nameable" claim is **not yet closed** — this run did not land inside the
|
||||
named set as an id, and nobody has mapped 282 to a name. That is the honest status.
|
||||
|
||||
The autosave is `d59bb9f2fd0eb535…` (66,746 B) — which is exactly the file lane L5's own
|
||||
`hooks=off` run produced. Two lanes, two processes, same outcome, by chance.
|
||||
|
||||
### 4.2 Runs C5a, pinned — the creation turn IS reproducible
|
||||
|
||||
C5a is C3 re-run with `aiseed=pin` set to the three seeds **C3 itself observed**. Its own natural
|
||||
seeds were entirely different (`0x227235b9` / `0x762d125e` / `0x9d77d4e6`) and were overwritten
|
||||
before the client ctor saw them.
|
||||
|
||||
| | C3 (unpinned) | C5a (pinned to C3's seeds) |
|
||||
|---|---|---|
|
||||
| natural seeds drawn | `e70a4703` / `0c63ca36` / `372be4df` | `227235b9` / `762d125e` / `9d77d4e6` |
|
||||
| seeds **used** | same | **C3's** |
|
||||
| research targets 32 / 496 / 512 | 144 / 90 / **282** | 144 / 90 / **282** |
|
||||
| every other gate and element record | — | **identical** |
|
||||
| `(Autosave).sav` | `d59bb9f2fd0eb535…` | **`d59bb9f2fd0eb535…`** |
|
||||
|
||||
**The workload that three lanes could not reproduce is reproducible once the seeds are pinned.**
|
||||
Lane L1's mechanism is confirmed from the other end: the seed is *the* per-process input, and
|
||||
`game/ai` is a deterministic function of (save, per-client seed). Rung B's input is therefore a
|
||||
**closed** record — save + seeds + block — and not a log of something that happened once.
|
||||
|
||||
The single difference in the whole decoded stream is **word 3 of list 23's unnamed `Population`
|
||||
body** (`876301736` vs `245`). By the argument of §2 — two runs, byte-identical autosaves — that
|
||||
word is not a word the applier reads either, which is one more word localised as noise, using the
|
||||
pinned pair as the instrument. That is what a control on a `k > 1` workload is *for*.
|
||||
|
||||
---
|
||||
|
||||
## 5. Rule 19, and the control that does not exist without pinning
|
||||
|
||||
**On the canonical pair the control is real.** `hooks=off` on VM146 reproduced both oracle hashes
|
||||
(run C0), and the instrumented run reproduced them again (run C1). That pair is a valid rule-19
|
||||
control because the workload is deterministic: there is one right answer and both runs gave it.
|
||||
|
||||
**On `turn1-state` there is no such thing as a single-run control, and this lane will not pretend
|
||||
otherwise.** Three lanes have run `hooks=off` on that save and got three different files. With an
|
||||
outcome set of size k, an instrumented run agreeing with one un-instrumented run is a **1/k
|
||||
coincidence**; at lane L4's k = 6 that is a 17 % chance of a clean bill of health that means
|
||||
nothing. A control on that workload requires the seeds *pinned*, which removes the only
|
||||
per-process input. That is what the `aiseed=pin` mode exists for.
|
||||
|
||||
---
|
||||
|
||||
## 6. The capture format, for lane RB
|
||||
|
||||
`verify/results/turncommands/<run>.json`, written by `tools/turncommands_capture.py` from the
|
||||
run's `shim.aiorders.txt` plus the run's own saves. Version 1.
|
||||
|
||||
```
|
||||
capture_version, lane, guest, build, captured_utc
|
||||
instrument { words, deep, seed, pins, detours } -- the run is self-describing
|
||||
workload, note
|
||||
binding {
|
||||
input { file, bytes, sha256 }
|
||||
outputs [ { file, bytes, sha256, path, oracle_sha256, matches_oracle } ]
|
||||
control_run
|
||||
}
|
||||
ai_seeds [ { call, netId, observed, used, pinned } ]
|
||||
list_size_self_check { mismatches, note }
|
||||
batches [ { seq, n, blocks_va, stride, blocks: [ {
|
||||
index, playerId,
|
||||
gates { researchRate, researchTarget, researchBoost, group4, group5, civilianRatios },
|
||||
list_sizes [27],
|
||||
lists [ { list, member_offset, size, elements: [ {
|
||||
index, node_va,
|
||||
raw_words [...], <- GROUND TRUTH
|
||||
vectors [ { at_word, first_va, capacity, count, words, truncated } ],
|
||||
strings [ { at_word, sso, len, text } ],
|
||||
decoded { record, <named fields>, wire [...], record_words }
|
||||
} ] } ] } ] } ]
|
||||
```
|
||||
|
||||
Rules for consuming it, in order of how much they cost to get wrong:
|
||||
|
||||
1. **`raw_words` is the ground truth. `decoded` is a typing.** If they ever disagree, `raw_words`
|
||||
wins, and the fix belongs in the tool, not in the replayer.
|
||||
2. **Use `decoded.wire`** — it is the values in the order the writer emits them, with the counted
|
||||
vectors already spliced in as `count` followed by elements. It is what a replayer feeds the
|
||||
applier.
|
||||
3. **`record_words` says how much of `raw_words` is the element.** Everything past it is the next
|
||||
heap node. The window is deliberately wider than any record.
|
||||
4. **A `vectors` entry at a word offset no record names is noise** and must be ignored. The
|
||||
follower is a shape test on a wide window and it fires on coincidences; every genuine payload in
|
||||
this capture sits at the word index its record predicts (list 8 `w1`, list 10 `w2`, list 23
|
||||
`w2`), and the decoder reads only those.
|
||||
5. **`binding.outputs` is what makes the capture checkable.** A capture with no outputs, or whose
|
||||
hashes are not the ones the run produced, cannot be used for a byte-match and the tool writes a
|
||||
`WARNING` into the file saying so.
|
||||
6. **`instrument.deep` must be `1`.** With `deep=0` the heap payloads are *absent*, not empty, and
|
||||
the tool writes `WARNING_INCOMPLETE`. A fleet move with no route is not a fleet move with a
|
||||
route of length zero.
|
||||
7. **List 3's element is stored backwards in memory** relative to its wire order. The tool handles
|
||||
it; anyone reading `raw_words` directly must.
|
||||
|
||||
---
|
||||
|
||||
## 7. Coverage, stated as loudly as the result (rule 15)
|
||||
|
||||
* **Six of twenty-seven lists** have ever carried an element, in this capture or any other: 1, 3,
|
||||
5, 8, 10, 14, 23 (seven, counting list 1 on the turn-1 workload). Lists 2, 4, 6, 7, 9, 11–22,
|
||||
24–27 are empty in every block of every run. **A replayer's handling of those twenty is untested
|
||||
by this lane and must be labelled as such** — including list 7, colonize, which lane Q typed from
|
||||
a *human* orders save and which no AI capture has ever exercised.
|
||||
* **One of six gates** is set on the canonical pair (research rate). Two on the turn-1 workload
|
||||
(rate and target). Gates 4, 5 and 6 have never been observed set by anything.
|
||||
* **One AI player with anything to do**, on a 28-star board with no contact: no colonise, no
|
||||
invade, no raid, no diplomacy, no combat, no trade route, no spy program.
|
||||
* **The `Population` body and list 10's payload are carried, not named.** This lane reports their
|
||||
bytes and declines to say what they mean.
|
||||
* The element-size measurement rests on **two runs**. Two is enough to show a word is *unstable*;
|
||||
it is not enough to show a word is *stable*, and the stable prefixes above are therefore upper
|
||||
bounds on noise, not proofs of a record. They agree with the writer's own instruction stream,
|
||||
which is the second, independent leg.
|
||||
520
tools/turncommands_capture.py
Normal file
520
tools/turncommands_capture.py
Normal file
|
|
@ -0,0 +1,520 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Turn a lane-CB `shim.aiorders.txt` into a `TurnCommands` capture (JSON) for the replayer.
|
||||
|
||||
WHY THIS IS A SEPARATE, OFFLINE STEP.
|
||||
|
||||
The shim's block dump reads element BYTES, not element TYPES -- lane L4's design point, kept
|
||||
deliberately: a wrong element record then shows up as a wrong value in a report instead of being
|
||||
baked into an instrument that needs a VM run to correct. This script is where the typing happens,
|
||||
so a corrected record costs a re-parse rather than a rebuild, a redeploy and a turn.
|
||||
|
||||
The consequence for anyone reading the output: `raw_words` is the GROUND TRUTH. `decoded` is a
|
||||
best-effort typing, present only for the six lists the campaign has actually observed, and
|
||||
regenerable from `raw_words` by re-running this script. If the two ever disagree, `raw_words` wins.
|
||||
|
||||
THE ONE THING THAT IS EASY TO GET WRONG. List 3's in-memory element is in the OPPOSITE order from
|
||||
its wire record: its writer (0x00822870) emits +0x14, +0x10, +0x0c, +0x08, descending, while lists
|
||||
5, 8, 10, 14 and 23 all write ascending. That is per-list, not a rule, and it is encoded as such
|
||||
below (`REVERSED`). A decoder that applies one order to all six produces a build order whose
|
||||
design id and ordinal are swapped -- which is a plausible-looking save with every id wrong.
|
||||
|
||||
Usage:
|
||||
uv run python3 tools/turncommands_capture.py \
|
||||
--log verify/results/shim/aiorders/cb-turn2to3.txt \
|
||||
--input verify/results/saves/turn2-state.sav \
|
||||
--autosave "(Autosave EndTurn).sav=<sha256>:<bytes>" \
|
||||
--autosave "(Autosave).sav=<sha256>:<bytes>" \
|
||||
--out verify/results/turncommands/cb-turn2to3.json
|
||||
"""
|
||||
import argparse, datetime, hashlib, json, os, re, struct, sys
|
||||
|
||||
CAPTURE_VERSION = 1
|
||||
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
# element records
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
# Each entry: (record name, field names in WIRE order, whether the memory words run backwards,
|
||||
# and which word index -- if any -- carries a counted heap vector whose contents belong on the
|
||||
# wire in place of a scalar).
|
||||
#
|
||||
# Lists with no entry here are carried as raw words only. That is deliberate (method rule 6): no
|
||||
# workload in this campaign has ever put an element in them, so any record would be a hypothesis,
|
||||
# and a hypothesis written into a replayer's input file is indistinguishable from a fact.
|
||||
REVERSED = {3}
|
||||
|
||||
# Lists whose element VALUES are certain but whose memory-to-wire mapping is NOT. Lane RB mapped
|
||||
# list 5's sliders straight through and regressed two leaves; until the writer's own order is read,
|
||||
# a capture must carry the values without asserting where they land. In the `.tcb` these words are
|
||||
# emitted as `?` -- byte-for-byte what lane RB's own converter emits -- with the memory-order values
|
||||
# on a `meta uncertain` line, so nothing is lost and nothing is claimed.
|
||||
UNCERTAIN_WIRE_ORDER = {5}
|
||||
# What IS known about list 5, recorded next to the values rather than baked into a field name.
|
||||
RATES_NOTE = ("memory member 1 is wire member SRsc (lane RB, from a replay that regressed two "
|
||||
"leaves when the memory order was used as the wire order); the other six memory "
|
||||
"members are UNREAD. Values are certain, positions are not.")
|
||||
|
||||
RECORDS = {
|
||||
1: ("NewDesign", None), # polymorphic; carried raw + its strings
|
||||
3: ("BuildOrder", ["ordinal", "designId", "systemId", "trailing"]),
|
||||
# NO RATES RECORD, ON PURPOSE -- the system id only.
|
||||
#
|
||||
# This element is dumped in MEMORY order and its memory field order is NOT its wire order.
|
||||
# Lane Q named the wire frame {SRs, SRt, SRsc, SRtf, SRi, SRoh, SRnr} from a HUMAN orders save;
|
||||
# lane RB mapped the AI's memory words straight onto it, predicted zero regressions on its
|
||||
# first replay and got TWO -- the AI's one non-zero slider landed in `SRt` where the oracle
|
||||
# holds `SRsc = 1.0`. The one mapping that is known is **memory member 1 -> wire member SRsc**;
|
||||
# the other six are unread.
|
||||
#
|
||||
# A capture is supposed to outlive whatever adapter happened to read it, so this ships the
|
||||
# values and NOT a naming. `rates_memory_order` carries the seven words as dumped, `wire` is
|
||||
# None, and a replayer that needs them must refuse rather than guess. A missing field is
|
||||
# honest; a mislabelled one propagates.
|
||||
5: ("SystemRates", ["systemId"]),
|
||||
7: ("Colonize", ["shipId", "trailing"]),
|
||||
8: ("FleetMove", ["fleetId", "@route"]), # `@` = the counted vector at this position
|
||||
10: ("List10", ["systemId", "fleetId", "@counted"]),
|
||||
14: ("FleetTask", ["fleetId", "mode", "flag"]),
|
||||
# CORRECTED from lane L4 §0, which read a trailing int here ("Population{vptr, vector(24 B),
|
||||
# -1}"). There is no trailing int. Two runs of THIS turn on two guests -- lane L4's on VM145
|
||||
# and lane CB's on VM146, both of which wrote byte-identical autosaves -- disagree on that
|
||||
# word (-1 vs 0x0035765f, an allocator cookie that also shows up mid-element in list 8).
|
||||
# A word that differs between two runs whose outputs are byte-identical cannot be a word the
|
||||
# applier reads. The element is {systemId, vptr, vector}.
|
||||
23: ("Population", ["systemId", "@vptr", "@body"]),
|
||||
}
|
||||
# Which fields of which record are floats rather than ints, by wire-field name.
|
||||
FLOAT_FIELDS = set() # the only float frame in the corpus is list 5's, and it is not named
|
||||
# The bool is ONE BYTE on the wire; the other three bytes of its word are padding and carry
|
||||
# heap garbage that differs run to run (0x00B5B601 vs 0x01138601 on two runs that produced
|
||||
# byte-identical autosaves). Masking to the low byte is not tidiness, it is the record.
|
||||
BOOL_FIELDS = {("FleetTask", "flag")}
|
||||
|
||||
GATES = [
|
||||
("researchRate", "rate"),
|
||||
("researchTarget", "target"),
|
||||
("researchBoost", "boost"),
|
||||
("group4", "g4"),
|
||||
("group5", "f3"),
|
||||
("civilianRatios", "civ"),
|
||||
]
|
||||
|
||||
|
||||
def u32_to_f32(v):
|
||||
return struct.unpack("<f", struct.pack("<I", v & 0xFFFFFFFF))[0]
|
||||
|
||||
|
||||
def sha256_of(path):
|
||||
h = hashlib.sha256()
|
||||
with open(path, "rb") as fh:
|
||||
for chunk in iter(lambda: fh.read(1 << 20), b""):
|
||||
h.update(chunk)
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
# the log
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
RE_CFG = re.compile(r"^aicfg (.*)$")
|
||||
RE_SEED = re.compile(r"^aiseed call=(\d+) netId=(-?\d+) observed=0x([0-9a-f]+) "
|
||||
r"used=0x([0-9a-f]+) pinned=(\d)")
|
||||
RE_BATCH = re.compile(r"^---- aibatch seq=(\d+) blocks=0x([0-9a-f]+) n=(-?\d+) stride=0x([0-9a-f]+)")
|
||||
RE_BLK = re.compile(r"^aiblk seq=(\d+) blk=(\d+)/(\d+) at=0x([0-9a-f]+) pid=(-?\d+) (.*)$")
|
||||
RE_SIZES = re.compile(r"^ailists seq=(\d+) blk=(\d+) pid=(-?\d+) nonEmpty=(\d+) "
|
||||
r"sizes\(1\.\.27\)=\[ (.*?)\]")
|
||||
RE_LIST = re.compile(r"^ailist blk=(\d+) pid=(-?\d+) list=(\d+) off=0x([0-9a-f]+) size=(\d+)")
|
||||
RE_MISM = re.compile(r"^ailist MISMATCH blk=(\d+) pid=(-?\d+) list=(\d+) _Mysize=(\d+) walked=(\d+)")
|
||||
# `words=` is lane CB's; a lane-L4 log has no such field and is still parsed, at its fixed 12.
|
||||
RE_ELEM = re.compile(r"^aielem blk=(\d+) pid=(-?\d+) list=(\d+) idx=(\d+) node=0x([0-9a-f]+) "
|
||||
r"(?:words=(\d+) )?f0=\S+ f1=\S+ ints=\[ .*?\] hex=\[ (.*?)\]")
|
||||
RE_VEC = re.compile(r"^aivec blk=(\d+) pid=(-?\d+) list=(\d+) idx=(\d+) at=w(\d+) "
|
||||
r"first=0x([0-9a-f]+) cap=(\d+) count=(\d+) ints=\[ .*?\] hex=\[ (.*?)\]"
|
||||
r"( TRUNCATED)?")
|
||||
RE_STR = re.compile(r'^aistr blk=(\d+) pid=(-?\d+) list=(\d+) idx=(\d+) at=w(\d+) sso=(\d) '
|
||||
r'len=(\d+) text="(.*)"$')
|
||||
|
||||
|
||||
def parse_gates(rest):
|
||||
"""`rate=1:0.8 target=0:880612328 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0` -> a dict."""
|
||||
out = {}
|
||||
fields = dict(tok.split("=", 1) for tok in rest.split() if "=" in tok)
|
||||
for name, key in GATES:
|
||||
raw = fields.get(key)
|
||||
if raw is None:
|
||||
continue
|
||||
if ":" in raw:
|
||||
setbit, payload = raw.split(":", 1)
|
||||
out[name] = {"set": setbit == "1", "payload": payload}
|
||||
else:
|
||||
out[name] = {"set": raw == "1"}
|
||||
return out
|
||||
|
||||
|
||||
def hexwords(s):
|
||||
return [int(w, 16) for w in s.split()]
|
||||
|
||||
|
||||
def decode(list_no, words, vectors, strings):
|
||||
"""Type one element. Returns None where the campaign has no record for the list."""
|
||||
entry = RECORDS.get(list_no)
|
||||
if entry is None:
|
||||
return None
|
||||
name, fields = entry
|
||||
if fields is None:
|
||||
return {"record": name, "wire": None,
|
||||
"note": "polymorphic object; carried as raw words and decoded strings only"}
|
||||
src = list(reversed(words[:len(fields)])) if list_no in REVERSED else words[:len(fields)]
|
||||
byword = {v["at_word"]: v for v in vectors}
|
||||
out, wire, wi = {"record": name}, [], 0
|
||||
for i, f in enumerate(fields):
|
||||
if f.startswith("@"):
|
||||
key = f[1:]
|
||||
if key == "vptr":
|
||||
out[key] = f"0x{words[i]:08x}"
|
||||
wi += 1
|
||||
continue
|
||||
v = byword.get(wi)
|
||||
if v is None:
|
||||
out[key] = None
|
||||
out.setdefault("incomplete", []).append(key)
|
||||
else:
|
||||
out[key] = v["words"]
|
||||
wire.append(len(v["words"]))
|
||||
wire.extend(v["words"])
|
||||
wi += 3 # a vector occupies three words of the element
|
||||
continue
|
||||
val = src[i] if list_no in REVERSED else words[wi]
|
||||
if (name, f) in FLOAT_FIELDS:
|
||||
val = u32_to_f32(val)
|
||||
elif (name, f) in BOOL_FIELDS:
|
||||
val = bool(val & 0xFF)
|
||||
elif val >= 0x80000000:
|
||||
val -= 1 << 32
|
||||
out[f] = val
|
||||
wire.append(val)
|
||||
wi += 1
|
||||
out["wire"] = wire
|
||||
# How many words of `raw_words` are the element. The window is deliberately wider than any
|
||||
# record (`aiorders.words=`), so everything past this is the NEXT heap node and is noise --
|
||||
# which is why the widened window also produces spurious `vectors` entries at word offsets
|
||||
# no record names. Measured independently: see the cross-run stability table in the report.
|
||||
out["record_words"] = wi
|
||||
if list_no == 5:
|
||||
# The seven words after the system id, exactly as dumped, as raw u32 and as f32.
|
||||
out["rates_memory_order_u32"] = words[1:8]
|
||||
out["rates_memory_order_f32"] = [u32_to_f32(w) for w in words[1:8]]
|
||||
out["record_words"] = 8
|
||||
out["wire"] = None
|
||||
out["wire_order_unread"] = True
|
||||
out["note"] = RATES_NOTE
|
||||
return out
|
||||
if list_no in UNCERTAIN_WIRE_ORDER:
|
||||
out["wire_order_uncertain"] = True
|
||||
out["wire_order_note"] = (
|
||||
"the VALUES are measured; their positions in the wire frame are NOT. `wire` is memory "
|
||||
"order. A replayer must not map these onto named members without reading the writer.")
|
||||
if strings:
|
||||
out["strings"] = [s["text"] for s in strings]
|
||||
return out
|
||||
|
||||
|
||||
def parse_log(path):
|
||||
cfg, seeds, batches = {}, [], []
|
||||
batch = block = None
|
||||
elems = {} # (blk, list, idx) -> element dict, so aivec/aistr can attach
|
||||
mismatches = []
|
||||
with open(path, "r", errors="replace") as fh:
|
||||
for line in fh:
|
||||
line = line.rstrip("\n")
|
||||
|
||||
m = RE_CFG.match(line)
|
||||
if m:
|
||||
cfg.update(dict(t.split("=", 1) for t in m.group(1).split() if "=" in t))
|
||||
continue
|
||||
|
||||
m = RE_SEED.match(line)
|
||||
if m:
|
||||
seeds.append({"call": int(m.group(1)), "netId": int(m.group(2)),
|
||||
"observed": f"0x{m.group(3)}", "used": f"0x{m.group(4)}",
|
||||
"pinned": m.group(5) == "1"})
|
||||
continue
|
||||
|
||||
m = RE_BATCH.match(line)
|
||||
if m:
|
||||
batch = {"seq": int(m.group(1)), "blocks_va": f"0x{m.group(2)}",
|
||||
"n": int(m.group(3)), "stride": int(m.group(4), 16), "blocks": []}
|
||||
batches.append(batch)
|
||||
elems = {}
|
||||
continue
|
||||
|
||||
m = RE_BLK.match(line)
|
||||
if m and batch is not None:
|
||||
block = {"index": int(m.group(2)), "n": int(m.group(3)),
|
||||
"block_va": f"0x{m.group(4)}", "playerId": int(m.group(5)),
|
||||
"gates": parse_gates(m.group(6)), "lists": []}
|
||||
batch["blocks"].append(block)
|
||||
continue
|
||||
|
||||
m = RE_SIZES.match(line)
|
||||
if m and block is not None:
|
||||
block["list_sizes"] = [int(x) for x in m.group(5).split()]
|
||||
continue
|
||||
|
||||
m = RE_MISM.match(line)
|
||||
if m:
|
||||
mismatches.append({"blk": int(m.group(1)), "list": int(m.group(3)),
|
||||
"mysize": int(m.group(4)), "walked": int(m.group(5))})
|
||||
continue
|
||||
|
||||
m = RE_LIST.match(line)
|
||||
if m and batch is not None:
|
||||
blk = int(m.group(1))
|
||||
tgt = next(b for b in batch["blocks"] if b["index"] == blk)
|
||||
tgt["lists"].append({"list": int(m.group(3)),
|
||||
"member_offset": f"0x{m.group(4)}",
|
||||
"size": int(m.group(5)), "elements": []})
|
||||
continue
|
||||
|
||||
m = RE_ELEM.match(line)
|
||||
if m and batch is not None:
|
||||
blk, lst, idx = int(m.group(1)), int(m.group(3)), int(m.group(4))
|
||||
e = {"index": idx, "node_va": f"0x{m.group(5)}",
|
||||
"raw_words": hexwords(m.group(7)), "vectors": [], "strings": []}
|
||||
tgt = next(b for b in batch["blocks"] if b["index"] == blk)
|
||||
lt = next(l for l in tgt["lists"] if l["list"] == lst)
|
||||
lt["elements"].append(e)
|
||||
elems[(blk, lst, idx)] = e
|
||||
continue
|
||||
|
||||
m = RE_VEC.match(line)
|
||||
if m:
|
||||
e = elems.get((int(m.group(1)), int(m.group(3)), int(m.group(4))))
|
||||
if e is not None:
|
||||
e["vectors"].append({"at_word": int(m.group(5)),
|
||||
"first_va": f"0x{m.group(6)}",
|
||||
"capacity": int(m.group(7)),
|
||||
"count": int(m.group(8)),
|
||||
"words": hexwords(m.group(9)),
|
||||
"truncated": bool(m.group(10))})
|
||||
continue
|
||||
|
||||
m = RE_STR.match(line)
|
||||
if m:
|
||||
e = elems.get((int(m.group(1)), int(m.group(3)), int(m.group(4))))
|
||||
if e is not None:
|
||||
e["strings"].append({"at_word": int(m.group(5)),
|
||||
"sso": m.group(6) == "1",
|
||||
"len": int(m.group(7)), "text": m.group(8)})
|
||||
continue
|
||||
|
||||
for b in batches:
|
||||
for blk in b["blocks"]:
|
||||
for lt in blk["lists"]:
|
||||
for e in lt["elements"]:
|
||||
d = decode(lt["list"], e["raw_words"], e["vectors"], e["strings"])
|
||||
if d is not None:
|
||||
e["decoded"] = d
|
||||
return cfg, seeds, batches, mismatches
|
||||
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
# lane RB's `.tcb`, with the payloads filled in
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
# Lane RB landed `tools/aiorders_to_tcb.py` and a line-oriented `.tcb` grammar before this lane
|
||||
# landed its JSON, and `sots_turn --turn-commands` reads `.tcb`. Rather than ask RB to read a
|
||||
# second format, this emits theirs -- with ONE additive extension, flagged here because a silent
|
||||
# superset is how two tools drift apart:
|
||||
#
|
||||
# `vN` a vector of N elements whose CONTENTS ARE UNKNOWN (RB's; the dump could not follow
|
||||
# the pointer)
|
||||
# `vN:a,b` a vector of N elements whose contents ARE known (lane CB's; the dump followed it)
|
||||
#
|
||||
# A reader that only knows `vN` must treat `vN:...` as unreadable rather than as `vN`, because the
|
||||
# whole point of RB's `vN` is that the replayer counts such a command and REFUSES to apply it. The
|
||||
# two mean opposite things about whether the command can be reproduced, and getting that backwards
|
||||
# turns "we cannot replay this" into "we replayed it wrong".
|
||||
#
|
||||
# `?` is preserved exactly: a word the record says is part of an object this window cannot read.
|
||||
def emit_tcb(cap, source):
|
||||
out = ["tcb 1",
|
||||
"meta source %s" % source,
|
||||
"meta input %s" % cap["binding"]["input"]["file"],
|
||||
"meta input_sha256 %s" % cap["binding"]["input"]["sha256"]]
|
||||
for o in cap["binding"]["outputs"]:
|
||||
out.append("meta output %s %d %s%s" % (
|
||||
o["file"], o["bytes"], o["sha256"],
|
||||
"" if "matches_oracle" not in o else (" oracle=%s" % o["matches_oracle"])))
|
||||
if cap["binding"].get("control_run"):
|
||||
out.append("meta control %s" % cap["binding"]["control_run"])
|
||||
out.append("meta lane CB capture_version %d build %s guest %s"
|
||||
% (cap["capture_version"], cap.get("build"), cap.get("guest")))
|
||||
out.append("meta extension vN:a,b -- a vector whose contents ARE known; bare vN still means "
|
||||
"unknown and must still be refused")
|
||||
|
||||
# The End-Turn batch is the LAST one: a process applies a batch at LOAD as well, and replaying
|
||||
# the load-time one against a save written after it would double-count. RB's default, kept.
|
||||
batch = cap["batches"][-1]
|
||||
out.append("meta batch seq=%d n=%d" % (batch["seq"], batch["n"]))
|
||||
for s in cap.get("ai_seeds", []):
|
||||
out.append("seed %d %s%s" % (s["netId"], s["used"], " pinned" if s["pinned"] else ""))
|
||||
|
||||
for blk in batch["blocks"]:
|
||||
out.append("block %d %d" % (blk["index"], blk["playerId"]))
|
||||
g = blk["gates"]
|
||||
if g.get("researchRate", {}).get("set"):
|
||||
out.append("gate %d rate %s" % (blk["index"], g["researchRate"]["payload"]))
|
||||
if g.get("researchTarget", {}).get("set"):
|
||||
out.append("gate %d target %s" % (blk["index"], g["researchTarget"]["payload"]))
|
||||
if g.get("researchBoost", {}).get("set"):
|
||||
out.append("gate %d boost %s" % (blk["index"], g["researchBoost"]["payload"]))
|
||||
for lt in blk["lists"]:
|
||||
out.append("list %d %d %d" % (blk["index"], lt["list"], lt["size"]))
|
||||
for e in lt["elements"]:
|
||||
out.append("elem %d %d %d %s"
|
||||
% (blk["index"], lt["list"], e["index"], tcb_tokens(lt["list"], e)))
|
||||
d = e.get("decoded") or {}
|
||||
for s in e.get("strings", []):
|
||||
# List 1's element is a polymorphic ShipDesignDef the window cannot type, but
|
||||
# its NAME is inline (short-string optimisation) and is the only human-readable
|
||||
# thing in the whole block. It is recorded, not decoded.
|
||||
out.append('meta string %d %d %d w%d "%s"'
|
||||
% (blk["index"], lt["list"], e["index"], s["at_word"], s["text"]))
|
||||
if d.get("wire_order_unread"):
|
||||
out.append("meta rates %d %d %d memory-order-f32 %s"
|
||||
% (blk["index"], lt["list"], e["index"],
|
||||
",".join(repr(v) for v in d["rates_memory_order_f32"])))
|
||||
out.append("meta rates-note %s" % RATES_NOTE)
|
||||
return "\n".join(out) + "\n"
|
||||
|
||||
|
||||
def tcb_tokens(list_no, e):
|
||||
entry = RECORDS.get(list_no)
|
||||
d = e.get("decoded")
|
||||
if entry is None or entry[1] is None or d is None:
|
||||
return "?"
|
||||
_, fields = entry
|
||||
name = entry[0]
|
||||
if list_no == 5:
|
||||
# Byte-for-byte what lane RB's own converter emits: the id, then seven unreadable words.
|
||||
return "i%d ? ? ? ? ? ? ?" % d["systemId"]
|
||||
byword = {v["at_word"]: v for v in e["vectors"]}
|
||||
toks, wi = [], 0
|
||||
for i, f in enumerate(fields):
|
||||
if f.startswith("@"):
|
||||
key = f[1:]
|
||||
if key == "vptr":
|
||||
toks.append("?") # a vftable pointer is not a wire field
|
||||
wi += 1
|
||||
continue
|
||||
v = byword.get(wi)
|
||||
if v is None:
|
||||
toks.append("?")
|
||||
else:
|
||||
toks.append("v%d:%s" % (v["count"], ",".join(str(w) for w in v["words"])))
|
||||
wi += 3
|
||||
continue
|
||||
val = d.get(f)
|
||||
|
||||
if (name, f) in BOOL_FIELDS:
|
||||
toks.append("b%d" % (1 if val else 0))
|
||||
elif (name, f) in FLOAT_FIELDS:
|
||||
toks.append("f%s" % repr(float(val)))
|
||||
elif val is None:
|
||||
toks.append("?")
|
||||
else:
|
||||
toks.append("i%d" % val)
|
||||
wi += 1
|
||||
return " ".join(toks)
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("--log", required=True)
|
||||
ap.add_argument("--input", required=True, help="the save the turn was run from")
|
||||
ap.add_argument("--autosave", action="append", default=[],
|
||||
help="NAME=PATH -- an output autosave of THIS run")
|
||||
ap.add_argument("--oracle", action="append", default=[],
|
||||
help="NAME=SHA256 -- the published oracle hash, if this pair has one")
|
||||
ap.add_argument("--control", default=None,
|
||||
help="name of the hooks=off run whose autosaves this run's must match")
|
||||
ap.add_argument("--guest", default="VM146")
|
||||
ap.add_argument("--build", default=None)
|
||||
ap.add_argument("--workload", default=None)
|
||||
ap.add_argument("--note", default=None)
|
||||
ap.add_argument("--out", required=True)
|
||||
ap.add_argument("--tcb", default=None,
|
||||
help="also emit lane RB's .tcb grammar, with the heap payloads "
|
||||
"filled in (see emit_tcb for the one extension)")
|
||||
a = ap.parse_args()
|
||||
|
||||
cfg, seeds, batches, mismatches = parse_log(a.log)
|
||||
oracle = dict(x.split("=", 1) for x in a.oracle)
|
||||
|
||||
outputs = []
|
||||
for spec in a.autosave:
|
||||
name, path = spec.split("=", 1)
|
||||
h = sha256_of(path)
|
||||
row = {"file": name, "bytes": os.path.getsize(path), "sha256": h,
|
||||
"path": os.path.relpath(path, start=os.path.dirname(os.path.abspath(a.out)))}
|
||||
if name in oracle:
|
||||
row["oracle_sha256"] = oracle[name]
|
||||
row["matches_oracle"] = (h == oracle[name])
|
||||
outputs.append(row)
|
||||
|
||||
cap = {
|
||||
"capture_version": CAPTURE_VERSION,
|
||||
"lane": "CB",
|
||||
"guest": a.guest,
|
||||
"build": a.build,
|
||||
"captured_utc": datetime.datetime.now(datetime.timezone.utc)
|
||||
.replace(microsecond=0).isoformat(),
|
||||
"instrument": cfg,
|
||||
"workload": a.workload,
|
||||
"note": a.note,
|
||||
"binding": {
|
||||
"input": {"file": os.path.basename(a.input),
|
||||
"bytes": os.path.getsize(a.input),
|
||||
"sha256": sha256_of(a.input)},
|
||||
"outputs": outputs,
|
||||
"control_run": a.control,
|
||||
},
|
||||
# Three words per process (lane L1). WITHOUT THESE THE CAPTURE IS A LOG FILE: the AI is
|
||||
# MT19937 from one word per client, so the block is the AI's answer and the seed is its
|
||||
# input. `pinned` says whether the run FORCED the value rather than observing it.
|
||||
"ai_seeds": seeds,
|
||||
"list_size_self_check": {
|
||||
"mismatches": mismatches,
|
||||
"note": ("every list is measured twice, by walking its node chain and by reading "
|
||||
"_Mysize; an empty list here means the container layout agreed on every "
|
||||
"list of every block, which is the evidence that a zero size is a real "
|
||||
"zero rather than a wrong offset"),
|
||||
},
|
||||
"batches": batches,
|
||||
}
|
||||
|
||||
if not outputs:
|
||||
cap["binding"]["WARNING"] = ("no output autosave recorded -- this capture CANNOT be "
|
||||
"checked by a byte-match and must not be used as one")
|
||||
if cfg.get("deep") != "1":
|
||||
cap["WARNING_INCOMPLETE"] = ("captured with aiorders.deep=0: every heap payload (list 8's "
|
||||
"route, list 10's counted vector, list 23's body) is ABSENT, "
|
||||
"not empty")
|
||||
|
||||
os.makedirs(os.path.dirname(os.path.abspath(a.out)), exist_ok=True)
|
||||
with open(a.out, "w") as fh:
|
||||
json.dump(cap, fh, indent=1, sort_keys=False)
|
||||
fh.write("\n")
|
||||
if a.tcb:
|
||||
os.makedirs(os.path.dirname(os.path.abspath(a.tcb)), exist_ok=True)
|
||||
with open(a.tcb, "w") as fh:
|
||||
fh.write(emit_tcb(cap, os.path.basename(a.log)))
|
||||
print("wrote", a.tcb)
|
||||
|
||||
nblocks = sum(len(b["blocks"]) for b in batches)
|
||||
nelem = sum(len(l["elements"]) for b in batches for k in b["blocks"] for l in k["lists"])
|
||||
print(f"wrote {a.out}: {len(batches)} batches, {nblocks} blocks, {nelem} elements, "
|
||||
f"{len(seeds)} seeds, {len(mismatches)} layout mismatches")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
36
verify/harness/cb/README.md
Normal file
36
verify/harness/cb/README.md
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# Lane CB's VM harness
|
||||
|
||||
Driving VM146 from WSL. Two lab facts these scripts exist to encode, both of which cost this lane
|
||||
a run before they were understood:
|
||||
|
||||
**1. The vmwatch wall caches frames for 5 seconds, and a cached frame is indistinguishable from a
|
||||
click that did nothing.** Four clicks were diagnosed as "not registering" when every one of them
|
||||
had worked and the screenshot was simply older than the click. Every screendump here goes through
|
||||
`vmshot.py --ssh`, which bypasses the service and costs ~4 s.
|
||||
|
||||
**2. The >60 s startup is real** (five confirmations on the board now). `cbmenu.py` polls the
|
||||
framebuffer for the main menu's red button column and refuses to return until it is up. Never
|
||||
sleep-and-click.
|
||||
|
||||
A third, less certain: `cbfull.sh` chains the whole path with fixed gaps and **lost the Load-dialog
|
||||
OK on one run** — the click helper is fired by `schtasks /Run`, which is asynchronous, so batches
|
||||
issued back to back can overlap and one gets dropped. Driving the path one `cbstep.sh` call per
|
||||
click, with a screendump between, did not fail once. Prefer `cbstep.sh` + `cbdo.sh` over `cbfull.sh`
|
||||
until that is understood.
|
||||
|
||||
| script | what |
|
||||
|---|---|
|
||||
| `cbstep.ps1` (on the guest, `C:\SOTS\cb\`) | one click-helper batch; lines joined with `;;` so PowerShell argument splitting cannot break `sleep 500` into two arguments — which it silently does |
|
||||
| `cbstep.sh` | send one batch |
|
||||
| `cbdo.sh` | send one batch, then a fresh screendump |
|
||||
| `cbmenu.py` | poll until the main menu is up |
|
||||
| `cbload.sh` | the Load-dialog steps |
|
||||
| `cbfull.sh` | the whole path (see the caveat above) |
|
||||
|
||||
On the guest: `cbdeploy.ps1 -Tag <cfg>` (stop, install DLL + cfg, clear autosaves and logs, launch),
|
||||
`cbgrab.ps1 -Name <run>` (collect autosaves + logs + cfg into `C:\SOTS\cb\<run>\` and print sha256s).
|
||||
|
||||
Row geometry: `cbdeploy.ps1` deletes the three autosaves, so the Load dialog always lists the same
|
||||
**six** files at y = 262, 291, 320, 349, 378, 407. `ref-turn2` is row 4 (**y=349**), `turn1-state`
|
||||
is row 5 (**y=378**). Selecting a row expands a preview panel that moves every row below it, so
|
||||
select from a collapsed list or re-read the geometry from a screendump.
|
||||
6
verify/harness/cb/cbdo.sh
Executable file
6
verify/harness/cb/cbdo.sh
Executable file
|
|
@ -0,0 +1,6 @@
|
|||
#!/usr/bin/env bash
|
||||
# lane CB: send a click-helper batch, then capture the guest's screen. One command per click.
|
||||
cd /home/alex/sots-re
|
||||
./dumps/cbstep.sh "$1" >/dev/null 2>&1
|
||||
sleep "${2:-2}"
|
||||
uv run --with pillow python3 tools/vmshot.py --ssh --one 146 2>&1 | tail -1
|
||||
29
verify/harness/cb/cbfull.sh
Executable file
29
verify/harness/cb/cbfull.sh
Executable file
|
|
@ -0,0 +1,29 @@
|
|||
#!/usr/bin/env bash
|
||||
# lane CB: deploy -> launch -> load <row> -> End Turn -> collect. One click per call, and the
|
||||
# main menu is POLLED for, never slept for: the >60 s startup is on the board four times and it
|
||||
# cost this lane one run before the poller existed.
|
||||
set -e
|
||||
TAG=$1; ROW_Y=$2; NAME=$3
|
||||
cd /home/alex/sots-re
|
||||
V=re@192.168.10.146
|
||||
step() { ./dumps/cbstep.sh "$1" >/dev/null 2>&1; sleep "${2:-3}"; }
|
||||
|
||||
ssh $V "powershell -ExecutionPolicy Bypass -File C:\\SOTS\\cb\\cbdeploy.ps1 -Tag $TAG" | grep -E "^tag:|^build:|launched|NOT RUNNING"
|
||||
step 'key {ESC};;sleep 1500;;key {ESC};;sleep 1500;;key {ESC};;sleep 1500;;key {ESC};;sleep 1500' 2
|
||||
uv run --with pillow python3 dumps/cbmenu.py 300 | tail -2
|
||||
step 'fg;;sleep 500;;move 512 536;;sleep 400;;click 512 536;;sleep 2500' 3
|
||||
step 'click 512 536;;sleep 2500' 3
|
||||
step 'move 512 290;;sleep 400;;click 512 290;;sleep 1200;;click 512 290;;sleep 2000' 3
|
||||
step 'move 551 523;;sleep 400;;click 551 523;;sleep 3000' 4
|
||||
step "move 350 $ROW_Y;;sleep 400;;click 350 $ROW_Y;;sleep 2000" 3
|
||||
step 'move 682 624;;sleep 400;;click 682 624;;sleep 4000' 5
|
||||
step 'move 511 663;;sleep 400;;click 511 663;;sleep 3000' 3
|
||||
echo "waiting for load..."
|
||||
until ssh $V "Select-String -Path C:\\SOTS\\shim.aiorders.txt -Pattern 'aibatch' -Quiet" 2>/dev/null | grep -q True; do sleep 6; done
|
||||
sleep 25
|
||||
uv run --with pillow python3 tools/vmshot.py --ssh --one 146 | tail -1
|
||||
step 'move 100 714;;sleep 500;;click 100 714;;sleep 3000' 3
|
||||
echo "end turn issued, waiting for autosave..."
|
||||
until ssh $V "Test-Path 'C:\\SOTS\\SavedGames\\(Autosave).sav'" 2>/dev/null | grep -q True; do sleep 6; done
|
||||
sleep 20
|
||||
ssh $V "powershell -ExecutionPolicy Bypass -File C:\\SOTS\\cb\\cbgrab.ps1 -Name $NAME"
|
||||
11
verify/harness/cb/cbload.sh
Executable file
11
verify/harness/cb/cbload.sh
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env bash
|
||||
# lane CB: the load path, one click per step, verified by a FRESH screendump each time.
|
||||
# (The vmwatch wall caches frames for 5 s; a cached frame reads exactly like a click that did
|
||||
# nothing, and cost this lane four wrong diagnoses before it was spotted.)
|
||||
set -e
|
||||
ROW_Y=${1:-349}
|
||||
cd /home/alex/sots-re
|
||||
step() { ./dumps/cbstep.sh "$1" >/dev/null 2>&1; sleep "${2:-3}"; }
|
||||
step 'move 551 523;;sleep 400;;click 551 523;;sleep 3000' 4 # OK -> the saved-game list
|
||||
step "move 350 $ROW_Y;;sleep 400;;click 350 $ROW_Y;;sleep 2000" 3
|
||||
uv run --with pillow python3 tools/vmshot.py --ssh --one 146 2>&1 | tail -1
|
||||
31
verify/harness/cb/cbmenu.py
Normal file
31
verify/harness/cb/cbmenu.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Poll VM146's framebuffer until the main menu's red buttons are up. Never sleep-and-click:
|
||||
the >60 s startup has cost this campaign at least five wasted runs, and it is on the board four
|
||||
times. A run that clicks into the Kerberos intro reads exactly like a run whose clicks did nothing.
|
||||
"""
|
||||
import subprocess, sys, time, glob, os
|
||||
from PIL import Image
|
||||
|
||||
DEADLINE = float(sys.argv[1]) if len(sys.argv) > 1 else 240.0
|
||||
t0 = time.time()
|
||||
while time.time() - t0 < DEADLINE:
|
||||
subprocess.run(["uv", "run", "--with", "pillow", "python3", "tools/vmshot.py",
|
||||
"--ssh", "--one", "146"], capture_output=True, check=False)
|
||||
shots = sorted(glob.glob("dumps/vmshot/vm146-*.png"), key=os.path.getmtime)
|
||||
if shots:
|
||||
im = Image.open(shots[-1]).convert("RGB")
|
||||
# The button column: Profiles..Exit sit at x 455-570, y 405-695, and are a saturated red
|
||||
# only when the menu has actually rendered.
|
||||
red = 0
|
||||
for y in range(405, 695, 3):
|
||||
for x in range(455, 570, 3):
|
||||
r, g, b = im.getpixel((x, y))
|
||||
if r > 110 and r > g * 2 and r > b * 2:
|
||||
red += 1
|
||||
print(f"t+{time.time()-t0:5.0f}s red={red} {os.path.basename(shots[-1])}", flush=True)
|
||||
if red > 400:
|
||||
print("MENU UP")
|
||||
sys.exit(0)
|
||||
time.sleep(6)
|
||||
print("MENU NOT SEEN -- do not click")
|
||||
sys.exit(1)
|
||||
3
verify/harness/cb/cbstep.sh
Executable file
3
verify/harness/cb/cbstep.sh
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env bash
|
||||
# lane CB: one click-helper batch, lines joined with ';;'. Never sleep-and-click.
|
||||
ssh re@192.168.10.146 "powershell -ExecutionPolicy Bypass -File C:\\SOTS\\cb\\cbstep.ps1 -Cmds '$1'"
|
||||
BIN
verify/results/saves/cb-c3-turn1to2-autosave.sav
Normal file
BIN
verify/results/saves/cb-c3-turn1to2-autosave.sav
Normal file
Binary file not shown.
BIN
verify/results/saves/cb-c5a-turn1to2-pinned-autosave.sav
Normal file
BIN
verify/results/saves/cb-c5a-turn1to2-pinned-autosave.sav
Normal file
Binary file not shown.
BIN
verify/results/saves/cb-turn2to3-autosave.sav
Normal file
BIN
verify/results/saves/cb-turn2to3-autosave.sav
Normal file
Binary file not shown.
BIN
verify/results/saves/cb-turn2to3-endturn.sav
Normal file
BIN
verify/results/saves/cb-turn2to3-endturn.sav
Normal file
Binary file not shown.
64
verify/results/shim/aiorders/cb-c1-turn2to3.txt
Normal file
64
verify/results/shim/aiorders/cb-c1-turn2to3.txt
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
aiorders: out=C:\SOTS\shim.aiorders.txt probes=0 of 20
|
||||
aicfg words=32 deep=1 research=0 seed=log pins=0 detours=2
|
||||
aiorders: batch hook StrategySim::ApplyTurnCommandBatch rva=0x0048f9b0 va=00a6f9b0 create=MH_OK enable=MH_OK
|
||||
aiseed: StrategyApp::RunAI rva=0x004706f0 va=00a506f0 create=MH_OK enable=MH_OK
|
||||
airesearch: disabled (airesearch=off)
|
||||
---- aibatch seq=1 blocks=0x0113f2e0 n=1 stride=0x1b4 ----
|
||||
aiblk seq=1 blk=0/1 at=0x0113f2e0 pid=16 rate=1:0.25 target=0:18084612 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=1 blk=0 pid=16 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiprobe seq=1 none installed (aiprobes=off)
|
||||
aiseed call=1 netId=32 observed=0x9dfad635 used=0x9dfad635 pinned=0
|
||||
aiseed call=2 netId=496 observed=0xb482b2d8 used=0xb482b2d8 pinned=0
|
||||
aiseed call=3 netId=512 observed=0xfb81e993 used=0xfb81e993 pinned=0
|
||||
---- aibatch seq=2 blocks=0x1e07e090 n=8 stride=0x1b4 ----
|
||||
aiblk seq=2 blk=0/8 at=0x1e07e090 pid=16 rate=1:0.25 target=0:12677740 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=0 pid=16 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiblk seq=2 blk=1/8 at=0x1e07e244 pid=32 rate=1:0.8 target=0:863629896 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=1 pid=32 nonEmpty=6 sizes(1..27)=[ 0 0 1 0 1 0 0 1 0 1 0 0 0 2 0 0 0 0 0 0 0 0 1 0 0 0 0 ]
|
||||
ailist blk=1 pid=32 list=3 off=0x088 size=1
|
||||
aielem blk=1 pid=32 list=3 idx=0 node=0x3389a730 words=32 f0=0 f1=4.03574e-43 ints=[ 0 288 18 2 1607561319 -2013089536 60959416 60959428 60959440 60959452 60959464 60959476 1607823459 -2013089280 60962080 60962092 60962104 60962116 60962128 60962140 1607037055 -2147306752 864659344 864659344 60962248 60962260 60962272 60962284 1607299195 -2013088768 61020688 61020700 ] hex=[ 00000000 00000120 00000012 00000002 5fd17067 8802b100 03a22ab8 03a22ac4 03a22ad0 03a22adc 03a22ae8 03a22af4 5fd57063 8802b200 03a23520 03a2352c 03a23538 03a23544 03a23550 03a2355c 5fc9707f 8002b300 3389a790 3389a790 03a235c8 03a235d4 03a235e0 03a235ec 5fcd707b 8802b400 03a31a10 03a31a1c ]
|
||||
aivec blk=1 pid=32 list=3 idx=0 at=w6 first=0x03a22ab8 cap=6 count=3 ints=[ 1080347716 1065353216 0 ] hex=[ 4064cc44 3f800000 00000000 ]
|
||||
aivec blk=1 pid=32 list=3 idx=0 at=w9 first=0x03a22adc cap=6 count=3 ints=[ 1054682907 1065353216 13 ] hex=[ 3edd2f1b 3f800000 0000000d ]
|
||||
aivec blk=1 pid=32 list=3 idx=0 at=w14 first=0x03a23520 cap=6 count=3 ints=[ 1077960980 1065353216 0 ] hex=[ 40406114 3f800000 00000000 ]
|
||||
aivec blk=1 pid=32 list=3 idx=0 at=w17 first=0x03a23544 cap=6 count=3 ints=[ 1054682907 1065353216 13 ] hex=[ 3edd2f1b 3f800000 0000000d ]
|
||||
aivec blk=1 pid=32 list=3 idx=0 at=w24 first=0x03a235c8 cap=6 count=3 ints=[ 0 1065353216 3 ] hex=[ 00000000 3f800000 00000003 ]
|
||||
ailist blk=1 pid=32 list=5 off=0x0a0 size=1
|
||||
aielem blk=1 pid=32 list=5 idx=0 node=0x332c0bf8 words=32 f0=4.03574e-43 f1=0 ints=[ 288 0 1065353216 0 0 0 0 0 1420739850 -1946140928 828994168 828998200 828997816 828996472 828996664 828998392 828995128 828994360 0 0 1420084484 -1946140672 858907224 858907228 858907228 0 0 0 0 0 0 0 ] hex=[ 00000120 00000000 3f800000 00000000 00000000 00000000 00000000 00000000 54aec50a 8c003f00 31697278 31698238 316980b8 31697b78 31697c38 316982f8 31697638 31697338 00000000 00000000 54a4c504 8c004000 3331e258 3331e25c 3331e25c 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ]
|
||||
aivec blk=1 pid=32 list=5 idx=0 at=w13 first=0x31697b78 cap=480 count=48 ints=[ 12688796 860427400 1953066309 544367988 2699816 15 31 0 836953936 0 0 12724708 861254736 1 0 12724708 861255336 1 0 12724708 861254784 1 0 12724708 861255384 1 0 12724708 861255072 1 0 860866040 ] hex=[ 00c19d9c 33491488 74696d45 20726574 00293228 0000000f 0000001f 00000000 31e2e750 00000000 00000000 00c229e4 3355b450 00000001 00000000 00c229e4 3355b6a8 00000001 00000000 00c229e4 3355b480 00000001 00000000 00c229e4 3355b6d8 00000001 00000000 00c229e4 3355b5a0 00000001 00000000 334fc5f8 ] TRUNCATED
|
||||
aivec blk=1 pid=32 list=5 idx=0 at=w22 first=0x3331e258 cap=1 count=1 ints=[ 835963424 ] hex=[ 31d3ca20 ]
|
||||
ailist blk=1 pid=32 list=8 off=0x0c4 size=1
|
||||
aielem blk=1 pid=32 list=8 idx=0 node=0x0d701aa0 words=32 f0=4.76441e-44 f1=5.82172e-08 ints=[ 34 863636088 863636092 863636092 16776961 1 1097156566 -2013011712 862814000 862814000 288 34 863636104 863636108 863636108 0 1097746387 -2013011456 862814760 862814760 288 12423408 864659216 864659240 864659240 3503711 1097549804 -2147228928 225413376 225413376 34 0 ] hex=[ 00000022 337a0a78 337a0a7c 337a0a7c 00ffff01 00000001 416547d6 8803e100 336d7f30 336d7f30 00000120 00000022 337a0a88 337a0a8c 337a0a8c 00000000 416e47d3 8803e200 336d8228 336d8228 00000120 00bd90f0 3389a710 3389a728 3389a728 0035765f 416b47ec 8003e300 0d6f8900 0d6f8900 00000022 00000000 ]
|
||||
aivec blk=1 pid=32 list=8 idx=0 at=w1 first=0x337a0a78 cap=1 count=1 ints=[ 272 ] hex=[ 00000110 ]
|
||||
aivec blk=1 pid=32 list=8 idx=0 at=w12 first=0x337a0a88 cap=1 count=1 ints=[ 1728 ] hex=[ 000006c0 ]
|
||||
aivec blk=1 pid=32 list=8 idx=0 at=w22 first=0x3389a710 cap=6 count=6 ints=[ 12422480 1 2 862581960 1000000000 0 ] hex=[ 00bd8d50 00000001 00000002 3369f4c8 3b9aca00 00000000 ]
|
||||
ailist blk=1 pid=32 list=10 off=0x0dc size=1
|
||||
aielem blk=1 pid=32 list=10 idx=0 node=0x0d701ac8 words=32 f0=4.03574e-43 f1=4.76441e-44 ints=[ 288 34 863636104 863636108 863636108 0 1097746387 -2013011456 862814760 862814760 288 12423408 864659216 864659240 864659240 3503711 1097549804 -2147228928 225413376 225413376 34 0 0 0 16776961 1 1098139625 -2147228672 225413336 225413336 288 34 ] hex=[ 00000120 00000022 337a0a88 337a0a8c 337a0a8c 00000000 416e47d3 8803e200 336d8228 336d8228 00000120 00bd90f0 3389a710 3389a728 3389a728 0035765f 416b47ec 8003e300 0d6f8900 0d6f8900 00000022 00000000 00000000 00000000 00ffff01 00000001 417447e9 8003e400 0d6f88d8 0d6f88d8 00000120 00000022 ]
|
||||
aivec blk=1 pid=32 list=10 idx=0 at=w2 first=0x337a0a88 cap=1 count=1 ints=[ 1728 ] hex=[ 000006c0 ]
|
||||
aivec blk=1 pid=32 list=10 idx=0 at=w12 first=0x3389a710 cap=6 count=6 ints=[ 12422480 1 2 862581960 1000000000 0 ] hex=[ 00bd8d50 00000001 00000002 3369f4c8 3b9aca00 00000000 ]
|
||||
ailist blk=1 pid=32 list=14 off=0x10c size=2
|
||||
aielem blk=1 pid=32 list=14 idx=0 node=0x3389a630 words=32 f0=4.76441e-44 f1=0 ints=[ 34 0 18070017 862581640 1609658439 -2013091338 60966604 60966592 60966580 60966568 60966556 60966544 1609920579 -1945982464 863188904 864658992 34 1 18070017 257 1609134175 -2013091072 60963160 60963172 60963184 60963196 60963208 60963220 1609396315 -2013090816 60972448 60972460 ] hex=[ 00000022 00000000 0113ba01 3369f388 5ff17047 8802a9f6 03a246cc 03a246c0 03a246b4 03a246a8 03a2469c 03a24690 5ff57043 8c02aa00 337337a8 3389a630 00000022 00000001 0113ba01 00000101 5fe9705f 8802ab00 03a23958 03a23964 03a23970 03a2397c 03a23988 03a23994 5fed705b 8802ac00 03a25da0 03a25dac ]
|
||||
aivec blk=1 pid=32 list=14 idx=0 at=w22 first=0x03a23958 cap=6 count=3 ints=[ 1070646664 1065353216 0 ] hex=[ 3fd0c588 3f800000 00000000 ]
|
||||
aivec blk=1 pid=32 list=14 idx=0 at=w25 first=0x03a2397c cap=6 count=3 ints=[ 1054682907 1065353216 13 ] hex=[ 3edd2f1b 3f800000 0000000d ]
|
||||
aielem blk=1 pid=32 list=14 idx=1 node=0x3389a670 words=32 f0=4.76441e-44 f1=1.4013e-45 ints=[ 34 1 18070017 257 1609134175 -2013091072 60963160 60963172 60963184 60963196 60963208 60963220 1609396315 -2013090816 60972448 60972460 60972472 60972484 60972496 60972508 1608609879 -2013090560 60962008 60962020 60962032 60962044 60962056 60962068 1608872019 -2013090304 60961936 60961948 ] hex=[ 00000022 00000001 0113ba01 00000101 5fe9705f 8802ab00 03a23958 03a23964 03a23970 03a2397c 03a23988 03a23994 5fed705b 8802ac00 03a25da0 03a25dac 03a25db8 03a25dc4 03a25dd0 03a25ddc 5fe17057 8802ad00 03a234d8 03a234e4 03a234f0 03a234fc 03a23508 03a23514 5fe57053 8802ae00 03a23490 03a2349c ]
|
||||
aivec blk=1 pid=32 list=14 idx=1 at=w6 first=0x03a23958 cap=6 count=3 ints=[ 1070646664 1065353216 0 ] hex=[ 3fd0c588 3f800000 00000000 ]
|
||||
aivec blk=1 pid=32 list=14 idx=1 at=w9 first=0x03a2397c cap=6 count=3 ints=[ 1054682907 1065353216 13 ] hex=[ 3edd2f1b 3f800000 0000000d ]
|
||||
aivec blk=1 pid=32 list=14 idx=1 at=w14 first=0x03a25da0 cap=6 count=3 ints=[ 1082130432 1065353216 0 ] hex=[ 40800000 3f800000 00000000 ]
|
||||
aivec blk=1 pid=32 list=14 idx=1 at=w17 first=0x03a25dc4 cap=6 count=3 ints=[ 0 1065353216 3 ] hex=[ 00000000 3f800000 00000003 ]
|
||||
aivec blk=1 pid=32 list=14 idx=1 at=w22 first=0x03a234d8 cap=6 count=3 ints=[ 1082130432 1065353216 0 ] hex=[ 40800000 3f800000 00000000 ]
|
||||
aivec blk=1 pid=32 list=14 idx=1 at=w25 first=0x03a234fc cap=6 count=3 ints=[ 0 1065353216 3 ] hex=[ 00000000 3f800000 00000003 ]
|
||||
ailist blk=1 pid=32 list=23 off=0x178 size=1
|
||||
aielem blk=1 pid=32 list=23 idx=0 node=0x0d701af0 words=32 f0=4.03574e-43 f1=1.74089e-38 ints=[ 288 12423408 864659216 864659240 864659240 3503711 1097549804 -2147228928 225413376 225413376 34 0 0 0 16776961 1 1098139625 -2147228672 225413336 225413336 288 34 0 0 0 1 1097943010 -2147228416 225412616 225412616 288 12329660 ] hex=[ 00000120 00bd90f0 3389a710 3389a728 3389a728 0035765f 416b47ec 8003e300 0d6f8900 0d6f8900 00000022 00000000 00000000 00000000 00ffff01 00000001 417447e9 8003e400 0d6f88d8 0d6f88d8 00000120 00000022 00000000 00000000 00000000 00000001 417147e2 8003e500 0d6f8608 0d6f8608 00000120 00bc22bc ]
|
||||
aivec blk=1 pid=32 list=23 idx=0 at=w2 first=0x3389a710 cap=6 count=6 ints=[ 12422480 1 2 862581960 1000000000 0 ] hex=[ 00bd8d50 00000001 00000002 3369f4c8 3b9aca00 00000000 ]
|
||||
aiblk seq=2 blk=2/8 at=0x1e07e3f8 pid=496 rate=1:0.8 target=0:-2147480387 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=2 pid=496 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiblk seq=2 blk=3/8 at=0x1e07e5ac pid=512 rate=1:0.8 target=0:0 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=3 pid=512 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiblk seq=2 blk=4/8 at=0x1e07e760 pid=0 rate=0:3.98302e+33 target=0:2000969918 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=4 pid=0 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiblk seq=2 blk=5/8 at=0x1e07e914 pid=0 rate=0:3.98302e+33 target=0:2000969918 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=5 pid=0 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiblk seq=2 blk=6/8 at=0x1e07eac8 pid=0 rate=0:3.98302e+33 target=0:2000969918 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=6 pid=0 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiblk seq=2 blk=7/8 at=0x1e07ec7c pid=0 rate=0:3.98302e+33 target=0:2000969918 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=7 pid=0 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiprobe seq=2 none installed (aiprobes=off)
|
||||
43
verify/results/shim/aiorders/cb-c3-turn1to2-run1.txt
Normal file
43
verify/results/shim/aiorders/cb-c3-turn1to2-run1.txt
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
aiorders: out=C:\SOTS\shim.aiorders.txt probes=0 of 20
|
||||
aicfg words=32 deep=1 research=0 seed=log pins=0 detours=2
|
||||
aiorders: batch hook StrategySim::ApplyTurnCommandBatch rva=0x0048f9b0 va=00a6f9b0 create=MH_OK enable=MH_OK
|
||||
aiseed: StrategyApp::RunAI rva=0x004706f0 va=00a506f0 create=MH_OK enable=MH_OK
|
||||
airesearch: disabled (airesearch=off)
|
||||
---- aibatch seq=1 blocks=0x004ff024 n=1 stride=0x1b4 ----
|
||||
aiblk seq=1 blk=0/1 at=0x004ff024 pid=16 rate=1:0.25 target=0:5238856 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=1 blk=0 pid=16 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiprobe seq=1 none installed (aiprobes=off)
|
||||
aiseed call=1 netId=32 observed=0xe70a4703 used=0xe70a4703 pinned=0
|
||||
aiseed call=2 netId=496 observed=0x0c63ca36 used=0x0c63ca36 pinned=0
|
||||
aiseed call=3 netId=512 observed=0x372be4df used=0x372be4df pinned=0
|
||||
---- aibatch seq=2 blocks=0x1db24e78 n=8 stride=0x1b4 ----
|
||||
aiblk seq=2 blk=0/8 at=0x1db24e78 pid=16 rate=1:0.25 target=0:0 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=0 pid=16 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiblk seq=2 blk=1/8 at=0x1db2502c pid=32 rate=1:0.8 target=1:144 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=1 pid=32 nonEmpty=4 sizes(1..27)=[ 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 ]
|
||||
ailist blk=1 pid=32 list=1 off=0x070 size=1
|
||||
aielem blk=1 pid=32 list=1 idx=0 node=0x345589a8 words=32 f0=1.74428e-38 f1=1.19209e-07 ints=[ 12447588 872415233 1869508424 1632378994 6644590 1 11 15 0 2 44 875531920 875532124 875532124 1000000000 0 0 0 3 2 41 867945912 867945980 867945980 4 0 0 0 12329660 2 46 875252112 ] hex=[ 00bdef64 34000001 6f6e6f48 614c2072 0065636e 00000001 0000000b 0000000f 00000000 00000002 0000002c 342f8e90 342f8f5c 342f8f5c 3b9aca00 00000000 00000000 00000000 00000003 00000002 00000029 33bbcdb8 33bbcdfc 33bbcdfc 00000004 00000000 00000000 00000000 00bc22bc 00000002 0000002e 342b4990 ]
|
||||
aivec blk=1 pid=32 list=1 idx=0 at=w11 first=0x342f8e90 cap=51 count=51 ints=[ 876649744 0 0 0 24 31 0 8 0 0 0 0 0 0 15 0 0 876649904 0 0 0 24 31 0 8 0 0 0 0 0 0 15 ] hex=[ 34409d10 00000000 00000000 00000000 00000018 0000001f 00000000 00000008 00000000 00000000 00000000 00000000 00000000 00000000 0000000f 00000000 00000000 34409db0 00000000 00000000 00000000 00000018 0000001f 00000000 00000008 00000000 00000000 00000000 00000000 00000000 00000000 0000000f ] TRUNCATED
|
||||
aivec blk=1 pid=32 list=1 idx=0 at=w21 first=0x33bbcdb8 cap=17 count=17 ints=[ 876650064 0 0 0 24 31 0 8 0 0 0 0 0 0 15 0 0 ] hex=[ 34409e50 00000000 00000000 00000000 00000018 0000001f 00000000 00000008 00000000 00000000 00000000 00000000 00000000 00000000 0000000f 00000000 00000000 ]
|
||||
aistr blk=1 pid=32 list=1 idx=0 at=w2 sso=1 len=11 text="Honor Lance"
|
||||
ailist blk=1 pid=32 list=3 off=0x088 size=1
|
||||
aielem blk=1 pid=32 list=3 idx=0 node=0x345f1de0 words=32 f0=0 f1=4.03574e-43 ints=[ 0 288 18 1 1818779688 -2013232640 57547244 57547232 57547220 57547208 57547196 57547184 1819566164 -2013232384 57547676 57547664 57547652 57547640 57547628 57547616 1819304016 -2013232128 12422480 1 2 876301736 1000000000 0 1820090460 -2013231872 57529316 57529304 ] hex=[ 00000000 00000120 00000012 00000001 6c686028 88008200 036e19ec 036e19e0 036e19d4 036e19c8 036e19bc 036e19b0 6c746054 88008300 036e1b9c 036e1b90 036e1b84 036e1b78 036e1b6c 036e1b60 6c706050 88008400 00bd8d50 00000001 00000002 343b4da8 3b9aca00 00000000 6c7c605c 88008500 036dd3e4 036dd3d8 ]
|
||||
ailist blk=1 pid=32 list=5 off=0x0a0 size=1
|
||||
aielem blk=1 pid=32 list=5 idx=0 node=0x33e89418 words=32 f0=4.03574e-43 f1=0 ints=[ 288 0 1065353216 0 0 0 0 0 1849004319 -1946151680 872880352 65297500 873273800 873273888 873273888 0 0 0 -1 0 1849659673 -1946151424 842600368 842604976 842603632 842605168 842601328 842605744 842600560 842600944 0 0 ] hex=[ 00000120 00000000 3f800000 00000000 00000000 00000000 00000000 00000000 6e35911f 8c001500 340718e0 03e45c5c 340d19c8 340d1a20 340d1a20 00000000 00000000 00000000 ffffffff 00000000 6e3f9119 8c001600 32390fb0 323921b0 32391c70 32392270 32391370 323924b0 32391070 323911f0 00000000 00000000 ]
|
||||
aivec blk=1 pid=32 list=5 idx=0 at=w12 first=0x340d19c8 cap=22 count=22 ints=[ 0 0 0 0 0 15 0 1280462679 68 0 0 5 15 0 -292270533 873432784 873432848 873432848 0 64 6 1 ] hex=[ 00000000 00000000 00000000 00000000 00000000 0000000f 00000000 4c524f57 00000044 00000000 00000000 00000005 0000000f 00000000 ee944e3b 340f86d0 340f8710 340f8710 00000000 00000040 00000006 00000001 ]
|
||||
ailist blk=1 pid=32 list=23 off=0x178 size=1
|
||||
aielem blk=1 pid=32 list=23 idx=0 node=0x34409a68 words=32 f0=4.03574e-43 f1=1.74089e-38 ints=[ 288 12423408 878648896 878648920 878648920 -1879506943 1687523526 -2013125459 1885431127 796094063 1600938338 1937072487 1702309491 1852797025 0 -1 1687195841 -2013125140 12393064 498112880 31 0 12393064 498114368 29 0 1687916748 -2013124914 1885431127 796094063 1600938338 1937072487 ] hex=[ 00000120 00bd90f0 345f1e40 345f1e58 345f1e58 8ff90001 649590c6 880224ad 70616557 2f736e6f 5f6c6162 73756167 65772e73 6e6f7061 00000000 ffffffff 649090c1 880225ec 00bd1a68 1db09970 0000001f 00000000 00bd1a68 1db09f40 0000001d 00000000 649b90cc 880226ce 70616557 2f736e6f 5f6c6162 73756167 ]
|
||||
aivec blk=1 pid=32 list=23 idx=0 at=w2 first=0x345f1e40 cap=6 count=6 ints=[ 12422480 1 2 876301736 1000000000 0 ] hex=[ 00bd8d50 00000001 00000002 343b4da8 3b9aca00 00000000 ]
|
||||
aiblk seq=2 blk=2/8 at=0x1db251e0 pid=496 rate=1:0.8 target=1:90 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=2 pid=496 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiblk seq=2 blk=3/8 at=0x1db25394 pid=512 rate=1:0.8 target=1:282 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=3 pid=512 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiblk seq=2 blk=4/8 at=0x1db25548 pid=0 rate=0:8.96831e-44 target=0:0 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=4 pid=0 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiblk seq=2 blk=5/8 at=0x1db256fc pid=0 rate=0:8.96831e-44 target=0:0 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=5 pid=0 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiblk seq=2 blk=6/8 at=0x1db258b0 pid=0 rate=0:8.96831e-44 target=0:0 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=6 pid=0 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiblk seq=2 blk=7/8 at=0x1db25a64 pid=0 rate=0:8.96831e-44 target=0:0 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=7 pid=0 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiprobe seq=2 none installed (aiprobes=off)
|
||||
49
verify/results/shim/aiorders/cb-c5a-turn1to2-pinned.txt
Normal file
49
verify/results/shim/aiorders/cb-c5a-turn1to2-pinned.txt
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
aiorders: out=C:\SOTS\shim.aiorders.txt probes=0 of 20
|
||||
aicfg words=32 deep=1 research=0 seed=pin pins=3 detours=2
|
||||
aiseed pin netId=32 value=0xe70a4703
|
||||
aiseed pin netId=496 value=0x0c63ca36
|
||||
aiseed pin netId=512 value=0x372be4df
|
||||
aiorders: batch hook StrategySim::ApplyTurnCommandBatch rva=0x0048f9b0 va=00a6f9b0 create=MH_OK enable=MH_OK
|
||||
aiseed: StrategyApp::RunAI rva=0x004706f0 va=00a506f0 create=MH_OK enable=MH_OK
|
||||
airesearch: disabled (airesearch=off)
|
||||
---- aibatch seq=1 blocks=0x0113f374 n=1 stride=0x1b4 ----
|
||||
aiblk seq=1 blk=0/1 at=0x0113f374 pid=16 rate=1:0.25 target=0:18084760 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=1 blk=0 pid=16 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiprobe seq=1 none installed (aiprobes=off)
|
||||
aiseed call=1 netId=32 observed=0x227235b9 used=0xe70a4703 pinned=1
|
||||
aiseed call=2 netId=496 observed=0x762d125e used=0x0c63ca36 pinned=1
|
||||
aiseed call=3 netId=512 observed=0x9d77d4e6 used=0x372be4df pinned=1
|
||||
---- aibatch seq=2 blocks=0x0d897e48 n=8 stride=0x1b4 ----
|
||||
aiblk seq=2 blk=0/8 at=0x0d897e48 pid=16 rate=1:0.25 target=0:-545755417 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=0 pid=16 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiblk seq=2 blk=1/8 at=0x0d897ffc pid=32 rate=1:0.8 target=1:144 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=1 pid=32 nonEmpty=4 sizes(1..27)=[ 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 ]
|
||||
ailist blk=1 pid=32 list=1 off=0x070 size=1
|
||||
aielem blk=1 pid=32 list=1 idx=0 node=0x339251e0 words=32 f0=1.74428e-38 f1=3.9443e-31 ints=[ 12447588 218103809 1869508424 1632378994 6644590 224058520 11 15 224067592 2 44 862213304 862213508 862213508 223751472 0 0 0 223754712 2 41 854718416 854718484 854718484 66761704 0 0 0 224096720 2 46 862066456 ] hex=[ 00bdef64 0d000001 6f6e6f48 614c2072 0065636e 0d5adc98 0000000b 0000000f 0d5b0008 00000002 0000002c 336454b8 33645584 33645584 0d562d30 00000000 00000000 00000000 0d5639d8 00000002 00000029 32f1f7d0 32f1f814 32f1f814 03fab3e8 00000000 00000000 00000000 0d5b71d0 00000002 0000002e 33621718 ]
|
||||
aivec blk=1 pid=32 list=1 idx=0 at=w11 first=0x336454b8 cap=51 count=51 ints=[ 863858608 0 0 0 24 31 0 8 0 0 0 0 0 0 15 0 0 863858328 0 0 0 24 31 0 8 0 0 0 0 0 0 15 ] hex=[ 337d6fb0 00000000 00000000 00000000 00000018 0000001f 00000000 00000008 00000000 00000000 00000000 00000000 00000000 00000000 0000000f 00000000 00000000 337d6e98 00000000 00000000 00000000 00000018 0000001f 00000000 00000008 00000000 00000000 00000000 00000000 00000000 00000000 0000000f ] TRUNCATED
|
||||
aivec blk=1 pid=32 list=1 idx=0 at=w21 first=0x32f1f7d0 cap=17 count=17 ints=[ 863858648 1 0 0 24 31 12329660 8 0 0 0 0 12329660 0 15 0 0 ] hex=[ 337d6fd8 00000001 00000000 00000000 00000018 0000001f 00bc22bc 00000008 00000000 00000000 00000000 00000000 00bc22bc 00000000 0000000f 00000000 00000000 ]
|
||||
aistr blk=1 pid=32 list=1 idx=0 at=w2 sso=1 len=11 text="Honor Lance"
|
||||
ailist blk=1 pid=32 list=3 off=0x088 size=1
|
||||
aielem blk=1 pid=32 list=3 idx=0 node=0x33834e10 words=32 f0=0 f1=4.03574e-43 ints=[ 0 288 18 1 1268701835 -2012964784 12422480 1 2 861588928 500000000 0 1267915399 -2147182336 864243280 864243280 228 201 234 103 1268177539 -2012964352 59224440 59224452 59224464 59224476 59224488 59224500 1267391135 -2147181600 864243056 864243056 ] hex=[ 00000000 00000120 00000012 00000001 4b9eda8b 88049850 00bd8d50 00000001 00000002 335acdc0 1dcd6500 00000000 4b92da87 80049900 33834e50 33834e50 000000e4 000000c9 000000ea 00000067 4b96da83 88049a00 0387b178 0387b184 0387b190 0387b19c 0387b1a8 0387b1b4 4b8ada9f 80049be0 33834d70 33834d70 ]
|
||||
aivec blk=1 pid=32 list=3 idx=0 at=w22 first=0x0387b178 cap=6 count=3 ints=[ 1082130432 1065353216 0 ] hex=[ 40800000 3f800000 00000000 ]
|
||||
aivec blk=1 pid=32 list=3 idx=0 at=w25 first=0x0387b19c cap=6 count=3 ints=[ 0 1065353216 3 ] hex=[ 00000000 3f800000 00000003 ]
|
||||
ailist blk=1 pid=32 list=5 off=0x0a0 size=1
|
||||
aielem blk=1 pid=32 list=5 idx=0 node=0x331b3a68 words=32 f0=4.03574e-43 f1=0 ints=[ 288 0 1065353216 0 0 0 0 0 1506268188 -1946148608 341479488 861573040 861573044 861573044 1230335333 0 0 0 7562340 0 1507709974 -1946148352 226986624 857423688 226986624 16 863661152 863756144 1 863661152 863633408 32 ] hex=[ 00000120 00000000 3f800000 00000000 00000000 00000000 00000000 00000000 59c7d41c 8c002100 145a9040 335a8fb0 335a8fb4 335a8fb4 49556d65 00000000 00000000 00000000 00736464 00000000 59ddd416 8c002200 0d878a80 331b3f48 0d878a80 00000010 337a6c60 337bdf70 00000001 337a6c60 337a0000 00000020 ]
|
||||
aivec blk=1 pid=32 list=5 idx=0 at=w11 first=0x335a8fb0 cap=1 count=1 ints=[ 861598792 ] hex=[ 335af448 ]
|
||||
ailist blk=1 pid=32 list=23 off=0x178 size=1
|
||||
aielem blk=1 pid=32 list=23 idx=0 node=0x337d7230 words=32 f0=4.03574e-43 f1=1.74089e-38 ints=[ 288 12423408 864242928 864242952 864242952 -1111687167 1396251908 -2147350997 863859288 863859288 860665816 863084720 863085040 863085328 16776961 -1414856703 1397103873 -2013132801 0 0 0 0 0 0 0 0 1396907290 -2147350436 1885431127 796094063 1600938338 1937072487 ] hex=[ 00000120 00bd90f0 33834cf0 33834d08 33834d08 bdbd0001 53391d04 8002062b 337d7258 337d7258 334cb7d8 3371a0b0 3371a1f0 3371a310 00ffff01 abab0001 53461d01 880207ff 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 53431d1a 8002085c 70616557 2f736e6f 5f6c6162 73756167 ]
|
||||
aivec blk=1 pid=32 list=23 idx=0 at=w2 first=0x33834cf0 cap=6 count=6 ints=[ 12422480 1 2 245 1000000000 0 ] hex=[ 00bd8d50 00000001 00000002 000000f5 3b9aca00 00000000 ]
|
||||
aivec blk=1 pid=32 list=23 idx=0 at=w11 first=0x3371a0b0 cap=152 count=80 ints=[ 863084720 863084720 863084944 432 -65535 -65281 1169459031 -2012797953 863084752 863084752 863084752 112 863830017 863830273 1169196883 -2012797697 863084784 863084784 863084944 448 863830017 863863568 1169983343 -1945688577 863084816 863084816 16 1 1144922112 1144922112 1169721195 -2012797185 ] hex=[ 3371a0b0 3371a0b0 3371a190 000001b0 ffff0001 ffff00ff 45b48757 880723ff 3371a0d0 3371a0d0 3371a0d0 00000070 337d0001 337d0101 45b08753 880724ff 3371a0f0 3371a0f0 3371a190 000001c0 337d0001 337d8310 45bc876f 8c0725ff 3371a110 3371a110 00000010 00000001 443e2000 443e2000 45b8876b 880726ff ] TRUNCATED
|
||||
aiblk seq=2 blk=2/8 at=0x0d8981b0 pid=496 rate=1:0.8 target=1:90 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=2 pid=496 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiblk seq=2 blk=3/8 at=0x0d898364 pid=512 rate=1:0.8 target=1:282 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=3 pid=512 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiblk seq=2 blk=4/8 at=0x0d898518 pid=0 rate=0:8.96831e-44 target=0:0 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=4 pid=0 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiblk seq=2 blk=5/8 at=0x0d8986cc pid=0 rate=0:8.96831e-44 target=0:0 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=5 pid=0 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiblk seq=2 blk=6/8 at=0x0d898880 pid=0 rate=0:8.96831e-44 target=0:0 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=6 pid=0 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiblk seq=2 blk=7/8 at=0x0d898a34 pid=0 rate=0:8.96831e-44 target=0:0 boost=0:0,0 g4=0:0,0 f3=0:1,1,1 civ=0
|
||||
ailists seq=2 blk=7 pid=0 nonEmpty=0 sizes(1..27)=[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
|
||||
aiprobe seq=2 none installed (aiprobes=off)
|
||||
1053
verify/results/turncommands/cb-turn1to2-pinned.json
Normal file
1053
verify/results/turncommands/cb-turn1to2-pinned.json
Normal file
File diff suppressed because it is too large
Load diff
38
verify/results/turncommands/cb-turn1to2-pinned.tcb
Normal file
38
verify/results/turncommands/cb-turn1to2-pinned.tcb
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
tcb 1
|
||||
meta source cb-c5a-turn1to2-pinned.txt
|
||||
meta input turn1-state.sav
|
||||
meta input_sha256 a3f9dc4b49fc669c814b09b87a9c6795de21bac80a1c7bfe3901b8e239fa36cc
|
||||
meta output (Autosave).sav 66746 d59bb9f2fd0eb5358c35954fbf2fcb70d06bafbba2560e0fa5d3f906bfb159d8
|
||||
meta control c3-turn1to2-run1 (UNPINNED, a different process with entirely different natural seeds); this run pinned C3's seeds and reproduced C3's autosave byte-for-byte
|
||||
meta lane CB capture_version 1 build cb2-20260908T2251Z guest VM146
|
||||
meta extension vN:a,b -- a vector whose contents ARE known; bare vN still means unknown and must still be refused
|
||||
meta batch seq=2 n=8
|
||||
seed 32 0xe70a4703 pinned
|
||||
seed 496 0x0c63ca36 pinned
|
||||
seed 512 0x372be4df pinned
|
||||
block 0 16
|
||||
gate 0 rate 0.25
|
||||
block 1 32
|
||||
gate 1 rate 0.8
|
||||
gate 1 target 144
|
||||
list 1 1 1
|
||||
elem 1 1 0 ?
|
||||
meta string 1 1 0 w2 "Honor Lance"
|
||||
list 1 3 1
|
||||
elem 1 3 0 i1 i18 i288 i0
|
||||
list 1 5 1
|
||||
elem 1 5 0 i288 ? ? ? ? ? ? ?
|
||||
meta rates 1 5 0 memory-order-f32 0.0,1.0,0.0,0.0,0.0,0.0,0.0
|
||||
meta rates-note memory member 1 is wire member SRsc (lane RB, from a replay that regressed two leaves when the memory order was used as the wire order); the other six memory members are UNREAD. Values are certain, positions are not.
|
||||
list 1 23 1
|
||||
elem 1 23 0 i288 ? v6:12422480,1,2,245,1000000000,0
|
||||
block 2 496
|
||||
gate 2 rate 0.8
|
||||
gate 2 target 90
|
||||
block 3 512
|
||||
gate 3 rate 0.8
|
||||
gate 3 target 282
|
||||
block 4 0
|
||||
block 5 0
|
||||
block 6 0
|
||||
block 7 0
|
||||
1008
verify/results/turncommands/cb-turn1to2-run1.json
Normal file
1008
verify/results/turncommands/cb-turn1to2-run1.json
Normal file
File diff suppressed because it is too large
Load diff
38
verify/results/turncommands/cb-turn1to2-run1.tcb
Normal file
38
verify/results/turncommands/cb-turn1to2-run1.tcb
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
tcb 1
|
||||
meta source cb-c3-turn1to2-run1.txt
|
||||
meta input turn1-state.sav
|
||||
meta input_sha256 a3f9dc4b49fc669c814b09b87a9c6795de21bac80a1c7bfe3901b8e239fa36cc
|
||||
meta output (Autosave).sav 66746 d59bb9f2fd0eb5358c35954fbf2fcb70d06bafbba2560e0fa5d3f906bfb159d8
|
||||
meta control NONE -- this workload has an outcome set of size k>1 and no single hooks=off run is a control for it.
|
||||
meta lane CB capture_version 1 build cb2-20260908T2251Z guest VM146
|
||||
meta extension vN:a,b -- a vector whose contents ARE known; bare vN still means unknown and must still be refused
|
||||
meta batch seq=2 n=8
|
||||
seed 32 0xe70a4703
|
||||
seed 496 0x0c63ca36
|
||||
seed 512 0x372be4df
|
||||
block 0 16
|
||||
gate 0 rate 0.25
|
||||
block 1 32
|
||||
gate 1 rate 0.8
|
||||
gate 1 target 144
|
||||
list 1 1 1
|
||||
elem 1 1 0 ?
|
||||
meta string 1 1 0 w2 "Honor Lance"
|
||||
list 1 3 1
|
||||
elem 1 3 0 i1 i18 i288 i0
|
||||
list 1 5 1
|
||||
elem 1 5 0 i288 ? ? ? ? ? ? ?
|
||||
meta rates 1 5 0 memory-order-f32 0.0,1.0,0.0,0.0,0.0,0.0,0.0
|
||||
meta rates-note memory member 1 is wire member SRsc (lane RB, from a replay that regressed two leaves when the memory order was used as the wire order); the other six memory members are UNREAD. Values are certain, positions are not.
|
||||
list 1 23 1
|
||||
elem 1 23 0 i288 ? v6:12422480,1,2,876301736,1000000000,0
|
||||
block 2 496
|
||||
gate 2 rate 0.8
|
||||
gate 2 target 90
|
||||
block 3 512
|
||||
gate 3 rate 0.8
|
||||
gate 3 target 282
|
||||
block 4 0
|
||||
block 5 0
|
||||
block 6 0
|
||||
block 7 0
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
"lane": "CB",
|
||||
"guest": "VM146",
|
||||
"build": "cb2-20260908T2251Z",
|
||||
"captured_utc": "2026-09-08T23:02:07+00:00",
|
||||
"captured_utc": "2026-09-08T23:09:13+00:00",
|
||||
"instrument": {
|
||||
"words": "32",
|
||||
"deep": "1",
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
"detours": "2"
|
||||
},
|
||||
"workload": "ref-turn2.sav (= turn2-state.sav) + one End Turn -> turn3-state.sav",
|
||||
"note": "THE CANONICAL PAIR, deterministic and oracle-hashed. This run reproduced BOTH oracle hashes with the instrument installed, so the stream and the autosave come from the same run and the instrument did not change the turn it recorded. (Autosave).sav is byte-identical to turn3-state.sav.",
|
||||
"note": "THE CANONICAL PAIR, deterministic and oracle-hashed. This run reproduced BOTH oracle hashes with the instrument installed. (Autosave).sav is byte-identical to turn3-state.sav.",
|
||||
"binding": {
|
||||
"input": {
|
||||
"file": "turn2-state.sav",
|
||||
|
|
@ -456,24 +456,28 @@
|
|||
"decoded": {
|
||||
"record": "SystemRates",
|
||||
"systemId": 288,
|
||||
"ship": 0.0,
|
||||
"terraform": 1.0,
|
||||
"sciences": 0.0,
|
||||
"trade": 0.0,
|
||||
"infrastructure": 0.0,
|
||||
"overharvest": 0.0,
|
||||
"noRate": 0,
|
||||
"wire": [
|
||||
288,
|
||||
"wire": null,
|
||||
"record_words": 8,
|
||||
"rates_memory_order_u32": [
|
||||
0,
|
||||
1065353216,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"rates_memory_order_f32": [
|
||||
0.0,
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0
|
||||
0.0
|
||||
],
|
||||
"record_words": 8
|
||||
"wire_order_unread": true,
|
||||
"note": "memory member 1 is wire member SRsc (lane RB, from a replay that regressed two leaves when the memory order was used as the wire order); the other six memory members are UNREAD. Values are certain, positions are not."
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@ gate 1 rate 0.8
|
|||
list 1 3 1
|
||||
elem 1 3 0 i2 i18 i288 i0
|
||||
list 1 5 1
|
||||
elem 1 5 0 i288 f0.0 f1.0 f0.0 f0.0 f0.0 f0.0 i0
|
||||
elem 1 5 0 i288 ? ? ? ? ? ? ?
|
||||
meta rates 1 5 0 memory-order-f32 0.0,1.0,0.0,0.0,0.0,0.0,0.0
|
||||
meta rates-note memory member 1 is wire member SRsc (lane RB, from a replay that regressed two leaves when the memory order was used as the wire order); the other six memory members are UNREAD. Values are certain, positions are not.
|
||||
list 1 8 1
|
||||
elem 1 8 0 i34 v1:272
|
||||
list 1 10 1
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue