nmarshall commited on
Commit
96e8a6c
·
1 Parent(s): b16a43c

gameplay: port location selection and cache policy

Browse files
crates/urt-gameplay/src/bin/urt-location-feedback.rs ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ use urt_gameplay::location_feedback::*;
2
+ fn list(v: &[u32]) -> String {
3
+ format!(
4
+ "[{}]",
5
+ v.iter()
6
+ .map(|v| v.to_string())
7
+ .collect::<Vec<_>>()
8
+ .join(",")
9
+ )
10
+ }
11
+ fn hex(v: &[u8]) -> String {
12
+ v.iter().map(|v| format!("{v:02x}")).collect()
13
+ }
14
+ fn optional(v: Option<usize>) -> String {
15
+ v.map(|v| v.to_string()).unwrap_or("null".into())
16
+ }
17
+ fn main() {
18
+ let mut args = std::env::args().skip(1);
19
+ let kind = args.next().unwrap();
20
+ let w: Vec<u32> = args.map(|v| v.parse().unwrap()).collect();
21
+ match kind.as_str() {
22
+ "nearest" => println!("{}", nearest(&w)),
23
+ _ => panic!("unknown contract"),
24
+ }
25
+ }
26
+ fn nearest(w: &[u32]) -> String {
27
+ assert!(w.len() >= 19);
28
+ let mut pos = 3;
29
+ let mut e = vec![];
30
+ for _ in 0..3 {
31
+ e.push(LocationEntry {
32
+ point: w[pos..pos + 3].try_into().unwrap(),
33
+ trigger: w[pos + 3] != 0,
34
+ visible: w[pos + 4] != 0,
35
+ });
36
+ pos += 5;
37
+ }
38
+ let q = w[pos] as usize;
39
+ pos += 1;
40
+ let query = w[pos..pos + q].iter().map(|v| *v as usize).collect();
41
+ pos += q;
42
+ let n = w[pos] as usize;
43
+ pos += 1;
44
+ let order = w[pos..pos + n].iter().map(|v| *v as usize).collect();
45
+ pos += n;
46
+ assert_eq!(pos, w.len());
47
+ let cache = if w[0] == u32::MAX {
48
+ None
49
+ } else {
50
+ Some(w[0] as usize)
51
+ };
52
+ let out = nearest_location(
53
+ &e,
54
+ &LocationInput {
55
+ actor: [0; 3],
56
+ cache,
57
+ expiry: w[1],
58
+ tick: w[2],
59
+ query,
60
+ order,
61
+ },
62
+ )
63
+ .unwrap();
64
+ let bounds = out
65
+ .queries
66
+ .iter()
67
+ .map(|b| format!("[{},{}]", list(&b[0]), list(&b[1])))
68
+ .collect::<Vec<_>>()
69
+ .join(",");
70
+ format!(
71
+ r#"{{"selected":{},"queries":[{}],"pvs":{},"cache":{}}}"#,
72
+ optional(out.selected),
73
+ bounds,
74
+ list(&out.pvs.iter().map(|v| *v as u32).collect::<Vec<_>>()),
75
+ optional(out.cache)
76
+ )
77
+ }
crates/urt-gameplay/src/lib.rs CHANGED
@@ -201,3 +201,5 @@ pub mod assistance;
201
  pub mod defuse;
202
 
203
  pub mod effect_feedback;
 
 
 
201
  pub mod defuse;
202
 
203
  pub mod effect_feedback;
