nmarshall commited on
Commit
e2a6045
·
1 Parent(s): 3579cc4

qvm: base-dependent firing gate

Browse files
docs/ASSET_PIPELINE_TODO.md CHANGED
@@ -484,3 +484,6 @@ Research progress: RE-599 [report](research/QVM_SERVER_SHOT_SETUP.md); remaining
484
 
485
 
486
  Research progress: RE-600 [report](research/QVM_GRENADE_SETUP.md); remaining native/content/runtime/platform scope stays open.
 
 
 
 
484
 
485
 
486
  Research progress: RE-600 [report](research/QVM_GRENADE_SETUP.md); remaining native/content/runtime/platform scope stays open.
487
+
488
+
489
+ Research progress: RE-601 [report](research/QVM_BASE_FIRE_GATE.md); remaining native/content/runtime/platform scope stays open.
docs/FINDINGS.md CHANGED
@@ -842,3 +842,6 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
842
 
843
 
844
  **RE-600 — Grenade record construction and inherited velocity:** 285971 looks up weapon7 mode, biases forwardZ by.2 and normalizes, builds a grenade descriptor, quantizes mode-scaled launch velocity, then adds owner and optionally matching-ground velocity. [Evidence](research/QVM_GRENADE_SETUP.md).
 
 
 
 
842
 
843
 
844
  **RE-600 — Grenade record construction and inherited velocity:** 285971 looks up weapon7 mode, biases forwardZ by.2 and normalizes, builds a grenade descriptor, quantizes mode-scaled launch velocity, then adds owner and optionally matching-ground velocity. [Evidence](research/QVM_GRENADE_SETUP.md).
845
+
846
+
847
+ **RE-601 — Base-dependent firing gate scan and distance contract:** 288903 requires mode8 and active!=1, scans type18 bases, then checks64-unit distance/ground and chooses nearest point with ties selecting the second; invalid base cardinalities are explicit stop boundaries. [Evidence](research/QVM_BASE_FIRE_GATE.md).
docs/PROVISIONAL_TODO.md CHANGED
@@ -802,3 +802,6 @@ Research progress: RE-599 [report](research/QVM_SERVER_SHOT_SETUP.md); remaining
802
 
803
 
804
  Research progress: RE-600 [report](research/QVM_GRENADE_SETUP.md); remaining native/content/runtime/platform scope stays open.
 
 
 
 
802
 
803
 
804
  Research progress: RE-600 [report](research/QVM_GRENADE_SETUP.md); remaining native/content/runtime/platform scope stays open.
805
+
806
+
807
+ Research progress: RE-601 [report](research/QVM_BASE_FIRE_GATE.md); remaining native/content/runtime/platform scope stays open.
docs/RESEARCH_LEDGER.md CHANGED
@@ -690,3 +690,8 @@ Actual outer31 publication reaches server151634, which writes client4140=0 and43
690
  ## 2026-10-20 — RE-600 Grenade record construction and inherited velocity (separate task commit)
691
 
