qvm: complete bounded weapon body
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_WEAPON_COMPLETE_BODY.md +11 -0
- docs/research/README.md +3 -0
- docs/research/qvm-weapon-complete-body.json +0 -0
- scripts/analyze_qvm_weapon_complete_body.py +70 -0
- scripts/test_qvm_weapon_complete_body.py +57 -0
docs/ASSET_PIPELINE_TODO.md
CHANGED
|
@@ -454,3 +454,6 @@ Research progress: RE-588 [report](research/QVM_FIRE_RESOURCE.md); remaining nat
|
|
| 454 |
|
| 455 |
|
| 456 |
Research progress: RE-589 [report](research/QVM_FIRE_DELAY.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
| 454 |
|
| 455 |
|
| 456 |
Research progress: RE-589 [report](research/QVM_FIRE_DELAY.md); remaining native/content/runtime/platform scope stays open.
|
| 457 |
+
|
| 458 |
+
|
| 459 |
+
Research progress: RE-590 [report](research/QVM_WEAPON_COMPLETE_BODY.md); remaining native/content/runtime/platform scope stays open.
|
docs/FINDINGS.md
CHANGED
|
@@ -812,3 +812,6 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
|
|
| 812 |
|
| 813 |
|
| 814 |
**RE-589 — Final firing delay and last-round exception:** 52989..53045 adds the retained selected delay to PS44 only if the post-debit magazine is nonzero or selectedID27; other empty magazines return without adding it. [Evidence](research/QVM_FIRE_DELAY.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 812 |
|
| 813 |
|
| 814 |
**RE-589 — Final firing delay and last-round exception:** 52989..53045 adds the retained selected delay to PS44 only if the post-debit magazine is nonzero or selectedID27; other empty magazines return without adding it. [Evidence](research/QVM_FIRE_DELAY.md).
|
| 815 |
+
|
| 816 |
+
|
| 817 |
+
**RE-590 — Complete bounded weapon body and actual main consumer suffix:** The entire50746 QVM body now executes with recovered children and agrees with independent staged oracles; actual main54444..54463 resumes through firing and non-firing returns with live state handoffs. [Evidence](research/QVM_WEAPON_COMPLETE_BODY.md).
|
docs/PROVISIONAL_TODO.md
CHANGED
|
@@ -770,3 +770,6 @@ Research progress: RE-588 [report](research/QVM_FIRE_RESOURCE.md); remaining nat
|
|
| 770 |
|
| 771 |
|
| 772 |
Research progress: RE-589 [report](research/QVM_FIRE_DELAY.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
| 770 |
|
| 771 |
|
| 772 |
Research progress: RE-589 [report](research/QVM_FIRE_DELAY.md); remaining native/content/runtime/platform scope stays open.
|
| 773 |
+
|
| 774 |
+
|
| 775 |
+
Research progress: RE-590 [report](research/QVM_WEAPON_COMPLETE_BODY.md); remaining native/content/runtime/platform scope stays open.
|
docs/RESEARCH_LEDGER.md
CHANGED
|
@@ -638,3 +638,8 @@ RE-580 additional regression: all19 reports from RE-560–569 and RE-571–579 r
|
|
| 638 |
## 2026-10-20 — RE-589 Final firing delay and last-round exception (separate task commit)
|
| 639 |
|
| 640 |
52989..53045 adds the retained selected delay to PS44 only if the post-debit magazine is nonzero or selectedID27; other empty magazines return without adding it. 108 independent timer/delay/ID/magazine probes plus actual debit handoffs for IDs22/27 check wrap and last-round timer behavior without reloading the delay record. Full suite: 871 tests pass. Report regenerates byte-identically (376037 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 638 |
## 2026-10-20 — RE-589 Final firing delay and last-round exception (separate task commit)
|
| 639 |
|
| 640 |
52989..53045 adds the retained selected delay to PS44 only if the post-debit magazine is nonzero or selectedID27; other empty magazines return without adding it. 108 independent timer/delay/ID/magazine probes plus actual debit handoffs for IDs22/27 check wrap and last-round timer behavior without reloading the delay record. Full suite: 871 tests pass. Report regenerates byte-identically (376037 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
| 641 |
+
|
| 642 |
+
|
| 643 |
+
## 2026-10-20 — RE-590 Complete bounded weapon body and actual main consumer suffix (separate task commit)
|
| 644 |
+
|
| 645 |
+
The entire50746 QVM body now executes with recovered children and agrees with independent staged oracles; actual main54444..54463 resumes through firing and non-firing returns with live state handoffs. 12 complete-body scenarios and two six-child main suffixes check every reached stage, complete final state, direct callee inventory and source-order event/animation effects. Full suite: 875 tests pass. Report regenerates byte-identically (1246760 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
|
@@ -811,3 +811,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 811 |
|
| 812 |
|
| 813 |
- [x] RE-589 Final firing delay and last-round exception ([report](research/QVM_FIRE_DELAY.md)).
|
|
|
|
|
|
|
|
|
|
|
|
| 811 |
|
| 812 |
|
| 813 |
- [x] RE-589 Final firing delay and last-round exception ([report](research/QVM_FIRE_DELAY.md)).
|
| 814 |
+
|
| 815 |
+
|
| 816 |
+
- [x] RE-590 Complete bounded weapon body and actual main consumer suffix ([report](research/QVM_WEAPON_COMPLETE_BODY.md)).
|
docs/research/QVM_WEAPON_COMPLETE_BODY.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Complete bounded weapon body and actual main consumer suffix
|
| 2 |
+
|
| 3 |
+
RE-590. Reproduce with `python3 scripts/analyze_qvm_weapon_complete_body.py`; check with `python3 scripts/test_qvm_weapon_complete_body.py`. The [machine report](qvm-weapon-complete-body.json) retains source identity and bounded fixtures.
|
| 4 |
+
|
| 5 |
+
Actual50747..53045 is now interpreted as one bounded body, with explicit byte24 and real recovered50250/50397/49327/48798/49028/49652/49918/50309/animation/event children. Interaction traces remain supplied. A separate staged reconstruction preserves the same parent locals and has independent state/delay oracles for each slice.12 fixtures cover ordinary/last/empty, flag4, charge start/release, burst, lowering, reload, death, preserved mode and new selection. Whole-body results match those oracles.
|
| 6 |
+
|
| 7 |
+
All direct call target families in this function are inventoried. Actual main54444..54463 now runs all six consumers in one driver: reload, interaction, complete weapon, torso, locomotion, water. Two fixtures verify actual handoffs and queue ordering. The earlier firing-body suspension has been closed for these finite fixture paths; no unknown child is silently treated as successful.
|
| 8 |
+
|
| 9 |
+
This is complete bounded QVM function coverage, not exhaustive legal-state coverage or full game execution. FRAME260/264 still only publishes a firing request. Earlier main setup/timers/movement/environment and final native snap54471 are omitted; native projectile/hitscan outcomes, input legality and platform/runtime parity remain open. Next: connect publication to the actual outer event consumer and test repeated calls with recovered timers.
|
| 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
|
@@ -371,3 +371,6 @@ The extension collector adds five focused tests for native tail calls, command-r
|
|
| 371 |
|
| 372 |
|
| 373 |
[RE-589: Final firing delay and last-round exception](QVM_FIRE_DELAY.md). Reproduce with `python3 scripts/analyze_qvm_fire_delay.py`; check with `python3 scripts/test_qvm_fire_delay.py`.
|
|
|
|
|
|
|
|
|
|
|
|
| 371 |
|
| 372 |
|
| 373 |
[RE-589: Final firing delay and last-round exception](QVM_FIRE_DELAY.md). Reproduce with `python3 scripts/analyze_qvm_fire_delay.py`; check with `python3 scripts/test_qvm_fire_delay.py`.
|
| 374 |
+
|
| 375 |
+
|
| 376 |
+
[RE-590: Complete bounded weapon body and actual main consumer suffix](QVM_WEAPON_COMPLETE_BODY.md). Reproduce with `python3 scripts/analyze_qvm_weapon_complete_body.py`; check with `python3 scripts/test_qvm_weapon_complete_body.py`.
|
docs/research/qvm-weapon-complete-body.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scripts/analyze_qvm_weapon_complete_body.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Entire bounded50746 body and actual main consumer suffix with recovered children."""
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
from qvm_research_support import source,execute
|
| 5 |
+
from qvm_firing_support import seed,state,fire_handlers
|
| 6 |
+
from analyze_qvm_weapon_prefix import LOCAL,mode_switch
|
| 7 |
+
from analyze_qvm_packed_controls import control
|
| 8 |
+
from analyze_qvm_weapon_select import select
|
| 9 |
+
from analyze_qvm_weapon_complete import complete
|
| 10 |
+
from analyze_qvm_reload_request import reload
|
| 11 |
+
from analyze_qvm_interaction_request import interaction
|
| 12 |
+
from analyze_qvm_torso_selector import torso
|
| 13 |
+
from analyze_qvm_locomotion import locomotion
|
| 14 |
+
from analyze_qvm_water_events import water_events
|
| 15 |
+
from analyze_qvm_weapon_return_chains import pre_fire
|
| 16 |
+
from analyze_qvm_fire_gate import gate
|
| 17 |
+
from analyze_qvm_fire_availability import availability
|
| 18 |
+
from analyze_qvm_fire_ammo import ammo
|
| 19 |
+
from analyze_qvm_fire_pose import pose
|
| 20 |
+
from analyze_qvm_fire_counter import counter
|
| 21 |
+
from analyze_qvm_fire_resource import resource
|
| 22 |
+
from analyze_qvm_fire_delay import delay
|
| 23 |
+
from analyze_qvm_acceleration import PS,FRAME
|
| 24 |
+
from analyze_qvm import write_json
|
| 25 |
+
MAIN=0x78000000
|
| 26 |
+
|
| 27 |
+
def weapon(ins,m,cmd=(0,0,0),contents=33554432):
|
| 28 |
+
initial=state(m);hs=fire_handlers()
|
| 29 |
+
def leaf(entry):
|
| 30 |
+
def apply(i,m,a,c):m,r=control(i,m,entry,c);return m,c,r['execution']['return'] or 0,r
|
| 31 |
+
return apply
|
| 32 |
+
def simple(fn):
|
| 33 |
+
def apply(i,m,a,c):m,r=fn(i,m,c);return m,c,0,r
|
| 34 |
+
return apply
|
| 35 |
+
def selected(i,m,a,c):m,r=select(i,m,a[8],c);return m,c,0,r
|
| 36 |
+
def reloaded(i,m,a,c):m,r=reload(i,m,a[8],c);return m,c,0,r
|
| 37 |
+
def action(i,m,a,c):m,r=interaction(i,m,contents,c);return m,c,0,r
|
| 38 |
+
hs.update({50250:leaf(50250),50397:leaf(50397),49327:simple(mode_switch),48798:selected,49028:simple(complete),49652:reloaded,49918:action})
|
| 39 |
+
m,c,r=execute(ins,50747,53046,m,cmd,LOCAL,hs,byte_inputs={FRAME+24:m[FRAME+24]&255})
|
| 40 |
+
return m,{'initial':initial,'execution':r,'final':state(m)}
|
| 41 |
+
|
| 42 |
+
def staged(ins,m,cmd=(0,0,0),contents=33554432):
|
| 43 |
+
initial=state(m);m,p=pre_fire(ins,m,cmd,contents);stop=p['stop'];rows=[]
|
| 44 |
+
for name,at,fn in [('gate',51802,gate),('availability',52085,availability),('ammo',52154,ammo),('pose',52253,pose),('counter',52730,counter),('resource',52873,resource),('delay',52989,delay)]:
|
| 45 |
+
if stop!=at:break
|
| 46 |
+
m,r=fn(ins,m,cmd,preserve_locals=True);rows.append({'name':name,'probe':r});stop=r['execution'].get('stop',53046)
|
| 47 |
+
assert stop==53046
|
| 48 |
+
return m,{'initial':initial,'pre_fire':p,'firing_stages':rows,'stop':stop,'final':state(m)}
|
| 49 |
+
|
| 50 |
+
def main_suffix(ins,m,cmd=(0,0,0),contents=33554432):
|
| 51 |
+
initial=state(m)
|
| 52 |
+
def reload_child(i,m,a,c):m,r=reload(i,m,a[8],c);return m,c,0,r
|
| 53 |
+
def action(i,m,a,c):m,r=interaction(i,m,contents,c);return m,c,0,r
|
| 54 |
+
def child(fn):
|
| 55 |
+
def apply(i,m,a,c):m,r=fn(i,m,c);return m,c,0,r
|
| 56 |
+
return apply
|
| 57 |
+
def firing(i,m,a,c):m,r=weapon(i,m,c,contents);return m,c,0,r
|
| 58 |
+
m,c,r=execute(ins,54444,54464,m,cmd,MAIN,{49652:reload_child,49918:action,50746:firing,49117:child(torso),47884:child(locomotion),48716:child(water_events)})
|
| 59 |
+
return m,{'initial':initial,'execution':r,'final':state(m),'stop_before':54464}
|
| 60 |
+
|
| 61 |
+
def main():
|
| 62 |
+
q,raw,h,ins=source();rows=[];mains=[]
|
| 63 |
+
cases=[('fire',22,2,{}),('last-round',22,1,{}),('empty',22,0,{}),('flag4',1,0,{}),('charge-start',11,2,{}),('charge-release',11,2,{PS+220:64,FRAME+20:0}),('burst',22,5,{4244+432*22+48:3,4244+432*22+8:100,4244+432*22+44:25}),('lowering',22,2,{PS+148:2,PS+44:16}),('reload',22,2,{PS+220:8,PS+44:16}),('dead',22,2,{PS+208:0}),('mode-local',1,1,{PS+312:1|(1<<8)|(1<<16)|(3<<24),4244+432+12:0}),('new-selection',1,2,{FRAME+24:22,PS+316:22|(2<<8)})]
|
| 64 |
+
for name,ident,mag,changes in cases:
|
| 65 |
+
m=seed(raw,h,ident,mag);m.update({FRAME+260:0,FRAME+264:0,35023932:16});m.update(changes);a,x=weapon(ins,dict(m));b,y=staged(ins,dict(m));assert state(a)==state(b),name;rows.append({'name':name,'supplied_changes':{str(k):v for k,v in changes.items()},'whole':x,'staged':y})
|
| 66 |
+
for mag in [0,2]:
|
| 67 |
+
m=seed(raw,h,22,mag);m.update({FRAME+260:0,FRAME+264:0,FRAME+212:3,35024028:0,35023932:16});m,p=main_suffix(ins,m);mains.append(p)
|
| 68 |
+
sites=[{'instruction':i['index'],'target':ins[i['index']-1]['operand']} for i in ins[50747:53046] if i['opcode']=='CALL']
|
| 69 |
+
write_json(Path('docs/research/qvm-weapon-complete-body.json'),{'source':q['source'],'sha256':q['sha256'],'direct_call_sites':sites,'probes':rows,'main_suffixes':mains,'limits':'Complete finite50746 body with recovered child calls and supplied interaction traces/durations. Actual54444..54463 six-call suffix included; no earlier main setup/movement/environment or native vector snap54471. Published firing request is not native shot execution; no full-game/reference tick claim.'})
|
| 70 |
+
if __name__=='__main__':main()
|
scripts/test_qvm_weapon_complete_body.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json,unittest,copy
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
from test_qvm_weapon_return_chains import selection_state
|
| 4 |
+
from test_qvm_weapon_guards import guard_state
|
| 5 |
+
from test_qvm_weapon_ready import ready_state
|
| 6 |
+
from test_qvm_reload_complete import reload_complete_state
|
| 7 |
+
from test_qvm_weapon_phases import phase_state
|
| 8 |
+
from test_qvm_fire_gate import gate_state
|
| 9 |
+
from test_qvm_fire_availability import availability_state
|
| 10 |
+
from test_qvm_fire_ammo import ammo_state
|
| 11 |
+
from test_qvm_fire_pose import full_pose_choice
|
| 12 |
+
from test_qvm_fire_pose_priority import pose_apply
|
| 13 |
+
from test_qvm_fire_counter import counter_state
|
| 14 |
+
from test_qvm_fire_resource import resource_state
|
| 15 |
+
from test_qvm_fire_delay import delay_state
|
| 16 |
+
from test_qvm_main_consumers import reload_state,interaction_state
|
| 17 |
+
from test_qvm_torso_selector import request
|
| 18 |
+
from test_qvm_locomotion_prefix import animation
|
| 19 |
+
from test_qvm_locomotion import locomotion_state
|
| 20 |
+
from test_qvm_water_events import enqueue,expected
|
| 21 |
+
|
| 22 |
+
def pre_state(test,p):
|
| 23 |
+
a=copy.deepcopy(p['initial']);stop=None;oracles={'guards':guard_state,'ready':ready_state,'reload':reload_complete_state,'phases':phase_state}
|
| 24 |
+
for stage in p['stages']:
|
| 25 |
+
q=stage['probe'];test.assertEqual(q['initial'],a)
|
| 26 |
+
if stage['name']=='selection':a,stop=selection_state(test,q)
|
| 27 |
+
else:result=oracles[stage['name']](q);a,stop=result[:2];test.assertEqual(q['final'],a);test.assertEqual(q['execution']['stop'],stop)
|
| 28 |
+
test.assertEqual(p['final'],a);test.assertEqual(p['stop'],stop);return a,stop
|
| 29 |
+
|
| 30 |
+
def complete_state(test,p):
|
| 31 |
+
a=copy.deepcopy(p['initial']);pre,stop=pre_state(test,p['pre_fire']);a.update(pre);oracles={'gate':gate_state,'availability':availability_state,'ammo':ammo_state,'resource':resource_state,'delay':delay_state};entries={'gate':51802,'availability':52085,'ammo':52154,'pose':52253,'counter':52730,'resource':52873,'delay':52989};selected=None
|
| 32 |
+
for stage in p['firing_stages']:
|
| 33 |
+
name,q=stage['name'],stage['probe'];test.assertEqual(stop,entries[name]);test.assertEqual(q['initial'],a)
|
| 34 |
+
if name=='pose':a=pose_apply(q,full_pose_choice(q));stop=52730
|
| 35 |
+
elif name=='counter':a,selected,stop=counter_state(q);test.assertEqual(q['selected_delay'],selected)
|
| 36 |
+
else:
|
| 37 |
+
if name=='delay':test.assertEqual(q['selected_delay'],selected)
|
| 38 |
+
a,stop=oracles[name](q)
|
| 39 |
+
test.assertEqual(q['final'],a);test.assertEqual(q['execution'].get('stop',53046),stop)
|
| 40 |
+
test.assertEqual(stop,53046);test.assertEqual(p['final'],a);return a
|
| 41 |
+
class WeaponCompleteBodyTests(unittest.TestCase):
|
| 42 |
+
@classmethod
|
| 43 |
+
def setUpClass(cls):cls.r=json.loads(Path('docs/research/qvm-weapon-complete-body.json').read_text())
|
| 44 |
+
def test_whole_body_matches_independent_stage_oracles(self):
|
| 45 |
+
self.assertEqual(len(self.r['probes']),12)
|
| 46 |
+
for p in self.r['probes']:self.assertEqual(p['whole']['initial'],p['staged']['initial']);self.assertEqual(p['whole']['final'],complete_state(self,p['staged']))
|
| 47 |
+
def test_actual_main_six_child_handoffs_and_queue_order(self):
|
| 48 |
+
for p in self.r['main_suffixes']:
|
| 49 |
+
self.assertEqual([c['target'] for c in p['execution']['calls']],[49652,49918,50746,49117,47884,48716]);a=copy.deepcopy(p['initial']);children=[x['effect'] for x in p['execution']['children']]
|
| 50 |
+
for q,oracle in zip(children[:2],[reload_state,interaction_state]):self.assertEqual(q['initial'],{k:a[k] for k in q['initial']});a.update(oracle(q))
|
| 51 |
+
weapon=children[2];self.assertEqual(weapon['initial'],a);name='empty' if not a['packed']&65280 else 'fire';ref=next(x for x in self.r['probes'] if x['name']==name);a=complete_state(self,ref['staged']);self.assertEqual(weapon['final'],a);torso,loco,water=children[3:];self.assertEqual(torso['initial'],{k:a[k] for k in torso['initial']});r=request(torso)
|
| 52 |
+
if r is not None:animation(a,39482,r,0)
|
| 53 |
+
self.assertEqual(torso['final'],{k:a[k] for k in torso['final']});self.assertEqual(loco['initial'],{k:a[k] for k in loco['initial']});a.update(locomotion_state(loco)[0]);self.assertEqual(water['initial'],{k:a[k] for k in water['initial']});a['queue']=enqueue(a['queue'],expected(water));self.assertEqual(p['final'],a);self.assertEqual(p['stop_before'],54464)
|
| 54 |
+
def test_all_direct_child_families_are_recovered(self):self.assertEqual(set(c['target'] for c in self.r['direct_call_sites']),{50250,50397,49327,48798,49028,49652,49918,50309,39482,39552,39238})
|
| 55 |
+
def test_last_round_burst_charge_and_no_native_shot_claim(self):
|
| 56 |
+
rows={p['name']:p['whole']['final'] for p in self.r['probes']};self.assertEqual(rows['fire']['weapon_timer'],75);self.assertEqual(rows['last-round']['weapon_timer'],0);self.assertEqual(rows['burst']['counter204'],2);self.assertEqual(rows['burst']['weapon_timer'],25);self.assertEqual(rows['charge-start']['request260'],0);self.assertEqual(rows['charge-release']['request260'],1);self.assertIn('not native shot execution',self.r['limits'])
|
| 57 |
+
if __name__=='__main__':unittest.main()
|