204
+
205
+ pub mod location_feedback;
crates/urt-gameplay/src/location_feedback.rs ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! Source-backed location selection/text with explicit engine replies.
2
+ use crate::native_policy::Error;
3
+ #[derive(Clone, Copy, Debug, PartialEq, Eq)]
4
+ pub struct LocationEntry {
5
+ pub point: [u32; 3],
6
+ pub trigger: bool,
7
+ pub visible: bool,
8
+ }
9
+ #[derive(Clone, Debug, PartialEq, Eq)]
10
+ pub struct LocationInput {
11
+ pub actor: [u32; 3],
12
+ pub cache: Option<usize>,
13
+ pub expiry: u32,
14
+ pub tick: u32,
15
+ pub query: Vec<usize>,
16
+ pub order: Vec<usize>,
17
+ }
18
+ #[derive(Clone, Debug, PartialEq, Eq)]
19
+ pub struct LocationSelection {
20
+ pub selected: Option<usize>,
21
+ pub queries: Vec<[[u32; 3]; 2]>,
22
+ pub pvs: Vec<usize>,
23
+ pub cache: Option<usize>,
24
+ }
25
+ /// Original268248 with supplied engine box/PVS replies. Later equal visible
26
+ /// distances replace earlier entries. This routine does not update the cache.
27
+ pub fn nearest_location(
28
+ entries: &[LocationEntry],
29
+ input: &LocationInput,
30
+ ) -> Result<LocationSelection, Error> {
31
+ let mut out = LocationSelection {
32
+ selected: None,
33
+ queries: vec![],
34
+ pvs: vec![],
35
+ cache: input.cache,
36
+ };
37
+ if let Some(index) = input.cache {
38
+ if (input.tick as i32) < input.expiry as i32 {
39
+ entries.get(index).ok_or(Error::InvalidIndex)?;
40
+ out.selected = Some(index);
41
+ return Ok(out);
42
+ }
43
+ }
44
+ if input.query.len() > 1024 || input.order.len() > 1024 {
45
+ return Err(Error::InvalidCount);
46
+ }
47
+ let mut actor = [0.; 3];
48
+ let mut bounds = [[0; 3]; 2];
49
+ for j in 0..3 {
50
+ actor[j] = f32::from_bits(input.actor[j]);
51
+ if !actor[j].is_finite() {
52
+ return Err(Error::NonFinite);
53
+ }
54
+ let extent = if j == 2 { 52. } else { 40. };
55
+ bounds[0][j] = (actor[j] - extent).to_bits();
56
+ bounds[1][j] = (actor[j] + extent).to_bits();
57
+ }
58
+ out.queries.push(bounds);
59
+ for &index in &input.query {
60
+ if entries.get(index).ok_or(Error::InvalidIndex)?.trigger {
61
+ out.selected = Some(index);
62
+ return Ok(out);
63
+ }
64
+ }
65
+ let mut best = 201326592f32;
66
+ for &index in &input.order {
67
+ let e = entries.get(index).ok_or(Error::InvalidIndex)?;
68
+ let mut d = [0.; 3];
69
+ for j in 0..3 {
70
+ let p = f32::from_bits(e.point[j]);
71
+ if !p.is_finite() {
72
+ return Err(Error::NonFinite);
73
+ }
74
+ d[j] = actor[j] - p;
75
+ }
76
+ let square = (d[0] * d[0] + d[1] * d[1]) + d[2] * d[2];
77
+ if !square.is_finite() {
78
+ return Err(Error::NonFinite);
79
+ }
80
+ if square <= best {
81
+ out.pvs.push(index);
82
+ if e.visible {
83
+ best = square;
84
+ out.selected = Some(index);
85
+ }
86
+ }
87
+ }
88
+ Ok(out)
89
+ }
90
+ #[cfg(test)]
91
+ mod nearest_tests {
92
+ use super::*;
93
+ fn input() -> LocationInput {
94
+ LocationInput {
95
+ actor: [0; 3],
96
+ cache: None,
97
+ expiry: 10001,
98
+ tick: 10000,
99
+ query: vec![],
100
+ order: vec![0, 1],
101
+ }
102
+ }
103
+ #[test]
104
+ fn equal_visible_distance_prefers_later_and_pvs_filters() {
105
+ let mut e = [LocationEntry {
106
+ point: [10f32.to_bits(), 0, 0],
107
+ trigger: false,
108
+ visible: true,
109
+ }; 2];
110
+ assert_eq!(nearest_location(&e, &input()).unwrap().selected, Some(1));
111
+ e[1].visible = false;
112
+ assert_eq!(nearest_location(&e, &input()).unwrap().selected, Some(0));
113
+ }
114
+ #[test]
115
+ fn cache_bypasses_unused_geometry_and_trigger_bypasses_list() {
116
+ let e = [LocationEntry {
117
+ point: [0; 3],
118
+ trigger: true,
119
+ visible: false,
120
+ }; 2];
121
+ assert_eq!(
122
+ nearest_location(
123
+ &e,
124
+ &LocationInput {
125
+ cache: Some(0),
126
+ actor: [f32::NAN.to_bits(); 3],
127
+ ..input()
128
+ }
129
+ )
130
+ .unwrap()
131
+ .queries
132
+ .len(),
133
+ 0
134
+ );
135
+ assert_eq!(
136
+ nearest_location(
137
+ &e,
138
+ &LocationInput {
139
+ query: vec![1, 0],
140
+ order: vec![99],
141
+ ..input()
142
+ }
143
+ )
144
+ .unwrap()
145
+ .selected,
146
+ Some(1)
147
+ );
148
+ }
149
+ }
docs/FINDINGS.md CHANGED
@@ -2011,3 +2011,5 @@ RE-1033: Rust matches48 full-source scenarios with actual constructor/radio/scor
2011
  RE-1024–1033 batch validation passed:1,998 Python tests,329 Rust tests,141 deterministic affected producers and612 documentation files. Source205260 is score update,283463 is indexed counter increment and193620 is team radio; old capture names remain compatibility labels. [Resolved feedback and next work](research/QVM_EFFECT_FEEDBACK_BATCH.md).
2012
 
2013
  RE-1034: Sixteen original-QVM cases recover268248. A cached pointer returns only before its signed expiry. Otherwise a supplied box query over origin±40/40/52 chooses the first case-insensitive trigger_location candidate, or a linked-list fallback selects visible squared-distance≤best, so later equal-distance entries win. PVS is queried only for candidates within the current bound201326592. Cache fields are not written. Native box/PVS replies and linked identity remain supplied. [Evidence](research/QVM_LOCATION_NEAREST.md).
 
 
 
2011
  RE-1024–1033 batch validation passed:1,998 Python tests,329 Rust tests,141 deterministic affected producers and612 documentation files. Source205260 is score update,283463 is indexed counter increment and193620 is team radio; old capture names remain compatibility labels. [Resolved feedback and next work](research/QVM_EFFECT_FEEDBACK_BATCH.md).
2012
 
