From 91a04377d46a54f256ba90f16f7f925c62a8ae2f Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 8 Sep 2026 16:36:45 -0400 Subject: [PATCH] lane PL: decompose the /Sim/players residual by mechanism; the bankruptcy protection factor is a float32 findings/subsystems/players-residual.md is the deliverable: every one of the 54 leaves on the reference pair and the 24 on pair 2 attributed to a named mechanism, with the rung split. 53 of 54 are pass-through -- the block is unmodelled, not mismodelled, and only player 32's Sav is a number we compute and get wrong. Three corrections to the record: - T31's self-check compared its post-turn result against the pre-turn stored value, so its 6-of-8 covered only the players whose limit never moves. - the AI difficulty column IS recoverable from the save, by recomputing BnkEl under both columns against the value the save carries; 1 AI + 1 non-AI on all eleven corpus saves. - BANKRUPTCY_PROTECTION_LIMIT_FACTOR is read fmul dword ptr, so it is a float32 in the image; the decimal disagrees at every max income divisible by ten and the corpus' seven records land where the two agree (rule 23). formula-gaps Q1 addendum + ghidra/addresses.d/lane-pl.json (3 data entries, fragment validated to a scratch path, no duplicate names). verify/results/standalone/{status.json,report.txt} refreshed from a build of main aabd8a3: the committed copy was stale at 131/55, the real number is 128/54. T34 RecordObservedDesigns is now readable off the corpus and is NOT an intel pass: a design's creator registers the design in its own odes, its weapons in owep, and re-stamps otnL on its techs in otch -- odes on build, otch on creation. Both are hypotheses until a save exists where a player observes someone else's design. Status stays open and is flagged as NOT identifiable: eighteen fields of the player record split the roster the same way and only two saves carry a non-zero value. The probe is an entry hook on W2's writer. --- findings/subsystems/formula-gaps.md | 38 ++++++++ findings/subsystems/players-residual.md | 118 ++++++++++++++++++++++++ ghidra/addresses.d/lane-pl.json | 28 ++++++ verify/results/standalone/report.txt | 24 +++-- verify/results/standalone/status.json | 88 ++++++++++-------- 5 files changed, 246 insertions(+), 50 deletions(-) create mode 100644 findings/subsystems/players-residual.md create mode 100644 ghidra/addresses.d/lane-pl.json diff --git a/findings/subsystems/formula-gaps.md b/findings/subsystems/formula-gaps.md index c1e5e80..792f63d 100644 --- a/findings/subsystems/formula-gaps.md +++ b/findings/subsystems/formula-gaps.md @@ -25,6 +25,44 @@ level changes (any change, 1↔2 included, resets it), and actions start the fol Call sequence: `OnAllCombatDone_Tail` → … → `ProcessBankruptcy` → (later in the tail) `UpdateBankruptcyLimits`, so the limits used by a turn's bankruptcy check are the ones computed at the end of the previous turn (and on load). +### Q1 addendum — lane PL, 2026-09-08: the two constants are stored at DIFFERENT WIDTHS + +The pseudo-code above is right about the shape and hides the thing that matters. The two +constants of this one routine are loaded by two different opcodes: + +``` +DB 45 FC fild dword [ebp-4] ; maxIncome, left on the stack +DD 05 30 EC A2 00 fld qword [0x00a2ec30] ; DD /0 = m64fp -- a DOUBLE +D8 F9 fdivr st(0), st(1) +E8 D2 CB 10 00 call _ftol2 ; -> BnkEl +3D 00 6C CA 88 cmp eax, -2000000000 ; the clamp +8B 0D DC DF AE 00 mov ecx, [0x00aedfdc] ; the loader's pointer slot +D8 09 fmul dword [ecx] ; D8 /1 = m32fp -- a FLOAT32 +E8 A5 CB 10 00 call _ftol2 +F7 D8 neg eax ; -> BnkPr +``` + +* `0x00a2ec30` reads `00 00 00 40 33 33 C3 BF` = **-0.15000000596046448**, i.e. + `(double)(float)-0.15f`. Already known (lane N) and already in the engine. +* `g_BANKRUPTCY_PROTECTION_LIMIT_FACTOR` at `0x00b23e28`, reached through the pointer slot + `0x00aedfdc`, is read **`fmul dword ptr`**. So whatever decimal the data file carries for + that key is **narrowed to a 4-byte float before the multiply**. Writing `-ftol(3.3 * m)` + with a `double` 3.3 disagrees with the image at **every max income that is a multiple of + ten**, starting at `maxIncome = 10` (decimal 33.0 truncates to 33; the image's + 3.299999952316284 gives 32.99999952, truncating to 32). Measured over 230,000..250,000: + 2,000 of 20,000 values disagree — exactly 10%. +* The slot's file image is zero; the config loader fills it at run time, and + `find-cross-references` shows exactly one read site in the whole binary (this one) plus the + loader's own table entry at `0x009ba5df`. So the *width* is a binary fact and the *value* is + a data-file fact. +* **The corpus cannot see this.** All seven non-zero `BnkPr` records in the eleven saves + invert to a max income where the two constants truncate the same. It is rule 23's exact + shape: a difference that survives every observation we have and is still real. Fixed in + `sots-engine` (`ComputeBankruptcyLimits` narrows through `F32`), which moved three + hand-written test expectations and zero leaves. + +Addresses filed in `ghidra/addresses.d/lane-pl.json`. + ### Q1 addendum — lane K, 2026-09-08 (instruction-verified) The call sequence above is now read off the instruction stream, with addresses: diff --git a/findings/subsystems/players-residual.md b/findings/subsystems/players-residual.md new file mode 100644 index 0000000..3cd1b02 --- /dev/null +++ b/findings/subsystems/players-residual.md @@ -0,0 +1,118 @@ +# The `/Sim/players` residual, decomposed + +- **Type:** subsystem +- **Address / RVA:** n/a (a measurement over the save corpus; the one binary read is + `ServerPlayer::UpdateBankruptcyLimits` 0x00818600) +- **Status:** verified +- **Confidence:** high for the decomposition and the leaf counts; the `Status` predicate is + explicitly **not identifiable** and is flagged as such +- **Owner / date:** lane PL · 2026-09-08 + +## Purpose + +Every lane so far attacked a named subsystem and reported which leaves fell out. This one runs +the other way: take the largest remaining block of the standalone's residual and say what the +leaves in it actually **are**, grouped by mechanism, so that no later lane has to re-derive it. + +The full write-up, with the predictions written before the build and where they were wrong, +is `sots-engine/docs/PL-players-residual.md`. This note is the evidence and the numbers. + +## The numbers (re-measured; the published breakdown was stale) + +`sots_turn` from `sots-engine` main `aabd8a3`, `tools/standalone_report.py --binary …`: + +| run | pair 1 | pair 2 | `/Sim/players` | +|---|---:|---:|---:| +| main, no options | 128 | 69 | **54 / 24** | +| main, `--commit-blocked=T31 --ai-player 1` | 126 | 67 | 52 / 22 | +| lane PL, no options | 126 | 65 | 52 / 20 | +| lane PL, `--data ROOT --commit-blocked=P11 --ai-player 1..3` | **122** | **62** | **48 / 17** | + +`status.json` said 55. It is 54. + +**53 of the 54 leaves on pair 1, and 23 of the 24 on pair 2, are values our turn writes back +unchanged from the input save.** Exactly one leaf in the whole block — player 32's `Sav` — is a +number we computed and got wrong. The block is *unmodelled*, not *mismodelled*, and a lane +looking for a formula error here will not find one. + +## The decomposition + +| # | mechanism | p1 | p2 | rung | +|---|---|---:|---:|---| +| M1 | AI research orders: `ResRate`, `ResTNm`, `ResErrRoll`, and the tech-tree state they move | 12 | 2 | B | +| M2 | AI ship construction: `ShipRecs/*`, `Maint`, `FNG/FNGNum`, `NumDes` + the new `Des[…]`, `lboid`, player 32's `Sav`/`PvSav` | 15 | 9 | B | +| M3 | Observation records refreshed by the AI's own new design: `odes`, `owep`, `otch/*/otnL` (T34, stub) | 9 | 1 | B | +| M4 | Events | 8 | 6 | 4/3 A + 4/3 B | +| M5 | `BnkEl`, `BnkPr` | 4 | 4 | A | +| M6 | `Status` | 4 | 0 | not identifiable | +| M7 | `PvSav` for the players M2 does not touch | 0 | 2 | A | +| M8 | player 528's one-off design `Des[1712 "Refugee Trade Ship"]` + `NumDes` | 2 | 0 | ? | + +## The finding that matters most + +**M3 is not an intel pass.** `RecordObservedDesigns` (T34) reads, on the reference workload, as +a **self-registration triggered by design creation**, not as a sweep over enemy fleets: + +* player 32's new `odes` entry is `odid=18, opid=32` — design 18 owned by player 32, which is + the design *that player itself created this turn* (`Des[18 "Honor Lance"]`, `NumDes` 5→6); +* its new `owep` entry is `bal_gauss`, that design's weapon; +* the three `otch` entries whose `otnL` moves 1→2 are `DRV_Fissn`, `WEP_GsDrvr`, `DRV_Hyper` — + that design's technologies. + +And the two lists refresh on **different events**: on pair 2 the same design is built again and +`odes/.[1]/otnL` moves 2→3 while every `otch` entry stays at 2. So `odes` is re-stamped on +**build** and `otch` on **creation**. One workload, two rules — both are hypotheses (rule 6) +until a save exists where a player observes someone *else's* design. + +## Corrections to the record (rule 11) + +1. **T31's self-check was not a self-check.** It reported "BnkEl reproduced for 6 of 8" on + `turn1-state` *regardless of the AI roster*, because it compared its **post-turn** + computation against the **pre-turn** stored value. The six it "reproduced" were exactly the + six players whose limit does not move (five with no colonies, plus the independent colony). + The phase's catalog text claimed "8 of 8 with the AI flag supplied", which the binary never + printed. Rule 15, in the wild. + The check is now taken at load, from the colony state the save was written from, and passes + for **every live player of all eleven corpus saves**. +2. **The AI flag is recoverable from the save.** `ServerPlayer+0xf9` is not serialised, but the + save's own `BnkEl` was written by the original from the colony state the save holds, and the + AI difficulty column is worth 10% of the max income against a `BnkEl` slope of 6.67 — far + more than a truncation. Recomputing under both columns and comparing identifies the column: + **1 AI and 1 non-AI on every one of the eleven saves**, the rest ambiguous. T31 therefore no + longer needs `--ai-player`, and closes 2 leaves per reference pair with no operator input. + *Ambiguous* means both columns give the same limit, which happens for two reasons and not + one: zero max income, **or an NPC** — the difficulty table's AI row is gated on + `isAI && !npc`, so "Independent Colony" is ambiguous despite owning a colony and carrying a + non-zero limit. +3. **The protection factor is a float32.** See `formula-gaps.md` Q1 addendum (lane PL) and + `ghidra/addresses.d/lane-pl.json`. +4. **The published residual overstates what is unmodelled.** 4 + 3 of the leaves belong to P11, + which is written and only wants `--data`. `tools/standalone_report.py` invokes the binary + with no data root, so the headline number measures the engine plus a missing argument. + Reproduced independently on CT111 against `/srv/re-lab/gob-extract`: **87 closed / 0 + regressed** on pair 1 and **46 / 0** on pair 2. + +## `Status` — a negative result worth keeping + +`Status` goes 0 → 4 on players 16, 32, 496, 512 and stays 0 on 528, 544, 560, 576, then stays 4 +on the next turn. The two sets are **perfectly correlated with species** (0/2 against 4), and +sweeping every scalar field of the player record on `turn1-state` finds **eighteen** that split +the roster identically: `ReqCL`, `AMine`, `CnTrd`, `CnVItl`, `cdp`, `hadvs`, `harcc`, `hgs`, +`PvMA`, `CstE`, `CstR`, `CstT`, `MinRate`, `MaxOH`, `NPTrk`, `PrGtTrf`, `TerraMod`, `pddm`. +Only two corpus saves carry a non-zero `Status` at all. + +So this is **one observation of one transition on one roster**, and any predicate chosen from it +is an eighteen-way coin flip. `ReqCL` is the most plausible on name and on meaning — W2 places +the writer at `OnMessage+0xa15` and `MarkPlayerTurnEnded` writes 4 from the End-Turn submission +paths — but it is a hypothesis with a workload attached. + +**The probe that settles it** (rules 18 and 20): an entry probe on that writer, capturing the +player index on every call for one turn. It names the set directly. Instrument the entry. + +## Cross-refs + +- Related: [[formula-gaps]] Q1 + the lane PL addendum, [[ship-construction]] (M2's 11,900), + [[population-growth]] (the `PvSav` prediction it held), [[strategic-turn-internals]] +- Engine: `sots-engine/docs/PL-players-residual.md`, `src/game/sim/player_turn.{h,cpp}`, + `tests/game_sim/test_player_turn.cpp` +- Addresses: `ghidra/addresses.d/lane-pl.json` diff --git a/ghidra/addresses.d/lane-pl.json b/ghidra/addresses.d/lane-pl.json new file mode 100644 index 0000000..8429224 --- /dev/null +++ b/ghidra/addresses.d/lane-pl.json @@ -0,0 +1,28 @@ +{ + "entries": [ + { + "name": "g_BankruptcyEliminationDivisor", + "addr": "0x00a2ec30", + "convention": "data", + "prototype": "double 0xBFC3333340000000 = -0.15000000596046448 = (double)(float)-0.15f -- the elimination-limit divisor, loaded by ServerPlayer::UpdateBankruptcyLimits at 0x00818612 with `DD 05` (fld QWORD). It is the negation of g_DebtInterestRate (0x009ed188), and the two are stored separately. Named here because lane N's fix cited the value but not the address", + "status": "verified", + "source": "lane PL own disassembly pass 2026-09-08 (reva_call read-memory 0x00818600 +200, 0x00a2ec30)" + }, + { + "name": "PTR_g_BANKRUPTCY_PROTECTION_LIMIT_FACTOR", + "addr": "0x00aedfdc", + "convention": "data", + "prototype": "float* -> 0x00b23e28. The config loader's pointer slot for the key BANKRUPTCY_PROTECTION_LIMIT_FACTOR, the same indirection pattern as ADDICTION_INCOME_MOD's (0x00aeca48 -> 0x00aeca44). Read once in the image, by UpdateBankruptcyLimits at 0x0081866e", + "status": "verified", + "source": "lane PL own disassembly pass 2026-09-08 (reva_call read-memory + find-cross-references)" + }, + { + "name": "g_BANKRUPTCY_PROTECTION_LIMIT_FACTOR", + "addr": "0x00b23e28", + "convention": "data", + "prototype": "FLOAT32 -- and the width is the finding. UpdateBankruptcyLimits multiplies it in at 0x00818674 with `D8 09` = FMUL m32fp, i.e. a DWORD, while the elimination divisor two instructions earlier is `DD 05` = FLD m64fp. So whatever decimal the data file carries for this key is narrowed to a 4-byte float before the multiply, and a `double` multiply truncates to a different integer at every boundary -- for a factor of 3.3 that is EVERY max income divisible by ten, starting at maxIncome = 10 (decimal 33.0 -> 33, image 32.99999952 -> 32). The file image of the slot is zero: the loader fills it at run time, so the value itself is a data-file fact, not a binary one. The corpus cannot see the difference -- all seven of its non-zero BnkPr records invert to a max income where the two agree -- so this is an instruction-stream reading, thin-covered by construction (rule 23)", + "status": "verified", + "source": "lane PL own disassembly pass 2026-09-08; docs/PL-players-residual.md in sots-engine" + } + ] +} diff --git a/verify/results/standalone/report.txt b/verify/results/standalone/report.txt index 536293f..160fb05 100644 --- a/verify/results/standalone/report.txt +++ b/verify/results/standalone/report.txt @@ -1,17 +1,18 @@ # standalone vs the oracle -generated 2026-09-08T19:48:40Z binary /srv/re-lab/build/eng-rep2/build-host/src/app/sots_turn +generated 2026-09-08T20:04:11Z binary /home/alex/sots-engine-pl/build-host/src/app/sots_turn phases: 16/44 of the two turn drivers modelled, 12 committed (implemented 4, partial 8, blocked 4, stub 28) 5/37 of the post-combat tail modelled ## turn1-state.sav -> turn2-state.sav (real End Turn) baseline (do nothing) 209 leaves diverge - after one standalone turn 131 leaves diverge - closed 78, regressed 0, byte match: no + after one standalone turn 128 leaves diverge + closed 81, regressed 0, byte match: no coverage proved on all three saves: {'input': True, 'oracle': True, 'ours': True} closed: + /Sim/Frame + + /Sim/players/Player[16 "re"]/Sav + /Sim/players/Player[496 "Singularity"]/dipstats/. + /Sim/players/Player[496 "Singularity"]/dipstats/.[0] + /Sim/players/Player[496 "Singularity"]/dipstats/.[1] @@ -43,12 +44,14 @@ phases: 16/44 of the two turn drivers modelled, 12 committed (implemented 4, par + /Sim/systems/Sys[112 "Gamma Cephei"]/ETS + /Sim/systems/Sys[112 "Gamma Cephei"]/Eid + /Sim/systems/Sys[112 "Gamma Cephei"]/NVE + + /Sim/systems/Sys[112 "Gamma Cephei"]/Pop2/PopG/PopC + /Sim/systems/Sys[112 "Gamma Cephei"]/ltis + /Sim/systems/Sys[112 "Gamma Cephei"]/ntdev + /Sim/systems/Sys[288 "Ke'Dolarra"]/EPid + /Sim/systems/Sys[288 "Ke'Dolarra"]/ETS + /Sim/systems/Sys[288 "Ke'Dolarra"]/Eid + /Sim/systems/Sys[288 "Ke'Dolarra"]/NVE + + /Sim/systems/Sys[288 "Ke'Dolarra"]/Pop2/PopG/PopC + /Sim/systems/Sys[288 "Ke'Dolarra"]/ltis + /Sim/systems/Sys[288 "Ke'Dolarra"]/ntdev + /Sim/systems/Sys[304 "Koa’Vo"]/EFlags @@ -92,11 +95,12 @@ phases: 16/44 of the two turn drivers modelled, 12 committed (implemented 4, par ## turn2-state.sav -> turn3-state.sav (real End Turn) baseline (do nothing) 108 leaves diverge - after one standalone turn 72 leaves diverge - closed 36, regressed 0, byte match: no + after one standalone turn 69 leaves diverge + closed 39, regressed 0, byte match: no coverage proved on all three saves: {'input': True, 'oracle': True, 'ours': True} closed: + /Sim/Frame + + /Sim/players/Player[16 "re"]/Sav + /Sim/players/Player[496 "Singularity"]/dipstats/.[1]/lastally + /Sim/players/Player[512 "Singularity"]/dipstats/.[1]/lastally + /Sim/players/Player[528 "Alien Menace"]/dipstats/.[1]/lastnap @@ -113,9 +117,11 @@ phases: 16/44 of the two turn drivers modelled, 12 committed (implemented 4, par + /Sim/players/Player[576 "Independent Colony"]/dipstats/.[2]/lastnap + /Sim/players/Player[576 "Independent Colony"]/dipstats/.[3]/lastnap + /Sim/systems/Sys[112 "Gamma Cephei"]/ETS + + /Sim/systems/Sys[112 "Gamma Cephei"]/Pop2/PopG/PopC + /Sim/systems/Sys[112 "Gamma Cephei"]/ltis + /Sim/systems/Sys[112 "Gamma Cephei"]/ntdev + /Sim/systems/Sys[288 "Ke'Dolarra"]/ETS + + /Sim/systems/Sys[288 "Ke'Dolarra"]/Pop2/PopG/PopC + /Sim/systems/Sys[288 "Ke'Dolarra"]/ltis + /Sim/systems/Sys[288 "Ke'Dolarra"]/ntdev + /Sim/systems/Sys[304 "Koa’Vo"]/ETS @@ -134,8 +140,8 @@ phases: 16/44 of the two turn drivers modelled, 12 committed (implemented 4, par + /Summary/Turn ## what still differs on the reference pair, by subsystem - 55 /Sim/players - 34 /Sim/systems + 54 /Sim/players + 32 /Sim/systems 24 /Sim/turnstats 8 /Sim/SvSctOb 1 /Sim/DesignIDs[] @@ -173,7 +179,6 @@ phases: 16/44 of the two turn drivers modelled, 12 committed (implemented 4, par /Sim/players/Player[16 "re"]/Events/Events/.: only-in-A /Sim/players/Player[16 "re"]/Events/Events/.[0]: only-in-B /Sim/players/Player[16 "re"]/Events/Events/.[EvTurn=2]: only-in-B - /Sim/players/Player[16 "re"]/Sav: 289092 -> 289688 /Sim/players/Player[16 "re"]/Status: 0 -> 4 /Sim/players/Player[32 "Fane Lao"]/BnkEl: -1811273 -> -1815833 /Sim/players/Player[32 "Fane Lao"]/BnkPr: -896580 -> -898837 @@ -187,6 +192,7 @@ phases: 16/44 of the two turn drivers modelled, 12 committed (implemented 4, par /Sim/players/Player[32 "Fane Lao"]/PvSav: 50000 -> 38100 /Sim/players/Player[32 "Fane Lao"]/ResRate: 0.25 -> 0.800000011920929 [1.34218e+07 ulp] /Sim/players/Player[32 "Fane Lao"]/ResTNm: '' -> 'IND_Waldo' - /Sim/players/Player[32 "Fane Lao"]/Sav: 297492 -> 92651 + /Sim/players/Player[32 "Fane Lao"]/Sav: 298113 -> 92651 /Sim/players/Player[32 "Fane Lao"]/ShipRecs/srb[0]: 0 -> 1 /Sim/players/Player[32 "Fane Lao"]/ShipRecs/srb[3]: only-in-B + /Sim/players/Player[32 "Fane Lao"]/ShipRecs/srbd: 0 -> 1 diff --git a/verify/results/standalone/status.json b/verify/results/standalone/status.json index 58e075f..7596781 100644 --- a/verify/results/standalone/status.json +++ b/verify/results/standalone/status.json @@ -1,19 +1,19 @@ { "schema": "sots-standalone-status/1", - "generated": "2026-09-08T19:48:40Z", - "binary": "/srv/re-lab/build/eng-rep2/build-host/src/app/sots_turn", + "generated": "2026-09-08T20:04:11Z", + "binary": "/home/alex/sots-engine-pl/build-host/src/app/sots_turn", "engineArgs": [], "reference": { "input": "turn1-state.sav", "oracle": "turn2-state.sav", "baselineDiverging": 209, - "divergingAfterTurn": 131, - "closed": 78, + "divergingAfterTurn": 128, + "closed": 81, "regressed": 0, "byteMatch": false, "subsystems": { - "/Sim/players": 55, - "/Sim/systems": 34, + "/Sim/players": 54, + "/Sim/systems": 32, "/Sim/turnstats": 24, "/Sim/SvSctOb": 8, "/Sim/DesignIDs[]": 1, @@ -60,7 +60,7 @@ "engineArgs": [], "exit": 0, "stdout": [ - "load: /srv/re-lab/build/sre3/verify/results/saves/turn1-state.sav", + "load: /home/alex/sots-re/verify/results/saves/turn1-state.sav", " 591376 inflated bytes, 0 error(s), 0 warning(s)", " turn 1, frame 1, modCount 0, 8 player(s), 28 system(s), 6 fleet(s)", "roundtrip (untouched): byte-identical (591376 bytes)", @@ -73,8 +73,8 @@ " verified 0 implemented 1 partial 2 blocked 2 stub 32", "", "this run", - " leaves written 87", - " leaves NOT written by a blocked phase 97", + " leaves written 89", + " leaves NOT written by a blocked phase 98", " generator words consumed 16 (state loaded, left untouched)", " generator words NOT accounted (never netted off the above):", " - encounter detection draws one unit value and one bounded integer per turn on every turn measured (2 words), with no derived rule behind the count -- its bound is the product of the contact and detector counts, so it is left unmodelled", @@ -83,8 +83,8 @@ " ! the generator advanced during this run but the save keeps its original state (--commit-rng to write it)", " ! the modelled words are a LOWER BOUND on the turn's cost, so a committed generator is short by the unaccounted sites below and its drawn VALUES are not the game's", "", - "wrote /tmp/tmpkd8jx34g/post-turn1-state.sav (65970 bytes gzipped, 595192 inflated)", - "metric -> /tmp/tmpkd8jx34g/metric-turn1-state.sav.json" + "wrote /tmp/tmpfmmdz_by/post-turn1-state.sav (65980 bytes gzipped, 595192 inflated)", + "metric -> /tmp/tmpfmmdz_by/metric-turn1-state.sav.json" ], "coverage": { "input": true, @@ -94,14 +94,15 @@ "roots": { "input": "64b836b966299d9b72fc02244ed31e31", "oracle": "4bed514f853332b9fa35b388c3aa5558", - "ours": "807894b688ac0c7d06171e2a15ad2b4f" + "ours": "0cf5b0cfe7dd11ab248eb4df2a1ea828" }, "baselineDiverging": 209, - "divergingAfterTurn": 131, - "closed": 78, + "divergingAfterTurn": 128, + "closed": 81, "regressed": 0, "closedPaths": [ "/Sim/Frame", + "/Sim/players/Player[16 \"re\"]/Sav", "/Sim/players/Player[496 \"Singularity\"]/dipstats/.", "/Sim/players/Player[496 \"Singularity\"]/dipstats/.[0]", "/Sim/players/Player[496 \"Singularity\"]/dipstats/.[1]", @@ -133,12 +134,14 @@ "/Sim/systems/Sys[112 \"Gamma Cephei\"]/ETS", "/Sim/systems/Sys[112 \"Gamma Cephei\"]/Eid", "/Sim/systems/Sys[112 \"Gamma Cephei\"]/NVE", + "/Sim/systems/Sys[112 \"Gamma Cephei\"]/Pop2/PopG/PopC", "/Sim/systems/Sys[112 \"Gamma Cephei\"]/ltis", "/Sim/systems/Sys[112 \"Gamma Cephei\"]/ntdev", "/Sim/systems/Sys[288 \"Ke'Dolarra\"]/EPid", "/Sim/systems/Sys[288 \"Ke'Dolarra\"]/ETS", "/Sim/systems/Sys[288 \"Ke'Dolarra\"]/Eid", "/Sim/systems/Sys[288 \"Ke'Dolarra\"]/NVE", + "/Sim/systems/Sys[288 \"Ke'Dolarra\"]/Pop2/PopG/PopC", "/Sim/systems/Sys[288 \"Ke'Dolarra\"]/ltis", "/Sim/systems/Sys[288 \"Ke'Dolarra\"]/ntdev", "/Sim/systems/Sys[304 \"Koa\u2019Vo\"]/EFlags", @@ -205,7 +208,6 @@ "/Sim/players/Player[16 \"re\"]/Events/Events/.: only-in-A", "/Sim/players/Player[16 \"re\"]/Events/Events/.[0]: only-in-B", "/Sim/players/Player[16 \"re\"]/Events/Events/.[EvTurn=2]: only-in-B", - "/Sim/players/Player[16 \"re\"]/Sav: 289092 -> 289688", "/Sim/players/Player[16 \"re\"]/Status: 0 -> 4", "/Sim/players/Player[32 \"Fane Lao\"]/BnkEl: -1811273 -> -1815833", "/Sim/players/Player[32 \"Fane Lao\"]/BnkPr: -896580 -> -898837", @@ -219,15 +221,16 @@ "/Sim/players/Player[32 \"Fane Lao\"]/PvSav: 50000 -> 38100", "/Sim/players/Player[32 \"Fane Lao\"]/ResRate: 0.25 -> 0.800000011920929 [1.34218e+07 ulp]", "/Sim/players/Player[32 \"Fane Lao\"]/ResTNm: '' -> 'IND_Waldo'", - "/Sim/players/Player[32 \"Fane Lao\"]/Sav: 297492 -> 92651", + "/Sim/players/Player[32 \"Fane Lao\"]/Sav: 298113 -> 92651", "/Sim/players/Player[32 \"Fane Lao\"]/ShipRecs/srb[0]: 0 -> 1", - "/Sim/players/Player[32 \"Fane Lao\"]/ShipRecs/srb[3]: only-in-B" + "/Sim/players/Player[32 \"Fane Lao\"]/ShipRecs/srb[3]: only-in-B", + "/Sim/players/Player[32 \"Fane Lao\"]/ShipRecs/srbd: 0 -> 1" ], "byteMatch": false, "standalone": { "schema": "sots-standalone-metric/1", - "input": "/srv/re-lab/build/sre3/verify/results/saves/turn1-state.sav", - "output": "/tmp/tmpkd8jx34g/post-turn1-state.sav", + "input": "/home/alex/sots-re/verify/results/saves/turn1-state.sav", + "output": "/tmp/tmpfmmdz_by/post-turn1-state.sav", "spine": { "total": 44, "verified": 0, @@ -249,8 +252,8 @@ "committed": 3 }, "run": { - "leafWrites": 87, - "blockedLeafWrites": 97, + "leafWrites": 89, + "blockedLeafWrites": 98, "rngWords": 16, "rngLoaded": true, "rngCommitted": false, @@ -397,7 +400,7 @@ "name": "SystemTurn", "status": "partial", "ran": 28, - "writes": 3, + "writes": 5, "blockedWrites": 0, "rng": 0 }, @@ -1038,7 +1041,7 @@ "status": "blocked", "ran": 8, "writes": 0, - "blockedWrites": 1, + "blockedWrites": 2, "rng": 0 }, { @@ -1111,7 +1114,7 @@ "engineArgs": [], "exit": 0, "stdout": [ - "load: /srv/re-lab/build/sre3/verify/results/saves/turn2-state.sav", + "load: /home/alex/sots-re/verify/results/saves/turn2-state.sav", " 603360 inflated bytes, 0 error(s), 0 warning(s)", " turn 2, frame 2, modCount 12, 8 player(s), 28 system(s), 7 fleet(s)", "roundtrip (untouched): byte-identical (603360 bytes)", @@ -1124,8 +1127,8 @@ " verified 0 implemented 1 partial 2 blocked 2 stub 32", "", "this run", - " leaves written 43", - " leaves NOT written by a blocked phase 73", + " leaves written 45", + " leaves NOT written by a blocked phase 74", " generator words consumed 16 (state loaded, left untouched)", " generator words NOT accounted (never netted off the above):", " - encounter detection draws one unit value and one bounded integer per turn on every turn measured (2 words), with no derived rule behind the count -- its bound is the product of the contact and detector counts, so it is left unmodelled", @@ -1134,8 +1137,8 @@ " ! the generator advanced during this run but the save keeps its original state (--commit-rng to write it)", " ! the modelled words are a LOWER BOUND on the turn's cost, so a committed generator is short by the unaccounted sites below and its drawn VALUES are not the game's", "", - "wrote /tmp/tmpkd8jx34g/post-turn2-state.sav (66879 bytes gzipped, 603360 inflated)", - "metric -> /tmp/tmpkd8jx34g/metric-turn2-state.sav.json" + "wrote /tmp/tmpfmmdz_by/post-turn2-state.sav (66880 bytes gzipped, 603360 inflated)", + "metric -> /tmp/tmpfmmdz_by/metric-turn2-state.sav.json" ], "coverage": { "input": true, @@ -1145,14 +1148,15 @@ "roots": { "input": "4bed514f853332b9fa35b388c3aa5558", "oracle": "e9c161e311f8ef8fad6f1aa1903dcf3f", - "ours": "4527034695edf755dbbdbf3605334c3d" + "ours": "853380c5c55cd7208c60afc2486c7e74" }, "baselineDiverging": 108, - "divergingAfterTurn": 72, - "closed": 36, + "divergingAfterTurn": 69, + "closed": 39, "regressed": 0, "closedPaths": [ "/Sim/Frame", + "/Sim/players/Player[16 \"re\"]/Sav", "/Sim/players/Player[496 \"Singularity\"]/dipstats/.[1]/lastally", "/Sim/players/Player[512 \"Singularity\"]/dipstats/.[1]/lastally", "/Sim/players/Player[528 \"Alien Menace\"]/dipstats/.[1]/lastnap", @@ -1169,9 +1173,11 @@ "/Sim/players/Player[576 \"Independent Colony\"]/dipstats/.[2]/lastnap", "/Sim/players/Player[576 \"Independent Colony\"]/dipstats/.[3]/lastnap", "/Sim/systems/Sys[112 \"Gamma Cephei\"]/ETS", + "/Sim/systems/Sys[112 \"Gamma Cephei\"]/Pop2/PopG/PopC", "/Sim/systems/Sys[112 \"Gamma Cephei\"]/ltis", "/Sim/systems/Sys[112 \"Gamma Cephei\"]/ntdev", "/Sim/systems/Sys[288 \"Ke'Dolarra\"]/ETS", + "/Sim/systems/Sys[288 \"Ke'Dolarra\"]/Pop2/PopG/PopC", "/Sim/systems/Sys[288 \"Ke'Dolarra\"]/ltis", "/Sim/systems/Sys[288 \"Ke'Dolarra\"]/ntdev", "/Sim/systems/Sys[304 \"Koa\u2019Vo\"]/ETS", @@ -1209,7 +1215,6 @@ "/Sim/players/Player[16 \"re\"]/Events/Events/.[0]: 1 -> 2", "/Sim/players/Player[16 \"re\"]/Events/Events/.[EvTurn=3]: only-in-B", "/Sim/players/Player[16 \"re\"]/PvSav: 50000 -> 289688", - "/Sim/players/Player[16 \"re\"]/Sav: 531773 -> 532369", "/Sim/players/Player[32 \"Fane Lao\"]/BnkEl: -1815833 -> -1820206", "/Sim/players/Player[32 \"Fane Lao\"]/BnkPr: -898837 -> -901002", "/Sim/players/Player[32 \"Fane Lao\"]/Events/EvNxID: 2 -> 4", @@ -1218,7 +1223,7 @@ "/Sim/players/Player[32 \"Fane Lao\"]/FNG/FNGNum: 1 -> 3", "/Sim/players/Player[32 \"Fane Lao\"]/Maint: 500 -> 1000", "/Sim/players/Player[32 \"Fane Lao\"]/PvSav: 38100 -> 80751", - "/Sim/players/Player[32 \"Fane Lao\"]/Sav: 142259 -> 135486", + "/Sim/players/Player[32 \"Fane Lao\"]/Sav: 142379 -> 135486", "/Sim/players/Player[32 \"Fane Lao\"]/ShipRecs/srb[0]: 1 -> 2", "/Sim/players/Player[32 \"Fane Lao\"]/ShipRecs/srb[3]: 1 -> 2", "/Sim/players/Player[32 \"Fane Lao\"]/ShipRecs/sri[0]: 1 -> 2", @@ -1228,15 +1233,16 @@ "/Sim/players/Player[32 \"Fane Lao\"]/lboid: 1 -> 2", "/Sim/players/Player[32 \"Fane Lao\"]/odes/.[1]/otnL: 2 -> 3", "/Sim/players/Player[576 \"Independent Colony\"]/PvSav: 0 -> 98871", - "/Sim/systems/Sys[112 \"Gamma Cephei\"]/Pop2/PopG/PopC: 520000000 -> 540000000", "/Sim/systems/Sys[112 \"Gamma Cephei\"]/PvPop2/PopG/PopC: 500000000 -> 520000000", - "/Sim/systems/Sys[112 \"Gamma Cephei\"]/RepCur: 336360.0 -> 336840.0 [15360 ulp]" + "/Sim/systems/Sys[112 \"Gamma Cephei\"]/RepCur: 336360.0 -> 336840.0 [15360 ulp]", + "/Sim/systems/Sys[112 \"Gamma Cephei\"]/RepMax: 336360.0 -> 336840.0 [15360 ulp]", + "/Sim/systems/Sys[112 \"Gamma Cephei\"]/TShn: 2 -> 3" ], "byteMatch": false, "standalone": { "schema": "sots-standalone-metric/1", - "input": "/srv/re-lab/build/sre3/verify/results/saves/turn2-state.sav", - "output": "/tmp/tmpkd8jx34g/post-turn2-state.sav", + "input": "/home/alex/sots-re/verify/results/saves/turn2-state.sav", + "output": "/tmp/tmpfmmdz_by/post-turn2-state.sav", "spine": { "total": 44, "verified": 0, @@ -1258,8 +1264,8 @@ "committed": 3 }, "run": { - "leafWrites": 43, - "blockedLeafWrites": 73, + "leafWrites": 45, + "blockedLeafWrites": 74, "rngWords": 16, "rngLoaded": true, "rngCommitted": false, @@ -1406,7 +1412,7 @@ "name": "SystemTurn", "status": "partial", "ran": 28, - "writes": 3, + "writes": 5, "blockedWrites": 0, "rng": 0 }, @@ -2047,7 +2053,7 @@ "status": "blocked", "ran": 8, "writes": 0, - "blockedWrites": 1, + "blockedWrites": 2, "rng": 0 }, {