nmarshall commited on
Commit
899bbba
·
1 Parent(s): a936c8c

qvm: queried grenade construction

Browse files
docs/ASSET_PIPELINE_TODO.md CHANGED
@@ -676,3 +676,6 @@ Research progress: RE-665 [report](research/QVM_COMPLETE_POSE.md); remaining nat
676
 
677
 
678
  Research progress: RE-666 [report](research/QVM_ENTITY_FREE.md); remaining native/content/runtime/platform scope stays open.
 
 
 
 
676
 
677
 
678
  Research progress: RE-666 [report](research/QVM_ENTITY_FREE.md); remaining native/content/runtime/platform scope stays open.
679
+
680
+
681
+ Research progress: RE-667 [report](research/QVM_QUERIED_GRENADE.md); remaining native/content/runtime/platform scope stays open.
docs/FINDINGS.md CHANGED
@@ -1022,3 +1022,6 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
1022
 
1023
 
1024
  **RE-666 — Entity free control flow and conditional record reset:** 277400 unlinks, requests ordered resource releases and clears nine pointer fields before deciding whether548 suppresses the whole880-byte reset. [Evidence](research/QVM_ENTITY_FREE.md).
 
 
 
 
1022
 
1023
 
1024
  **RE-666 — Entity free control flow and conditional record reset:** 277400 unlinks, requests ordered resource releases and clears nine pointer fields before deciding whether548 suppresses the whole880-byte reset. [Evidence](research/QVM_ENTITY_FREE.md).
1025
+
1026
+
1027
+ **RE-667 — Grenade constructor with actual entity query and allocation:** Grenade construction now runs actual276433 over an explicit pool and inherits the selected entity velocity only when its ID equals the owner ground ID. [Evidence](research/QVM_QUERIED_GRENADE.md).
docs/PROVISIONAL_TODO.md CHANGED
@@ -999,3 +999,6 @@ Research progress: RE-665 [report](research/QVM_COMPLETE_POSE.md); remaining nat
999
 
1000
 
1001
  Research progress: RE-666 [report](research/QVM_ENTITY_FREE.md); remaining native/content/runtime/platform scope stays open.
 
 
 
 
999
 
1000
 
1001
  Research progress: RE-666 [report](research/QVM_ENTITY_FREE.md); remaining native/content/runtime/platform scope stays open.
1002
+
1003
+
1004
+ Research progress: RE-667 [report](research/QVM_QUERIED_GRENADE.md); remaining native/content/runtime/platform scope stays open.
docs/RESEARCH_LEDGER.md CHANGED
@@ -992,3 +992,8 @@ Complete32254 now reaches its void output boundary with actual swing, vector-ang
992
  ## 2026-10-20 — RE-666 Entity free control flow and conditional record reset (separate task commit)
993
 
