nmarshall commited on
Commit
5179729
·
1 Parent(s): 4ed547e

qvm: complete health and impulse flow

Browse files
docs/ASSET_PIPELINE_TODO.md CHANGED
@@ -859,3 +859,6 @@ Research progress: RE-730 [report](research/QVM_HEALTH_TERMINAL.md); original as
859
 
860
 
861
  Research progress: RE-731 [report](research/QVM_HEALTH_IMPULSE.md); original assets unchanged.
 
 
 
 
859
 
860
 
861
  Research progress: RE-731 [report](research/QVM_HEALTH_IMPULSE.md); original assets unchanged.
862
+
863
+
864
+ Research progress: RE-732 [report](research/QVM_HEALTH_COMPLETE.md); original assets unchanged.
docs/FINDINGS.md CHANGED
@@ -1205,3 +1205,6 @@ RE-714–723 batch complete: [complete contact and health prefixes](research/QVM
1205
 
1206
 
1207
  **RE-731 — Complete velocity impulse and movement timer:** Complete213009 adds direction×(global scale×knockback/200) in source float32 order, and only a zero existing timer gets clamp(trunc(knockback×2),50,200) plus movement flag64. [Evidence](research/QVM_HEALTH_IMPULSE.md).
 
 
 
 
1205
 
1206
 
1207
  **RE-731 — Complete velocity impulse and movement timer:** Complete213009 adds direction×(global scale×knockback/200) in source float32 order, and only a zero existing timer gets clamp(trunc(knockback×2),50,200) plus movement flag64. [Evidence](research/QVM_HEALTH_IMPULSE.md).
1208
+
1209
+
1210
+ **RE-732 — Complete health function with actual velocity impulses:** Complete211239 now composes gates, routing, normalization, bookkeeping, special targets, health publication and terminal branches with actual RNG/meter/impulse children. Late health−999 clamp can leave client208 below the entity clamp. [Evidence](research/QVM_HEALTH_COMPLETE.md).
docs/PROVISIONAL_TODO.md CHANGED
@@ -1194,3 +1194,6 @@ Research progress: RE-730 [report](research/QVM_HEALTH_TERMINAL.md); full native
1194
 
1195
 
1196
  Research progress: RE-731 [report](research/QVM_HEALTH_IMPULSE.md); full native/platform/game scope remains open.
 
 
 
 
1194
 
1195
 
1196
  Research progress: RE-731 [report](research/QVM_HEALTH_IMPULSE.md); full native/platform/game scope remains open.
1197
+
1198
+
1199
+ Research progress: RE-732 [report](research/QVM_HEALTH_COMPLETE.md); full native/platform/game scope remains open.
docs/RESEARCH_LEDGER.md CHANGED
@@ -1298,3 +1298,8 @@ Terminal processing caps client228 low16 values above500 (except method26), clam
1298
  ## 2026-10-21 — RE-731 Complete velocity impulse and movement timer
1299
 
1300
  Complete213009 adds direction×(global scale×knockback/200) in source float32 order, and only a zero existing timer gets clamp(trunc(knockback×2),50,200) plus movement flag64. Focused `cargo xtask test-group health` passes (36 Python tests); selected reports regenerate twice byte-identically, with storage, links and whitespace guards. New report: 74485 bytes. Full-suite validation is deferred to the tenth batch commit. No original assets, Rust runtime or shared VM evaluator changed.
 
 
 
 
 
 
1298
  ## 2026-10-21 — RE-731 Complete velocity impulse and movement timer
1299
 
1300
  Complete213009 adds direction×(global scale×knockback/200) in source float32 order, and only a zero existing timer gets clamp(trunc(knockback×2),50,200) plus movement flag64. Focused `cargo xtask test-group health` passes (36 Python tests); selected reports regenerate twice byte-identically, with storage, links and whitespace guards. New report: 74485 bytes. Full-suite validation is deferred to the tenth batch commit. No original assets, Rust runtime or shared VM evaluator changed.
1301
+
1302
+
1303
+ ## 2026-10-21 — RE-732 Complete health function with actual velocity impulses
1304
+
1305
+ Complete211239 now composes gates, routing, normalization, bookkeeping, special targets, health publication and terminal branches with actual RNG/meter/impulse children. Late health−999 clamp can leave client208 below the entity clamp. Focused `cargo xtask test-group health` passes (41 Python tests); selected reports regenerate twice byte-identically, with storage, links and whitespace guards. New report: 804258 bytes. Full-suite validation is deferred to the tenth batch commit. No original assets, Rust runtime or shared VM evaluator changed.
docs/REVERSE_ENGINEERING_TODO.md CHANGED
@@ -1237,3 +1237,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
1237
 
1238
 
1239
  - [x] RE-731 Complete velocity impulse and movement timer ([report](research/QVM_HEALTH_IMPULSE.md)).
 
 
 
 
1237
 
1238
 
1239
  - [x] RE-731 Complete velocity impulse and movement timer ([report](research/QVM_HEALTH_IMPULSE.md)).
1240
+
1241
+
1242
+ - [x] RE-732 Complete health function with actual velocity impulses ([report](research/QVM_HEALTH_COMPLETE.md)).
docs/research/QVM_HEALTH_COMPLETE.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # Complete health function with actual velocity impulses
2
+
3
+ RE-732. Reproduce with `python3 scripts/analyze_qvm_health_complete.py`; validate with `cargo xtask test-group health`. See the [machine report](qvm-health-complete.json).
4
+
5
+ Complete211239 executes211240–213006 through all recovered branches on96 finite nonnull-client fixtures, using actual33715,36717,211197 and213009. Independent composed source-order oracles check every tracked entity/client field, attacker credit, direction, RNG and tracking flag. An observed ordering detail is preserved: client208 is published before the terminal entity−999 clamp and is not republished afterward. Native sqrt is modeled; intercept206128, protected update152386 and supplied pain/death/object callback pointers are captured without effects. Complete caller control flow therefore does not imply original callback/native/runtime parity. Null-client full-call legality remains unproven.
6
+
7
+ No original executable/full VM/native world collision or rendering runs. Supplied callback/native responses and fixture domains remain explicit; complete macOS/Linux Rust/Bevy/Solari gameplay remains open.
docs/research/README.md CHANGED
@@ -795,3 +795,6 @@ The extension collector adds five focused tests for native tail calls, command-r
795
 
796
 
797
  [RE-731: Complete velocity impulse and movement timer](QVM_HEALTH_IMPULSE.md).
 
 
 
 
795
 
796
 
797
  [RE-731: Complete velocity impulse and movement timer](QVM_HEALTH_IMPULSE.md).
798
+
799
+
800
+ [RE-732: Complete health function with actual velocity impulses](QVM_HEALTH_COMPLETE.md).
docs/research/qvm-health-complete.json ADDED
The diff for this file is too large to render. See raw diff
 
scripts/analyze_qvm_health_complete.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Complete211239 with actual impulse/meter/RNG and explicit callback boundaries."""
3
+ import itertools
4
+ from pathlib import Path
5
+ from qvm_research_support import source
6
+ from qvm_health_effects_support import seed,run,H,MAGIC
7
+ from analyze_qvm_health_impulse import impulse
8
+ from analyze_qvm import write_json
9
+
10
+ def complete(ins,m,args=None):
11
+ if args:
12
+ for o,v in args.items():m[H+108+o]=v
13
+ return run(ins,m,211240,213007,impulse_resolver=impulse,target=m[H+116])
14
+
15
+ def main():
16
+ q,raw,h,ins=source();rows=[];m=seed(raw,h);table=[{'method':m[4200+432*w],'knockback_word':m[4192+432*w]} for w in range(m[17412])]
17
+ cases=[dict(method=method,damage=damage,health=health,flags220=flags,pain=True,death=True) for method,damage,health,flags in itertools.product([12,22,24,26,37],[0,1,100,2000],[1,100],[0,16384])]
18
+ cases += [dict(**a) for a in [dict(mode=9),dict(now=3999),dict(entity_flags=16),dict(client4040=1),dict(same_team=True),dict(same_team=True,friendly_fire=1),dict(mode=10),dict(method=24,override=1,damage=1),dict(target_kind=4,callback=True),dict(target_kind=4,callback=False),dict(tracking=1),dict(direction=None,damage=1),dict(self=True)]]
19
+ cases += [dict(checksum=MAGIC,callback=True,**a) for a in [dict(method=25,**{'class':5},damage=101),dict(method=12,**{'class':6}),dict(method=34)]]
20
+ for a in cases:
21
+ m,p=complete(ins,seed(raw,h,**a));p.update(input=a,tracking=m[34999664]);rows.append(p)
22
+ write_json(Path('docs/research/qvm-health-complete.json'),{'source':q['source'],'sha256':q['sha256'],'descriptor_table':table,'probes':rows,'limits':'Complete211239 numeric body to void exit with actual33715,36717,211197 and213009. Native sqrt modeled;206128/152386 and supplied callback pointers captured without effects. Finite nonnull-client fixtures, no original executable or world runtime.'})
23
+ if __name__=='__main__':main()
scripts/qvm_health_effects_support.py CHANGED
@@ -29,7 +29,7 @@ def seed(raw,h,**a):
29
 
30
  def state(m,target=TARGET):
31
  client=m[target+520]
32
- return {'entity':{str(o):m[target+o]&0xffffffff for o in ENTITY_FIELDS},'client':{str(o):m[client+o]&0xffffffff for o in CLIENT_FIELDS} if client else None,'attacker_credits':m.get(m.get(m.get(H+124,ATTACKER)+520,0)+252,0)&0xffffffff,'direction':[m[DIRECTION+4*j]&0xffffffff for j in range(3)],'args':{str(o):m[H+o]&0xffffffff for o in [120,124,128,136,140,144,148]},'selected_damage':m[H+40]&0xffffffff,'knockback_word':m[H+32]&0xffffffff,'rng':m[21044]&0xffffffff}
33
 
34
  def handlers(effects,impulse_resolver=None):
35
  def root(i,m,a):v=word(math.sqrt(number(a[8])));return m,v,{'input_word':a[8]&0xffffffff,'result_word':v,'native_math_modeled':True}
 
29
 
30
  def state(m,target=TARGET):
31
  client=m[target+520]
32
+ return {'entity':{str(o):m[target+o]&0xffffffff for o in ENTITY_FIELDS},'client':{str(o):m[client+o]&0xffffffff for o in CLIENT_FIELDS} if client else None,'attacker_credits':m.get(m.get(m.get(H+124,ATTACKER)+520,0)+252,0)&0xffffffff,'direction':[m[(m[H+128] or DIRECTION)+4*j]&0xffffffff for j in range(3)],'args':{str(o):m[H+o]&0xffffffff for o in [120,124,128,136,140,144,148]},'selected_damage':m[H+40]&0xffffffff,'knockback_word':m[H+32]&0xffffffff,'rng':m[21044]&0xffffffff}
33
 
34
  def handlers(effects,impulse_resolver=None):
35
  def root(i,m,a):v=word(math.sqrt(number(a[8])));return m,v,{'input_word':a[8]&0xffffffff,'result_word':v,'native_math_modeled':True}
scripts/test_qvm_health_complete.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import copy,json,unittest
2
+ from pathlib import Path
3
+ from test_qvm_ground import word,n,f
4
+ from test_qvm_health_gates import accepted
5
+ from test_qvm_health_knockback import oracle as knockback
6
+ from test_qvm_health_special_target import oracle as special_target
7
+ from test_qvm_health_impulse import expected as impulse_expected
8
+ from qvm_health_effects_support import MAGIC,ATTACKER,TARGET
9
+
10
+ def expected(p,table):
11
+ a=p['input'];r=copy.deepcopy(p['initial']);e=r['entity'];cl=r['client'];tracking=0
12
+ if not accepted(a):return r,tracking
13
+ cl['4328']=1
14
+ if a.get('tracking') and a.get('method',12)>11 and not a.get('same_team',False) and not a.get('self',False):tracking=1
15
+ if a.get('target_kind',1)==4 and a.get('checksum',0)!=MAGIC:return r,tracking
16
+ flags,direction,kb,stop=knockback(a,table);r['direction']=direction
17
+ if stop==213007:return r,tracking
18
+ method=a.get('method',12);same=a.get('self',False);attacker=TARGET if same else ATTACKER;attacker_id=65 if same else 7
19
+ if not same and a.get('health',100)>0 and a.get('target_kind',1) not in (0,3,4):r['attacker_credits']=(-1 if a.get('mode',3)>=3 and a.get('mode',3) not in (9,11) and a.get('same_team',False) else 1)&0xffffffff
20
+ take=max(1,a.get('damage',100));cl['272']=attacker_id;cl['4128']=attacker_id;cl['4132']=method;cl['4084' if method==23 else '4088']+=take
21
+ origin=method==23 or a.get('direction',[3,4,0]) is None;cl['4108']=int(origin)
22
+ for j,v in enumerate(list(map(word,[10,20,30])) if origin else direction):cl[str(4096+4*j)]=v
23
+ if method==6 and take>=30:cl['12']|=128
24
+ if a.get('checksum',0)==MAGIC:
25
+ inputs=dict(a,damage=take);health,selected,seed,called,_=special_target(inputs);e['684']=health&0xffffffff;r['rng']=seed
26
+ if called:e['720']=attacker
27
+ return r,tracking
28
+ intercept=a.get('mode',3)==10 and not same and a.get('health',100)-take<=0 and not a.get('flags220',0)&16384 and method not in (6,7,1,3,2,4,9,31,35,33,32)
29
+ if intercept:return r,tracking
30
+ def impulse_apply(zero_z):
31
+ if zero_z:r['direction'][2]=0
32
+ fake={'input':{'knockback':n(kb),'scale':a.get('scale',1000),'direction':list(map(n,r['direction']))},'initial':{str(o):cl[str(o)] for o in [12,16,32,36,40]}}
33
+ cl.update(impulse_expected(fake))
34
+ if method==24 and a.get('override',0):impulse_apply(True);return r,tracking
35
+ health=a.get('health',100)-take
36
+ if cl['220']&16384:
37
+ health=max(5,health);cl['220']&=~896;cl['236']&=~1;cl['6332']=word(f(n(cl['6332'])+f(f(take)*n(-1012924416))))
38
+ e.update({'684':health&0xffffffff,'836':attacker,'840':a.get('location',3)});cl['208']=health&0xffffffff;cl['184']=max(0,cl['184']-300*take)
39
+ if method!=26 and cl['228']&65535>500:cl['228']=500
40
+ if health<=0:
41
+ impulse_apply(False);e['684']=max(-999,health)&0xffffffff;e['720']=attacker
42
+ elif method in (16,43,22,25,29,24,37):impulse_apply(True)
43
+ return r,tracking
44
+
45
+ class CompleteHealthTests(unittest.TestCase):
46
+ @classmethod
47
+ def setUpClass(cls):cls.r=json.loads(Path('docs/research/qvm-health-complete.json').read_text());cls.ps=cls.r['probes']
48
+ def test_independent_composed_all_external_state(self):
49
+ for p in self.ps:
50
+ r,tracking=expected(p,self.r['descriptor_table'])
51
+ for key in ['entity','client','attacker_credits','direction','rng']:self.assertEqual(p['final'][key],r[key],(p['input'],key))
52
+ self.assertEqual(p['tracking'],tracking)
53
+ def test_actual_impulse_and_meter_children(self):
54
+ rows=[c for p in self.ps for c in p['execution']['children'] if c['call']['target']==213009];self.assertTrue(rows)
55
+ for c in rows:self.assertEqual(c['effect']['execution']['calls'],[]);self.assertIn('final',c['effect'])
56
+ self.assertTrue(any(c['target']==211197 for p in self.ps for c in p['execution']['calls']))
57
+ def test_late_entity_clamp_does_not_republish_client_health(self):
58
+ rows=[p for p in self.ps if p['input'].get('damage')==2000 and not p['input'].get('flags220',0)&16384];self.assertTrue(rows)
59
+ for p in rows:self.assertEqual(p['final']['entity']['684'],(-999)&0xffffffff);self.assertEqual(p['final']['client']['208'],(p['input']['health']-2000)&0xffffffff)
60
+ def test_void_exit_and_explicit_callback_boundaries(self):
61
+ self.assertEqual(len(self.ps),96)
62
+ for p in self.ps:self.assertEqual(p['execution']['stop'],213007);self.assertIsNone(p['execution']['return']);self.assertEqual(p['effects']['impulses'],[])
63
+ def test_native_math_only_sqrt_no_original_runtime(self):
64
+ for p in self.ps:self.assertTrue(all(c['target']>=0 or c['target']==-107 for c in p['execution']['calls']))
65
+ if __name__=='__main__':unittest.main()
xtask/checks.tsv CHANGED
@@ -1157,3 +1157,5 @@ report scripts/analyze_qvm_health_terminal.py docs/research/qvm-health-terminal.
1157
  edge docs/research/qvm-health-terminal.json scripts/test_qvm_health_terminal.py
1158
  report scripts/analyze_qvm_health_impulse.py docs/research/qvm-health-impulse.json
1159
  edge docs/research/qvm-health-impulse.json scripts/test_qvm_health_impulse.py
 
 
 
1157
  edge docs/research/qvm-health-terminal.json scripts/test_qvm_health_terminal.py
1158
  report scripts/analyze_qvm_health_impulse.py docs/research/qvm-health-impulse.json
1159
  edge docs/research/qvm-health-impulse.json scripts/test_qvm_health_impulse.py
1160
+ report scripts/analyze_qvm_health_complete.py docs/research/qvm-health-complete.json
1161
+ edge docs/research/qvm-health-complete.json scripts/test_qvm_health_complete.py