nmarshall commited on
Commit
c377fd6
·
1 Parent(s): bbf9a55

qvm: complete bounded walking

Browse files
docs/ASSET_PIPELINE_TODO.md CHANGED
@@ -367,3 +367,6 @@ Research progress: RE-556 [report](research/QVM_WALK_WISH.md); remaining native/
367
 
368
 
369
  Research progress: RE-557 [report](research/QVM_WALK_POLICY.md); remaining native/content/runtime/platform scope stays open.
 
 
 
 
367
 
368
 
369
  Research progress: RE-557 [report](research/QVM_WALK_POLICY.md); remaining native/content/runtime/platform scope stays open.
370
+
371
+
372
+ Research progress: RE-558 [report](research/QVM_WALKING_MODE.md); remaining native/content/runtime/platform scope stays open.
docs/FINDINGS.md CHANGED
@@ -725,3 +725,6 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
725
 
726
 
727
  **RE-557 — Recover walking speed policy acceleration projection and resource:** Walking applies flag/state/resource/water caps then a timed state128 override, selects acceleration from surface/flags/speed, performs two normalized plane projections and passes saved pre-projection speed into39595. [Evidence](research/QVM_WALK_POLICY.md).
 
 
 
 
725
 
726
 
727
  **RE-557 — Recover walking speed policy acceleration projection and resource:** Walking applies flag/state/resource/water caps then a timed state128 override, selects acceleration from surface/flags/speed, performs two normalized plane projections and passes saved pre-projection speed into39595. [Evidence](research/QVM_WALK_POLICY.md).
728
+
729
+
730
+ **RE-558 — Complete bounded walking wrapper and combined main handoffs:** Complete43626 routes actual entry to air/water or normal policy, clears32 and runs60091(0) only when horizontal velocity is nonzero; actual main posture/contents/ground/timer/action/query and post-ground share the resulting state. [Evidence](research/QVM_WALKING_MODE.md).
docs/PROVISIONAL_TODO.md CHANGED
@@ -679,3 +679,6 @@ Research progress: RE-556 [report](research/QVM_WALK_WISH.md); remaining native/
679
 
680
 
681
  Research progress: RE-557 [report](research/QVM_WALK_POLICY.md); remaining native/content/runtime/platform scope stays open.
 
 
 
 
679
 
680
 
681
  Research progress: RE-557 [report](research/QVM_WALK_POLICY.md); remaining native/content/runtime/platform scope stays open.
682
+
683
+
684
+ Research progress: RE-558 [report](research/QVM_WALKING_MODE.md); remaining native/content/runtime/platform scope stays open.
docs/RESEARCH_LEDGER.md CHANGED
@@ -487,3 +487,12 @@ Walking friction and copied-command scaling precede actual40679, flattening and
487
  ## 2026-10-19 — RE-557 Recover walking speed policy acceleration projection and resource (separate task commit)
488
 
