nmarshall commited on
Commit
7f21133
·
1 Parent(s): ab2ce3b

qvm: active movement

Browse files
docs/ASSET_PIPELINE_TODO.md CHANGED
@@ -324,3 +324,6 @@ Research progress: [QVM nested ground-loss action](research/QVM_LOST_ACTION.md)
324
 
325
 
326
  Research progress: [QVM shared query/main acquisition event](research/QVM_MAIN_QUERY.md) completes bounded RE-533–535: actual side-clearance child, full query state into main and reached event23 queue across30 standalone/20 main cases. RE-532/536 retain other modes/combined producers/native/consumers/full runtime/platform work and broad game/rendering milestones.
 
 
 
 
324
 
325
 
326
  Research progress: [QVM shared query/main acquisition event](research/QVM_MAIN_QUERY.md) completes bounded RE-533–535: actual side-clearance child, full query state into main and reached event23 queue across30 standalone/20 main cases. RE-532/536 retain other modes/combined producers/native/consumers/full runtime/platform work and broad game/rendering milestones.
327
+
328
+
329
+ Research progress: [QVM57312 active-state mode](research/QVM_ACTIVE_MODE.md) completes bounded RE-537–539: live friction/scale/acceleration, wish overwrite, stationary query and gravity-off slide across66 standalone/12 main cases. RE-536/540 retain combined producers/other modes/native/runtime work. The [progress assessment](PROGRESS.md) estimates5–10% overall and0% playable Rust runtime, with evidence and uncertainty.
docs/FINDINGS.md CHANGED
@@ -674,3 +674,10 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
674
  **F-260 — Full query/main state:**20 actual main chains preserve query velocity/anchor/field44/torso and old-state-dependent flags2, replacing isolated return/state-only transfer. Main action suppresses ten queries; routing selects ten evaluated41768, five omitted55465, four omitted43626 and one omitted57312. [MAINQUERY-002](research/QVM_MAIN_QUERY.md).
675
 
676
  **F-261 — Acquisition event queue:**exactly two new-acquisition main fixtures execute39238(23)/29913 before routing, storing numeric event23/parameter0 and advancing the two-slot queue. Existing-active/exit/failed/gated controls do not emit; event meaning and consumers remain open. [MAINQUERY-003](research/QVM_MAIN_QUERY.md).
 
 
 
 
 
 
 
 
674
  **F-260 — Full query/main state:**20 actual main chains preserve query velocity/anchor/field44/torso and old-state-dependent flags2, replacing isolated return/state-only transfer. Main action suppresses ten queries; routing selects ten evaluated41768, five omitted55465, four omitted43626 and one omitted57312. [MAINQUERY-002](research/QVM_MAIN_QUERY.md).
675
 
676
  **F-261 — Acquisition event queue:**exactly two new-acquisition main fixtures execute39238(23)/29913 before routing, storing numeric event23/parameter0 and advancing the two-slot queue. Existing-active/exit/failed/gated controls do not emit; event meaning and consumers remain open. [MAINQUERY-003](research/QVM_MAIN_QUERY.md).
677
+
678
+
679
+ **F-262 — Active-state wish overwrite:**57312 evaluates friction/command scale, replaces the initial up-inclusive wish through its plane branch, forces Z±70 for nonzero forward, then zeros wish and PS velocity X/Y before actual40275 acceleration. Zero-forward basis Z and indirect up-through-scale effects remain observable. [ACTIVEMODE-001](research/QVM_ACTIVE_MODE.md).
680
+
681
+ **F-263 — Stationary query then gravity-off slide:**57312 traces current origin against itself with current hull; fraction<1 requests logging5123, then both branches request57714(0).66 finite fixtures check actual acceleration/slide outputs; native consistency/logging effects remain unverified. [ACTIVEMODE-002](research/QVM_ACTIVE_MODE.md).
682
+
683
+ **F-264 — Query-to-active-mode state:**12 main chains yield four actual57312, six higher-priority41768 and two omitted55465 paths. Four acquisitions execute event23 before movement; full query/queue state persists. Other environment/modes/native/runtime scope remains open. [ACTIVEMODE-003](research/QVM_ACTIVE_MODE.md).
docs/PROGRESS.md ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Provisional progress toward the complete game
2
+
3
+ Assessment date: **2026-10-19**, after the57312 movement analysis batch. **Estimated overall completion: approximately5–10%. Playable Rust rewrite completion:0%.** This is a low-confidence engineering estimate against the full [G1–G9 goals](GOALS.md), including every required game feature/content path, Bevy/Solari, native macOS/Linux operation and release qualification. It is not a measured percentage of recovered behavior, a calendar forecast or a claim that90–95% of a fixed number of hours remains.
4
+
5
+ The project has a substantial static research and extraction foundation. The implementation and integration work required for a playable replacement has not started in this checkout. The strongest observable fact is that the repository has **no Cargo.toml and no Rust source files**. There is no demonstrated Rust client, dedicated server, Bevy application, Solari scene or native platform gameplay result.
6
+
7
+ ## Evidence available now
8
+
9
+ | Evidence | Current state | What it establishes |
10
+ | --- | --- | --- |
11
+ | Reference inventory |39 installation files;23 PK3 archives | A pinned initial scope and original-file identities; see [inventory](inventory/README.md). |
12
+ | Extraction |9835 verified file occurrences,10578 central-directory entries, including743 directory records | Source variants and provenance are preserved; see [extraction](extraction/README.md). This is unpacking, not a complete runtime conversion pipeline. |
13
+ | Analysis tools |178 Python files, including85 test modules | Reproducible inspection/evaluation infrastructure, including this batch. |
14
+ | Verification |687 passing tests | Analyzer/parser/storage and bounded synthetic behavior regression checks. This is not687 original-runtime or Rust gameplay conformance tests. |
15
+ | Canonical RE checklist |248 checked,292 open after this batch | Completed scoped research deliverables. These540 tasks are uneven in size, and new bounded tasks have been added over time.248/540 must not be read as46% of the game being complete. |
16
+ | Asset pipeline checklist |4 checked,129 open | Extraction has verified steps; content schemas, complete dependency resolution, conversion, runtime packaging and QA remain open. Partial work on unchecked items is described in the checklist. |
17
+ | Rewrite checklist |0 checked,173 open | No validated runtime deliverable yet. |
18
+ | Runtime and platform evidence |No Rust/Cargo project; no demonstrated Solari or macOS/Linux game execution | No playable or release gate can currently be credited. |
19
+
20
+ Counts describe this repository snapshot, not all possible work. The [research ledger](RESEARCH_LEDGER.md) records what was verified and which inputs/effects remain supplied. Static QVM decoding and bounded synthetic instruction evaluation are valuable specifications, but they do not establish complete game logic, native collision consistency, scheduler fidelity, networking interoperability or end-to-end gameplay.
21
+
22
+ ## Basis for the5–10% estimate
23
+
24
+ These are deliberately coarse judgments of remaining engineering effort. Weights are planning assumptions, not measurements. The categories cover the full requested game and overlap only through integration work assigned to the relevant runtime/presentation/release category.
25
+
26
+ | Work category | Assumed share of total effort | Estimated completion within category | Evidence and gap |
27
+ | --- | ---: | ---: | --- |
28
+ | Reference research and behavioral specification |25% |15–25% | Broad static binary/format/ABI analysis and many bounded helper fixtures exist. Original execution/reference traces, complete modules/engine/service behavior and exhaustive semantic coverage remain. |
29
+ | Production content pipeline |15% |10–20% | Inventory/extraction/variant preservation exist. Complete conversion, material/animation/collision/navigation runtime contracts, dependency resolution and content-wide QA remain. |
30
+ | Shared Rust simulation, collision, gameplay and server |25% |0% | No Rust runtime. Movement, weapons, damage, all modes, entities and authoritative scheduling must be implemented and compared. |
31
+ | Multiplayer, bots, demos, audio, UI and services |15% |0% | No demonstrated replacement systems. Research evidence does not count as their runtime implementation. |
32
+ | Bevy/Solari presentation and platform integration |15% |0% | Required native hardware capability, animated content/material pipeline, rendering/performance and application integration have no passing prototype evidence. |
33
+ | Packaging, integration QA and release qualification |5% |0% | Storage/tooling checks exist, but no game build can pass native installation, multiplayer, fidelity, performance or full-content release tests yet. |
34
+
35
+ These assumptions produce approximately5.25–9.25% overall; rounding to5–10% avoids implying precision the evidence does not support. Plausible discovery or implementation surprises can move this estimate substantially. The0% playable-runtime assessment is much firmer than the overall effort estimate. No completion date is defensible from the current evidence.
36
+
37
+ ## Milestone status
38
+
39
+ Using the existing [milestone exit criteria](VALIDATION_AND_MILESTONES.md), **no complete milestone is credited as passed** by this assessment. This does not discard partial work:
40
+
41
+ - M0 research baseline: strong inventory/extraction/tooling progress; the executable reference-observation/harness requirement remains open.
42
+ - M1 platform feasibility: no passing Bevy/Solari prototype and declared native GPU/OS test matrix.
43
+ - M2 engine/content contracts: meaningful partial static/ABI/format/helper evidence; complete controlled runtime contracts remain open.
44
+ - M3 complete initial asset pipeline: extraction works; required runtime conversion, dependencies and content validation remain open.
45
+ - M4–M8 playable movement/combat/rules/presentation/bots-services: no working Rust integration demonstrated.
46
+ - M9 exhaustive coverage: inventory coverage is not exhaustive semantic analysis or validated runtime content.
47
+ - M10–M11 platform qualification/entire-game completion: pending the runtime and full-content gates.
48
+
49
+ ## Highest-value next completion evidence
50
+
51
+ 1. Prove M1 with a pinned Rust/Bevy/Solari application on actual target macOS/Linux hardware and record capabilities, failures and measured frame behavior. Do not infer Solari feasibility from a planned raster fallback or static documentation.
52
+ 2. Establish an original reference execution harness and capture real movement/collision/event traces for the recovered paths. Keep synthetic cases separately identified.
53
+ 3. Build the first Rust vertical slice: load one converted map, share collision/movement with a headless server, and validate camera/input/step/ground/query behavior against those traces.
54
+ 4. Add a single complete weapon and two-client controlled match, then expand authoritative rules, content and presentation using measured integration results.
55
+ 5. Re-estimate after the prototype and first match. Those milestones will reveal constraints and a delivery rate that repeated small static research batches cannot currently quantify.
56
+
57
+ This assessment does not change the requested all-file/all-feature scope or close any unmet task. Continue the detailed [RE](REVERSE_ENGINEERING_TODO.md), [asset](ASSET_PIPELINE_TODO.md), [rewrite](RUST_BEVY_SOLARI_TODO.md) and [provisional](PROVISIONAL_TODO.md) checklists, with completed deliverables linked to testable evidence.
docs/PROVISIONAL_TODO.md CHANGED
@@ -636,3 +636,6 @@ Research progress: [QVM nested ground-loss action](research/QVM_LOST_ACTION.md)
636
 