994
  277400 unlinks, requests ordered resource releases and clears nine pointer fields before deciding whether548 suppresses the whole880-byte reset. 49 fixtures independently check every final record word, null/protected exits, resource ordering, aliased release requests and exact zero-fill gating. Full suite: 1129 tests pass. Report regenerates byte-identically (808034 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
 
 
 
 
 
 
992
  ## 2026-10-20 — RE-666 Entity free control flow and conditional record reset (separate task commit)
993
 
994
  277400 unlinks, requests ordered resource releases and clears nine pointer fields before deciding whether548 suppresses the whole880-byte reset. 49 fixtures independently check every final record word, null/protected exits, resource ordering, aliased release requests and exact zero-fill gating. Full suite: 1129 tests pass. Report regenerates byte-identically (808034 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
995
+
996
+
997
+ ## 2026-10-20 — RE-667 Grenade constructor with actual entity query and allocation (separate task commit)
998
+
999
+ Grenade construction now runs actual276433 over an explicit pool and inherits the selected entity velocity only when its ID equals the owner ground ID. 28 complete constructor fixtures check actual first-eligible query, skipped used/name/tag records, allocation reuse/extension and all220 final record words. Full suite: 1133 tests pass. Report regenerates byte-identically (1340521 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
@@ -1042,3 +1042,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
1042
 
1043
 
1044
  - [x] RE-666 Entity free control flow and conditional record reset ([report](research/QVM_ENTITY_FREE.md)).
 
 
 
 
1042
 
1043
 
1044
  - [x] RE-666 Entity free control flow and conditional record reset ([report](research/QVM_ENTITY_FREE.md)).
1045
+
1046
+
1047
+ - [x] RE-667 Grenade constructor with actual entity query and allocation ([report](research/QVM_QUERIED_GRENADE.md)).
docs/research/QVM_QUERIED_GRENADE.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # Grenade constructor with actual entity query and allocation
2
+
3
+ RE-667. Reproduce with `python3 scripts/analyze_qvm_queried_grenade.py`; check with `python3 scripts/test_qvm_queried_grenade.py`. The [machine report](qvm-queried-grenade.json) retains source identity and bounded fixtures.
4
+
5
+ An optional query resolver composes recovered276433 into285971 while preserving byte-identical default supplied-query reports. New fixtures combine actual lookup31691, allocation277165/277125 and query276433; no query response pointer is supplied. Query returns the first eligible record, including skipping unused/null-name/wrong-tag candidates. The report captures velocity from that actual selected record rather than a fixed fixture address. Independent full-record oracles check inherited velocity for ground matches, unchanged owner-only velocity for mismatches/no result, and both allocation reuse/extension modes. Finite sqrt remains modeled and native−16 registration captured. Grenade callback223156, trajectory/collision/explosion and live entity-pool legality 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
@@ -600,3 +600,6 @@ The extension collector adds five focused tests for native tail calls, command-r
600
 
601
 
602
  [RE-666: Entity free control flow and conditional record reset](QVM_ENTITY_FREE.md). Reproduce with `python3 scripts/analyze_qvm_entity_free.py`; check with `python3 scripts/test_qvm_entity_free.py`.
 
 
 
 
600
 
601
 
602
  [RE-666: Entity free control flow and conditional record reset](QVM_ENTITY_FREE.md). Reproduce with `python3 scripts/analyze_qvm_entity_free.py`; check with `python3 scripts/test_qvm_entity_free.py`.
603
+
604
+
605
+ [RE-667: Grenade constructor with actual entity query and allocation](QVM_QUERIED_GRENADE.md). Reproduce with `python3 scripts/analyze_qvm_queried_grenade.py`; check with `python3 scripts/test_qvm_queried_grenade.py`.
docs/research/qvm-queried-grenade.json ADDED
The diff for this file is too large to render. See raw diff
 
scripts/analyze_qvm_grenade_setup.py CHANGED
@@ -11,7 +11,7 @@ from analyze_qvm_slide_prefix import vec
11
  from analyze_qvm import write_json
12
  LOCAL=0x7f000000
13
 
14
- def grenade(ins,m,query_pointer=0,allocator=None):
15
  initial=state(m);before=record(m);weapons=[m[PS+312+4*j]&0xffffffff for j in range(16)];minus=m[PS+308]&0xffffffff;m[LOCAL+84]=ENTITY;query=[];speeds={str(mode):m[7304+52*mode]&0xffffffff for mode in [0,1]};velocity=vec(m,PS+32);ground_velocity=vec(m,BASES+36)
16
  pointers=[]
17
  def allocated(i,m,a,c):
@@ -21,7 +21,13 @@ def grenade(ins,m,query_pointer=0,allocator=None):
21
  m,r=allocator(i,m);p=r['selected']
22
  if p is None:raise ValueError('Grenade allocation did not return')
23
  pointers.append(p);before=record(m,p);return m,c,p,r
24
- def find(i,m,a,c):r={'arguments':a,'supplied_pointer':query_pointer,'entity_id':m.get(query_pointer),'query_not_executed':True};query.append(r);return m,c,query_pointer,r
 
 
 
 
 
 
25
  m,c,r=execute(ins,285972,286471,m,(0,0,0),LOCAL,{31691:lookup,277165:allocated,276433:find});slot=r['children'][0]['effect']['execution']['return'];mode=m[LOCAL+24]
26
  return m,{'initial':initial,'initial_record':before,'weapon_slots':weapons,'slot_minus1_word':minus,'lookup_slot':slot,'mode':mode,'speeds':speeds,'word7224':m[7224]&0xffffffff,'time':m[34992532],'owner_velocity':velocity,'ground_velocity':ground_velocity,'query':query,'execution':r,'final_record':record(m,pointers[0]),'final':state(m)}
27
 
 
11
  from analyze_qvm import write_json
12
  LOCAL=0x7f000000
13
 
14
+ def grenade(ins,m,query_pointer=0,allocator=None,query_resolver=None):
15
  initial=state(m);before=record(m);weapons=[m[PS+312+4*j]&0xffffffff for j in range(16)];minus=m[PS+308]&0xffffffff;m[LOCAL+84]=ENTITY;query=[];speeds={str(mode):m[7304+52*mode]&0xffffffff for mode in [0,1]};velocity=vec(m,PS+32);ground_velocity=vec(m,BASES+36)
16
  pointers=[]
17
  def allocated(i,m,a,c):
 
21
  m,r=allocator(i,m);p=r['selected']
22
  if p is None:raise ValueError('Grenade allocation did not return')
23
  pointers.append(p);before=record(m,p);return m,c,p,r
24
+ def find(i,m,a,c):
25
+ nonlocal ground_velocity
26
+ if query_resolver is None:
27
+ r={'arguments':a,'supplied_pointer':query_pointer,'entity_id':m.get(query_pointer),'query_not_executed':True};query.append(r);return m,c,query_pointer,r
28
+ m,e=query_resolver(i,m,a[8],a[12]);pointer=e['result']
29
+ if pointer:ground_velocity=vec(m,pointer+36)
30
+ r={'arguments':a,'selected_pointer':pointer,'entity_id':m.get(pointer),'execution':e};query.append(r);return m,c,pointer,r
31
  m,c,r=execute(ins,285972,286471,m,(0,0,0),LOCAL,{31691:lookup,277165:allocated,276433:find});slot=r['children'][0]['effect']['execution']['return'];mode=m[LOCAL+24]
32
  return m,{'initial':initial,'initial_record':before,'weapon_slots':weapons,'slot_minus1_word':minus,'lookup_slot':slot,'mode':mode,'speeds':speeds,'word7224':m[7224]&0xffffffff,'time':m[34992532],'owner_velocity':velocity,'ground_velocity':ground_velocity,'query':query,'execution':r,'final_record':record(m,pointers[0]),'final':state(m)}
33
 
scripts/analyze_qvm_queried_grenade.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Actual allocator and276433 query composed into grenade construction."""
3
+ import itertools
4
+ from pathlib import Path
5
+ from qvm_research_support import source
6
+ from qvm_server_fire_support import BASES
7
+ from analyze_qvm_entity_allocate import allocate
8
+ from analyze_qvm_entity_query import query,TAG
9
+ from analyze_qvm_entity_init import POOL,STRIDE
10
+ from analyze_qvm_allocated_event import setup
11
+ from analyze_qvm_grenade_setup import grenade
12
+ from analyze_qvm_acceleration import PS,word
13
+ from analyze_qvm import write_json
14
+
15
+ def main():
16
+ q,raw,h,ins=source();rows=[]
17
+ for reused,mode,kind in itertools.product([False,True],[0,1],['none','first-ground','first-other','skip-unused','skip-null','skip-tag','two-matches']):
18
+ m=setup(raw,h,reused);m[0x90000+192]=7;m[PS+312]=7|(mode<<16);m[PS+68]=8 if kind in ['first-other','skip-unused','skip-null','skip-tag'] else 2
19
+ for o in range(0,880,4):m[BASES+o]=0
20
+ for j in range(64):
21
+ for o in [532,536,540]:m[POOL+j*STRIDE+o]=0
22
+ candidates=[]
23
+ for j in [2,8]:
24
+ pointer=POOL+j*STRIDE
25
+ for o in range(0,880,4):m[pointer+o]=0
26
+ used=0 if kind=='none' or (j==2 and kind=='skip-unused') else 1;name=0 if j==2 and kind=='skip-null' else 0x50000+4*j;tag=0 if j==2 and kind=='skip-tag' else TAG;m.update({pointer:j,pointer+532:used,pointer+536:name,pointer+540:tag})
27
+ velocity=[word(v) for v in ([.5,-.25,2] if j==2 else [3,4,-1])]
28
+ for k,v in enumerate(velocity):m[pointer+36+4*k]=v
29
+ candidates.append({'pointer':pointer,'id':j,'used':used,'name_pointer':name,'tag':tag,'velocity':velocity})
30
+ _,r=grenade(ins,m,allocator=allocate,query_resolver=query);r.update({'reuse':reused,'kind':kind,'pool_candidates':candidates});rows.append(r)
31
+ write_json(Path('docs/research/qvm-queried-grenade.json'),{'source':q['source'],'sha256':q['sha256'],'probes':rows,'limits':'Actual285971/31691/277165/277125/276433. Native−16 registration captured and finite sqrt modeled. Entity pool is explicit; no trajectory/223156/native world collision/explosion or live reference parity.'})
32
+ if __name__=='__main__':main()
scripts/test_qvm_queried_grenade.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json,unittest,copy
2
+ from pathlib import Path
3
+ from test_qvm_grenade_setup import projectile
4
+ class QueriedGrenadeTests(unittest.TestCase):
5
+ @classmethod
6
+ def setUpClass(cls):cls.rows=json.loads(Path('docs/research/qvm-queried-grenade.json').read_text())['probes']
7
+ def test_query_selects_first_eligible_record(self):
8
+ self.assertEqual(len(self.rows),28)
9
+ for p in self.rows:
10
+ candidates=[c for c in p['pool_candidates'] if c['used'] and c['name_pointer'] and c['tag']==-913528516];q=p['query'][0];expected=candidates[0]['pointer'] if candidates else 0;self.assertEqual(q['selected_pointer'],expected);self.assertEqual(q['execution']['result'],expected)
11
+ if candidates:self.assertEqual(p['ground_velocity'],candidates[0]['velocity']);self.assertEqual(q['entity_id'],candidates[0]['id'])
12
+ def test_whole_constructor_record_with_independent_velocity_oracle(self):
13
+ for p in self.rows:
14
+ fixture=copy.deepcopy(p);fixture['query'][0]['supplied_pointer']=fixture['query'][0]['selected_pointer'];self.assertEqual(p['final_record'],projectile(fixture))
15
+ def test_actual_allocation_query_and_caller_order(self):
16
+ for p in self.rows:
17
+ self.assertEqual([c['target'] for c in p['execution']['calls']],[31691,-107,277165,276433]);self.assertNotIn('query_not_executed',p['query'][0]);self.assertNotIn('supplied_pointer',p['query'][0]);self.assertEqual(p['query'][0]['arguments'],{'8':0,'12':-913528516});self.assertEqual(p['execution']['children'][2]['effect']['selected'],34147688)
18
+ def test_ground_mismatch_and_no_hit_paths_covered(self):
19
+ self.assertTrue(any(not p['query'][0]['selected_pointer'] for p in self.rows));self.assertTrue(any(p['query'][0]['selected_pointer'] and p['query'][0]['entity_id']!=p['initial']['ground'] for p in self.rows))
20
+ if __name__=='__main__':unittest.main()