qvm: damage caps and pellet accumulation
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_DAMAGE_CLAMP.md +7 -0
- docs/research/README.md +3 -0
- docs/research/qvm-damage-clamp.json +0 -0
- scripts/analyze_qvm_damage_clamp.py +17 -0
- scripts/test_qvm_damage_clamp.py +24 -0
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()
|