692
  285971 looks up weapon7 mode, biases forwardZ by.2 and normalizes, builds a grenade descriptor, quantizes mode-scaled launch velocity, then adds owner and optionally matching-ground velocity. 37 independent full-record fixtures check slot0/15/missing lookup, two source speeds, zero after bias, allocation/query ABI and all position/trajectory/ownership/think fields. Full suite: 911 tests pass. Report regenerates byte-identically (649857 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
 
 
 
 
 
 
690
  ## 2026-10-20 — RE-600 Grenade record construction and inherited velocity (separate task commit)
691
 
692
  285971 looks up weapon7 mode, biases forwardZ by.2 and normalizes, builds a grenade descriptor, quantizes mode-scaled launch velocity, then adds owner and optionally matching-ground velocity. 37 independent full-record fixtures check slot0/15/missing lookup, two source speeds, zero after bias, allocation/query ABI and all position/trajectory/ownership/think fields. Full suite: 911 tests pass. Report regenerates byte-identically (649857 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
693
+
694
+
695
+ ## 2026-10-20 — RE-601 Base-dependent firing gate scan and distance contract (separate task commit)
696
+
697
+ 288903 requires mode8 and active!=1, scans type18 bases, then checks64-unit distance/ground and chooses nearest point with ties selecting the second; invalid base cardinalities are explicit stop boundaries. 36 probes independently check mode/active priority,0/1/2/3 bases, exact65655 float distances and short-circuit calls,64 equality, airborne rejection and tie selection. Full suite: 915 tests pass. Report regenerates byte-identically (169227 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
@@ -844,3 +844,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
844
 
845
 
846
  - [x] RE-600 Grenade record construction and inherited velocity ([report](research/QVM_GRENADE_SETUP.md)).
 
 
 
 
844
 
845
 
846
  - [x] RE-600 Grenade record construction and inherited velocity ([report](research/QVM_GRENADE_SETUP.md)).
847
+
848
+
849
+ - [x] RE-601 Base-dependent firing gate scan and distance contract ([report](research/QVM_BASE_FIRE_GATE.md)).
docs/research/QVM_BASE_FIRE_GATE.md ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Base-dependent firing gate scan and distance contract
2
+
3
+ RE-601. Reproduce with `python3 scripts/analyze_qvm_base_fire_gate.py`; check with `python3 scripts/test_qvm_base_fire_gate.py`. The [machine report](qvm-base-fire-gate.json) retains source identity and bounded fixtures.
4
+
5
+ 288904..289110 is interpreted only through pre-allocation logic. Mode unequal8 or active global35000400==1 returns. The entity scan collects type18 records using880-byte stride. On a third base, execution stops before2319 error handling. With fewer than2, it stops before source reads uninitialized base pointers; no fake pointer is supplied.
6
+
7
+ For exactly2 bases actual65655 computes float32 Euclidean distance using a supplied finite sqrt. Both distances>64 reset weapon timer/state0 and return; ground1023 also rejects after range tests. Otherwise both distances are computed for selection; strict first<second selects first and equality selects second. The chosen point is copied to global35000416 before pending allocator277165.
8
+
9
+ 36 fixtures verify each state/point outcome and1/2/3/4 distance-call short circuit. Allocation, later temp_bomb record setup/linking and round effects are not executed. Source cardinality assumptions and native/world legality require original/reference validation before porting a checked failure policy.
10
+
11
+ 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
@@ -403,3 +403,6 @@ The extension collector adds five focused tests for native tail calls, command-r
403
 
404
 
405
  [RE-600: Grenade record construction and inherited velocity](QVM_GRENADE_SETUP.md). Reproduce with `python3 scripts/analyze_qvm_grenade_setup.py`; check with `python3 scripts/test_qvm_grenade_setup.py`.
 
 
 
 
403
 
404
 
405
  [RE-600: Grenade record construction and inherited velocity](QVM_GRENADE_SETUP.md). Reproduce with `python3 scripts/analyze_qvm_grenade_setup.py`; check with `python3 scripts/test_qvm_grenade_setup.py`.
406
+
407
+
408
+ [RE-601: Base-dependent firing gate scan and distance contract](QVM_BASE_FIRE_GATE.md). Reproduce with `python3 scripts/analyze_qvm_base_fire_gate.py`; check with `python3 scripts/test_qvm_base_fire_gate.py`.
docs/research/qvm-base-fire-gate.json ADDED
The diff for this file is too large to render. See raw diff
 
scripts/analyze_qvm_base_fire_gate.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """288903 mode/base scan and exact distances, stopping before entity allocation."""
3
+ import itertools
4
+ from pathlib import Path
5
+ from qvm_research_support import source,execute
6
+ from qvm_server_fire_support import seed,state,ENTITY,BASES
7
+ from analyze_qvm_acceleration import PS,word
8
+ from analyze_qvm_slide_prefix import vec
9
+ from analyze_qvm import write_json
10
+ LOCAL=0x7b100000
11
+ DISTANCE=0x7b200000
12
+
13
+ def distance(ins,m,args):
14
+ points=[vec(m,args[o]) for o in [8,12]];m[DISTANCE+48]=args[8];m[DISTANCE+52]=args[12];m,c,r=execute(ins,65656,65728,m,(0,0,0),DISTANCE)
15
+ return m,{'points':points,'execution':r,'result':r['return']&0xffffffff}
16
+
17
+ def base_gate(ins,m):
18
+ initial=state(m);mode=m[34090788];active=m[35000400];entities=[{'pointer':BASES+880*j,'type':m[BASES+880*j+4],'point':vec(m,BASES+880*j+92)} for j in range(m[34992508])];before=vec(m,35000416);m[LOCAL+84]=ENTITY
19
+ m,c,scan=execute(ins,288904,289233,m,(0,0,0),LOCAL,boundaries=[288942,288978]);stop=scan['stop'];tail=None;count=m[LOCAL+28]
20
+ if stop==289233:status='mode-rejected'
21
+ elif stop==288942:status='overflow-handler-pending'
22
+ elif count!=2:status='insufficient-bases-unchecked-source'
23
+ else:
24
+ def measured(i,m,a,c):m,r=distance(i,m,a);return m,c,r['result'],r
25
+ m,c,tail=execute(ins,288978,289233,m,(0,0,0),LOCAL,{65655:measured},boundaries=[289111]);stop=tail['stop'];status='allocation-pending' if stop==289111 else 'distance-or-ground-rejected'
26
+ return m,{'initial':initial,'mode':mode,'active':active,'entities':entities,'count':count,'scan_execution':scan,'distance_execution':tail,'status':status,'stop':stop,'selected_point_before':before,'selected_point_after':vec(m,35000416),'final':state(m)}
27
+
28
+ def setup(m,types,points):
29
+ m[34992508]=len(types)
30
+ for j,t in enumerate(types):
31
+ p=BASES+880*j
32
+ for o in range(0,880,4):m[p+o]=0
33
+ m[p+4]=t
34
+ for k,v in enumerate(points[j]):m[p+92+4*k]=word(v)
35
+ return m
36
+
37
+ def main():
38
+ q,raw,h,ins=source();rows=[]
39
+ for mode,active,types in itertools.product([0,8,9],[0,1],[[],[18],[18,0,18],[18,18,18]]):
40
+ m=seed(raw,h,16);m.update({34090788:mode,35000400:active});setup(m,types,[(0,0,0)]*len(types));rows.append(base_gate(ins,m)[1])
41
+ pairs=[((63,0,0),(64,0,0)),((64,0,0),(65,0,0)),((65,0,0),(64,0,0)),((65,0,0),(65,0,0)),((3,4,0),(0,0,5)),((0,0,0),(1,0,0))]
42
+ for points,ground in itertools.product(pairs,[8,1023]):
43
+ m=seed(raw,h,16);m.update({PS+68:ground,PS+44:99,PS+148:3});setup(m,[18,18],points)
44
+ for j in range(3):m[ENTITY+488+4*j]=word(0)
45
+ rows.append(base_gate(ins,m)[1])
46
+ write_json(Path('docs/research/qvm-base-fire-gate.json'),{'source':q['source'],'sha256':q['sha256'],'probes':rows,'limits':'288904..289110 only; actual65655 and supplied sqrt. Stops before allocator289113. Fewer than2 bases stops before uninitialized pointer reads; third base stops before2319 error handler. No invented allocator/world outcome.'})
47
+ if __name__=='__main__':main()
scripts/test_qvm_base_fire_gate.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json,unittest,copy,math
2
+ from pathlib import Path
3
+ from test_qvm_ground import word,n,f
4
+
5
+ def distance_words(a,b):
6
+ v=[f(n(y)-n(x)) for x,y in zip(a,b)];return word(math.sqrt(f(f(f(v[0]*v[0])+f(v[1]*v[1]))+f(v[2]*v[2]))))
7
+
8
+ def expected(p):
9
+ a=copy.deepcopy(p['initial']);point=p['selected_point_before'];bases=[e for e in p['entities'] if e['type']==18]
10
+ if p['mode']!=8 or p['active']==1:return a,point,'mode-rejected',289233
11
+ if len(bases)>2:return a,point,'overflow-handler-pending',288942
12
+ if len(bases)<2:return a,point,'insufficient-bases-unchecked-source',288978
13
+ d=[n(distance_words(a['entity_origin'],e['point'])) for e in bases]
14
+ if min(d)>64 or a['ground']==1023:a['timer']=a['weapon_state']=0;return a,point,'distance-or-ground-rejected',289233
15
+ return a,bases[0 if d[0]<d[1] else 1]['point'],'allocation-pending',289111
16
+ class BaseFireGateTests(unittest.TestCase):
17
+ @classmethod
18
+ def setUpClass(cls):cls.r=json.loads(Path('docs/research/qvm-base-fire-gate.json').read_text())
19
+ def test_all_exact_gate_and_selected_point_outcomes(self):
20
+ self.assertEqual(len(self.r['probes']),36)
21
+ for p in self.r['probes']:a,point,status,stop=expected(p);self.assertEqual((p['final'],p['selected_point_after'],p['status'],p['stop']),(a,point,status,stop))
22
+ def test_actual_distance_helper_squared_sum_and_sqrt(self):
23
+ for p in self.r['probes']:
24
+ if p['distance_execution']:
25
+ for c in p['distance_execution']['children']:
26
+ r=c['effect'];self.assertEqual(r['result'],distance_words(*r['points']));self.assertEqual([x['target'] for x in r['execution']['calls']],[-107])
27
+ def test_call_short_circuit_distance_and_ground(self):
28
+ for p in self.r['probes']:
29
+ if p['distance_execution']:
30
+ bases=[e for e in p['entities'] if e['type']==18];first=n(distance_words(p['initial']['entity_origin'],bases[0]['point']));count=1+(first>64)
31
+ if p['status']=='allocation-pending':count+=2
32
+ self.assertEqual(len(p['distance_execution']['calls']),count)
33
+ def test_ties_choose_second_and_no_unrecovered_call_executes(self):
34
+ for p in self.r['probes']:
35
+ if p['status']=='allocation-pending':
36
+ bases=[e for e in p['entities'] if e['type']==18];a,b=[distance_words(p['initial']['entity_origin'],e['point']) for e in bases]
37
+ if a==b:self.assertEqual(p['selected_point_after'],bases[1]['point'])
38
+ for r in [p['scan_execution'],p['distance_execution']]:
39
+ if r:self.assertTrue(all(c['target']==65655 for c in r['calls']))
40
+ if __name__=='__main__':unittest.main()