637
 
638
  Research progress: [QVM shared query/main acquisition event](research/QVM_MAIN_QUERY.md) completes bounded RE-533–535: actual side-clearance child, full query state into main and reached event23 queue across30 standalone/20 main cases. RE-532/536 retain other modes/combined producers/native/consumers/full runtime/platform work and broad game/rendering milestones.
 
 
 
 
636
 
637
 
638
  Research progress: [QVM shared query/main acquisition event](research/QVM_MAIN_QUERY.md) completes bounded RE-533–535: actual side-clearance child, full query state into main and reached event23 queue across30 standalone/20 main cases. RE-532/536 retain other modes/combined producers/native/consumers/full runtime/platform work and broad game/rendering milestones.
639
+
640
+
641
+ Research progress: [QVM57312 active-state mode](research/QVM_ACTIVE_MODE.md) completes bounded RE-537–539: live friction/scale/acceleration, wish overwrite, stationary query and gravity-off slide across66 standalone/12 main cases. RE-536/540 retain combined producers/other modes/native/runtime work. The [progress assessment](PROGRESS.md) estimates5–10% overall and0% playable Rust runtime, with evidence and uncertainty.
docs/README.md CHANGED
@@ -4,6 +4,8 @@ Planning snapshot: **2026-10-10**. Reference installation: `.cache/UrbanTerror43
4
 
5
  The objective is to reverse engineer and document the supplied game, then rewrite its client and dedicated server in Rust with Bevy and Solari, running on macOS and Linux. The planning pass produced documentation and static inventory evidence. The first research step now also implements and verifies complete PK3 extraction; see [extraction findings](extraction/README.md). Repository storage setup now also includes Git/LFS/Xet filters and commit/push guards, described in [STORAGE.md](STORAGE.md). The [first QVM/native binary analysis](research/README.md) now provides reusable static scripts, reports and disassembly. The game, converters, runtime harnesses and further behavior analysis remain TODO; the original game binaries have not been launched.
6
 
 
 
7
  ## Reading order
8
 
9
  1. [Goals and definition of completion](GOALS.md): scope, fidelity, platforms, and deliverables.
 
4
 
5
  The objective is to reverse engineer and document the supplied game, then rewrite its client and dedicated server in Rust with Bevy and Solari, running on macOS and Linux. The planning pass produced documentation and static inventory evidence. The first research step now also implements and verifies complete PK3 extraction; see [extraction findings](extraction/README.md). Repository storage setup now also includes Git/LFS/Xet filters and commit/push guards, described in [STORAGE.md](STORAGE.md). The [first QVM/native binary analysis](research/README.md) now provides reusable static scripts, reports and disassembly. The game, converters, runtime harnesses and further behavior analysis remain TODO; the original game binaries have not been launched.
6
 
7
+ Current assessment: see [progress toward the complete game](PROGRESS.md) for the2026-10-19 estimate, implemented evidence and remaining runtime/platform gates.
8
+
9
  ## Reading order
10
 
11
  1. [Goals and definition of completion](GOALS.md): scope, fidelity, platforms, and deliverables.
docs/RESEARCH_LEDGER.md CHANGED
@@ -419,3 +419,9 @@ Completed bounded RE-529–531 with `analyze_qvm_lost_action.py`:48 standalone46
419
  ## 2026-10-19 — Game-QVM shared query, side-clearance child and main acquisition event
420
 
421
  Completed bounded RE-533–535 with `analyze_qvm_main_query.py`:30 standalone full-PS query probes and20 actual clock/timer/action/query/main chains. MAINQUERY-001–003/F-259–261 evaluate reached56335 with live memory and disjoint frames, independently verify side roots/geometry/first-clear short circuit and all256 PS words, then carry actual56639 velocity/anchor/field44/torso/state/return into main. Fractional Z300.75 acquires anchor300; release applies the normalized impulse to current velocity and clears anchor/state with field44 floor300. Main old-state snapshot controls flags2 after nonzero return; ten action-produced feet-hit cases suppress query entirely. Ten remaining queries route to ten total evaluated41768 chains; alternative totals are five55465, four43626 and one57312 with omitted effects. Exactly two new-acquisition fixtures execute actual39238(23)/29913 before routing, storing numeric event23/parameter0 and advancing the two-slot queue; event meaning/consumers remain open. Optional shared-memory/query/event/state inputs preserve old defaults. Native roots/fractions/records and initial basis/ground/bounds/state remain supplied; environment/posture/alternative-mode/other suffix/full53418/scheduler/legal collision/platform gameplay remain omitted or unverified in these fixtures. No original executable/full QVM/native collision/physics/rendering executes. Eight independent tests cover transitions/full PS/geometry, skipped children and caller gating, old-state flags2/mode priority, reached event queue and full outputs into movement, independent slide/mode gravity checks, source identity and scope. All679 tests pass. Prior traversal-query, clearance-mode, main-contact and lost-action reports regenerate byte-identically; new report reproduces twice byte-identically (809190 bytes). Storage/filter setup, documentation links and whitespace checks pass. No assets or shared instruction evaluator changed. RE-532 remains open for broader scope; RE-536 tracks other movement bodies/combined producers/native/legal/event-consumer/main/platform work. Broad game/assets/rendering/protocol milestones remain open.
 
 
 
 
 
 
 
419
  ## 2026-10-19 — Game-QVM shared query, side-clearance child and main acquisition event
420
 
421
  Completed bounded RE-533–535 with `analyze_qvm_main_query.py`:30 standalone full-PS query probes and20 actual clock/timer/action/query/main chains. MAINQUERY-001–003/F-259–261 evaluate reached56335 with live memory and disjoint frames, independently verify side roots/geometry/first-clear short circuit and all256 PS words, then carry actual56639 velocity/anchor/field44/torso/state/return into main. Fractional Z300.75 acquires anchor300; release applies the normalized impulse to current velocity and clears anchor/state with field44 floor300. Main old-state snapshot controls flags2 after nonzero return; ten action-produced feet-hit cases suppress query entirely. Ten remaining queries route to ten total evaluated41768 chains; alternative totals are five55465, four43626 and one57312 with omitted effects. Exactly two new-acquisition fixtures execute actual39238(23)/29913 before routing, storing numeric event23/parameter0 and advancing the two-slot queue; event meaning/consumers remain open. Optional shared-memory/query/event/state inputs preserve old defaults. Native roots/fractions/records and initial basis/ground/bounds/state remain supplied; environment/posture/alternative-mode/other suffix/full53418/scheduler/legal collision/platform gameplay remain omitted or unverified in these fixtures. No original executable/full QVM/native collision/physics/rendering executes. Eight independent tests cover transitions/full PS/geometry, skipped children and caller gating, old-state flags2/mode priority, reached event queue and full outputs into movement, independent slide/mode gravity checks, source identity and scope. All679 tests pass. Prior traversal-query, clearance-mode, main-contact and lost-action reports regenerate byte-identically; new report reproduces twice byte-identically (809190 bytes). Storage/filter setup, documentation links and whitespace checks pass. No assets or shared instruction evaluator changed. RE-532 remains open for broader scope; RE-536 tracks other movement bodies/combined producers/native/legal/event-consumer/main/platform work. Broad game/assets/rendering/protocol milestones remain open.
422
+
423
+ ## 2026-10-19 — Game-QVM57312 active-state movement and full-project progress assessment
424
+
425
+ Completed bounded RE-537–539 with `analyze_qvm_active_mode.py`:66 standalone57312 fixtures and12 actual main chains. ACTIVEMODE-001–003/F-262–264 evaluate live39988 friction,40397 command scaling, source plane/up wish replacement, forward-sign fixed Z±70 and wish/PS horizontal zeroing, actual40275 acceleration, stationary hull request/logging priority and reached57714(0) clear/contact state. Two additional tilted-basis controls isolate zero-forward basis-Z input and discarded direct-up addition; roots and exact float words retain source rounding/sign behavior. Actual main callback at54424 executes57312 in four chains; six higher-priority41768 controls and two gated55465 requests never receive its effects. Four acquisitions evaluate event23 before movement with persistent queue/anchor/state. Friction shared-memory/return-memory options and main active-mode callback preserve old defaults. Native roots/fractions/ordered records/interpolated positions, finite basis/state/configuration remain supplied; logging/environment/posture/other modes/main prefix-suffix/native/legal/full scheduler/platform gameplay remain omitted or unverified. No original executable/full QVM/native collision/physics/rendering executes. Eight independent tests verify helper arithmetic/whole movement outputs, overwritten wish/up/horizontal state, tilted basis, stationary native pointer/bounds/mask/logging order,12 actual query/event/main handoffs, skipped children, initialized-word provenance and scope. All687 tests pass. Prior friction/main-contact/main-query reports regenerate byte-identically; new report reproduces twice byte-identically (1730167 bytes, below normal-Git2MiB). Storage/filter, documentation links and whitespace checks pass. No assets or shared instruction evaluator changed. RE-536 remains open for broader scope; RE-540 tracks other modes/combined producers/native/reference/main/platform completion.
426
+
427
+ Also documented the requested provisional completion estimate in `docs/PROGRESS.md`:5–10% of the full requested project under explicit subjective effort weights, and0% playable Rust runtime. Audited evidence includes no Cargo manifests/Rust sources,687 analyzer/tool tests,248 checked/292 open RE items,4 checked/129 open asset-pipeline items and0 checked/173 open rewrite items. Checkbox/test counts do not measure full-game fidelity. No complete M0–M11 exit gate is credited; M0/M2/M3 have partial evidence and the native Bevy/Solari proof/first Rust vertical slice/reference execution harness are concrete next completion milestones. Estimate has low confidence and supplies no delivery date or unsupported platform claim.
docs/REVERSE_ENGINEERING_TODO.md CHANGED
@@ -666,3 +666,9 @@ Purpose: turn the supplied installation into an evidence-backed specification of
666
  - [x] RE-534 Carry full query velocity/anchor/field44/torso/state/return into actual main gating, old-state flags2 and mode selection ([MAINQUERY-002](research/QVM_MAIN_QUERY.md)).
667
  - [x] RE-535 Evaluate reached main39238(23)/29913 acquisition queue effects before routing and verify conditional emission/persistence ([MAINQUERY-003](research/QVM_MAIN_QUERY.md)).
668
  - [ ] RE-536 Recover57312/55465/41848/43626/42838 movement bodies, combine query with posture/ground/nested-action producers, main prefix/suffix/event/PS216 consumers and real basis/input/environment/native collision ABI/legal domains; complete53418/scheduler/macOS/Linux Rust/Bevy/Solari gameplay and broader game/assets/rendering/protocol work.
 
 
 
 
 
 
 
666
  - [x] RE-534 Carry full query velocity/anchor/field44/torso/state/return into actual main gating, old-state flags2 and mode selection ([MAINQUERY-002](research/QVM_MAIN_QUERY.md)).
667
  - [x] RE-535 Evaluate reached main39238(23)/29913 acquisition queue effects before routing and verify conditional emission/persistence ([MAINQUERY-003](research/QVM_MAIN_QUERY.md)).
668
  - [ ] RE-536 Recover57312/55465/41848/43626/42838 movement bodies, combine query with posture/ground/nested-action producers, main prefix/suffix/event/PS216 consumers and real basis/input/environment/native collision ABI/legal domains; complete53418/scheduler/macOS/Linux Rust/Bevy/Solari gameplay and broader game/assets/rendering/protocol work.
669
+
670
+
671
+ - [x] RE-537 Evaluate57312 live39988 friction/40397 scale, source plane/up wish overwrite and forced vertical-speed/horizontal-zero stores ([ACTIVEMODE-001](research/QVM_ACTIVE_MODE.md)).
672
+ - [x] RE-538 Evaluate actual40275, stationary hull/logging priority and reached57714(0) clear/contact state with independent arithmetic/slide checks ([ACTIVEMODE-002](research/QVM_ACTIVE_MODE.md)).
673
+ - [x] RE-539 Compose57312 at actual main query/event-to-mode boundary and suppress effects on higher-priority/gated alternative paths ([ACTIVEMODE-003](research/QVM_ACTIVE_MODE.md)).
674
+ - [ ] RE-540 Recover55465/41848/43626/42838, combine actual posture/ground/nested action/query/57312 and remaining main prefix/suffix/event consumers, original reference traces/native collision ABI/legal domains and full53418/scheduler/macOS/Linux Rust/Bevy/Solari gameplay. Continue broader game/assets/rendering/protocol work and platform feasibility/first Rust vertical slice.
docs/research/QVM_ACTIVE_MODE.md ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # QVM57312 active-state movement and actual main caller
2
+
3
+ This batch completes bounded RE-537–539 / F-262–264 by evaluating the movement body selected when query state220 retains bit1024. It extends [shared query/main state](QVM_MAIN_QUERY.md), [friction](QVM_FRICTION.md), [command scaling/acceleration](QVM_ACCELERATION.md) and [continuous slide](QVM_SLIDE_REPEATED.md). No original executable, full QVM, native collision, physics or rendering executes.
4
+
5
+ Reproduce with `python3 scripts/analyze_qvm_active_mode.py`; validate with `python3 scripts/test_qvm_active_mode.py`. The [machine report](qvm-active-mode.json) contains the complete57312–57713 instruction partition, initialized configuration words,66 standalone fixtures and12 main chains. The evaluated body stops at57712 before the void PUSH/LEAVE epilogue, after applying the requested57714 child. Native responses remain supplied. The report occupies1730167 bytes in ordinary Git; assets are unchanged.
6
+
7
+ ## ACTIVEMODE-001 — Live friction, command scale and wish-vector overwrite (RE-537)
8
+
9
+ Mode57312 first calls39988 friction against current PS/global state, then40397 with the actual command pointer FRAME+4. Both children return complete shared memory. File-backed initialized words include21228=10 for the later acceleration request; these words are supplied configuration, not proven immutable or current runtime values. Friction retains its earlier recovered speed/drop/override policy. Main fixtures consume the clock's actual float timestep.
10
+
11
+ The64-case standalone grid varies commands(0,0,0), (1,0,0), (−128,127,1), (0,127,−128), plane0/1, two initial velocities, stationary fraction1/0.5 and clear/contact slide records. Two extra controls supply forward-basis Z0.5 and right-basis Z−0.25. Other supplied basis vectors use planar forward(3,4,0), right(−4,3,0); these deliberately finite inputs do not prove native input normalization or legal gameplay domains. Existing friction and scale formulas independently predict the child outputs.
12
+
13
+ The initial wish construction combines scaled forward/right and up input, but the subsequent plane branch replaces the whole vector: with plane0 only scaled right remains, and with plane1 scaled forward plus right remain. Direct up addition therefore does not survive this branch; up can still affect command normalization/scale. Forward input then replaces Z with +70 when positive or −70 when negative. With zero forward, basis Z can still supply a vertical component, as the two extra controls demonstrate.
14
+
15
+ Finally57549–57576 zero wish X/Y and PS velocity X/Y. The mode normalizes only the remaining vertical wish, then requests40275 with that speed and coefficient21228. Thus the horizontal friction result is discarded before acceleration, while friction's current vertical velocity remains live. Zero root skips normalization and preserves exact source float signs. This documents numeric source behavior without assigning a complete gameplay name to the mode or its flag.
16
+
17
+ ## ACTIVEMODE-002 — Actual acceleration, stationary query and gravity-off slide (RE-538)
18
+
19
+ Actual40275 receives the live mode-local direction pointer and float-word speed/coefficient arguments. Its projection, positive gap, acceleration amount cap and all resulting velocity words are checked independently. The mode then issues a stationary hull trace: start and end both point at current PS origin, using current frame bounds, entity7 and mask65537 in these fixtures.
20
+
21
+ Supplied fraction below1 requests5123 with string pointer55142. Fraction1 skips it. Logging effects remain omitted; this call is not treated as a state reset, collision result or movement cancellation. Mode57312 proceeds to57714(0) in both cases. That child evaluates the recovered continuous slide with gravity disabled, current velocity/origin/plane/touch/impact state and ordered supplied native records. Clear and repeated-contact outputs are independently predicted, including conditional contact registration and solver exits.
22
+
23
+ No60091/59710 step wrapper or41768 gravity tail is attached to this mode. Its own final state is the actual57714 child output. Native stationary/slide record consistency, side effects and legal collision domains remain unverified.
24
+
25
+ ## ACTIVEMODE-003 — Reached query/event-to57312 handoff (RE-539)
26
+
27
+ Twelve main chains vary acquisition/existing active/gated cases, flags32/160 and clear/contact slide patterns. Actual clock/timer and54981(0) run before the recovered query; newly acquired state evaluates event23 and its queue writer before routing. An optional57312 effect runs after main CALL54422/POP54423, before the caller continues at54424. Other mode paths never receive these effects, and existing no-callback main reports remain byte-identical.
28
+
29
+ Four chains select57312 and execute its complete bounded child composition. Six flags160 controls select41768 by higher priority and retain that mode's established effects. Two flags32 feet-hit controls suppress the query and request55465 with omitted effects. Four acquisition chains emit numeric event23 before either reached movement mode; their queue/anchor/state outputs survive movement. Existing active-state cases do not emit a second acquisition event.
30
+
31
+ This batch does not yet combine the query/57312 path with actual posture/ground/nested-ground-action environment producers. Ground, basis, bounds and native records are still supplied in these main fixtures. Other alternative movement bodies, main prefix/suffix, logging/event consumers, complete53418/scheduler and macOS/Linux Rust/Bevy/Solari runtime behavior remain open.
32
+
33
+ ## Validation and next tasks
34
+
35
+ Eight new tests cover all66 helper/wish/acceleration/slide fixtures, discarded horizontal state, signed input and fixed vertical speed, direct-up overwrite and nonzero-basis-Z controls, stationary pointer/bounds/mask/logging priority,12 reached/skipped main mode handoffs, acquisition queue order/persistence, initialized-word provenance and source/scope limits. All687 tests pass. Prior friction, main-contact and main-query reports regenerate byte-identically; the new report reproduces twice byte-identically. Storage/filter, documentation links and whitespace checks are recorded in the ledger.
36
+
37
+ RE-536 remains open for broader alternative modes, combined producers, native behavior and runtime work. RE-540 tracks55465/41848/43626/42838, combined posture/ground/query/57312 ordering, original reference traces, native collision/legal domains and remaining main/scheduler/consumer/platform scope. See also the [whole-project progress estimate](../PROGRESS.md).
docs/research/QVM_MAIN_QUERY.md CHANGED
@@ -35,3 +35,6 @@ Eight tests independently check query transition formulas, call order and hull g
35
  RE-532 remains open for its broader modes/consumers/native/runtime scope. RE-536 tracks actual57312/55465/41848/43626/42838 movement bodies, query integration with combined posture/ground/nested-action producers, omitted main prefix/suffix and event/PS216 consumers, native trace/content/root ABI and collision-consistent legal domains. Full53418/scheduler and macOS/Linux Rust/Bevy/Solari gameplay remain open, alongside game assets, rendering and protocol work.
36
 
37
  For the Rust rewrite, preserve the pre-query old-state snapshot, exact float32 arithmetic/truncation, conditional child requests, full state mutation and event queue order. Keep supplied native responses explicit until collision behavior is recovered. These bounded fixtures provide future port comparison cases; no Rust or Bevy/Solari implementation is added here.
 
 
 
 
35
  RE-532 remains open for its broader modes/consumers/native/runtime scope. RE-536 tracks actual57312/55465/41848/43626/42838 movement bodies, query integration with combined posture/ground/nested-action producers, omitted main prefix/suffix and event/PS216 consumers, native trace/content/root ABI and collision-consistent legal domains. Full53418/scheduler and macOS/Linux Rust/Bevy/Solari gameplay remain open, alongside game assets, rendering and protocol work.
36
 
37
  For the Rust rewrite, preserve the pre-query old-state snapshot, exact float32 arithmetic/truncation, conditional child requests, full state mutation and event queue order. Keep supplied native responses explicit until collision behavior is recovered. These bounded fixtures provide future port comparison cases; no Rust or Bevy/Solari implementation is added here.
38
+
39
+
40
+ Follow-up: [active-state57312 movement](QVM_ACTIVE_MODE.md) now evaluates the reached mode and friction/scale/acceleration/slide children at the real main boundary. Other modes, combined environment producers and native/full runtime scope remain open.
docs/research/README.md CHANGED
@@ -237,3 +237,6 @@ The extension collector adds five focused tests for native tail calls, command-r
237
 
238
 
239
  [QVM shared query and main acquisition event](QVM_MAIN_QUERY.md) adds RE-533–535. Reproduce with `python3 scripts/analyze_qvm_main_query.py`; check with `python3 scripts/test_qvm_main_query.py`. Actual side-clearance/query/full state and conditional event23 compose at main; other modes/combined environment/native/full runtime remain open.
 
 
 
 
237
 
238
 
239
  [QVM shared query and main acquisition event](QVM_MAIN_QUERY.md) adds RE-533–535. Reproduce with `python3 scripts/analyze_qvm_main_query.py`; check with `python3 scripts/test_qvm_main_query.py`. Actual side-clearance/query/full state and conditional event23 compose at main; other modes/combined environment/native/full runtime remain open.
240
+
241
+
242
+ [QVM57312 active-state movement](QVM_ACTIVE_MODE.md) adds RE-537–539. Reproduce with `python3 scripts/analyze_qvm_active_mode.py`; check with `python3 scripts/test_qvm_active_mode.py`. Live friction/scale/acceleration/slide compose at actual main routing; native/combined environment/other modes/full runtime remain open. See [project progress](../PROGRESS.md) for the completion estimate and remaining implementation gates.
docs/research/qvm-active-mode.json ADDED
The diff for this file is too large to render. See raw diff
 
scripts/analyze_qvm_active_mode.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Actual57312 friction/command/acceleration/zero-distance trace/slide composition."""
3
+ import itertools,json,math
4
+ from pathlib import Path
5
+ from analyze_bsp_references import trace_fields
6
+ from analyze_deferred_auth import trace_slice
7
+ from analyze_qvm import decode,write_json
8
+ from analyze_qvm_acceleration import PS,FRAME,SCALE_FRAME,ACCEL_FRAME,word,number,s8
9
+ from analyze_qvm_friction import friction_probe
10
+ from analyze_qvm_traversal_query import root_word
11
+ from analyze_qvm_slide_repeated import run,specs
12
+ from analyze_qvm_slide_prefix import vec
13
+ from analyze_qvm_contact_callers import snapshot
14
+ from analyze_qvm_main_query import seed,coupled
15
+ from analyze_qvm_action_probe import action,PATTERNS
16
+ from analyze_qvm_main_contact import probe
17
+ from analyze_qvm_landing import event
18
+ from analyze_vm_extensions import verified
19
+
20
+ LOCAL=0x5e000000
21
+ CONSTANTS=[21160,21200,21208,21212,21220,21224,21228]
22
+
23
+
24
+ def initialized(raw,h):return {a:int.from_bytes(raw[h['data_offset']+a:h['data_offset']+a+4],'little') for a in CONSTANTS}
25
+
26
+
27
+ def command_scale(ins,m,cmd):
28
+ movement=[v&255 for v in cmd];root=word(math.sqrt(sum(s8(v)**2 for v in movement)));t=trace_slice(ins,40398,40677,m,{60:FRAME+4},byte_memory={FRAME+25+i:v for i,v in enumerate(movement)},call_results={40655:root},halt_on_leave=True,capture_stack=True,local_base=SCALE_FRAME,limit=512)
29
+ return t['memory'],{'movement_bytes':movement,'buttons_word':m[FRAME+20],'meter_word':m[PS+184],'supplied_sqrt_word':root,'result_scale_float_word':t['stack'][-1]&0xffffffff,'calls':t['calls'],**trace_fields(t,False)}
30
+
31
+
32
+ def accelerate(ins,m,args):
33
+ before=vec(m,PS+32);direction=vec(m,args[8]);t=trace_slice(ins,40276,40395,m,{48:args[8],52:args[12],56:args[16]},local_base=ACCEL_FRAME,limit=512);m=t['memory']
34
+ return m,{'initial_velocity_float_words':before,'direction_float_words':direction,'wish_speed_float_word':args[12],'acceleration_float_word':args[16],'dt_float_word':m[35023928]&0xffffffff,'projection_float_word':m[ACCEL_FRAME+20]&0xffffffff,'gap_float_word':m[ACCEL_FRAME+16]&0xffffffff,'amount_float_word':m[ACCEL_FRAME+12]&0xffffffff if 40333 in t['trace'] else None,'result_velocity_float_words':vec(m,PS+32),**trace_fields(t,False)}
35
+
36
+
37
+ def active(ins,m,cmd,fraction=1,pattern='clear'):
38
+ m=dict(m);initial=snapshot(m);pc=57313;trace=[];calls=[];friction=None;scale=None;root=0;acceleration=None;request=None;slide=None;constructed=None;wish=None
39
+ while True:
40
+ t=trace_slice(ins,57313,57713,m,{},resume_at=pc,stop_targets=[s for s in [57316,57325,57549,57580,57652,57698,57712] if s!=pc],byte_memory={FRAME+25+i:v&255 for i,v in enumerate(cmd)},local_base=LOCAL,call_results={57323:0 if scale is None else scale['result_scale_float_word'],57604:root},limit=2048);m=t['memory'];trace+=t['trace'];calls+=t['calls'];pc=t['stop']
41
+ if pc==57316:m,friction=friction_probe(ins,{},(0,0,0),initial_memory=m,return_memory=True)
42
+ elif pc==57325:m,scale=command_scale(ins,m,cmd);m[LOCAL+128]=scale['result_scale_float_word']
43
+ elif pc==57549:constructed=vec(m,LOCAL+60)
44
+ elif pc==57580:wish=vec(m,LOCAL+36);root=root_word(list(map(number,wish)))
45
+ elif pc==57652:m,acceleration=accelerate(ins,m,t['calls'][-1]['args'])
46
+ elif pc==57698:
47
+ c=t['calls'][-1];a=c['args'];request={'call':c,'start':vec(m,a[12]),'end':vec(m,a[24]),'bounds':vec(m,a[16])+vec(m,a[20]),'supplied_fraction':word(fraction)}
48
+ for o in range(72,128,4):m[LOCAL+o]=0
49
+ m[LOCAL+80]=word(fraction)
50
+ elif pc==57712:
51
+ before=snapshot(m);records=[{'fraction':1,'normal':[0,0,1],'entity':8}] if pattern=='clear' else specs([(1,0,0)]*4)
52
+ m,child=run(ins,pattern,records,0,m[PS+16],m[35023940],number(m[35023928]),number(m[35024000]),initial_memory=m,return_memory=True);slide={'before':before,'probe':child,'after':snapshot(m)};break
53
+ elif pc==57713:break
54
+ else:raise AssertionError('Unexpected57312 boundary')
55
+ return m,{'initial':initial,'commands':list(cmd),'plane':m[35023940],'forward_basis':vec(m,35023892),'right_basis':vec(m,35023904),'friction':friction,'scale':scale,'constructed_wish':constructed,'wish_before_normalization':wish,'supplied_wish_root':root,'acceleration':acceleration,'stationary_trace':request,'slide':slide,'final':snapshot(m),'calls':calls,**trace_fields({'trace':trace},False)}
56
+
57
+
58
+ def memory(constants,cmd,plane=0,velocity=(1,2,3)):
59
+ m=seed(32,{'state':1024},(3,4));m.update(constants);m.update({FRAME+20:256,35023928:word(.016),35023940:plane,35023936:plane,35023988:0,FRAME+212:0,PS+104:0,35024000:word(0),35023900:word(0),35023912:word(0)})
60
+ for i,v in enumerate(velocity):m[PS+32+4*i]=word(v)
61
+ return m
62
+
63
+
64
+ def standalone(ins,constants,cmd,plane,velocity,fraction,pattern):return active(ins,memory(constants,cmd,plane,velocity),cmd,fraction,pattern)[1]
65
+
66
+
67
+ def main_case(ins,constants,name,flags,pattern):
68
+ spec={'state':1024} if name=='active' else {'forward':1};cmd=(1,0,0);m=memory(constants,cmd);m[PS+220]=spec.get('state',0);m[PS+12]=flags
69
+ def query(ins,m):return coupled(ins,m,spec)
70
+ def act(ins,m):return action(ins,m,0,PATTERNS['none' if name!='gated' else 'feet'])
71
+ def mode(ins,m):return active(ins,m,cmd,.5,pattern)
72
+ p=probe(ins,1016,0,flags,'clear',initial_memory=m,action_effect=act,query_effect=query,event_effect=event,state220=m[PS+220],active_mode_effect=mode);p.update({'variant':name,'input_flags':flags,'slide_pattern':pattern});return p
73
+
74
+
75
+ def main():
76
+ q=json.loads(Path('docs/research/qvm/qagame.json').read_text());raw=verified(Path(q['source']['member']['output']).read_bytes(),q['sha256']);h,ins=decode(raw);constants=initialized(raw,h)
77
+ probes=[standalone(ins,constants,*v) for v in itertools.product([(0,0,0),(1,0,0),(-128,127,1),(0,127,-128)],[0,1],[(1,2,3),(200,-100,50)],[1,.5],['clear','contacts'])]
78
+ for plane in [0,1]:
79
+ m=memory(constants,(0,127,-128),plane);m[35023900]=word(.5);m[35023912]=word(-.25);probes.append(active(ins,m,(0,127,-128),1,'clear')[1])
80
+ out={'source':q['source'],'sha256':q['sha256'],'initialized_words':{str(a):v for a,v in constants.items()},'instructions':ins[57312:57714],'probes':probes,'main_chains':[main_case(ins,constants,*v) for v in itertools.product(['acquire','active','gated'],[32,160],['clear','contacts'])],'limitations':'Bounded finite synthetic shipped-QVM57312/shared-main composition; no original executable/full QVM/native collision/physics/rendering executes. Actual39988 friction,40397 scale,40275 acceleration and57714 slide children share memory with57312, reached at actual main54424. Native sqrt returns, stationary trace fractions and ordered slide records/interpolated endpoints remain supplied, not collision-derived. Initialized data words are file-backed configuration, not proven live or immutable. Logging5123 effects, environment/posture/other alternative modes/main prefix-suffix/native consumers/legal collision domains/full53418/scheduler/macOS/Linux/Rust/Bevy/Solari gameplay remain omitted or unverified.'}
81
+ write_json(Path('docs/research/qvm-active-mode.json'),out);print('Recovered active-state57312 mode and reached main query-to-movement state')
82
+
83
+
84
+ if __name__=='__main__':main()
scripts/analyze_qvm_friction.py CHANGED
@@ -18,10 +18,14 @@ MODE_FRAME=0x44000000
18
  def length_word(v):return word(math.sqrt(f(f(f(v[0]*v[0])+f(v[1]*v[1]))+f(v[2]*v[2]))))
19
 
20
 
21
- def friction_probe(ins,constants,velocity,grounded=0,level=0,surface=0,psflags=0,kind=0,flags220=0,override=0,dt=.016):
22
  m=dict(constants);m.update({35024032:FRAME,FRAME:PS,35023936:grounded,FRAME+212:level,35023988:surface,PS+12:psflags,PS+4:kind,PS+220:flags220,PS+104:override,35023928:word(dt)})
23
  for i,v in enumerate(velocity):m[PS+32+4*i]=word(v)
24
- measured=list(map(lambda v:number(word(v)),velocity));measured[2]=0 if grounded else measured[2];root=length_word(measured);t=trace_slice(ins,39989,40273,m,{},call_results={40031:root},local_base=FRICTION_FRAME,limit=512);mem=t['memory'];return {'initial_velocity_float_words':[word(v) for v in velocity],'grounded_word':grounded,'level_word':level,'surface_word':surface,'ps_flags_word':psflags,'type_word':kind,'flags220_word':flags220,'override_word':override,'dt_float_word':word(dt),'supplied_sqrt_word':root,'drop_float_word':mem[FRICTION_FRAME+36]&0xffffffff if FRICTION_FRAME+36 in mem else None,'ratio_float_word':mem[FRICTION_FRAME+28]&0xffffffff if FRICTION_FRAME+28 in mem else None,'result_velocity_float_words':[mem[PS+32+4*i]&0xffffffff for i in range(3)],'calls':t['calls'],**trace_fields(t,False)}
 
 
 
 
25
 
26
 
27
  def mode_probe(ins,constants,velocity,dt):
 
18
  def length_word(v):return word(math.sqrt(f(f(f(v[0]*v[0])+f(v[1]*v[1]))+f(v[2]*v[2]))))
19
 
20
 
21
+ def friction_probe(ins,constants,velocity,grounded=0,level=0,surface=0,psflags=0,kind=0,flags220=0,override=0,dt=.016,initial_memory=None,return_memory=False):
22
  m=dict(constants);m.update({35024032:FRAME,FRAME:PS,35023936:grounded,FRAME+212:level,35023988:surface,PS+12:psflags,PS+4:kind,PS+220:flags220,PS+104:override,35023928:word(dt)})
23
  for i,v in enumerate(velocity):m[PS+32+4*i]=word(v)
24
+ if initial_memory is not None:
25
+ m=dict(initial_memory);velocity=[number(m[PS+32+4*i]) for i in range(3)];grounded=m[35023936];level=m[FRAME+212];surface=m[35023988];psflags=m[PS+12];kind=m[PS+4];flags220=m[PS+220];override=m[PS+104];dt=number(m[35023928])
26
+ measured=list(map(lambda v:number(word(v)),velocity));measured[2]=0 if grounded else measured[2];root=length_word(measured);t=trace_slice(ins,39989,40273,m,{},call_results={40031:root},local_base=FRICTION_FRAME,limit=512);mem=t['memory'];report={'initial_velocity_float_words':[word(v) for v in velocity],'grounded_word':grounded,'level_word':level,'surface_word':surface,'ps_flags_word':psflags,'type_word':kind,'flags220_word':flags220,'override_word':override,'dt_float_word':word(dt),'supplied_sqrt_word':root,'drop_float_word':mem[FRICTION_FRAME+36]&0xffffffff if FRICTION_FRAME+36 in mem else None,'ratio_float_word':mem[FRICTION_FRAME+28]&0xffffffff if FRICTION_FRAME+28 in mem else None,'result_velocity_float_words':[mem[PS+32+4*i]&0xffffffff for i in range(3)],'calls':t['calls'],**trace_fields(t,False)}
27
+
28
+ return (mem,report) if return_memory else report
29
 
30
 
31
  def mode_probe(ins,constants,velocity,dt):
scripts/analyze_qvm_main_contact.py CHANGED
@@ -15,12 +15,12 @@ from analyze_vm_extensions import verified
15
  def timer_state(m):return {'flags':m[PS+12]&0xffffffff,'movement':m[PS+16],'leg':m[PS+72],'torso':m[PS+80],'dt':m[35023932]}
16
 
17
 
18
- def probe(ins,requested,timer,flags,pattern,initial_memory=None,environment_effect=None,posture_effect=None,action_effect=None,query_effect=None,event_effect=None,state220=0):
19
  m=seed(flags=flags,timer=timer) if initial_memory is None else dict(initial_memory);m.update({PS:1000,FRAME+4:requested,PS+4:0,PS+72:m.get(PS+72,200),PS+80:m.get(PS+80,17),PS+220:state220,FRAME+212:0,35023936:1,35024000:word(0)});initial=snapshot(m)
20
  clock=trace_slice(ins,53723,53789,m,{104:FRAME},local_base=MAIN_LOCAL);m=clock['memory'];clock_report={'old_time':1000,'requested':requested,'result_time':m[PS],'elapsed':m[35023932],'ps_elapsed':m[PS+284],'float_dt':m[35023928]&0xffffffff,'origin_snapshot':vec(m,35024004),'velocity_snapshot':vec(m,35024016),**trace_fields(clock,False)}
21
- pc=54244;calls=[];trace=[];timers=None;mode=None;at_mode=None;environment=[];posture=None;action=None;query=None;events=[];policy='overlap_solid' if requested==1016 else 'clear'
22
  while True:
23
- t=trace_slice(ins,54244,54473,m,{104:FRAME},resume_at=pc,stop_targets=[s for s in ([54274,54382,54438]+([54247,54260,54441,54444] if environment_effect else [])+([54257] if posture_effect else [])+([54279] if action_effect else [])+([54315] if query_effect else [])+([54369] if event_effect else [])) if s!=pc],local_base=MAIN_LOCAL,call_results={54313:0},limit=1024);m=t['memory'];calls+=t['calls'];trace+=t['trace'];pc=t['stop']
24
  if environment_effect and pc in [54247,54260,54441,54444]:
25
  target=47217 if pc in [54247,54444] else 46773;phase='before' if pc<54438 else 'after';m,effect=environment_effect(ins,m,target,phase);environment.append(effect)
26
  elif action_effect and pc==54279:m,action=action_effect(ins,m)
@@ -30,6 +30,8 @@ def probe(ins,requested,timer,flags,pattern,initial_memory=None,environment_effe
30
  elif event_effect and pc==54369:
31
  for c in t['calls']:
32
  if c['target']==39238:m,e=event_effect(ins,m,c['target'],c['args']);events.append(e)
 
 
33
  elif pc==54274:
34
  before=timer_state(m);tt=trace_slice(ins,53049,53184,m,{},local_base=TIMER_LOCAL);m=tt['memory'];timers={'before':before,'after':timer_state(m),'calls':tt['calls'],**trace_fields(tt,False)}
35
  elif pc==54382:
@@ -46,6 +48,7 @@ def probe(ins,requested,timer,flags,pattern,initial_memory=None,environment_effe
46
  if query_effect:
47
  report['query']=query;report['query_final']={str(o):m[PS+o]&0xffffffff for o in [12,20,24,28,32,36,40,44,80,84,108,112,116,120,124,200,220]}
48
  if event_effect:report['events']=events
 
49
  return report
50
 
51
 
 
15
  def timer_state(m):return {'flags':m[PS+12]&0xffffffff,'movement':m[PS+16],'leg':m[PS+72],'torso':m[PS+80],'dt':m[35023932]}
16
 
17
 
18
+ def probe(ins,requested,timer,flags,pattern,initial_memory=None,environment_effect=None,posture_effect=None,action_effect=None,query_effect=None,event_effect=None,state220=0,active_mode_effect=None):
19
  m=seed(flags=flags,timer=timer) if initial_memory is None else dict(initial_memory);m.update({PS:1000,FRAME+4:requested,PS+4:0,PS+72:m.get(PS+72,200),PS+80:m.get(PS+80,17),PS+220:state220,FRAME+212:0,35023936:1,35024000:word(0)});initial=snapshot(m)
20
  clock=trace_slice(ins,53723,53789,m,{104:FRAME},local_base=MAIN_LOCAL);m=clock['memory'];clock_report={'old_time':1000,'requested':requested,'result_time':m[PS],'elapsed':m[35023932],'ps_elapsed':m[PS+284],'float_dt':m[35023928]&0xffffffff,'origin_snapshot':vec(m,35024004),'velocity_snapshot':vec(m,35024016),**trace_fields(clock,False)}
21
+ pc=54244;calls=[];trace=[];timers=None;mode=None;at_mode=None;environment=[];posture=None;action=None;query=None;events=[];active_mode=None;policy='overlap_solid' if requested==1016 else 'clear'
22
  while True:
23
+ t=trace_slice(ins,54244,54473,m,{104:FRAME},resume_at=pc,stop_targets=[s for s in ([54274,54382,54438]+([54247,54260,54441,54444] if environment_effect else [])+([54257] if posture_effect else [])+([54279] if action_effect else [])+([54315] if query_effect else [])+([54369] if event_effect else [])+([54424] if active_mode_effect else [])) if s!=pc],local_base=MAIN_LOCAL,call_results={54313:0},limit=1024);m=t['memory'];calls+=t['calls'];trace+=t['trace'];pc=t['stop']
24
  if environment_effect and pc in [54247,54260,54441,54444]:
25
  target=47217 if pc in [54247,54444] else 46773;phase='before' if pc<54438 else 'after';m,effect=environment_effect(ins,m,target,phase);environment.append(effect)
26
  elif action_effect and pc==54279:m,action=action_effect(ins,m)
 
30
  elif event_effect and pc==54369:
31
  for c in t['calls']:
32
  if c['target']==39238:m,e=event_effect(ins,m,c['target'],c['args']);events.append(e)
33
+ elif active_mode_effect and pc==54424:
34
+ at_mode=snapshot(m);m,active_mode=active_mode_effect(ins,m)
35
  elif pc==54274:
36
  before=timer_state(m);tt=trace_slice(ins,53049,53184,m,{},local_base=TIMER_LOCAL);m=tt['memory'];timers={'before':before,'after':timer_state(m),'calls':tt['calls'],**trace_fields(tt,False)}
37
  elif pc==54382:
 
48
  if query_effect:
49
  report['query']=query;report['query_final']={str(o):m[PS+o]&0xffffffff for o in [12,20,24,28,32,36,40,44,80,84,108,112,116,120,124,200,220]}
50
  if event_effect:report['events']=events
51
+ if active_mode_effect:report['active_mode']=active_mode
52
  return report
53
 
54
 
scripts/test_qvm_active_mode.py ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Independent57312 wish overwrite, helper, slide and actual-main oracles."""
3
+ import hashlib,json,math
4
+ from pathlib import Path
5
+ import unittest
6
+ from test_qvm_ground import word,n,f
7
+ from test_qvm_friction import friction_oracle
8
+ from test_qvm_acceleration import scale_oracle,accel_oracle,s8
9
+ from test_qvm_slide_repeated import oracle as slide_oracle
10
+ from test_qvm_main_query import check_query
11
+
12
+
13
+ def wish_oracle(p):
14
+ scale=n(scale_oracle(p['scale']));forward,right,up=map(s8,p['scale']['movement_bytes']);fw=list(map(n,p['forward_basis']));rt=list(map(n,p['right_basis']))
15
+ v=[f(f(f(scale*x)*forward)+f(f(scale*y)*right)) if p['plane'] else f(f(scale*y)*right) for x,y in zip(fw,rt)]
16
+ if forward>0:v[2]=70
17
+ elif forward<0:v[2]=-70
18
+ constructed=list(map(word,v));wish=[word(0),word(0),word(v[2])];square=f(f(f(0*0)+f(0*0))+f(v[2]*v[2]));root=f(math.sqrt(square));inverse=f(1/root) if root else None;direction=[word(f(x*inverse)) for x in [0,0,v[2]]] if root else wish
19
+ return constructed,wish,word(root),direction,word(square)
20
+
21
+
22
+ def check_mode(test,p,constants):
23
+ fr=p['friction'];root,drop,ratio,velocity=friction_oracle(fr,constants);test.assertEqual([fr['supplied_sqrt_word'],fr['drop_float_word'],fr['ratio_float_word'],fr['result_velocity_float_words']],[root,drop,ratio,velocity]);test.assertEqual(fr['initial_velocity_float_words'],p['initial']['velocity'])
24
+ test.assertEqual(p['scale']['result_scale_float_word'],scale_oracle(p['scale']));constructed,wish,root,direction,square=wish_oracle(p)
25
+ test.assertEqual(p['constructed_wish'],constructed);test.assertEqual(p['wish_before_normalization'],wish);test.assertEqual(p['supplied_wish_root'],root)
26
+ ap=p['acceleration'];test.assertEqual(ap['initial_velocity_float_words'],[0,0,velocity[2]]);test.assertEqual(ap['direction_float_words'],direction);test.assertEqual(ap['wish_speed_float_word'],root);test.assertEqual(ap['acceleration_float_word'],word(constants[21228]))
27
+ test.assertEqual([ap['projection_float_word'],ap['gap_float_word'],ap['amount_float_word'],ap['result_velocity_float_words']],list(accel_oracle(ap,ap['initial_velocity_float_words'])))
28
+ c=next(c for c in p['calls'] if c['instruction']==57604);test.assertEqual(c['args'],{'8':square})
29
+ slide=p['slide'];test.assertEqual(slide['before']['velocity'],ap['result_velocity_float_words']);test.assertEqual(slide['probe']['gravity'],0);slide_oracle(test,slide['probe'],slide['before']);test.assertEqual(p['final'],slide['after'])
30
+ test.assertEqual(p['final']['origin'],slide['probe']['final']['origin']);test.assertEqual(p['final']['velocity'],slide['probe']['final']['velocity'])
31
+
32
+
33
+ class QvmActiveModeTests(unittest.TestCase):
34
+ @classmethod
35
+ def setUpClass(cls):cls.r=json.loads(Path('docs/research/qvm-active-mode.json').read_text());cls.c={int(a):n(v) for a,v in cls.r['initialized_words'].items()}
36
+
37
+ def test_every_helper_wish_projection_and_slide_state(self):
38
+ self.assertEqual(len(self.r['probes']),66)
39
+ for p in self.r['probes']:check_mode(self,p,self.c)
40
+
41
+ def test_horizontal_friction_is_discarded_before_acceleration(self):
42
+ rows=[p for p in self.r['probes'] if n(p['initial']['velocity'][0])==200];self.assertTrue(rows)
43
+ for p in rows:self.assertEqual(p['acceleration']['initial_velocity_float_words'][:2],[0,0]);self.assertEqual(p['acceleration']['result_velocity_float_words'][:2],[0,0])
44
+ self.assertTrue(any(n(p['friction']['result_velocity_float_words'][0])!=0 for p in rows))
45
+
46
+ def test_forward_fixed_vertical_speed_and_zero_forward_up_not_added(self):
47
+ for p in self.r['probes']:
48
+ fw,rt,up=p['commands'];wish=p['wish_before_normalization'];self.assertEqual(wish[:2],[0,0])
49
+ if fw:self.assertEqual(wish[2],word(70 if fw>0 else -70));self.assertEqual(p['acceleration']['wish_speed_float_word'],word(70))
50
+ elif all(n(v)==0 for v in [p['forward_basis'][2],p['right_basis'][2]]):self.assertEqual(n(wish[2]),0)
51
+ zero=[p for p in self.r['probes'] if p['commands']==[0,0,0]];self.assertTrue(zero)
52
+ for p in zero:self.assertEqual(p['scale']['calls'],[]);self.assertEqual(p['acceleration']['wish_speed_float_word'],0)
53
+
54
+ def test_nonzero_basis_z_plane_and_up_overwrite_controls(self):
55
+ tilted=self.r['probes'][-2:];self.assertEqual([p['plane'] for p in tilted],[0,1])
56
+ for p in tilted:
57
+ self.assertEqual(p['commands'],[0,127,-128]);scale=n(p['scale']['result_scale_float_word']);expected=f(f(scale*-.25)*127);self.assertEqual(p['wish_before_normalization'][2],word(expected));self.assertNotEqual(expected,f(expected+f(scale*-128)))
58
+
59
+ def test_stationary_hull_trace_and_conditional_logging_before_slide(self):
60
+ for p in self.r['probes']:
61
+ r=p['stationary_trace'];self.assertEqual(r['start'],p['initial']['origin']);self.assertEqual(r['end'],r['start']);self.assertEqual(r['bounds'],list(map(word,[-15,-15,-24,15,15,45])))
62
+ self.assertEqual(r['call']['args'],{'8':0x5e000048,'12':0x10014,'16':0x300b8,'20':0x300c4,'24':0x10014,'28':7,'32':65537})
63
+ logging=n(r['supplied_fraction'])<1;self.assertEqual([c['target'] for c in p['calls']],[39988,40397,-107,40275,-25]+([5123] if logging else [])+[57714])
64
+ if logging:self.assertEqual(next(c for c in p['calls'] if c['target']==5123)['args'],{'8':55142})
65
+
66
+ def test_main_only_reached57312_executes_and_matches_live_query(self):
67
+ self.assertEqual(len(self.r['main_chains']),12);selected=0
68
+ for p in self.r['main_chains']:
69
+ q=p['query'];mode=p['active_mode'];self.assertEqual(mode is not None,p['selected_mode']==57312)
70
+ if q:check_query(self,q)
71
+ if mode:
72
+ selected+=1;check_mode(self,mode,self.c);self.assertEqual(mode['initial'],p['at_mode']);self.assertEqual(mode['initial']['velocity'],q['result_velocity_float_words']);self.assertEqual(mode['friction']['flags220_word'],q['result_state220_word']);self.assertEqual(mode['friction']['dt_float_word'],p['clock']['float_dt']);self.assertEqual(p['after_dispatch'],mode['final']);self.assertEqual(p['final'],mode['final']);self.assertIsNone(p['mode'])
73
+ elif p['input_flags']==160:self.assertEqual(p['selected_mode'],41768);self.assertIsNotNone(p['mode'])
74
+ else:self.assertEqual(p['selected_mode'],55465);self.assertIsNone(q)
75
+ self.assertEqual(selected,4)
76
+
77
+ def test_main_acquisition_event_precedes_mode_and_survives(self):
78
+ emitted=0
79
+ for p in self.r['main_chains']:
80
+ acquired=p['variant']=='acquire';self.assertEqual(len(p['events']),int(acquired));emitted+=int(acquired)
81
+ self.assertEqual(p['query_final']['108'],int(acquired));self.assertEqual(p['query_final']['112'],23 if acquired else 700)
82
+ if acquired:
83
+ targets=[c['target'] for c in p['calls']];self.assertLess(targets.index(39238),targets.index(p['selected_mode']));self.assertEqual(p['query_final']['200'],300);self.assertEqual(p['query_final']['220'],1024)
84
+ self.assertEqual(emitted,4)
85
+
86
+ def test_file_backed_constants_source_partition_and_scope(self):
87
+ q=json.loads(Path('docs/research/qvm/qagame.json').read_text());raw=Path(q['source']['member']['output']).read_bytes();self.assertEqual(self.r['sha256'],hashlib.sha256(raw).hexdigest());self.assertEqual(self.r['source'],q['source'])
88
+ self.assertEqual(self.c,{21160:100,21200:8,21208:4,21212:1,21220:5,21224:3000,21228:10});self.assertEqual(self.r['instructions'][0]['index'],57312);self.assertEqual(self.r['instructions'][-1]['index'],57713)
89
+ from analyze_qvm import decode
90
+ header,_=decode(raw)
91
+ for a,v in self.r['initialized_words'].items():self.assertEqual(int.from_bytes(raw[header['data_offset']+int(a):header['data_offset']+int(a)+4],'little'),v)
92
+ for phrase in ['no original executable/full QVM/native collision/physics/rendering executes','not collision-derived','Logging5123 effects','not proven live or immutable']:self.assertIn(phrase,self.r['limitations'])
93
+
94
+
95
+ if __name__=='__main__':unittest.main()