qvm: pose pitch and lateral scratch
Browse files- docs/ASSET_PIPELINE_TODO.md +3 -0
- docs/FINDINGS.md +3 -0
- docs/PROVISIONAL_TODO.md +3 -0
- docs/RESEARCH_LEDGER.md +5 -0
- docs/REVERSE_ENGINEERING_TODO.md +3 -0
- docs/research/QVM_POSE_LEAN.md +7 -0
- docs/research/README.md +3 -0
- docs/research/qvm-pose-lean.json +0 -0
- scripts/analyze_qvm_pose_lean.py +27 -0
- scripts/test_qvm_pose_lean.py +27 -0
docs/ASSET_PIPELINE_TODO.md
CHANGED
|
@@ -664,3 +664,6 @@ Research progress: RE-661 [report](research/QVM_VECTOR_ANGLES.md); remaining nat
|
|
| 664 |
|
| 665 |
|
| 666 |
Research progress: RE-662 [report](research/QVM_POSE_MOTION_YAW.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
| 664 |
|
| 665 |
|
| 666 |
Research progress: RE-662 [report](research/QVM_POSE_MOTION_YAW.md); remaining native/content/runtime/platform scope stays open.
|
| 667 |
+
|
| 668 |
+
|
| 669 |
+
Research progress: RE-663 [report](research/QVM_POSE_LEAN.md); remaining native/content/runtime/platform scope stays open.
|
docs/FINDINGS.md
CHANGED
|
@@ -1010,3 +1010,6 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
|
|
| 1010 |
|
| 1011 |
|
| 1012 |
**RE-662 — Animation-dispatched movement yaw and speed scaling:** 32254 dispatches forward/reverse/default yaw branches, clamps integer horizontal speed to200 and yaw delta to±60, and preserves an integer reciprocal scratch calculation. [Evidence](research/QVM_POSE_MOTION_YAW.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 1010 |
|
| 1011 |
|
| 1012 |
**RE-662 — Animation-dispatched movement yaw and speed scaling:** 32254 dispatches forward/reverse/default yaw branches, clamps integer horizontal speed to200 and yaw delta to±60, and preserves an integer reciprocal scratch calculation. [Evidence](research/QVM_POSE_MOTION_YAW.md).
|
| 1013 |
+
|
| 1014 |
+
|
| 1015 |
+
**RE-663 — Pose pitch publication and lateral scratch arithmetic:** 32254 publishes animation-biased pitch, normalizes full velocity with a floating reciprocal and computes an unconsumed lateral scratch scalar. [Evidence](research/QVM_POSE_LEAN.md).
|
docs/PROVISIONAL_TODO.md
CHANGED
|
@@ -987,3 +987,6 @@ Research progress: RE-661 [report](research/QVM_VECTOR_ANGLES.md); remaining nat
|
|
| 987 |
|
| 988 |
|
| 989 |
Research progress: RE-662 [report](research/QVM_POSE_MOTION_YAW.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
| 987 |
|
| 988 |
|
| 989 |
Research progress: RE-662 [report](research/QVM_POSE_MOTION_YAW.md); remaining native/content/runtime/platform scope stays open.
|
| 990 |
+
|
| 991 |
+
|
| 992 |
+
Research progress: RE-663 [report](research/QVM_POSE_LEAN.md); remaining native/content/runtime/platform scope stays open.
|
docs/RESEARCH_LEDGER.md
CHANGED
|
@@ -972,3 +972,8 @@ One direct append caller156173 and three direct reset callers174399/203011/21963
|
|
| 972 |
## 2026-10-20 — RE-662 Animation-dispatched movement yaw and speed scaling (separate task commit)
|
| 973 |
|
| 974 |
32254 dispatches forward/reverse/default yaw branches, clamps integer horizontal speed to200 and yaw delta to±60, and preserves an integer reciprocal scratch calculation. 144 fixtures independently check dispatch, integer/sqrt boundaries, signed deltas, capped speed, actual62944/63746 composition and signed zero scratch vectors. Full suite: 1113 tests pass. Report regenerates byte-identically (588314 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 972 |
## 2026-10-20 — RE-662 Animation-dispatched movement yaw and speed scaling (separate task commit)
|
| 973 |
|
| 974 |
32254 dispatches forward/reverse/default yaw branches, clamps integer horizontal speed to200 and yaw delta to±60, and preserves an integer reciprocal scratch calculation. 144 fixtures independently check dispatch, integer/sqrt boundaries, signed deltas, capped speed, actual62944/63746 composition and signed zero scratch vectors. Full suite: 1113 tests pass. Report regenerates byte-identically (588314 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
| 975 |
+
|
| 976 |
+
|
| 977 |
+
## 2026-10-20 — RE-663 Pose pitch publication and lateral scratch arithmetic (separate task commit)
|
| 978 |
+
|
| 979 |
+
32254 publishes animation-biased pitch, normalizes full velocity with a floating reciprocal and computes an unconsumed lateral scratch scalar. 96 fixtures independently check pitch gating/bias, full3D float32 normalization, scaled length, basis/dot arithmetic and zero-velocity call suppression. Full suite: 1117 tests pass. Report regenerates byte-identically (300961 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
docs/REVERSE_ENGINEERING_TODO.md
CHANGED
|
@@ -1030,3 +1030,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 1030 |
|
| 1031 |
|
| 1032 |
- [x] RE-662 Animation-dispatched movement yaw and speed scaling ([report](research/QVM_POSE_MOTION_YAW.md)).
|
|
|
|
|
|
|
|
|
|
|
|
| 1030 |
|
| 1031 |
|
| 1032 |
- [x] RE-662 Animation-dispatched movement yaw and speed scaling ([report](research/QVM_POSE_MOTION_YAW.md)).
|
| 1033 |
+
|
| 1034 |
+
|
| 1035 |
+
- [x] RE-663 Pose pitch publication and lateral scratch arithmetic ([report](research/QVM_POSE_LEAN.md)).
|
docs/research/QVM_POSE_LEAN.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Pose pitch publication and lateral scratch arithmetic
|
| 2 |
+
|
| 3 |
+
RE-663. Reproduce with `python3 scripts/analyze_qvm_pose_lean.py`; check with `python3 scripts/test_qvm_pose_lean.py`. The [machine report](qvm-pose-lean.json) retains source identity and bounded fixtures.
|
| 4 |
+
|
| 5 |
+
Actual32797–33167 uses half-pitch only when flag96 is active, subtracts360 once above180, adds15 for IDs20/21 or5 otherwise, and publishes through argument40. Velocity is freshly copied and normalized with floating1/length, unlike the earlier integer reciprocal scratch. Nonzero velocity scales length by0.1, builds a basis from local60/64/68 and computes a lateral dot-product scalar at local168. The remaining32254 instructions contain no LOAD of that scalar, so it is documented as an unconsumed calculation rather than a proven visible lean effect. Zero velocity skips basis/native trig calls. Finite sqrt/trig models and original legal-input/library limitations remain explicit.
|
| 6 |
+
|
| 7 |
+
No original executable/full QVM/native collision/physics/rendering executes. Native responses and legal input domains are supplied or unverified where stated; full runtime/macOS/Linux Rust/Bevy/Solari gameplay remains open.
|
docs/research/README.md
CHANGED
|
@@ -588,3 +588,6 @@ The extension collector adds five focused tests for native tail calls, command-r
|
|
| 588 |
|
| 589 |
|
| 590 |
[RE-662: Animation-dispatched movement yaw and speed scaling](QVM_POSE_MOTION_YAW.md). Reproduce with `python3 scripts/analyze_qvm_pose_motion_yaw.py`; check with `python3 scripts/test_qvm_pose_motion_yaw.py`.
|
|
|
|
|
|
|
|
|
|
|
|
| 588 |
|
| 589 |
|
| 590 |
[RE-662: Animation-dispatched movement yaw and speed scaling](QVM_POSE_MOTION_YAW.md). Reproduce with `python3 scripts/analyze_qvm_pose_motion_yaw.py`; check with `python3 scripts/test_qvm_pose_motion_yaw.py`.
|
| 591 |
+
|
| 592 |
+
|
| 593 |
+
[RE-663: Pose pitch publication and lateral scratch arithmetic](QVM_POSE_LEAN.md). Reproduce with `python3 scripts/analyze_qvm_pose_lean.py`; check with `python3 scripts/test_qvm_pose_lean.py`.
|
docs/research/qvm-pose-lean.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scripts/analyze_qvm_pose_lean.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Pose pitch publication, full velocity normalization and lateral scratch scalar."""
|
| 3 |
+
import itertools
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
from qvm_research_support import source,execute,constants
|
| 6 |
+
from qvm_shot_math_support import TRIG
|
| 7 |
+
from analyze_qvm_pose_prefix import fixture,LOCAL,VELOCITY
|
| 8 |
+
from analyze_qvm_pose_controllers import controllers
|
| 9 |
+
from analyze_qvm_pose_motion_yaw import motion
|
| 10 |
+
from analyze_qvm_acceleration import word
|
| 11 |
+
from analyze_qvm_slide_prefix import vec
|
| 12 |
+
from analyze_qvm import write_json
|
| 13 |
+
|
| 14 |
+
def lean(ins,m):
|
| 15 |
+
m=dict(m);before={'animation':m[LOCAL+88],'pitch':m[LOCAL+48]&0xffffffff,'active':m[LOCAL+96],'velocity':vec(m,m[LOCAL+248]),'basis_angles':vec(m,LOCAL+60)}
|
| 16 |
+
m,_,e=execute(ins,32797,33168,m,(0,0,0),LOCAL,TRIG)
|
| 17 |
+
nonzero=any(v&0x7fffffff for v in before['velocity'])
|
| 18 |
+
return m,{'initial':before,'published_pitch':m[m[LOCAL+276]]&0xffffffff,'body_pitch':m[LOCAL+36]&0xffffffff,'velocity_unit':vec(m,LOCAL+72),'scaled_length':m[LOCAL+84]&0xffffffff,'lateral_scalar':m[LOCAL+168]&0xffffffff if nonzero else None,'execution':e}
|
| 19 |
+
|
| 20 |
+
def main():
|
| 21 |
+
q,raw,h,ins=source();constants_map=constants(raw,h,list(range(20536+22*4,20536+41*4,4))+[21348,21352,21356]);rows=[]
|
| 22 |
+
for first,second,pitch,velocity in itertools.product([0,20,21,41],[0,22],[0,30,400,-400],[(0,0,0),(3,4,12),(-.5,1,0)]):
|
| 23 |
+
m,a=fixture(first,second,(pitch,45,0));m.update(constants_map)
|
| 24 |
+
for j,v in enumerate(velocity):m[VELOCITY+4*j]=word(v)
|
| 25 |
+
m,_=controllers(ins,m,a);m,_=motion(ins,m);rows.append(lean(ins,m)[1])
|
| 26 |
+
write_json(Path('docs/research/qvm-pose-lean.json'),{'source':q['source'],'sha256':q['sha256'],'probes':rows,'limits':'Actual32797–33167 after actual controllers/motion. Explicit finite sqrt/trig responses. Lateral scalar local168 is scratch and has no subsequent LOAD in32254; no asserted physical lean effect or original native parity.'})
|
| 27 |
+
if __name__=='__main__':main()
|
scripts/test_qvm_pose_lean.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json,unittest,math
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
from test_qvm_ground import word,n,f
|
| 4 |
+
from test_qvm_server_fire_basis import vectors
|
| 5 |
+
|
| 6 |
+
def expected(p):
|
| 7 |
+
a=p['initial'];pitch=n(a['pitch']) if a['active'] else 0
|
| 8 |
+
if a['active'] and pitch>180:pitch=f(pitch-360)
|
| 9 |
+
pitch=f(pitch+(15 if a['animation'] in [20,21] else 5));v=list(map(n,a['velocity']));length=f(math.sqrt(f(f(f(v[0]*v[0])+f(v[1]*v[1]))+f(v[2]*v[2]))));unit=[f(x*f(1/length)) for x in v] if length else v
|
| 10 |
+
if not length:return word(pitch),list(map(word,unit)),word(length),None
|
| 11 |
+
scaled=f(length*n(1036831949));right=vectors(a['basis_angles'])[1];opposite=[f(0-n(x)) for x in right];dot=f(f(f(unit[0]*opposite[0])+f(unit[1]*opposite[1]))+f(unit[2]*opposite[2]));scalar=f(scaled*dot)
|
| 12 |
+
return word(pitch),list(map(word,unit)),word(scaled),word(scalar)
|
| 13 |
+
class PoseLeanTests(unittest.TestCase):
|
| 14 |
+
@classmethod
|
| 15 |
+
def setUpClass(cls):cls.rows=json.loads(Path('docs/research/qvm-pose-lean.json').read_text())['probes']
|
| 16 |
+
def test_independent_pitch_normalization_and_lateral_scalar(self):
|
| 17 |
+
self.assertEqual(len(self.rows),96)
|
| 18 |
+
for p in self.rows:self.assertEqual((p['published_pitch'],p['velocity_unit'],p['scaled_length'],p['lateral_scalar']),expected(p));self.assertEqual(p['body_pitch'],p['published_pitch'])
|
| 19 |
+
def test_zero_velocity_skips_basis_calls(self):
|
| 20 |
+
for p in self.rows:self.assertEqual([c['target'] for c in p['execution']['calls']],[-107]+([-104,-105]*3 if p['lateral_scalar'] is not None else []))
|
| 21 |
+
def test_pitch_special_ids_and_inactive_cases_present(self):
|
| 22 |
+
self.assertEqual({p['initial']['animation'] for p in self.rows},{0,20,21,41});self.assertEqual({p['initial']['active'] for p in self.rows},{0,1})
|
| 23 |
+
def test_lateral_scratch_has_no_later_consumer(self):
|
| 24 |
+
from qvm_research_support import source
|
| 25 |
+
ins=source()[3]
|
| 26 |
+
self.assertFalse(any(a['opcode']=='LOCAL' and a['operand']==168 and b['opcode']=='LOAD4' for a,b in zip(ins[33168:33389],ins[33169:33390])))
|
| 27 |
+
if __name__=='__main__':unittest.main()
|