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

qvm: grenade record construction

Browse files
docs/ASSET_PIPELINE_TODO.md CHANGED
@@ -481,3 +481,6 @@ Research progress: RE-598 [report](research/QVM_TEMP_EVENT.md); remaining native
481
 
482
 
483
  Research progress: RE-599 [report](research/QVM_SERVER_SHOT_SETUP.md); remaining native/content/runtime/platform scope stays open.
 
 
 
 
481
 
482
 
483
  Research progress: RE-599 [report](research/QVM_SERVER_SHOT_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.
docs/FINDINGS.md CHANGED
@@ -839,3 +839,6 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
839
 
840
 
841
  **RE-599 — Event57 firing setup quantization and actual PRNG:** 285840 builds event57, stores trunc(forward×4096) as float direction, derives a seed byte from actual36717 xorshift, records shooter/weapon IDs and prepares295018 arguments. [Evidence](research/QVM_SERVER_SHOT_SETUP.md).
 
 
 
 
839
 
840
 
841
  **RE-599 — Event57 firing setup quantization and actual PRNG:** 285840 builds event57, stores trunc(forward×4096) as float direction, derives a seed byte from actual36717 xorshift, records shooter/weapon IDs and prepares295018 arguments. [Evidence](research/QVM_SERVER_SHOT_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).
docs/PROVISIONAL_TODO.md CHANGED
@@ -799,3 +799,6 @@ Research progress: RE-598 [report](research/QVM_TEMP_EVENT.md); remaining native
799
 
800
 
801
  Research progress: RE-599 [report](research/QVM_SERVER_SHOT_SETUP.md); remaining native/content/runtime/platform scope stays open.
 
 
 
 
799
 
800
 
801
  Research progress: RE-599 [report](research/QVM_SERVER_SHOT_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.
docs/RESEARCH_LEDGER.md CHANGED
@@ -685,3 +685,8 @@ Actual outer31 publication reaches server151634, which writes client4140=0 and43
685
  ## 2026-10-20 — RE-599 Event57 firing setup quantization and actual PRNG (separate task commit)
686
 
687
  285840 builds event57, stores trunc(forward×4096) as float direction, derives a seed byte from actual36717 xorshift, records shooter/weapon IDs and prepares295018 arguments. 24 independent full-record/PRNG fixtures check fractional/negative quantization, seed0/1/hex/unsigned−1, tempEntity handoff, link-time ordering and exact opaque-call ABI. Full suite: 907 tests pass. Report regenerates byte-identically (1527580 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
 
 
 
 
 
 
685
  ## 2026-10-20 — RE-599 Event57 firing setup quantization and actual PRNG (separate task commit)
686
 
687
  285840 builds event57, stores trunc(forward×4096) as float direction, derives a seed byte from actual36717 xorshift, records shooter/weapon IDs and prepares295018 arguments. 24 independent full-record/PRNG fixtures check fractional/negative quantization, seed0/1/hex/unsigned−1, tempEntity handoff, link-time ordering and exact opaque-call ABI. Full suite: 907 tests pass. Report regenerates byte-identically (1527580 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
688
+
689
+
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.
docs/REVERSE_ENGINEERING_TODO.md CHANGED
@@ -841,3 +841,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
841
 
842
 
843
  - [x] RE-599 Event57 firing setup quantization and actual PRNG ([report](research/QVM_SERVER_SHOT_SETUP.md)).
 
 
 
 
841
 
842
 
843
  - [x] RE-599 Event57 firing setup quantization and actual PRNG ([report](research/QVM_SERVER_SHOT_SETUP.md)).
844
+
845
+
846
+ - [x] RE-600 Grenade record construction and inherited velocity ([report](research/QVM_GRENADE_SETUP.md)).
docs/research/QVM_GRENADE_SETUP.md ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Grenade record construction and inherited velocity
2
+
3
+ RE-600. Reproduce with `python3 scripts/analyze_qvm_grenade_setup.py`; check with `python3 scripts/test_qvm_grenade_setup.py`. The [machine report](qvm-grenade-setup.json) retains source identity and bounded fixtures.
4
+
5
+ File-backed classname97541 is grenade. Actual31691 finds weapon7's first slot and decodes its mode; a missing−1 slot reads the explicitly supplied adjacent PS308 fixture rather than inventing a valid slot. Global forwardZ adds source.2, then actual float operations use a supplied finite sqrt to normalize unless zero.
6
+
7
+ With a supplied277165 record, the body initializes type/trajectory/owner/flags/mask/timing and numeric scalar fields and copies global muzzle to base/live origin. Direction×source speed7304+52×mode is truncated to integer then converted back to float, after which owner PS velocity is added. A supplied276433 query result contributes its velocity only when its entity ID matches PS ground.
8
+
9
+ 37 fixtures reconstruct every record word and transformed forward vector independently. The exact query hash/arguments and supplied record pointer are retained. Allocator/query engine effects, entity linking, trajectory integration, explosion and damage are not executed. Construction alone does not prove a working projectile or native outcome.
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
@@ -400,3 +400,6 @@ The extension collector adds five focused tests for native tail calls, command-r
400
 
401
 
402
  [RE-599: Event57 firing setup quantization and actual PRNG](QVM_SERVER_SHOT_SETUP.md). Reproduce with `python3 scripts/analyze_qvm_server_shot_setup.py`; check with `python3 scripts/test_qvm_server_shot_setup.py`.
 
 
 
 
400
 
401
 
402
  [RE-599: Event57 firing setup quantization and actual PRNG](QVM_SERVER_SHOT_SETUP.md). Reproduce with `python3 scripts/analyze_qvm_server_shot_setup.py`; check with `python3 scripts/test_qvm_server_shot_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`.
docs/research/qvm-grenade-setup.json ADDED
The diff for this file is too large to render. See raw diff
 
scripts/analyze_qvm_grenade_setup.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """285971 construction: lookup, biased normalized direction, record and inherited velocity."""
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,PROJECTILE,BASES,FORWARD,MUZZLE
7
+ from analyze_qvm_temp_event import record
8
+ from analyze_qvm_weapon_lookup import lookup
9
+ from analyze_qvm_acceleration import PS,word
10
+ 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):
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
+ def allocated(i,m,a,c):return m,c,PROJECTILE,{'supplied_record_pointer':PROJECTILE,'allocator_not_executed':True}
17
+ 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
18
+ 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]
19
+ 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),'final':state(m)}
20
+
21
+ def main():
22
+ q,raw,h,ins=source();rows=[]
23
+ for fw,slot,mode,query_kind in itertools.product([(1,0,0),(.6,-.25,.8),(0,0,-.2)],[0,15],[0,1],['none','match','other']):
24
+ m=seed(raw,h,7)
25
+ for j in range(16):m[PS+312+4*j]=22
26
+ m[PS+312+4*slot]=7|(mode<<16);m[PS+308]=7
27
+ for o in range(0,880,4):m[BASES+o]=0
28
+ m[BASES]=8 if query_kind=='match' else 9;m[PS+68]=8
29
+ for p,v in [(FORWARD,fw),(BASES+36,(.5,-.25,2))]:
30
+ for j,x in enumerate(v):m[p+4*j]=word(x)
31
+ rows.append(grenade(ins,m,0 if query_kind=='none' else BASES)[1])
32
+ m=seed(raw,h,7);m[PS+312]=22;m[PS+308]=7|(1<<16)
33
+ for o in range(0,880,4):m[BASES+o]=0
34
+ rows.append(grenade(ins,m)[1])
35
+ classname=raw[h['data_offset']+97541:].split(b'\0',1)[0].decode()
36
+ write_json(Path('docs/research/qvm-grenade-setup.json'),{'source':q['source'],'sha256':q['sha256'],'classname':{'address':97541,'text':classname},'probes':rows,'limits':'Complete finite285971 with actual31691/supplied sqrt, explicit allocator and276433 query responses. Missing lookup−1 uses supplied PS308 fixture, not asserted legal. No entity allocation/link/trajectory physics/explosion or damage executes.'})
37
+ if __name__=='__main__':main()
scripts/test_qvm_grenade_setup.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json,unittest,copy,math
2
+ from pathlib import Path
3
+ from test_qvm_ground import word,n,f
4
+
5
+ def normalized(p):
6
+ v=list(map(n,p['initial']['forward']));v[2]=f(v[2]+n(1045220557));length=f(math.sqrt(f(f(f(v[0]*v[0])+f(v[1]*v[1]))+f(v[2]*v[2]))))
7
+ return [f(x*f(1/length)) for x in v] if length else v
8
+
9
+ def projectile(p):
10
+ r=copy.deepcopy(p['initial_record']);r.update({str(k):v&0xffffffff for k,v in {536:97541,540:513611514,644:p['time']+2500,648:223156,4:3,424:160,192:7,8:256,512:p['initial']['entity_id'],516:589824,692:90,696:180,700:300,704:p['word7224'],708:p['word7224'],588:100663297,624:0,12:5,16:p['time']-50}.items()})
11
+ direction=normalized(p);velocity=[f(float(int(f(x*n(p['speeds'][str(p['mode'])]))))) for x in direction];velocity=[f(x+n(y)) for x,y in zip(velocity,p['owner_velocity'])]
12
+ if p['query'][0]['supplied_pointer'] and p['query'][0]['entity_id']==p['initial']['ground']:velocity=[f(x+n(y)) for x,y in zip(velocity,p['ground_velocity'])]
13
+ for base in [24,488]:
14
+ for j,v in enumerate(p['initial']['muzzle']):r[str(base+4*j)]=v
15
+ for j,v in enumerate(velocity):r[str(36+4*j)]=word(v)
16
+ return r
17
+ class GrenadeSetupTests(unittest.TestCase):
18
+ @classmethod
19
+ def setUpClass(cls):cls.r=json.loads(Path('docs/research/qvm-grenade-setup.json').read_text())
20
+ def test_exact_projectile_descriptor_and_velocity(self):
21
+ self.assertEqual(len(self.r['probes']),37)
22
+ for p in self.r['probes']:self.assertEqual(p['final_record'],projectile(p));a=copy.deepcopy(p['initial']);a['forward']=list(map(word,normalized(p)));self.assertEqual(p['final'],a)
23
+ def test_actual_first16_lookup_and_mode_source(self):
24
+ for p in self.r['probes']:
25
+ slot=next((j for j,v in enumerate(p['weapon_slots']) if v&255==7),-1);packed=p['weapon_slots'][slot] if slot>=0 else p['slot_minus1_word'];self.assertEqual((p['lookup_slot'],p['mode']),(slot,packed>>16&255))
26
+ def test_actual_child_order_and_supplied_engine_contracts(self):
27
+ for p in self.r['probes']:self.assertEqual([c['target'] for c in p['execution']['calls']],[31691,-107,277165,276433]);self.assertEqual(p['query'][0]['arguments'],{'8':0,'12':-913528516});self.assertTrue(p['query'][0]['query_not_executed'])
28
+ def test_file_classname_zero_direction_and_missing_slot_fixture(self):
29
+ self.assertEqual(self.r['classname'],{'address':97541,'text':'grenade'});self.assertTrue(any(all(v==0 for v in normalized(p)) for p in self.r['probes']));self.assertEqual(self.r['probes'][-1]['lookup_slot'],-1)
30
+ if __name__=='__main__':unittest.main()