qvm: damage descriptors and range term
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_RANGE.md +7 -0
- docs/research/README.md +3 -0
- docs/research/qvm-damage-range.json +0 -0
- scripts/analyze_qvm_damage_range.py +20 -0
- scripts/test_qvm_damage_range.py +21 -0
docs/ASSET_PIPELINE_TODO.md
CHANGED
|
@@ -775,3 +775,6 @@ Research progress: RE-701 [report](research/RUST_MD3.md); remaining native/conte
|
|
| 775 |
|
| 776 |
|
| 777 |
Research progress: RE-703 [report](research/QVM_DAMAGE_PROTECTION.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
| 775 |
|
| 776 |
|
| 777 |
Research progress: RE-703 [report](research/QVM_DAMAGE_PROTECTION.md); remaining native/content/runtime/platform scope stays open.
|
| 778 |
+
|
| 779 |
+
|
| 780 |
+
Research progress: RE-704 [report](research/QVM_DAMAGE_RANGE.md); remaining native/content/runtime/platform scope stays open.
|
docs/FINDINGS.md
CHANGED
|
@@ -1121,3 +1121,6 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
|
|
| 1121 |
|
| 1122 |
|
| 1123 |
**RE-703 — Damage protection and armor location selection:** 289594 rejects mode9 and strictly active spawn protection before location output; actual32155/32117 reclassifies head/torso using live inventory low bytes and health, excluding slot16. [Evidence](research/QVM_DAMAGE_PROTECTION.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 1121 |
|
| 1122 |
|
| 1123 |
**RE-703 — Damage protection and armor location selection:** 289594 rejects mode9 and strictly active spawn protection before location output; actual32155/32117 reclassifies head/torso using live inventory low bytes and health, excluding slot16. [Evidence](research/QVM_DAMAGE_PROTECTION.md).
|
| 1124 |
+
|
| 1125 |
+
|
| 1126 |
+
**RE-704 — Damage descriptor and cubic range term:** 289762 selects two words at4068+432×weapon+8×location and independently computes weapon4 ratio clamp and cubic complement using context84. [Evidence](research/QVM_DAMAGE_RANGE.md).
|
docs/PROVISIONAL_TODO.md
CHANGED
|
@@ -1110,3 +1110,6 @@ RE-692–701 batch complete: [original models and Rust asset foundation](researc
|
|
| 1110 |
|
| 1111 |
|
| 1112 |
Research progress: RE-703 [report](research/QVM_DAMAGE_PROTECTION.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
| 1110 |
|
| 1111 |
|
| 1112 |
Research progress: RE-703 [report](research/QVM_DAMAGE_PROTECTION.md); remaining native/content/runtime/platform scope stays open.
|
| 1113 |
+
|
| 1114 |
+
|
| 1115 |
+
Research progress: RE-704 [report](research/QVM_DAMAGE_RANGE.md); remaining native/content/runtime/platform scope stays open.
|
docs/RESEARCH_LEDGER.md
CHANGED
|
@@ -1157,3 +1157,8 @@ A dependency-free Rust asset crate parses all619 originals with Python parity fo
|
|
| 1157 |
## 2026-10-21 — RE-703 Damage protection and armor location selection (separate task commit)
|
| 1158 |
|
| 1159 |
289594 rejects mode9 and strictly active spawn protection before location output; actual32155/32117 reclassifies head/torso using live inventory low bytes and health, excluding slot16. 356 gate/inventory fixtures and independent boundary/notification/location oracles pass. Full suite: 1263 tests pass. Report regenerates byte-identically (653493 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1157 |
## 2026-10-21 — RE-703 Damage protection and armor location selection (separate task commit)
|
| 1158 |
|
| 1159 |
289594 rejects mode9 and strictly active spawn protection before location output; actual32155/32117 reclassifies head/torso using live inventory low bytes and health, excluding slot16. 356 gate/inventory fixtures and independent boundary/notification/location oracles pass. Full suite: 1263 tests pass. Report regenerates byte-identically (653493 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
| 1160 |
+
|
| 1161 |
+
|
| 1162 |
+
## 2026-10-21 — RE-704 Damage descriptor and cubic range term (separate task commit)
|
| 1163 |
+
|
| 1164 |
+
289762 selects two words at4068+432×weapon+8×location and independently computes weapon4 ratio clamp and cubic complement using context84. 208 original-table and explicit range boundary fixtures pass exact float32 and descriptor oracles. Full suite: 1267 tests pass. Report regenerates byte-identically (341409 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
|
@@ -1153,3 +1153,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 1153 |
|
| 1154 |
|
| 1155 |
- [x] RE-703 Damage protection and armor location selection ([report](research/QVM_DAMAGE_PROTECTION.md)).
|
|
|
|
|
|
|
|
|
|
|
|
| 1153 |
|
| 1154 |
|
| 1155 |
- [x] RE-703 Damage protection and armor location selection ([report](research/QVM_DAMAGE_PROTECTION.md)).
|
| 1156 |
+
|
| 1157 |
+
|
| 1158 |
+
- [x] RE-704 Damage descriptor and cubic range term ([report](research/QVM_DAMAGE_RANGE.md)).
|
docs/research/QVM_DAMAGE_RANGE.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Damage descriptor and cubic range term
|
| 2 |
+
|
| 3 |
+
RE-704. Reproduce with `python3 scripts/analyze_qvm_damage_range.py`; check with `python3 scripts/test_qvm_damage_range.py`. The [machine report](qvm-damage-range.json) retains source identity and bounded fixtures.
|
| 4 |
+
|
| 5 |
+
Actual289762–289861 uses signed positive descriptor4188+432×weapon as range. Only weapon4 computes context84/(range×10), clamps to[0,1], and stores (1−ratio) cubed with source-order float32 products. Nonpositive range leaves ratio0 and complement1. This is a local term, not yet the final damage factor. The location selects a pair at4068+432×weapon+8×location: first float factor and second wound word. Source descriptor words are preserved; range overrides are explicitly labeled synthetic fixtures. No external 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
|
@@ -711,3 +711,6 @@ The extension collector adds five focused tests for native tail calls, command-r
|
|
| 711 |
|
| 712 |
|
| 713 |
[RE-703: Damage protection and armor location selection](QVM_DAMAGE_PROTECTION.md). Reproduce with `python3 scripts/analyze_qvm_damage_protection.py`; check with `python3 scripts/test_qvm_damage_protection.py`.
|
|
|
|
|
|
|
|
|
|
|
|
| 711 |
|
| 712 |
|
| 713 |
[RE-703: Damage protection and armor location selection](QVM_DAMAGE_PROTECTION.md). Reproduce with `python3 scripts/analyze_qvm_damage_protection.py`; check with `python3 scripts/test_qvm_damage_protection.py`.
|
| 714 |
+
|
| 715 |
+
|
| 716 |
+
[RE-704: Damage descriptor and cubic range term](QVM_DAMAGE_RANGE.md). Reproduce with `python3 scripts/analyze_qvm_damage_range.py`; check with `python3 scripts/test_qvm_damage_range.py`.
|
docs/research/qvm-damage-range.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scripts/analyze_qvm_damage_range.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Actual weapon/location descriptor selection and weapon4 cubic distance term."""
|
| 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 probe(ins,raw,h,a):
|
| 11 |
+
m=seed(raw,h,**a);w=a['weapon'];loc=a['location']
|
| 12 |
+
if 'range' in a:m[4188+432*w]=a['range']
|
| 13 |
+
table=4068+432*w+8*loc;descriptor=[m[table],m[table+4]];maximum=m[4188+432*w]
|
| 14 |
+
m,p=run(ins,m,289762,289862);p.update({'input':a,'table_address':table,'descriptor_words':descriptor,'range_integer':maximum,'distance_word':word(a.get('distance',0))});return p
|
| 15 |
+
|
| 16 |
+
def main():
|
| 17 |
+
q,raw,h,ins=source();cases=[dict(weapon=w,location=loc,distance=d) for w,loc,d in itertools.product([3,4,24],range(15),[0,1500,3000,4500])]
|
| 18 |
+
cases += [dict(weapon=4,location=1,distance=d,range=r) for r,d in itertools.product([-1,0,1,300],[-10,0,5,10,2999,3000,3001])]
|
| 19 |
+
write_json(Path('docs/research/qvm-damage-range.json'),{'source':q['source'],'sha256':q['sha256'],'probes':[probe(ins,raw,h,a) for a in cases],'limits':'Actual289762..289861. Descriptors and default range from original file data; explicit range overrides probe boundaries. Cubic term stored separately from descriptor factor here.'})
|
| 20 |
+
if __name__=='__main__':main()
|
scripts/test_qvm_damage_range.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json,unittest
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
from test_qvm_ground import word,n,f
|
| 4 |
+
class DamageRangeTests(unittest.TestCase):
|
| 5 |
+
@classmethod
|
| 6 |
+
def setUpClass(cls):cls.ps=json.loads(Path('docs/research/qvm-damage-range.json').read_text())['probes']
|
| 7 |
+
def test_exact_descriptor_pair_and_stride(self):
|
| 8 |
+
for p in self.ps:
|
| 9 |
+
a=p['input'];self.assertEqual(p['table_address'],4068+432*a['weapon']+8*a['location']);self.assertEqual([p['final']['locals'][k] for k in ['20','24']],p['descriptor_words'])
|
| 10 |
+
def test_independent_cubic_float32_term(self):
|
| 11 |
+
for p in self.ps:
|
| 12 |
+
a=p['input'];r=0.;cubic=1.
|
| 13 |
+
if a['weapon']==4 and p['range_integer']>0:
|
| 14 |
+
r=min(1.,max(0.,f(n(p['distance_word'])/f(p['range_integer']*10))))
|
| 15 |
+
v=f(1.-r);cubic=f(f(v*v)*v)
|
| 16 |
+
self.assertEqual(p['final']['locals']['32'],word(r));self.assertEqual(p['final']['locals']['36'],word(cubic))
|
| 17 |
+
def test_no_calls_or_early_return(self):
|
| 18 |
+
for p in self.ps:self.assertEqual(p['execution']['calls'],[]);self.assertIsNone(p['execution']['return']);self.assertEqual(p['execution']['stop'],289862)
|
| 19 |
+
def test_provenance_and_domains(self):
|
| 20 |
+
self.assertEqual(len(self.ps),208);self.assertTrue(any(p['range_integer']<=0 for p in self.ps));self.assertTrue(any(p['range_integer']==300 and p['input']['distance']==3001 for p in self.ps))
|
| 21 |
+
if __name__=='__main__':unittest.main()
|