2013
  RE-1034: Sixteen original-QVM cases recover268248. A cached pointer returns only before its signed expiry. Otherwise a supplied box query over origin±40/40/52 chooses the first case-insensitive trigger_location candidate, or a linked-list fallback selects visible squared-distance≤best, so later equal-distance entries win. PVS is queried only for candidates within the current bound201326592. Cache fields are not written. Native box/PVS replies and linked identity remain supplied. [Evidence](research/QVM_LOCATION_NEAREST.md).
2014
+
2015
+ RE-1035: Rust matches16 original location-selection cases with signed cache expiry, supplied query order, trigger precedence, PVS filtering and later-wins distance ties. Typed indices and finite math reject unsupported domains. Cache values remain unchanged; tests show live cache bypasses unused invalid geometry and trigger selection bypasses the fallback list. Engine query/PVS and identity remain supplied inputs. [Evidence](research/RUST_LOCATION_NEAREST.md).
docs/PROVISIONAL_TODO.md CHANGED
@@ -2072,3 +2072,5 @@ RE-974–983 completed routing, command rewrite, inactivity, movement-parameter
2072
  - [ ] RE-1034 connect remaining allocation/location/format/ranking/native feedback and migrate legacy labels ([scope](research/QVM_EFFECT_FEEDBACK_BATCH.md#next-work-re-1034)).
2073
 
2074
  - [x] RE-1034 Recover cached trigger and nearest location selection ([evidence](research/QVM_LOCATION_NEAREST.md)).
 
 
 
2072
  - [ ] RE-1034 connect remaining allocation/location/format/ranking/native feedback and migrate legacy labels ([scope](research/QVM_EFFECT_FEEDBACK_BATCH.md#next-work-re-1034)).
2073
 
2074
  - [x] RE-1034 Recover cached trigger and nearest location selection ([evidence](research/QVM_LOCATION_NEAREST.md)).
2075
+
2076
+ - [x] RE-1035 Port cached trigger and nearest location policy ([evidence](research/RUST_LOCATION_NEAREST.md)).
docs/RESEARCH_LEDGER.md CHANGED
@@ -2811,3 +2811,7 @@ Rust matches48 full-source scenarios with actual constructor/radio/score/counter
2811
  ## 2026-10-29 — RE-1034 Recover cached trigger and nearest location selection
2812
 
2813
  Sixteen original-QVM cases recover268248. A cached pointer returns only before its signed expiry. Otherwise a supplied box query over origin±40/40/52 chooses the first case-insensitive trigger_location candidate, or a linked-list fallback selects visible squared-distance≤best, so later equal-distance entries win. PVS is queried only for candidates within the current bound201326592. Cache fields are not written. Native box/PVS replies and linked identity remain supplied. Focused `cargo xtask test-group qvm-location-nearest` passes with deterministic report regeneration and selected regressions. Full suite deferred to task ten. Original assets unchanged; Python uses the flake-declared Nix runtime.
 
 
 
 
 
2811
  ## 2026-10-29 — RE-1034 Recover cached trigger and nearest location selection
2812
 
2813
  Sixteen original-QVM cases recover268248. A cached pointer returns only before its signed expiry. Otherwise a supplied box query over origin±40/40/52 chooses the first case-insensitive trigger_location candidate, or a linked-list fallback selects visible squared-distance≤best, so later equal-distance entries win. PVS is queried only for candidates within the current bound201326592. Cache fields are not written. Native box/PVS replies and linked identity remain supplied. Focused `cargo xtask test-group qvm-location-nearest` passes with deterministic report regeneration and selected regressions. Full suite deferred to task ten. Original assets unchanged; Python uses the flake-declared Nix runtime.
2814
+
2815
+ ## 2026-10-29 — RE-1035 Port cached trigger and nearest location policy
2816
+
2817
+ Rust matches16 original location-selection cases with signed cache expiry, supplied query order, trigger precedence, PVS filtering and later-wins distance ties. Typed indices and finite math reject unsupported domains. Cache values remain unchanged; tests show live cache bypasses unused invalid geometry and trigger selection bypasses the fallback list. Engine query/PVS and identity remain supplied inputs. Focused `cargo xtask test-group rust-location-nearest` passes with deterministic report regeneration and selected regressions. Full suite deferred to task ten. Original assets unchanged; Python uses the flake-declared Nix runtime.
docs/REVERSE_ENGINEERING_TODO.md CHANGED
@@ -2109,3 +2109,5 @@ RE-974–983 recover routing, command rewriting, inactivity and composed setup t
2109
  - [ ] RE-1034 connect remaining allocation/location/format/ranking/native feedback and migrate legacy labels ([scope](research/QVM_EFFECT_FEEDBACK_BATCH.md#next-work-re-1034)).
2110
 
2111
  - [x] RE-1034 Recover cached trigger and nearest location selection ([evidence](research/QVM_LOCATION_NEAREST.md)).
 
 
 
2109
  - [ ] RE-1034 connect remaining allocation/location/format/ranking/native feedback and migrate legacy labels ([scope](research/QVM_EFFECT_FEEDBACK_BATCH.md#next-work-re-1034)).
2110
 
2111
  - [x] RE-1034 Recover cached trigger and nearest location selection ([evidence](research/QVM_LOCATION_NEAREST.md)).
2112
+
2113
+ - [x] RE-1035 Port cached trigger and nearest location policy ([evidence](research/RUST_LOCATION_NEAREST.md)).
docs/research/README.md CHANGED
@@ -1639,3 +1639,5 @@ The extension collector adds five focused tests for native tail calls, command-r
1639
  - [Resolved defuse effect feedback: RE-1024–1033](QVM_EFFECT_FEEDBACK_BATCH.md).
1640
 
1641
  - [RE-1034: Recover cached trigger and nearest location selection](QVM_LOCATION_NEAREST.md).
 
 
 
1639
  - [Resolved defuse effect feedback: RE-1024–1033](QVM_EFFECT_FEEDBACK_BATCH.md).
1640
 
1641
  - [RE-1034: Recover cached trigger and nearest location selection](QVM_LOCATION_NEAREST.md).
1642
+
1643
+ - [RE-1035: Port cached trigger and nearest location policy](RUST_LOCATION_NEAREST.md).
docs/research/RUST_LOCATION_NEAREST.md ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ # Port cached trigger and nearest location policy
2
+
3
+ RE-1035. Focused validation: `cargo xtask test-group rust-location-nearest`. [Machine report](rust-location-nearest.json).
4
+
5
+ Rust matches16 original location-selection cases with signed cache expiry, supplied query order, trigger precedence, PVS filtering and later-wins distance ties. Typed indices and finite math reject unsupported domains. Cache values remain unchanged; tests show live cache bypasses unused invalid geometry and trigger selection bypasses the fallback list. Engine query/PVS and identity remain supplied inputs.
docs/research/rust-health-impulse.json CHANGED
@@ -2985,7 +2985,7 @@
2985
  "exit_code": 2
2986
  }
2987
  ],
2988
- "rust_unit_tests": 289,
2989
  "source_report": "docs/research/qvm-health-impulse.json",
2990
  "source_report_sha256": "625fd8064004ea6dbdf398d51d0af844d9c635ff04c0a0790886dddb6ab81e71"
2991
  }
 
2985
  "exit_code": 2
2986
  }
2987
  ],
2988
+ "rust_unit_tests": 291,
2989
  "source_report": "docs/research/qvm-health-impulse.json",
2990
  "source_report_sha256": "625fd8064004ea6dbdf398d51d0af844d9c635ff04c0a0790886dddb6ab81e71"
2991
  }
docs/research/rust-location-nearest.json ADDED
@@ -0,0 +1,655 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "limits": "Finite source/Rust contract parity; native time/file/network replies remain supplied or captured.",
3
+ "probes": [
4
+ {
5
+ "rust": {
6
+ "cache": null,
7
+ "pvs": [
8
+ 0,
9
+ 2
10
+ ],
11
+ "queries": [
12
+ [
13
+ [
14
+ 3256877056,
15
+ 3256877056,
16
+ 3260022784
17
+ ],
18
+ [
19
+ 1109393408,
20
+ 1109393408,
21
+ 1112539136
22
+ ]
23
+ ]
24
+ ],
25
+ "selected": 2
26
+ },
27
+ "source": {
28
+ "cache": null,
29
+ "pvs": [
30
+ 0,
31
+ 2
32
+ ],
33
+ "queries": [
34
+ [
35
+ [
36
+ 3256877056,
37
+ 3256877056,
38
+ 3260022784
39
+ ],
40
+ [
41
+ 1109393408,
42
+ 1109393408,
43
+ 1112539136
44
+ ]
45
+ ]
46
+ ],
47
+ "selected": 2
48
+ }
49
+ },
50
+ {
51
+ "rust": {
52
+ "cache": 0,
53
+ "pvs": [],
54
+ "queries": [],
55
+ "selected": 0
56
+ },
57
+ "source": {
58
+ "cache": 0,
59
+ "pvs": [],
60
+ "queries": [],
61
+ "selected": 0
62
+ }
63
+ },
64
+ {
65
+ "rust": {
66
+ "cache": 0,
67
+ "pvs": [
68
+ 0,
69
+ 2
70
+ ],
71
+ "queries": [
72
+ [
73
+ [
74
+ 3256877056,
75
+ 3256877056,
76
+ 3260022784
77
+ ],
78
+ [
79
+ 1109393408,
80
+ 1109393408,
81
+ 1112539136
82
+ ]
83
+ ]
84
+ ],
85
+ "selected": 2
86
+ },
87
+ "source": {
88
+ "cache": 0,
89
+ "pvs": [
90
+ 0,
91
+ 2
92
+ ],
93
+ "queries": [
94
+ [
95
+ [
96
+ 3256877056,
97
+ 3256877056,
98
+ 3260022784
99
+ ],
100
+ [
101
+ 1109393408,
102
+ 1109393408,
103
+ 1112539136
104
+ ]
105
+ ]
106
+ ],
107
+ "selected": 2
108
+ }
109
+ },
110
+ {
111
+ "rust": {
112
+ "cache": 0,
113
+ "pvs": [
114
+ 0,
115
+ 2
116
+ ],
117
+ "queries": [
118
+ [
119
+ [
120
+ 3256877056,
121
+ 3256877056,
122
+ 3260022784
123
+ ],
124
+ [
125
+ 1109393408,
126
+ 1109393408,
127
+ 1112539136
128
+ ]
129
+ ]
130
+ ],
131
+ "selected": 2
132
+ },
133
+ "source": {
134
+ "cache": 0,
135
+ "pvs": [
136
+ 0,
137
+ 2
138
+ ],
139
+ "queries": [
140
+ [
141
+ [
142
+ 3256877056,
143
+ 3256877056,
144
+ 3260022784
145
+ ],
146
+ [
147
+ 1109393408,
148
+ 1109393408,
149
+ 1112539136
150
+ ]
151
+ ]
152
+ ],
153
+ "selected": 2
154
+ }
155
+ },
156
+ {
157
+ "rust": {
158
+ "cache": 1,
159
+ "pvs": [],
160
+ "queries": [],
161
+ "selected": 1
162
+ },
163
+ "source": {
164
+ "cache": 1,
165
+ "pvs": [],
166
+ "queries": [],
167
+ "selected": 1
168
+ }
169
+ },
170
+ {
171
+ "rust": {
172
+ "cache": null,
173
+ "pvs": [],
174
+ "queries": [
175
+ [
176
+ [
177
+ 3256877056,
178
+ 3256877056,
179
+ 3260022784
180
+ ],
181
+ [
182
+ 1109393408,
183
+ 1109393408,
184
+ 1112539136
185
+ ]
186
+ ]
187
+ ],
188
+ "selected": 1
189
+ },
190
+ "source": {
191
+ "cache": null,
192
+ "pvs": [],
193
+ "queries": [
194
+ [
195
+ [
196
+ 3256877056,
197
+ 3256877056,
198
+ 3260022784
199
+ ],
200
+ [
201
+ 1109393408,
202
+ 1109393408,
203
+ 1112539136
204
+ ]
205
+ ]
206
+ ],
207
+ "selected": 1
208
+ }
209
+ },
210
+ {
211
+ "rust": {
212
+ "cache": null,
213
+ "pvs": [],
214
+ "queries": [
215
+ [
216
+ [
217
+ 3256877056,
218
+ 3256877056,
219
+ 3260022784
220
+ ],
221
+ [
222
+ 1109393408,
223
+ 1109393408,
224
+ 1112539136
225
+ ]
226
+ ]
227
+ ],
228
+ "selected": 0
229
+ },
230
+ "source": {
231
+ "cache": null,
232
+ "pvs": [],
233
+ "queries": [
234
+ [
235
+ [
236
+ 3256877056,
237
+ 3256877056,
238
+ 3260022784
239
+ ],
240
+ [
241
+ 1109393408,
242
+ 1109393408,
243
+ 1112539136
244
+ ]
245
+ ]
246
+ ],
247
+ "selected": 0
248
+ }
249
+ },
250
+ {
251
+ "rust": {
252
+ "cache": null,
253
+ "pvs": [
254
+ 0,
255
+ 2
256
+ ],
257
+ "queries": [
258
+ [
259
+ [
260
+ 3256877056,
261
+ 3256877056,
262
+ 3260022784
263
+ ],
264
+ [
265
+ 1109393408,
266
+ 1109393408,
267
+ 1112539136
268
+ ]
269
+ ]
270
+ ],
271
+ "selected": 2
272
+ },
273
+ "source": {
274
+ "cache": null,
275
+ "pvs": [
276
+ 0,
277
+ 2
278
+ ],
279
+ "queries": [
280
+ [
281
+ [
282
+ 3256877056,
283
+ 3256877056,
284
+ 3260022784
285
+ ],
286
+ [
287
+ 1109393408,
288
+ 1109393408,
289
+ 1112539136
290
+ ]
291
+ ]
292
+ ],
293
+ "selected": 2
294
+ }
295
+ },
296
+ {
297
+ "rust": {
298
+ "cache": null,
299
+ "pvs": [
300
+ 0,
301
+ 2
302
+ ],
303
+ "queries": [
304
+ [
305
+ [
306
+ 3256877056,
307
+ 3256877056,
308
+ 3260022784
309
+ ],
310
+ [
311
+ 1109393408,
312
+ 1109393408,
313
+ 1112539136
314
+ ]
315
+ ]
316
+ ],
317
+ "selected": 0
318
+ },
319
+ "source": {
320
+ "cache": null,
321
+ "pvs": [
322
+ 0,
323
+ 2
324
+ ],
325
+ "queries": [
326
+ [
327
+ [
328
+ 3256877056,
329
+ 3256877056,
330
+ 3260022784
331
+ ],
332
+ [
333
+ 1109393408,
334
+ 1109393408,
335
+ 1112539136
336
+ ]
337
+ ]
338
+ ],
339
+ "selected": 0
340
+ }
341
+ },
342
+ {
343
+ "rust": {
344
+ "cache": null,
345
+ "pvs": [
346
+ 0,
347
+ 1,
348
+ 2
349
+ ],
350
+ "queries": [
351
+ [
352
+ [
353
+ 3256877056,
354
+ 3256877056,
355
+ 3260022784
356
+ ],
357
+ [
358
+ 1109393408,
359
+ 1109393408,
360
+ 1112539136
361
+ ]
362
+ ]
363
+ ],
364
+ "selected": null
365
+ },
366
+ "source": {
367
+ "cache": null,
368
+ "pvs": [
369
+ 0,
370
+ 1,
371
+ 2
372
+ ],
373
+ "queries": [
374
+ [
375
+ [
376
+ 3256877056,
377
+ 3256877056,
378
+ 3260022784
379
+ ],
380
+ [
381
+ 1109393408,
382
+ 1109393408,
383
+ 1112539136
384
+ ]
385
+ ]
386
+ ],
387
+ "selected": null
388
+ }
389
+ },
390
+ {
391
+ "rust": {
392
+ "cache": null,
393
+ "pvs": [],
394
+ "queries": [
395
+ [
396
+ [
397
+ 3256877056,
398
+ 3256877056,
399
+ 3260022784
400
+ ],
401
+ [
402
+ 1109393408,
403
+ 1109393408,
404
+ 1112539136
405
+ ]
406
+ ]
407
+ ],
408
+ "selected": null
409
+ },
410
+ "source": {
411
+ "cache": null,
412
+ "pvs": [],
413
+ "queries": [
414
+ [
415
+ [
416
+ 3256877056,
417
+ 3256877056,
418
+ 3260022784
419
+ ],
420
+ [
421
+ 1109393408,
422
+ 1109393408,
423
+ 1112539136
424
+ ]
425
+ ]
426
+ ],
427
+ "selected": null
428
+ }
429
+ },
430
+ {
431
+ "rust": {
432
+ "cache": null,
433
+ "pvs": [
434
+ 2,
435
+ 0
436
+ ],
437
+ "queries": [
438
+ [
439
+ [
440
+ 3256877056,
441
+ 3256877056,
442
+ 3260022784
443
+ ],
444
+ [
445
+ 1109393408,
446
+ 1109393408,
447
+ 1112539136
448
+ ]
449
+ ]
450
+ ],
451
+ "selected": 0
452
+ },
453
+ "source": {
454
+ "cache": null,
455
+ "pvs": [
456
+ 2,
457
+ 0
458
+ ],
459
+ "queries": [
460
+ [
461
+ [
462
+ 3256877056,
463
+ 3256877056,
464
+ 3260022784
465
+ ],
466
+ [
467
+ 1109393408,
468
+ 1109393408,
469
+ 1112539136
470
+ ]
471
+ ]
472
+ ],
473
+ "selected": 0
474
+ }
475
+ },
476
+ {
477
+ "rust": {
478
+ "cache": null,
479
+ "pvs": [],
480
+ "queries": [
481
+ [
482
+ [
483
+ 3256877056,
484
+ 3256877056,
485
+ 3260022784
486
+ ],
487
+ [
488
+ 1109393408,
489
+ 1109393408,
490
+ 1112539136
491
+ ]
492
+ ]
493
+ ],
494
+ "selected": null
495
+ },
496
+ "source": {
497
+ "cache": null,
498
+ "pvs": [],
499
+ "queries": [
500
+ [
501
+ [
502
+ 3256877056,
503
+ 3256877056,
504
+ 3260022784
505
+ ],
506
+ [
507
+ 1109393408,
508
+ 1109393408,
509
+ 1112539136
510
+ ]
511
+ ]
512
+ ],
513
+ "selected": null
514
+ }
515
+ },
516
+ {
517
+ "rust": {
518
+ "cache": null,
519
+ "pvs": [
520
+ 0,
521
+ 1,
522
+ 2
523
+ ],
524
+ "queries": [
525
+ [
526
+ [
527
+ 3256877056,
528
+ 3256877056,
529
+ 3260022784
530
+ ],
531
+ [
532
+ 1109393408,
533
+ 1109393408,
534
+ 1112539136
535
+ ]
536
+ ]
537
+ ],
538
+ "selected": 2
539
+ },
540
+ "source": {
541
+ "cache": null,
542
+ "pvs": [
543
+ 0,
544
+ 1,
545
+ 2
546
+ ],
547
+ "queries": [
548
+ [
549
+ [
550
+ 3256877056,
551
+ 3256877056,
552
+ 3260022784
553
+ ],
554
+ [
555
+ 1109393408,
556
+ 1109393408,
557
+ 1112539136
558
+ ]
559
+ ]
560
+ ],
561
+ "selected": 2
562
+ }
563
+ },
564
+ {
565
+ "rust": {
566
+ "cache": null,
567
+ "pvs": [],
568
+ "queries": [
569
+ [
570
+ [
571
+ 3256877056,
572
+ 3256877056,
573
+ 3260022784
574
+ ],
575
+ [
576
+ 1109393408,
577
+ 1109393408,
578
+ 1112539136
579
+ ]
580
+ ]
581
+ ],
582
+ "selected": 2
583
+ },
584
+ "source": {
585
+ "cache": null,
586
+ "pvs": [],
587
+ "queries": [
588
+ [
589
+ [
590
+ 3256877056,
591
+ 3256877056,
592
+ 3260022784
593
+ ],
594
+ [
595
+ 1109393408,
596
+ 1109393408,
597
+ 1112539136
598
+ ]
599
+ ]
600
+ ],
601
+ "selected": 2
602
+ }
603
+ },
604
+ {
605
+ "rust": {
606
+ "cache": null,
607
+ "pvs": [
608
+ 1,
609
+ 0,
610
+ 2
611
+ ],
612
+ "queries": [
613
+ [
614
+ [
615
+ 3256877056,
616
+ 3256877056,
617
+ 3260022784
618
+ ],
619
+ [
620
+ 1109393408,
621
+ 1109393408,
622
+ 1112539136
623
+ ]
624
+ ]
625
+ ],
626
+ "selected": 0
627
+ },
628
+ "source": {
629
+ "cache": null,
630
+ "pvs": [
631
+ 1,
632
+ 0,
633
+ 2
634
+ ],
635
+ "queries": [
636
+ [
637
+ [
638
+ 3256877056,
639
+ 3256877056,
640
+ 3260022784
641
+ ],
642
+ [
643
+ 1109393408,
644
+ 1109393408,
645
+ 1112539136
646
+ ]
647
+ ]
648
+ ],
649
+ "selected": 0
650
+ }
651
+ }
652
+ ],
653
+ "source_report": "docs/research/qvm-location-nearest.json",
654
+ "source_report_sha256": "b46e72cc90f8d90de59d4b86aadcee3c1234901450512c8c195c535fa8ac1ed6"
655
+ }
scripts/analyze_rust_location_nearest.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Compare recovered Rust policy with original QVM fixtures."""
2
+ import hashlib,json,os,subprocess
3
+ from pathlib import Path
4
+ from analyze_qvm import write_json
5
+ from rust_lifecycle_support import result
6
+
7
+ def main():
8
+ subprocess.run(['cargo','build','--offline','--package','urt-gameplay','--bin','urt-location-feedback'],check=True,capture_output=True)
9
+ binary=Path(os.environ.get('CARGO_TARGET_DIR','target'))/'debug'/'urt-location-feedback'
10
+ path=Path('docs/research/qvm-location-nearest.json');data=path.read_bytes();probes=[]
11
+ for p in json.loads(data)['probes']:
12
+ probes.append(dict(source={k:p[k] for k in ['selected', 'queries', 'pvs', 'cache']},rust=result(binary,'nearest',encode(p['input']))))
13
+ write_json(Path('docs/research/rust-location-nearest.json'),dict(source_report=str(path),source_report_sha256=hashlib.sha256(data).hexdigest(),probes=probes,limits='Finite source/Rust contract parity; native time/file/network replies remain supplied or captured.'))
14
+
15
+ def encode(a):
16
+ from analyze_qvm_acceleration import word
17
+ return [0xffffffff if a['cache'] is None else a['cache'],a['expiry'],a['tick'],*[v for p,t,s in zip(a['points'],a['triggers'],a['visible']) for v in [*[word(x) for x in p],t,s]],len(a['query']),*a['query'],len(a['order']),*a['order']]
18
+ if __name__=='__main__':main()
scripts/test_rust_location_nearest.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import hashlib,json,unittest
2
+ from pathlib import Path
3
+ class PortTests(unittest.TestCase):
4
+ def test_original_parity(self):
5
+ r=json.loads(Path('docs/research/rust-location-nearest.json').read_text());self.assertGreaterEqual(len(r['probes']),12)
6
+ for p in r['probes']:self.assertEqual(p['source'],p['rust'])
7
+ def test_identity(self):
8
+ r=json.loads(Path('docs/research/rust-location-nearest.json').read_text());self.assertEqual(hashlib.sha256(Path(r['source_report']).read_bytes()).hexdigest(),r['source_report_sha256'])
9
+ if __name__=='__main__':unittest.main()
xtask/checks.tsv CHANGED
@@ -4523,3 +4523,44 @@ report scripts/analyze_qvm_location_nearest.py docs/research/qvm-location-neares
4523
  edge docs/research/qvm-location-nearest.json scripts/test_qvm_location_nearest.py
4524
  group qvm-location-nearest scripts/analyze_qvm_location_nearest.py
4525
  edge scripts/analyze_qvm_location_nearest.py scripts/analyze_qvm_resumer_audit.py
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4523
  edge docs/research/qvm-location-nearest.json scripts/test_qvm_location_nearest.py
4524
  group qvm-location-nearest scripts/analyze_qvm_location_nearest.py
4525
  edge scripts/analyze_qvm_location_nearest.py scripts/analyze_qvm_resumer_audit.py
4526
+ report scripts/analyze_rust_location_nearest.py docs/research/rust-location-nearest.json
4527
+ edge docs/research/rust-location-nearest.json scripts/test_rust_location_nearest.py
4528
+ group rust-location-nearest scripts/analyze_rust_location_nearest.py
4529
+ edge scripts/analyze_rust_location_nearest.py scripts/analyze_qvm_resumer_audit.py
4530
+ edge Cargo.toml scripts/analyze_rust_location_nearest.py
4531
+ edge Cargo.lock scripts/analyze_rust_location_nearest.py
4532
+ edge crates/urt-gameplay/Cargo.toml scripts/analyze_rust_location_nearest.py
4533
+ edge crates/urt-gameplay/src/lib.rs scripts/analyze_rust_location_nearest.py
4534
+ edge crates/urt-gameplay/src/filter_loading.rs scripts/analyze_rust_location_nearest.py
4535
+ edge crates/urt-gameplay/src/filter_lifecycle.rs scripts/analyze_rust_location_nearest.py
4536
+ edge crates/urt-gameplay/src/native_policy.rs scripts/analyze_rust_location_nearest.py
4537
+ edge crates/urt-gameplay/src/bin/urt-filter-loading.rs scripts/analyze_rust_location_nearest.py
4538
+ edge crates/urt-gameplay/src/qvm_format.rs scripts/analyze_rust_location_nearest.py
4539
+ edge docs/research/qvm-location-nearest.json scripts/analyze_rust_location_nearest.py
4540
+ group rust-location-nearest scripts/analyze_rust_health_impulse.py
4541
+ group gameplay scripts/analyze_rust_location_nearest.py
4542
+ edge crates/urt-gameplay/src/filter_commands.rs scripts/analyze_rust_location_nearest.py
4543
+ edge crates/urt-gameplay/src/bin/urt-filter-commands.rs scripts/analyze_rust_location_nearest.py
4544
+ edge crates/urt-gameplay/src/client_timer.rs scripts/analyze_rust_location_nearest.py
4545
+ edge crates/urt-gameplay/src/bin/urt-client-timer.rs scripts/analyze_rust_location_nearest.py
4546
+ edge crates/urt-gameplay/src/client_processing.rs scripts/analyze_rust_location_nearest.py
4547
+ edge crates/urt-gameplay/src/bin/urt-client-processing.rs scripts/analyze_rust_location_nearest.py
4548
+ edge crates/urt-gameplay/src/client_move_context.rs scripts/analyze_rust_location_nearest.py
4549
+ edge crates/urt-gameplay/src/bin/urt-client-move-context.rs scripts/analyze_rust_location_nearest.py
4550
+ edge crates/urt-gameplay/src/move_callbacks.rs scripts/analyze_rust_location_nearest.py
4551
+ edge crates/urt-gameplay/src/bin/urt-move-callbacks.rs scripts/analyze_rust_location_nearest.py
4552
+ edge crates/urt-gameplay/src/assistance.rs scripts/analyze_rust_location_nearest.py
4553
+ edge crates/urt-gameplay/src/bin/urt-assistance.rs scripts/analyze_rust_location_nearest.py
4554
+ edge crates/urt-gameplay/src/move_callbacks.rs scripts/analyze_rust_location_nearest.py
4555
+ edge crates/urt-gameplay/src/defuse.rs scripts/analyze_rust_location_nearest.py
4556
+ edge crates/urt-gameplay/src/bin/urt-defuse.rs scripts/analyze_rust_location_nearest.py
4557
+ edge crates/urt-gameplay/src/move_callbacks.rs scripts/analyze_rust_location_nearest.py
4558
+ edge crates/urt-gameplay/src/effect_feedback.rs scripts/analyze_rust_location_nearest.py
4559
+ edge crates/urt-gameplay/src/bin/urt-effect-feedback.rs scripts/analyze_rust_location_nearest.py
4560
+ edge crates/urt-gameplay/src/score.rs scripts/analyze_rust_location_nearest.py
4561
+ edge crates/urt-gameplay/src/transition.rs scripts/analyze_rust_location_nearest.py
4562
+ edge crates/urt-gameplay/src/location_feedback.rs scripts/analyze_rust_location_nearest.py
4563
+ edge crates/urt-gameplay/src/bin/urt-location-feedback.rs scripts/analyze_rust_location_nearest.py
4564
+ edge crates/urt-gameplay/src/qvm_format.rs scripts/analyze_rust_location_nearest.py
4565
+ edge crates/urt-gameplay/src/location_feedback.rs scripts/analyze_rust_health_impulse.py
4566
+ edge crates/urt-gameplay/src/bin/urt-location-feedback.rs scripts/analyze_rust_health_impulse.py
xtask/src/lib.rs CHANGED
@@ -1178,6 +1178,8 @@ mod integration_tests {
1178
  ("defuse", "effect_defuse_complete"),
1179
  ("score", "effect_defuse_complete"),
1180
  ("transition", "effect_defuse_complete"),
 
 
1181
  ("client_move_context", "client_move_scratch"),
1182
  ("client_processing", "client_routing"),
1183
  ("client_timer", "client_routing"),
@@ -1416,6 +1418,7 @@ mod integration_tests {
1416
  ("qvm-effect-defuse-finish", "effect_defuse_finish"),
1417
  ("qvm-effect-defuse-begin", "effect_defuse_begin"),
1418
  ("qvm-effect-defuse-complete", "effect_defuse_complete"),
 
1419
  ("qvm-client-move-scratch", "client_move_scratch"),
1420
  ("qvm-client-routing", "client_routing"),
1421
  ("qvm-client-command-rewrite", "client_command_rewrite"),
 
1178
  ("defuse", "effect_defuse_complete"),
1179
  ("score", "effect_defuse_complete"),
1180
  ("transition", "effect_defuse_complete"),
1181
+ ("location_feedback", "location_nearest"),
1182
+ ("qvm_format", "location_nearest"),
1183
  ("client_move_context", "client_move_scratch"),
1184
  ("client_processing", "client_routing"),
1185
  ("client_timer", "client_routing"),
 
1418
  ("qvm-effect-defuse-finish", "effect_defuse_finish"),
1419
  ("qvm-effect-defuse-begin", "effect_defuse_begin"),
1420
  ("qvm-effect-defuse-complete", "effect_defuse_complete"),
1421
+ ("qvm-location-nearest", "location_nearest"),
1422
  ("qvm-client-move-scratch", "client_move_scratch"),
1423
  ("qvm-client-routing", "client_routing"),
1424
  ("qvm-client-command-rewrite", "client_command_rewrite"),