nmarshall commited on
Commit
c3bab00
·
1 Parent(s): 0a30e8c

qvm: damage caps and pellet accumulation

Browse files
docs/ASSET_PIPELINE_TODO.md CHANGED
@@ -781,3 +781,6 @@ Research progress: RE-704 [report](research/QVM_DAMAGE_RANGE.md); remaining nati
781
 
782
 
783
  Research progress: RE-705 [report](research/QVM_DAMAGE_ATTENUATION.md); remaining native/content/runtime/platform scope stays open.
 
 
 
 
781
 
782
 
783
  Research progress: RE-705 [report](research/QVM_DAMAGE_ATTENUATION.md); remaining native/content/runtime/platform scope stays open.
784
+
785
+
786
+ Research progress: RE-706 [report](research/QVM_DAMAGE_CLAMP.md); remaining native/content/runtime/platform scope stays open.
docs/FINDINGS.md CHANGED
@@ -1127,3 +1127,6 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
1127
 
1128
 
1129
  **RE-705 — Weapon24 distance attenuation:** Weapon24 preserves the factor below half range, linearly falls to float32 0.1 by full range, and stays at that floor thereafter; zero range takes the floor without division. [Evidence](research/QVM_DAMAGE_ATTENUATION.md).
 
 
 
 
1127
 
1128
 
1129
  **RE-705 — Weapon24 distance attenuation:** Weapon24 preserves the factor below half range, linearly falls to float32 0.1 by full range, and stays at that floor thereafter; zero range takes the floor without division. [Evidence](research/QVM_DAMAGE_ATTENUATION.md).
1130
+
1131
+
1132
+ **RE-706 — Damage saturation and weapon4 accumulation:** Positive damage factors cap at1 and weapon4 additionally caps at float32 0.35; its optional accumulator adds that capped factor without a total clamp. Nonpositive factors return zero immediately. [Evidence](research/QVM_DAMAGE_CLAMP.md).
docs/PROVISIONAL_TODO.md CHANGED
@@ -1116,3 +1116,6 @@ Research progress: RE-704 [report](research/QVM_DAMAGE_RANGE.md); remaining nati
1116
 
1117
 
1118
  Research progress: RE-705 [report](research/QVM_DAMAGE_ATTENUATION.md); remaining native/content/runtime/platform scope stays open.
 
 
 
 
1116
 
1117
 
1118
  Research progress: RE-705 [report](research/QVM_DAMAGE_ATTENUATION.md); remaining native/content/runtime/platform scope stays open.
1119
+
1120
+
1121
+ Research progress: RE-706 [report](research/QVM_DAMAGE_CLAMP.md); remaining native/content/runtime/platform scope stays open.
docs/RESEARCH_LEDGER.md CHANGED
@@ -1167,3 +1167,8 @@ A dependency-free Rust asset crate parses all619 originals with Python parity fo
1167
  ## 2026-10-21 — RE-705 Weapon24 distance attenuation (separate task commit)
1168
 