489
  Walking applies flag/state/resource/water caps then a timed state128 override, selects acceleration from surface/flags/speed, performs two normalized plane projections and passes saved pre-projection speed into39595. 30 command/policy profiles and four independent tests reproduce exact speed/cap/coefficient rounding, acceleration, both projections, timed250 boundary and resource outputs. Full suite: 755 tests pass. Report regenerates byte-identically (416388 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
 
 
 
 
 
 
 
 
 
 
487
  ## 2026-10-19 — RE-557 Recover walking speed policy acceleration projection and resource (separate task commit)
488
 
489
  Walking applies flag/state/resource/water caps then a timed state128 override, selects acceleration from surface/flags/speed, performs two normalized plane projections and passes saved pre-projection speed into39595. 30 command/policy profiles and four independent tests reproduce exact speed/cap/coefficient rounding, acceleration, both projections, timed250 boundary and resource outputs. Full suite: 755 tests pass. Report regenerates byte-identically (416388 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
490
+
491
+
492
+ ## 2026-10-19 — RE-558 Complete bounded walking wrapper and combined main handoffs (separate task commit)
493
+
494
+ Complete43626 routes actual entry to air/water or normal policy, clears32 and runs60091(0) only when horizontal velocity is nonzero; actual main posture/contents/ground/timer/action/query and post-ground share the resulting state. 26 standalone/8 combined-main fixtures and four independent tests compose all prior child oracles, native-supplied wrapper/step paths, zero-horizontal controls, entry events/resource and higher-priority mode suppression. All ten direct test entrypoints are executable. Full suite: 759 tests pass. Report regenerates byte-identically (1716605 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
495
+
496
+ ### Ten-task batch final regression audit
497
+
498
+ RE-549–558 each has its own code/tests/report/documentation commit. All759 tests pass; all ten direct test commands execute four tests each. Ten new reports and six prior contact/main/active/flagged/walk-entry/air reports regenerate byte-identically after final integration. New reports remain below the2MiB normal-Git cap. Completed coverage and explicit native-supplied limits are indexed in `research/QVM_MOVEMENT_BATCH.md`; RE-559 preserves remaining original-reference/native/runtime/rendering/content/platform work. No asset payloads or Rust runtime were added.
docs/REVERSE_ENGINEERING_TODO.md CHANGED
@@ -716,3 +716,9 @@ Purpose: turn the supplied installation into an evidence-backed specification of
716
 
717
 
718
  - [x] RE-557 Recover walking speed policy acceleration projection and resource ([report](research/QVM_WALK_POLICY.md)).
 
 
 
 
 
 
 
716
 
717
 
718
  - [x] RE-557 Recover walking speed policy acceleration projection and resource ([report](research/QVM_WALK_POLICY.md)).
719
+
720
+
721
+ - [ ] RE-559 Validate these movement paths against original execution and collision-consistent native traces; complete remaining main prefix/suffix/scheduler/event-resource-animation consumers, full cross-module rules/network/audio/rendering/assets coverage and Rust/Bevy/Solari macOS/Linux platform prototype and runtime. See the [ten-task batch](research/QVM_MOVEMENT_BATCH.md) for bounded completed coverage.
722
+
723
+
724
+ - [x] RE-558 Complete bounded walking wrapper and combined main handoffs ([report](research/QVM_WALKING_MODE.md)).
docs/research/QVM_MOVEMENT_BATCH.md CHANGED
@@ -4,15 +4,18 @@ Each task has its own tested code/report/documentation commit. Completed rows li
4
 
5
  | Task | Completion scope |
6
  | --- | --- |
7
- | RE-549 | Complete40679 direction classifier and idle transitions. |
8
- | RE-550 | File-backed162-direction encode/decode services and tie/index rules. |
9
- | RE-551 | Wall-contact42838 guards, trace geometry, hull restoration and failure state. |
10
- | RE-552 | Wall success40966/event86/animation and ordinary-air continuation. |
11
- | RE-553 | Complete41486 water-entry query and launch state. |
12
- | RE-554 | Actual41848 water-entry guard and41768 fallback routing. |
13
- | RE-555 | Remaining41848 swim wish/acceleration/clip/slide body. |
14
- | RE-556 | Walking43626 ordinary direction/basis/wish producer. |
15
- | RE-557 | Walking acceleration, slope velocity and resource suffix. |
16
- | RE-558 | Complete bounded walking wrapper and actual main/environment handoffs. |
17
 
18
  Native roots, trace/content records and initial finite state remain supplied until actual native behavior is established. These tasks add research fixtures, not a Rust/Bevy/Solari runtime or platform proof. The wall/swim/walk scopes may expose additional required callees; those dependencies are recovered or explicitly recorded within the corresponding task before it is marked complete.
 
 
 
 
4
 
5
  | Task | Completion scope |
6
  | --- | --- |
7
+ | [RE-549](QVM_MOVE_DIRECTION.md) ✓ | Complete40679 direction classifier and idle transitions. |
8
+ | [RE-550](QVM_DIRECTION_CODEC.md) ✓ | File-backed162-direction encode/decode services and tie/index rules. |
9
+ | [RE-551](QVM_WALL_PROBE.md) ✓ | Wall-contact42838 guards, trace geometry, hull restoration and failure state. |
10
+ | [RE-552](QVM_WALL_ACTION.md) ✓ | Wall success40966/event86/animation and ordinary-air continuation. |
11
+ | [RE-553](QVM_WATER_ENTRY.md) ✓ | Complete41486 water-entry query and launch state. |
12
+ | [RE-554](QVM_WATER_ROUTE.md) ✓ | Actual41848 water-entry guard and41768 fallback routing. |
13
+ | [RE-555](QVM_SWIM_MODE.md) ✓ | Remaining41848 swim wish/acceleration/clip/slide body. |
14
+ | [RE-556](QVM_WALK_WISH.md) ✓ | Walking43626 ordinary direction/basis/wish producer. |
15
+ | [RE-557](QVM_WALK_POLICY.md) ✓ | Walking acceleration, slope velocity and resource suffix. |
16
+ | [RE-558](QVM_WALKING_MODE.md) ✓ | Complete bounded walking wrapper and actual main/environment handoffs. |
17
 
18
  Native roots, trace/content records and initial finite state remain supplied until actual native behavior is established. These tasks add research fixtures, not a Rust/Bevy/Solari runtime or platform proof. The wall/swim/walk scopes may expose additional required callees; those dependencies are recovered or explicitly recorded within the corresponding task before it is marked complete.
19
+
20
+
21
+ All ten tasks are complete as separately tested commits. Each report labels finite/native-supplied inputs and remaining runtime limits. The final batch verifies all direct test entrypoints, full-suite checks and byte-identical regeneration of existing reports. RE-559 tracks follow-up reference/native/renderer/runtime and remaining scheduler/consumer work.
docs/research/QVM_WALKING_MODE.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # Complete bounded walking wrapper and combined main handoffs
2
+
3
+ RE-558. Reproduce with `python3 scripts/analyze_qvm_walking_mode.py`; check with `python3 scripts/test_qvm_walking_mode.py`. The [machine report](qvm-walking-mode.json) retains source identity and bounded fixtures.
4
+
5
+ Normal walking now continues after the resource update into source horizontal-zero routing and the real gravity-off60091 wrapper, including conditional step/second-slide/fallback. A vertical-only control confirms the skip checks X/Y, not full speed. Successful40966 delegation uses actual ordinary air or41848 water body/fallback; normal walking uses the recovered speed/resource policy. Eight main fixtures combine actual posture, contents, ground, timer, action, query, selected movement and post-environment. Flat-ground source processing can clear128 before dispatch; retained128 controls use supplied steep-ground responses and select41768, suppressing walking effects. Native trace/content/root inputs remain supplied and legal consistency is unverified. The task also validates batch test CLI entrypoints and preserves earlier default report formats. Whole-game runtime, reference execution, native collision correctness, main prefix/suffix consumers, networking/rendering/assets and macOS/Linux Rust/Bevy/Solari implementation remain open.
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
@@ -280,3 +280,6 @@ The extension collector adds five focused tests for native tail calls, command-r
280
 
281
 
282
  [RE-557: Recover walking speed policy acceleration projection and resource](QVM_WALK_POLICY.md). Reproduce with `python3 scripts/analyze_qvm_walk_policy.py`; check with `python3 scripts/test_qvm_walk_policy.py`.
 
 
 
 
280
 
281
 
282
  [RE-557: Recover walking speed policy acceleration projection and resource](QVM_WALK_POLICY.md). Reproduce with `python3 scripts/analyze_qvm_walk_policy.py`; check with `python3 scripts/test_qvm_walk_policy.py`.
283
+
284
+
285
+ [RE-558: Complete bounded walking wrapper and combined main handoffs](QVM_WALKING_MODE.md). Reproduce with `python3 scripts/analyze_qvm_walking_mode.py`; check with `python3 scripts/test_qvm_walking_mode.py`.
docs/research/qvm-walking-mode.json ADDED
The diff for this file is too large to render. See raw diff
 
scripts/analyze_qvm_walk_entry.py CHANGED
@@ -18,7 +18,7 @@ from analyze_vm_extensions import verified
18
  LOCAL=0x62000000
19
 
20
 
21
- def route(ins,m,cmd,air_effect=None):
22
  initial=snapshot(m);level=m[FRAME+212];basis=[m[35023892+4*i]&0xffffffff for i in range(3)];normal=[m[35023968+4*i]&0xffffffff for i in range(3)];pc=43627;trace=[];calls=[];launch=None;air=None
23
  while True:
24
  t=trace_slice(ins,43627,45199,m,{},resume_at=pc,stop_targets=[s for s in [43662,43683] if s!=pc],local_base=LOCAL,call_results={43660:0},limit=1024);m=t['memory'];trace+=t['trace'];calls+=t['calls'];pc=t['stop']
@@ -26,7 +26,12 @@ def route(ins,m,cmd,air_effect=None):
26
  else:break
27
  delegated=[c['target'] for c in calls if c['target'] in [41848,42838]];target=delegated[0] if delegated else None
28
  if target==42838 and air_effect:m,air=air_effect(ins,m,cmd)
29
- return m,{'initial':initial,'level':level,'basis':basis,'normal':normal,'commands':list(cmd),'entry':launch,'delegated_target':target,'stop_instruction':pc,'air':air,'final':snapshot(m),'calls':calls,**trace_fields({'trace':trace},False)}
 
 
 
 
 
30
 
31
 
32
  def main_case(ins,constants,up,flags,air_effect=None,meter=4000):
 
18
  LOCAL=0x62000000
19
 
20
 
21
+ def route(ins,m,cmd,air_effect=None,water_effect=None):
22
  initial=snapshot(m);level=m[FRAME+212];basis=[m[35023892+4*i]&0xffffffff for i in range(3)];normal=[m[35023968+4*i]&0xffffffff for i in range(3)];pc=43627;trace=[];calls=[];launch=None;air=None
23
  while True:
24
  t=trace_slice(ins,43627,45199,m,{},resume_at=pc,stop_targets=[s for s in [43662,43683] if s!=pc],local_base=LOCAL,call_results={43660:0},limit=1024);m=t['memory'];trace+=t['trace'];calls+=t['calls'];pc=t['stop']
 
26
  else:break
27
  delegated=[c['target'] for c in calls if c['target'] in [41848,42838]];target=delegated[0] if delegated else None
28
  if target==42838 and air_effect:m,air=air_effect(ins,m,cmd)
29
+ water=None
30
+ if target==41848 and water_effect:m,water=water_effect(ins,m,cmd)
31
+ report={'initial':initial,'level':level,'basis':basis,'normal':normal,'commands':list(cmd),'entry':launch,'delegated_target':target,'stop_instruction':pc,'air':air,'final':snapshot(m),'calls':calls,**trace_fields({'trace':trace},False)}
32
+
33
+ if water_effect:report['water']=water
34
+ return m,report
35
 
36
 
37
  def main_case(ins,constants,up,flags,air_effect=None,meter=4000):
scripts/analyze_qvm_walking_mode.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Full finite43626 routing/ordinary policy/wrapper and actual combined main."""
3
+ import itertools
4
+ from pathlib import Path
5
+ from qvm_research_support import source,memory,constants,execute
6
+ from analyze_qvm_walk_policy import policy,CONFIG
7
+ from analyze_qvm_walk_wish import LOCAL
8
+ from analyze_qvm_walk_entry import route
9
+ from analyze_qvm_air_mode import air
10
+ from analyze_qvm_swim_mode import swim
11
+ from analyze_qvm_contact_callers import wrapper
12
+ from analyze_qvm_acceleration import PS,FRAME,word
13
+ from analyze_qvm_jump_entry import snapshot
14
+ from analyze_qvm_main_contact import probe
15
+ from analyze_qvm_main_environment import contents
16
+ from analyze_qvm_combined_ground import ground_all
17
+ from analyze_qvm_main_posture import posture
18
+ from analyze_qvm_action_probe import action,PATTERNS
19
+ from analyze_qvm_main_query import coupled
20
+ from analyze_qvm import write_json
21
+
22
+
23
+ def walking(ins,m,cmd,pattern='clear'):
24
+ def airborne(i,m,c):return air(i,m,c,pattern)
25
+ def water(i,m,c):return swim(i,m,c,(1,0) if c[2]>=10 else (0,0),pattern)
26
+ m,p=route(ins,m,cmd,airborne,water);normal=None;w=None;tail=None
27
+ if p['stop_instruction']==43683:
28
+ cmd=p['commands'];m,normal=policy(ins,m,cmd)
29
+ def move(i,m,a,c):
30
+ nonlocal w
31
+ m,w=wrapper(i,m,pattern,'clear','clear',a[8]);return m,c,w['return_word'],{}
32
+ m,cmd,tail=execute(ins,45143,45199,m,cmd,LOCAL,{60091:move})
33
+ return m,{'route':p,'policy':normal,'wrapper':w,'tail':tail,'final':snapshot(m)}
34
+
35
+
36
+ def main():
37
+ q,raw,h,ins=source();cfg=constants(raw,h,CONFIG+[21196]);rows=[]
38
+ for cmd,level,pattern in itertools.product([(0,0,0),(100,0,0),(-128,127,0),(100,0,10)],[0,2,3],['clear','contacts']):
39
+ m=memory(raw,h,cmd);m.update(cfg);m[PS+220]=0;m[FRAME+212]=level;rows.append(walking(ins,m,cmd,pattern)[1])
40
+ for z in [0,1]:
41
+ m=memory(raw,h,(0,0,0),flags=32);m.update(cfg);m[PS+220]=0
42
+ for j,v in enumerate([0,0,z]):m[PS+32+4*j]=word(v)
43
+ for j,v in enumerate([0,0,1]):m[35023968+4*j]=word(v)
44
+ rows.append(walking(ins,m,(0,0,0))[1])
45
+ chains=[]
46
+ for up,flags,pattern in itertools.product([0,10],[32,160],['clear','contacts']):
47
+ cmd=(100,0,up);m=memory(raw,h,cmd,flags=flags);m.update(cfg);m.update({PS+220:0,PS+184:8000,PS+376:17})
48
+ def env(i,m,target,phase):
49
+ m,r=contents(i,m,[0,0,0]) if target==47217 else ground_all(i,m,'flat' if flags==32 else 'steep');r['phase']=phase;return m,r
50
+ def post(i,m):return posture(i,m,up,0)
51
+ def act(i,m):return action(i,m,0,PATTERNS['none'])
52
+ def query(i,m):return coupled(i,m,{'forward':100,'fractions':(1,1)})
53
+ def mode(i,m):return walking(i,m,cmd,pattern)
54
+ p=probe(ins,1016,0,flags,'clear',initial_memory=m,environment_effect=env,posture_effect=post,action_effect=act,query_effect=query,walking_mode_effect=mode);p.update({'commands':list(cmd),'input_flags':flags});chains.append(p)
55
+ write_json(Path('docs/research/qvm-walking-mode.json'),{'source':q['source'],'sha256':q['sha256'],'constants':{str(a):v for a,v in cfg.items()},'probes':rows,'main_chains':chains,'limits':'Full bounded43626 entry/ordinary/water-air delegation with recovered children; actual main posture/content/ground/timer/action/query/walking and post-environment share memory. Native roots/contents/stand/ground/slide/step traces supplied, not collision-derived. No original executable/full QVM/native physics/rendering executes. Remaining wall-specific main integration, other main prefix/suffix/consumers/native legal domains/reference execution/full Rust/Bevy/Solari platforms remain open.'})
56
+
57
+
58
+ if __name__=='__main__':main()
scripts/test_qvm_direction_codec.py CHANGED
@@ -27,3 +27,6 @@ class DirectionCodecTests(unittest.TestCase):
27
  q=json.loads(Path('docs/research/qvm/qagame.json').read_text());raw=Path(q['source']['member']['output']).read_bytes();h,_=decode(raw);self.assertEqual(self.r['sha256'],hashlib.sha256(raw).hexdigest())
28
  for i,v in enumerate(self.r['table']):
29
  for j,w in enumerate(v):self.assertEqual(int.from_bytes(raw[h['data_offset']+21732+12*i+4*j:h['data_offset']+21736+12*i+4*j],'little'),w)
 
 
 
 
27
  q=json.loads(Path('docs/research/qvm/qagame.json').read_text());raw=Path(q['source']['member']['output']).read_bytes();h,_=decode(raw);self.assertEqual(self.r['sha256'],hashlib.sha256(raw).hexdigest())
28
  for i,v in enumerate(self.r['table']):
29
  for j,w in enumerate(v):self.assertEqual(int.from_bytes(raw[h['data_offset']+21732+12*i+4*j:h['data_offset']+21736+12*i+4*j],'little'),w)
30
+
31
+
32
+ if __name__=='__main__':unittest.main()
scripts/test_qvm_move_direction.py CHANGED
@@ -20,3 +20,6 @@ class MoveDirectionTests(unittest.TestCase):
20
  for p in self.r['probes']:self.assertEqual(p['calls'],[]);self.assertEqual(p['canary'],123)
21
  def test_source_partition_identity(self):
22
  q=json.loads(Path('docs/research/qvm/qagame.json').read_text());self.assertEqual(self.r['sha256'],hashlib.sha256(Path(q['source']['member']['output']).read_bytes()).hexdigest());self.assertEqual(self.r['instructions'][0]['index'],40679);self.assertEqual(self.r['instructions'][-1]['index'],40965)
 
 
 
 
20
  for p in self.r['probes']:self.assertEqual(p['calls'],[]);self.assertEqual(p['canary'],123)
21
  def test_source_partition_identity(self):
22
  q=json.loads(Path('docs/research/qvm/qagame.json').read_text());self.assertEqual(self.r['sha256'],hashlib.sha256(Path(q['source']['member']['output']).read_bytes()).hexdigest());self.assertEqual(self.r['instructions'][0]['index'],40679);self.assertEqual(self.r['instructions'][-1]['index'],40965)
23
+
24
+
25
+ if __name__=='__main__':unittest.main()
scripts/test_qvm_swim_mode.py CHANGED
@@ -40,3 +40,6 @@ class SwimTests(unittest.TestCase):
40
  self.assertEqual(sum(m['water_mode']['body'] is None for m in self.r['main_chains']),2)
41
  for m in self.r['main_chains']:
42
  p=m['water_mode'];self.assertEqual(p['body'] is None,p['prefix']['fallback'] is not None)
 
 
 
 
40
  self.assertEqual(sum(m['water_mode']['body'] is None for m in self.r['main_chains']),2)
41
  for m in self.r['main_chains']:
42
  p=m['water_mode'];self.assertEqual(p['body'] is None,p['prefix']['fallback'] is not None)
43
+
44
+
45
+ if __name__=='__main__':unittest.main()
scripts/test_qvm_walk_policy.py CHANGED
@@ -46,3 +46,6 @@ class WalkPolicyTests(unittest.TestCase):
46
  def test_surface_or_flag_selects_gravity_and_low_accel(self):
47
  rows=[p for p in self.r['probes'] if p['inputs']['surface']&2 or p['inputs']['flags']&64];self.assertEqual(len(rows),6)
48
  for p in rows:self.assertEqual(p['acceleration']['acceleration_float_word'],speed(p,self.c)[1])
 
 
 
 
46
  def test_surface_or_flag_selects_gravity_and_low_accel(self):
47
  rows=[p for p in self.r['probes'] if p['inputs']['surface']&2 or p['inputs']['flags']&64];self.assertEqual(len(rows),6)
48
  for p in rows:self.assertEqual(p['acceleration']['acceleration_float_word'],speed(p,self.c)[1])
49
+
50
+
51
+ if __name__=='__main__':unittest.main()
scripts/test_qvm_walk_wish.py CHANGED
@@ -31,3 +31,6 @@ class WalkWishTests(unittest.TestCase):
31
  flat=n(p['normal'][2])==1;self.assertEqual(all(n(v[2])==0 for v in p['basis_after']),flat)
32
  def test_idle_old2_and6_feed_real_direction_child(self):
33
  idle=[p for p in self.r['probes'] if p['scale']['movement_bytes']==[0,0,0]];self.assertEqual({p['direction']['after'] for p in idle},{1,7})
 
 
 
 
31
  flat=n(p['normal'][2])==1;self.assertEqual(all(n(v[2])==0 for v in p['basis_after']),flat)
32
  def test_idle_old2_and6_feed_real_direction_child(self):
33
  idle=[p for p in self.r['probes'] if p['scale']['movement_bytes']==[0,0,0]];self.assertEqual({p['direction']['after'] for p in idle},{1,7})
34
+
35
+
36
+ if __name__=='__main__':unittest.main()
scripts/test_qvm_walking_mode.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import copy,json,unittest
2
+ from pathlib import Path
3
+ from test_qvm_ground import f,n,word
4
+ from test_qvm_walk_policy import check as check_policy
5
+ from test_qvm_air_mode import check as check_air
6
+ from test_qvm_swim_mode import check as check_swim
7
+ from test_qvm_water_route import check_wrapper
8
+ from test_qvm_jump_entry import check as check_entry
9
+
10
+
11
+ def check(test,p,c):
12
+ route=p['route']
13
+ if route['entry']:check_entry(test,route['entry'])
14
+ if p['policy']:
15
+ check_policy(test,p['policy'],c);s=copy.deepcopy(p['policy']['final']);s['flags']&=~32
16
+ if p['wrapper']:
17
+ w=p['wrapper'];check_wrapper(test,w,p['policy']['wish']['normal']);test.assertEqual(w['before']['velocity'],s['velocity']);test.assertEqual(w['before']['flags'],s['flags']);test.assertEqual(w['first_slide']['gravity'],0);s.update(w['final'])
18
+ else:test.assertEqual([n(x) for x in s['velocity'][:2]],[0,0]);test.assertEqual(p['tail']['calls'],[])
19
+ test.assertEqual(p['final'],s)
20
+ else:
21
+ test.assertEqual(p['final'],route['final'])
22
+ if route['air']:check_air(test,route['air'],c)
23
+ if route['water']:
24
+ w=route['water'];check_swim(test,w,c)
25
+ if w['prefix']['fallback']:
26
+ mode=w['prefix']['fallback'];check_wrapper(test,mode['wrapper'],w['prefix']['normal']);s=copy.deepcopy(mode['wrapper']['final']);z=f(n(s['velocity'][2])-f(800*n(w['prefix']['dt'])));s['velocity'][2]=word(z)
27
+ if z<0:s['flags']&=~192;s['timer']=0
28
+ test.assertEqual(mode['mode_final'],s)
29
+
30
+
31
+ class WalkingModeTests(unittest.TestCase):
32
+ @classmethod
33
+ def setUpClass(cls):cls.r=json.loads(Path('docs/research/qvm-walking-mode.json').read_text());cls.c={21160:100,21212:1,21220:5,21224:3000,**{int(a):n(v) for a,v in cls.r['constants'].items()}}
34
+ def test_all26_walking_or_delegated_states(self):
35
+ self.assertEqual(len(self.r['probes']),26)
36
+ for p in self.r['probes']:check(self,p,self.c)
37
+ def test_horizontal_zero_skips_wrapper_even_vertical_nonzero(self):
38
+ a,b=self.r['probes'][-2:]
39
+ for p in [a,b]:self.assertIsNone(p['wrapper']);self.assertFalse(p['final']['flags']&32)
40
+ self.assertEqual(n(a['final']['velocity'][2]),0);self.assertEqual(n(b['final']['velocity'][2]),1)
41
+ def test_main_actual_selected_walking_and_mode_handoff(self):
42
+ self.assertEqual(len(self.r['main_chains']),8);count=0
43
+ for m in self.r['main_chains']:
44
+ p=m['walking_mode'];self.assertEqual(p is not None,m['selected_mode']==43626);self.assertIsNotNone(m['posture']);self.assertEqual(len(m['environment']),4)
45
+ if p:
46
+ count+=1;check(self,p,self.c);self.assertEqual(p['route']['initial']['velocity'],m['at_mode']['velocity']);self.assertEqual(p['final']['velocity'],m['after_dispatch']['velocity']);self.assertEqual(p['final']['origin'],m['after_dispatch']['origin'])
47
+ else:self.assertEqual(m['selected_mode'],41768)
48
+ self.assertEqual(count,4)
49
+ def test_resource_and_entry_queue_survive_wrapper_and_main(self):
50
+ for m in self.r['main_chains']:
51
+ p=m['walking_mode']
52
+ if p:
53
+ self.assertEqual(m['walking_final']['184'],p['final']['meter']);self.assertEqual(m['walking_final']['108'],p['final']['queue']['sequence'])
54
+ if m['commands'][2]==10:self.assertEqual(p['final']['queue']['events'][0],99);self.assertIsNotNone(p['route']['air'])
55
+
56
+
57
+ if __name__=='__main__':unittest.main()
scripts/test_qvm_wall_action.py CHANGED
@@ -31,3 +31,6 @@ class WallActionTests(unittest.TestCase):
31
  for p in self.r['probes']:
32
  if p['air']:
33
  check_air(self,p['air'],self.c);self.assertEqual(p['air']['initial']['velocity'],p['before_air']['velocity']);self.assertEqual(p['final']['velocity'],p['air']['final']['velocity']);self.assertEqual(p['final']['queue'],p['before_air']['queue'])
 
 
 
 
31
  for p in self.r['probes']:
32
  if p['air']:
33
  check_air(self,p['air'],self.c);self.assertEqual(p['air']['initial']['velocity'],p['before_air']['velocity']);self.assertEqual(p['final']['velocity'],p['air']['final']['velocity']);self.assertEqual(p['final']['queue'],p['before_air']['queue'])
34
+
35
+
36
+ if __name__=='__main__':unittest.main()
scripts/test_qvm_wall_probe.py CHANGED
@@ -23,3 +23,6 @@ class WallProbeTests(unittest.TestCase):
23
  for p in self.r['probes']:
24
  self.assertEqual(len(p['calls']),int(p['request'] is not None))
25
  if p['old_count']==5:self.assertIsNone(p['request'])
 
 
 
 
23
  for p in self.r['probes']:
24
  self.assertEqual(len(p['calls']),int(p['request'] is not None))
25
  if p['old_count']==5:self.assertIsNone(p['request'])
26
+
27
+
28
+ if __name__=='__main__':unittest.main()
scripts/test_qvm_water_entry.py CHANGED
@@ -22,3 +22,6 @@ class WaterEntryTests(unittest.TestCase):
22
  for j,q in enumerate(p['queries']):self.assertEqual(q['point'],base[:2]+[word(f(n(base[2])+4+16*j))]);self.assertEqual(q['entity'],7)
23
  def test_no_event_or_inventory_cost_side_effect(self):
24
  for p in self.r['probes']:self.assertEqual(p['final']['queue'],p['initial']['queue']);self.assertEqual(p['final']['meter'],p['initial']['meter']);self.assertEqual(p['final']['inventory'],p['initial']['inventory'])
 
 
 
 
22
  for j,q in enumerate(p['queries']):self.assertEqual(q['point'],base[:2]+[word(f(n(base[2])+4+16*j))]);self.assertEqual(q['entity'],7)
23
  def test_no_event_or_inventory_cost_side_effect(self):
24
  for p in self.r['probes']:self.assertEqual(p['final']['queue'],p['initial']['queue']);self.assertEqual(p['final']['meter'],p['initial']['meter']);self.assertEqual(p['final']['inventory'],p['initial']['inventory'])
25
+
26
+
27
+ if __name__=='__main__':unittest.main()
scripts/test_qvm_water_route.py CHANGED
@@ -36,3 +36,6 @@ class WaterRouteTests(unittest.TestCase):
36
  for k,v in s.items():self.assertEqual(p['final'][k],v)
37
  def test_call_order_no_prepared_fallback_on_failure(self):
38
  for p in self.r['probes']:self.assertEqual([c['target'] for c in p['execution']['calls']],[41486,41768] if p['fallback'] else [41486])
 
 
 
 
36
  for k,v in s.items():self.assertEqual(p['final'][k],v)
37
  def test_call_order_no_prepared_fallback_on_failure(self):
38
  for p in self.r['probes']:self.assertEqual([c['target'] for c in p['execution']['calls']],[41486,41768] if p['fallback'] else [41486])
39
+
40
+
41
+ if __name__=='__main__':unittest.main()