qvm: victim and team statistics
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_VICTIM_STATS.md +7 -0
- docs/research/README.md +3 -0
- docs/research/qvm-victim-stats.json +0 -0
- scripts/analyze_qvm_victim_stats.py +38 -0
- scripts/test_qvm_victim_stats.py +21 -0
docs/ASSET_PIPELINE_TODO.md
CHANGED
|
@@ -631,3 +631,6 @@ Research progress: RE-649 [report](research/QVM_HISTORY_APPEND.md); remaining na
|
|
| 631 |
|
| 632 |
|
| 633 |
Research progress: RE-650 [report](research/QVM_PRODUCED_HISTORY_REWIND.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
| 631 |
|
| 632 |
|
| 633 |
Research progress: RE-650 [report](research/QVM_PRODUCED_HISTORY_REWIND.md); remaining native/content/runtime/platform scope stays open.
|
| 634 |
+
|
| 635 |
+
|
| 636 |
+
Research progress: RE-651 [report](research/QVM_VICTIM_STATS.md); remaining native/content/runtime/platform scope stays open.
|
docs/FINDINGS.md
CHANGED
|
@@ -977,3 +977,6 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
|
|
| 977 |
|
| 978 |
|
| 979 |
**RE-650 — Source-produced twenty-row history through rewind and restoration:** Reset plus25 actual append calls produce newest-first retained history consumed by complete143100 and restored by144165. [Evidence](research/QVM_PRODUCED_HISTORY_REWIND.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 977 |
|
| 978 |
|
| 979 |
**RE-650 — Source-produced twenty-row history through rewind and restoration:** Reset plus25 actual append calls produce newest-first retained history consumed by complete143100 and restored by144165. [Evidence](research/QVM_PRODUCED_HISTORY_REWIND.md).
|
| 980 |
+
|
| 981 |
+
|
| 982 |
+
**RE-651 — Victim team and hit statistic bookkeeping:** Complete279820 updates attacker/victim hit/location/value counters;33715 enables same-team accounting for modes≥3 except9/11. [Evidence](research/QVM_VICTIM_STATS.md).
|
docs/PROVISIONAL_TODO.md
CHANGED
|
@@ -951,3 +951,6 @@ Research progress: RE-649 [report](research/QVM_HISTORY_APPEND.md); remaining na
|
|
| 951 |
|
| 952 |
|
| 953 |
Research progress: RE-650 [report](research/QVM_PRODUCED_HISTORY_REWIND.md); remaining native/content/runtime/platform scope stays open.
|
|
|
|
|
|
|
|
|
|
|
|
| 951 |
|
| 952 |
|
| 953 |
Research progress: RE-650 [report](research/QVM_PRODUCED_HISTORY_REWIND.md); remaining native/content/runtime/platform scope stays open.
|
| 954 |
+
|
| 955 |
+
|
| 956 |
+
Research progress: RE-651 [report](research/QVM_VICTIM_STATS.md); remaining native/content/runtime/platform scope stays open.
|
docs/RESEARCH_LEDGER.md
CHANGED
|
@@ -917,3 +917,8 @@ Direct285840 now composes actual allocation, event57, quantized direction/global
|
|
| 917 |
## 2026-10-20 — RE-650 Source-produced twenty-row history through rewind and restoration (separate task commit)
|
| 918 |
|
| 919 |
Reset plus25 actual append calls produce newest-first retained history consumed by complete143100 and restored by144165. Five target-time compositions independently reconstruct every producer transition, retained20 timestamps, full rewind state and restore round trip. Full suite: 1070 tests pass. Report regenerates byte-identically (1131284 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 917 |
## 2026-10-20 — RE-650 Source-produced twenty-row history through rewind and restoration (separate task commit)
|
| 918 |
|
| 919 |
Reset plus25 actual append calls produce newest-first retained history consumed by complete143100 and restored by144165. Five target-time compositions independently reconstruct every producer transition, retained20 timestamps, full rewind state and restore round trip. Full suite: 1070 tests pass. Report regenerates byte-identically (1131284 bytes). Storage/filter, links and whitespace checks pass. No assets/Rust runtime/shared VM evaluator changed; native/reference/legal/full platform scope remains open.
|
| 920 |
+
|
| 921 |
+
|
| 922 |
+
## 2026-10-20 — RE-651 Victim team and hit statistic bookkeeping (separate task commit)
|
| 923 |
+
|
| 924 |
+
Complete279820 updates attacker/victim hit/location/value counters;33715 enables same-team accounting for modes≥3 except9/11. 16 mode predicates and62 two-client/self/location/value cases independently check all380 words per client and exact child order. Full suite: 1074 tests pass. Report regenerates byte-identically (1482109 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
|
@@ -994,3 +994,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 994 |
|
| 995 |
|
| 996 |
- [x] RE-650 Source-produced twenty-row history through rewind and restoration ([report](research/QVM_PRODUCED_HISTORY_REWIND.md)).
|
|
|
|
|
|
|
|
|
|
|
|
| 994 |
|
| 995 |
|
| 996 |
- [x] RE-650 Source-produced twenty-row history through rewind and restoration ([report](research/QVM_PRODUCED_HISTORY_REWIND.md)).
|
| 997 |
+
|
| 998 |
+
|
| 999 |
+
- [x] RE-651 Victim team and hit statistic bookkeeping ([report](research/QVM_VICTIM_STATS.md)).
|
docs/research/QVM_VICTIM_STATS.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Victim team and hit statistic bookkeeping
|
| 2 |
+
|
| 3 |
+
RE-651. Reproduce with `python3 scripts/analyze_qvm_victim_stats.py`; check with `python3 scripts/test_qvm_victim_stats.py`. The [machine report](qvm-victim-stats.json) retains source identity and bounded fixtures.
|
| 4 |
+
|
| 5 |
+
The recovered mode predicate returns1 for signed mode≥3 except9/11. Complete279820 now executes category mapping and this predicate on valid location paths. It increments attempt/hit and location counters, accumulates supplied float values through source f32-add/integer truncation, updates corresponding victim counters and conditionally adds same-team counters/values. Invalid location remains the miss path. Independent full-stat-array oracles cover same/different teams, five modes, three location IDs, positive fractional and negative values, plus explicit attacker/victim aliasing. These are bookkeeping inputs, not evidence of geometry validation, actual health damage or legal self/negative-value gameplay.
|
| 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
|
@@ -552,3 +552,6 @@ The extension collector adds five focused tests for native tail calls, command-r
|
|
| 552 |
|
| 553 |
|
| 554 |
[RE-650: Source-produced twenty-row history through rewind and restoration](QVM_PRODUCED_HISTORY_REWIND.md). Reproduce with `python3 scripts/analyze_qvm_produced_history_rewind.py`; check with `python3 scripts/test_qvm_produced_history_rewind.py`.
|
|
|
|
|
|
|
|
|
|
|
|
| 552 |
|
| 553 |
|
| 554 |
[RE-650: Source-produced twenty-row history through rewind and restoration](QVM_PRODUCED_HISTORY_REWIND.md). Reproduce with `python3 scripts/analyze_qvm_produced_history_rewind.py`; check with `python3 scripts/test_qvm_produced_history_rewind.py`.
|
| 555 |
+
|
| 556 |
+
|
| 557 |
+
[RE-651: Victim team and hit statistic bookkeeping](QVM_VICTIM_STATS.md). Reproduce with `python3 scripts/analyze_qvm_victim_stats.py`; check with `python3 scripts/test_qvm_victim_stats.py`.
|
docs/research/qvm-victim-stats.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scripts/analyze_qvm_victim_stats.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Complete279820 victim/team statistics with actual33715 mode predicate."""
|
| 3 |
+
import itertools
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
from qvm_research_support import source,execute
|
| 6 |
+
from analyze_qvm_no_target_stats import prepare,category,LOCAL
|
| 7 |
+
from analyze_qvm_entity_init import POOL,STRIDE
|
| 8 |
+
from analyze_qvm_acceleration import PS,word
|
| 9 |
+
from analyze_qvm import write_json
|
| 10 |
+
MODE_LOCAL=0x78030000
|
| 11 |
+
VICTIM=0x20000
|
| 12 |
+
|
| 13 |
+
def mode(ins,m,value):
|
| 14 |
+
m=dict(m);m[MODE_LOCAL+20]=value;m,_,e=execute(ins,33716,33738,m,(0,0,0),MODE_LOCAL);return m,{'input':value,'result':e['return'],'execution':e}
|
| 15 |
+
|
| 16 |
+
def flat(m,client):return [m[client+856+4*j]&0xffffffff for j in range(380)]
|
| 17 |
+
|
| 18 |
+
def statistics(ins,m,args):
|
| 19 |
+
m=dict(m);attacker=m[POOL+args[8]*STRIDE+520];victim=m[POOL+args[20]*STRIDE+520];clients=sorted({attacker,victim});before={str(c):flat(m,c) for c in clients};teams={str(c):m[c+3096] for c in clients}
|
| 20 |
+
for o,v in args.items():m[LOCAL+80+o]=v
|
| 21 |
+
def mapper(target):
|
| 22 |
+
def call(i,m,a,c):m,e=category(i,m,target,a[8]);return m,c,e['result'],e
|
| 23 |
+
return call
|
| 24 |
+
def game_mode(i,m,a,c):m,e=mode(i,m,a[8]);return m,c,e['result'],e
|
| 25 |
+
m,_,e=execute(ins,279821,280296,m,(0,0,0),LOCAL,{278587:mapper(278587),278692:mapper(278692),33715:game_mode})
|
| 26 |
+
return m,{'arguments':args,'mode':m[34090788],'attacker_client':attacker,'victim_client':victim,'teams':teams,'initial':before,'final':{str(c):flat(m,c) for c in clients},'weapon_category':m[LOCAL+12],'location_category':m[LOCAL+24],'execution':e}
|
| 27 |
+
|
| 28 |
+
def main():
|
| 29 |
+
q,raw,h,ins=source();m=prepare(raw,h);mode_probes=[mode(ins,m,value)[1] for value in range(-1,15)];rows=[]
|
| 30 |
+
cases=[(game,same,location,damage,1) for game,same,location,damage in itertools.product([2,3,9,11,12],[False,True],[0,1,14],[1.9,-2.5])]+[(3,True,1,1.9,7),(2,True,1,1.9,7)]
|
| 31 |
+
for game,same,location,damage,victim_id in cases:
|
| 32 |
+
m=prepare(raw,h);victim_client=PS if victim_id==7 else VICTIM;m[POOL+victim_id*STRIDE+520]=victim_client;m[34090788]=game;m[PS+3096]=1;m[victim_client+3096]=1 if same else 2
|
| 33 |
+
for client in {PS,victim_client}:
|
| 34 |
+
for j in range(20):
|
| 35 |
+
for o in range(0,76,4):m[client+856+76*j+o]=1+j+o
|
| 36 |
+
rows.append(statistics(ins,m,{8:7,12:4,16:location,20:victim_id,24:word(damage)})[1])
|
| 37 |
+
write_json(Path('docs/research/qvm-victim-stats.json'),{'source':q['source'],'sha256':q['sha256'],'mode_probes':mode_probes,'probes':rows,'limits':'Complete279820 finite victim/client paths with actual33715/category maps. Supplied hit location/value is bookkeeping input, not validated geometry or health damage. Synthetic self/negative-value cases expose source arithmetic without asserting gameplay legality.'})
|
| 38 |
+
if __name__=='__main__':main()
|
scripts/test_qvm_victim_stats.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json,copy,unittest
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
from test_qvm_ground import word,n,f
|
| 4 |
+
class VictimStatsTests(unittest.TestCase):
|
| 5 |
+
@classmethod
|
| 6 |
+
def setUpClass(cls):cls.r=json.loads(Path('docs/research/qvm-victim-stats.json').read_text())
|
| 7 |
+
def test_independent_mode_predicate(self):
|
| 8 |
+
for p in self.r['mode_probes']:self.assertEqual(p['result'],int(p['input']>=3 and p['input'] not in [9,11]));self.assertEqual(p['execution']['calls'],[])
|
| 9 |
+
def test_independent_entire_two_client_statistics(self):
|
| 10 |
+
for p in self.r['probes']:
|
| 11 |
+
want=copy.deepcopy(p['initial']);a=want[str(p['attacker_client'])];v=want[str(p['victim_client'])];base=p['weapon_category']*19;loc=p['location_category'];damage=n(p['arguments']['24']);add=lambda old:int(f(float(old)+damage))&0xffffffff;a[base]+=1
|
| 12 |
+
if loc>=0:
|
| 13 |
+
a[base+2]+=1;a[base+6+loc]+=1;a[base+4]=add(a[base+4]);v[base+10+loc]+=1;v[base+17]=add(v[base+17])
|
| 14 |
+
if p['mode']>=3 and p['mode'] not in [9,11] and p['teams'][str(p['attacker_client'])]==p['teams'][str(p['victim_client'])]:a[base+5]=add(a[base+5]);a[base+3]+=1;v[base+18]=add(v[base+18])
|
| 15 |
+
else:a[base+1]+=1
|
| 16 |
+
a[base+14]=word(f(100-f(f(float(a[base+1])/float(a[base]))*100)));self.assertEqual(p['final'],want)
|
| 17 |
+
def test_actual_mode_child_only_on_valid_location_paths(self):
|
| 18 |
+
for p in self.r['probes']:self.assertEqual([c['target'] for c in p['execution']['calls']],[278587,278692]+([33715] if p['location_category']>=0 else []))
|
| 19 |
+
def test_aliasing_attacker_victim_is_explicit(self):
|
| 20 |
+
self.assertEqual(self.r['probes'][-1]['attacker_client'],self.r['probes'][-1]['victim_client']);self.assertEqual(len(self.r['probes'][-1]['final']),1)
|
| 21 |
+
if __name__=='__main__':unittest.main()
|