1169
  Weapon24 preserves the factor below half range, linearly falls to float32 0.1 by full range, and stays at that floor thereafter; zero range takes the floor without division. 315 piecewise boundary/weapon/factor probes pass exact float32 independent oracles. Full suite: 1271 tests pass. Report regenerates byte-identically (473777 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
 
 
 
 
 
 
1167
  ## 2026-10-21 — RE-705 Weapon24 distance attenuation (separate task commit)
1168
 
1169
  Weapon24 preserves the factor below half range, linearly falls to float32 0.1 by full range, and stays at that floor thereafter; zero range takes the floor without division. 315 piecewise boundary/weapon/factor probes pass exact float32 independent oracles. Full suite: 1271 tests pass. Report regenerates byte-identically (473777 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
1170
+
1171
+
1172
+ ## 2026-10-21 — RE-706 Damage saturation and weapon4 accumulation (separate task commit)
1173
+
1174
+ Positive damage factors cap at1 and weapon4 additionally caps at float32 0.35; its optional accumulator adds that capped factor without a total clamp. Nonpositive factors return zero immediately. 144 finite factor/weapon/pointer/accumulator combinations pass exact saturation and additive oracles. Full suite: 1275 tests pass. Report regenerates byte-identically (215368 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
@@ -1159,3 +1159,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
1159
 
1160
 
1161
  - [x] RE-705 Weapon24 distance attenuation ([report](research/QVM_DAMAGE_ATTENUATION.md)).
 
 
 
 
1159
 
1160
 
1161
  - [x] RE-705 Weapon24 distance attenuation ([report](research/QVM_DAMAGE_ATTENUATION.md)).
1162
+
1163
+
1164
+ - [x] RE-706 Damage saturation and weapon4 accumulation ([report](research/QVM_DAMAGE_CLAMP.md)).
docs/research/QVM_DAMAGE_CLAMP.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # Damage saturation and weapon4 accumulation
2
+
3
+ RE-706. Reproduce with `python3 scripts/analyze_qvm_damage_clamp.py`; check with `python3 scripts/test_qvm_damage_clamp.py`. The [machine report](qvm-damage-clamp.json) retains source identity and bounded fixtures.
4
+
5
+ Actual289953–290001 clamps factors at1, returns zero at nonpositive values, and caps positive weapon4 factors to word1050253722 (float32 0.35). Weapon4 with a nonnull extra pointer adds that factor to its existing float32 value. The accumulator can exceed1 and accepts explicit negative starting fixtures; no total clamp occurs in this range. The separately computed cubic local36 is not consumed by this slice. Later caller event clamping and legal runtime domains remain separate questions. No calls or health writes occur.
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
@@ -717,3 +717,6 @@ The extension collector adds five focused tests for native tail calls, command-r
717
 
718
 
719
  [RE-705: Weapon24 distance attenuation](QVM_DAMAGE_ATTENUATION.md). Reproduce with `python3 scripts/analyze_qvm_damage_attenuation.py`; check with `python3 scripts/test_qvm_damage_attenuation.py`.
 
 
 
 
717
 
718
 
719
  [RE-705: Weapon24 distance attenuation](QVM_DAMAGE_ATTENUATION.md). Reproduce with `python3 scripts/analyze_qvm_damage_attenuation.py`; check with `python3 scripts/test_qvm_damage_attenuation.py`.
720
+
721
+
722
+ [RE-706: Damage saturation and weapon4 accumulation](QVM_DAMAGE_CLAMP.md). Reproduce with `python3 scripts/analyze_qvm_damage_clamp.py`; check with `python3 scripts/test_qvm_damage_clamp.py`.
docs/research/qvm-damage-clamp.json ADDED
The diff for this file is too large to render. See raw diff
 
scripts/analyze_qvm_damage_clamp.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Damage factor saturation, weapon4 cap and optional pellet accumulation."""
3
+ import itertools
4
+ from pathlib import Path
5
+ from qvm_research_support import source
6
+ from qvm_damage_support import seed,run,L
7
+ from analyze_qvm_acceleration import word
8
+ from analyze_qvm import write_json
9
+
10
+ def main():
11
+ q,raw,h,ins=source();rows=[]
12
+ for w,factor,extra,pointer in itertools.product([3,4,24],[-1,0,0.00001,0.2,0.35,0.35001,1,2],[-0.25,0,0.9],[False,True]):
13
+ a=dict(weapon=w,factor=factor,extra=extra,pointer=pointer);m=seed(raw,h,**a)
14
+ if not pointer:m[L+112]=0
15
+ _,p=run(ins,m,289953,290002);p['input']=a;rows.append(p)
16
+ write_json(Path('docs/research/qvm-damage-clamp.json'),{'source':q['source'],'sha256':q['sha256'],'probes':rows,'limits':'Actual289953..290001 finite factors. Extra pointer explicitly supplied/null. Accumulator is not capped here. No later wound/health execution.'})
17
+ if __name__=='__main__':main()
scripts/test_qvm_damage_clamp.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json,unittest
2
+ from pathlib import Path
3
+ from test_qvm_ground import word,n,f
4
+ class DamageClampTests(unittest.TestCase):
5
+ @classmethod
6
+ def setUpClass(cls):cls.ps=json.loads(Path('docs/research/qvm-damage-clamp.json').read_text())['probes']
7
+ def test_independent_saturation_cap_and_early_zero(self):
8
+ for p in self.ps:
9
+ a=p['input'];v=f(a['factor']);v=min(v,1.)
10
+ if a['weapon']==4 and v>0:v=min(v,n(1050253722))
11
+ self.assertEqual(p['final']['locals']['20'],word(v))
12
+ self.assertEqual(p['execution']['return'],0 if a['factor']<=0 else None)
13
+ def test_accumulate_only_positive_weapon_four_nonnull(self):
14
+ for p in self.ps:
15
+ a=p['input'];v=f(a['extra'])
16
+ if a['weapon']==4 and a['factor']>0 and a['pointer']:v=f(v+n(p['final']['locals']['20']))
17
+ self.assertEqual(p['final']['extra'],word(v))
18
+ def test_accumulator_can_exceed_one(self):
19
+ ps=[p for p in self.ps if p['input']==dict(weapon=4,factor=2,extra=0.9,pointer=True)]
20
+ self.assertEqual(len(ps),1);self.assertGreater(n(ps[0]['final']['extra']),1)
21
+ def test_no_calls_and_early_stop(self):
22
+ for p in self.ps:
23
+ self.assertEqual(p['execution']['calls'],[]);self.assertEqual(p['execution']['stop'],290002)
24
+ if __name__=='__main__':unittest.main()