qvm: queried grenade construction
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_QUERIED_GRENADE.md +7 -0
- docs/research/README.md +3 -0
- docs/research/qvm-queried-grenade.json +0 -0
- scripts/analyze_qvm_grenade_setup.py +8 -2
- scripts/analyze_qvm_queried_grenade.py +32 -0
- scripts/test_qvm_queried_grenade.py +20 -0
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):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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()
|