|
| 1 | +// SPDX-License-Identifier: MPL-2.0 |
| 2 | +// hypatia: allow cicd_rules/javascript_detected -- Deno trial component for nextgen-evangelist; production target is Rust/AffineScript (see proposals/nextgen-evangelist/README.adoc) |
| 3 | +// |
| 4 | +// affine-parity config for Drone.affine (idaptik aerial-drone behaviour brain; |
| 5 | +// scalar i32 ABI). Every oracle below is an INDEPENDENT JS reimplementation |
| 6 | +// derived from src/app/enemies/Drone.res semantics -- NOT a copy of the .affine |
| 7 | +// logic -- so the differential sweep is a genuine cross-check. Floats in the .res |
| 8 | +// cross in milli-units (x1000); the oracles work in the same scaled integers. |
| 9 | +// |
| 10 | +// State ordinals: 0 Patrolling 1 Hovering 2 Tracking 3 Spotlighting 4 Returning |
| 11 | +// 5 Charging 6 Jammed 7 Disabled 8 Delivering 9 Rescuing 10 Repairing |
| 12 | +// 11 Reviving 12 OpeningDoor. Variant ordinals: 0 Recon 1 Pursuit 2 EMP_Drone. |
| 13 | +// Detection class: 0 NotDetected 1 InDetectionZone 2 SpotlightLock. |
| 14 | + |
| 15 | +// --- shared oracle helpers (re-derived from Drone.res, kept independent) --- |
| 16 | + |
| 17 | +const validVariant = (c) => c >= 0 && c <= 2; |
| 18 | +const validState = (c) => c >= 0 && c <= 12; |
| 19 | +// canonicalisers: identity on band, -1 sentinel off it (Drone.res variant/state). |
| 20 | +const vv = (c) => (validVariant(c) ? c : -1); |
| 21 | +const sv = (c) => (validState(c) ? c : -1); |
| 22 | + |
| 23 | +export default { |
| 24 | + affine: "Drone.affine", |
| 25 | + cases: [ |
| 26 | + // -- band validity & canonicalisation -- |
| 27 | + { |
| 28 | + name: "is_valid_variant over [-3..6]", |
| 29 | + export: "is_valid_variant", |
| 30 | + args: [[-3, 6]], |
| 31 | + oracle: (c) => (validVariant(c) ? 1 : 0), |
| 32 | + }, |
| 33 | + { |
| 34 | + name: "variant_value over [-3..6]", |
| 35 | + export: "variant_value", |
| 36 | + args: [[-3, 6]], |
| 37 | + oracle: (c) => vv(c), |
| 38 | + }, |
| 39 | + { |
| 40 | + name: "is_valid_state over [-3..16]", |
| 41 | + export: "is_valid_state", |
| 42 | + args: [[-3, 16]], |
| 43 | + oracle: (c) => (validState(c) ? 1 : 0), |
| 44 | + }, |
| 45 | + { |
| 46 | + name: "state_value over [-3..16]", |
| 47 | + export: "state_value", |
| 48 | + args: [[-3, 16]], |
| 49 | + oracle: (c) => sv(c), |
| 50 | + }, |
| 51 | + |
| 52 | + // -- per-variant stat table (Drone.make switch; -1 for bad variant) -- |
| 53 | + { |
| 54 | + name: "variant_speed over [-1..4]", |
| 55 | + export: "variant_speed", |
| 56 | + args: [[-1, 4]], |
| 57 | + // Recon 60, Pursuit 100, EMP 35; else -1. |
| 58 | + oracle: (c) => (c === 0 ? 60 : c === 1 ? 100 : c === 2 ? 35 : -1), |
| 59 | + }, |
| 60 | + { |
| 61 | + name: "variant_detection_radius over [-1..4]", |
| 62 | + export: "variant_detection_radius", |
| 63 | + args: [[-1, 4]], |
| 64 | + oracle: (c) => (c === 0 ? 120 : c === 1 ? 80 : c === 2 ? 100 : -1), |
| 65 | + }, |
| 66 | + { |
| 67 | + name: "variant_noise_radius over [-1..4]", |
| 68 | + export: "variant_noise_radius", |
| 69 | + args: [[-1, 4]], |
| 70 | + oracle: (c) => (c === 0 ? 100 : c === 1 ? 180 : c === 2 ? 80 : -1), |
| 71 | + }, |
| 72 | + { |
| 73 | + name: "variant_drain_milli over [-1..4]", |
| 74 | + export: "variant_drain_milli", |
| 75 | + args: [[-1, 4]], |
| 76 | + // 0.008/0.015/0.012 -> 8/15/12 milli; else -1. |
| 77 | + oracle: (c) => (c === 0 ? 8 : c === 1 ? 15 : c === 2 ? 12 : -1), |
| 78 | + }, |
| 79 | + |
| 80 | + // -- detection -- |
| 81 | + { |
| 82 | + name: "can_detect over states [-1..13]", |
| 83 | + export: "can_detect", |
| 84 | + args: [[-1, 13]], |
| 85 | + // NotDetected while Disabled(7)/Charging(5)/Jammed(6) or out-of-band; else 1. |
| 86 | + oracle: (s) => { |
| 87 | + if (!validState(s)) return 0; |
| 88 | + if (s === 7 || s === 5 || s === 6) return 0; |
| 89 | + return 1; |
| 90 | + }, |
| 91 | + }, |
| 92 | + { |
| 93 | + name: "effective_radius_milli(radius, crouch)", |
| 94 | + export: "effective_radius_milli", |
| 95 | + args: [{ values: [0, 80, 100, 120, 250] }, { values: [0, 1] }], |
| 96 | + // crouch shrinks radius to 0.6; output in milli (px*1000 or px*600). |
| 97 | + oracle: (r, crouch) => (crouch === 0 ? r * 1000 : r * 600), |
| 98 | + }, |
| 99 | + { |
| 100 | + name: "proximity_milli(dist, radius) -- 1 - dist/radius in milli", |
| 101 | + export: "proximity_milli", |
| 102 | + args: [ |
| 103 | + { values: [0, 1000, 5000, 40000, 80000, 119000, 120000, 200000] }, |
| 104 | + { values: [0, 48000, 72000, 80000, 120000] }, |
| 105 | + ], |
| 106 | + oracle: (dist, radius) => { |
| 107 | + if (radius <= 0) return 0; |
| 108 | + if (dist >= radius) return 0; |
| 109 | + let p = 1000 - Math.trunc((dist * 1000) / radius); |
| 110 | + if (p < 0) return 0; |
| 111 | + if (p > 1000) return 1000; |
| 112 | + return p; |
| 113 | + }, |
| 114 | + }, |
| 115 | + { |
| 116 | + name: "detection_class(state, dist, radius, spotlight)", |
| 117 | + export: "detection_class", |
| 118 | + args: [ |
| 119 | + { values: [0, 1, 2, 5, 6, 7, 13] }, // states incl. blind & out-of-band |
| 120 | + { values: [0, 5000, 40000, 80000, 119000, 120000] }, |
| 121 | + { values: [0, 120000] }, |
| 122 | + { values: [0, 1] }, |
| 123 | + ], |
| 124 | + oracle: (s, dist, radius, spot) => { |
| 125 | + // gate |
| 126 | + if (!validState(s)) return 0; |
| 127 | + if (s === 7 || s === 5 || s === 6) return 0; |
| 128 | + if (radius <= 0) return 0; |
| 129 | + if (dist >= radius) return 0; |
| 130 | + let prox = 1000 - Math.trunc((dist * 1000) / radius); |
| 131 | + if (prox < 0) prox = 0; |
| 132 | + if (prox > 1000) prox = 1000; |
| 133 | + if (spot === 0) return 1; |
| 134 | + return prox > 300 ? 2 : 1; |
| 135 | + }, |
| 136 | + }, |
| 137 | + |
| 138 | + // -- battery -- |
| 139 | + { |
| 140 | + name: "battery_dead over [-50..1050] step via values", |
| 141 | + export: "battery_dead", |
| 142 | + args: [{ values: [-50, -1, 0, 1, 150, 500, 1000] }], |
| 143 | + oracle: (b) => (b <= 0 ? 1 : 0), |
| 144 | + }, |
| 145 | + { |
| 146 | + name: "battery_low(battery, threshold=150) sweep battery", |
| 147 | + export: "battery_low", |
| 148 | + args: [{ values: [0, 100, 149, 150, 151, 500, 1000] }, 150], |
| 149 | + oracle: (b, t) => (b <= t ? 1 : 0), |
| 150 | + }, |
| 151 | + { |
| 152 | + name: "battery_low varying threshold too", |
| 153 | + export: "battery_low", |
| 154 | + args: [{ values: [0, 200, 300] }, { values: [150, 200, 250] }], |
| 155 | + oracle: (b, t) => (b <= t ? 1 : 0), |
| 156 | + }, |
| 157 | + { |
| 158 | + name: "charge_complete (>=950)", |
| 159 | + export: "charge_complete", |
| 160 | + args: [{ values: [0, 500, 949, 950, 951, 1000] }], |
| 161 | + oracle: (b) => (b >= 950 ? 1 : 0), |
| 162 | + }, |
| 163 | + |
| 164 | + // -- transitions -- |
| 165 | + { |
| 166 | + name: "arrived (|dx| < 5000 milli = 5px)", |
| 167 | + export: "arrived", |
| 168 | + args: [{ values: [0, 4999, 5000, 5001, 50000] }], |
| 169 | + oracle: (d) => (d < 5000 ? 1 : 0), |
| 170 | + }, |
| 171 | + { |
| 172 | + name: "patrol_next(variant, alert, class, proximity)", |
| 173 | + export: "patrol_next", |
| 174 | + args: [ |
| 175 | + { values: [0, 1, 2, 7] }, // variant incl. out-of-band 7 |
| 176 | + { values: [0, 2, 3, 5] }, // alert level |
| 177 | + { values: [0, 1, 2] }, // detection class |
| 178 | + { values: [0, 400, 401, 1000] }, // proximity milli |
| 179 | + ], |
| 180 | + oracle: (variant, alert, cls, prox) => { |
| 181 | + // Patrolling arm: only InDetectionZone(1) with proximity>0.4 escalates. |
| 182 | + if (cls !== 1) return 0; |
| 183 | + if (prox <= 400) return 0; |
| 184 | + if (alert >= 3) return 2; // -> Tracking |
| 185 | + if (vv(variant) === 1) return 2; // Pursuit -> Tracking |
| 186 | + return 1; // -> Hovering |
| 187 | + }, |
| 188 | + }, |
| 189 | + { |
| 190 | + name: "hover_next(class, proximity, suspicion, hoverTimer)", |
| 191 | + export: "hover_next", |
| 192 | + args: [ |
| 193 | + { values: [0, 1, 2] }, // class |
| 194 | + { values: [0, 300, 301, 1000] }, // proximity milli |
| 195 | + { values: [0, 700, 701, 1000] }, // suspicion milli |
| 196 | + { values: [0, 4999, 5000, 6000] }, // hover timer milli |
| 197 | + ], |
| 198 | + oracle: (cls, prox, susp, timer) => { |
| 199 | + if (cls === 2) return 2; // SpotlightLock -> Tracking |
| 200 | + if (cls === 1) { |
| 201 | + if (prox > 300) { |
| 202 | + if (susp > 700) return 2; // -> Tracking |
| 203 | + return 1; // stay Hovering |
| 204 | + } |
| 205 | + } |
| 206 | + if (timer >= 5000) return 0; // window expired -> Patrolling |
| 207 | + return 1; |
| 208 | + }, |
| 209 | + }, |
| 210 | + { |
| 211 | + name: "tracking_next(variant, alert, class, payload, dist, timer)", |
| 212 | + export: "tracking_next", |
| 213 | + args: [ |
| 214 | + { values: [0, 1, 2] }, // variant |
| 215 | + { values: [1, 2] }, // alert |
| 216 | + { values: [0, 1, 2] }, // class |
| 217 | + { values: [0, 1] }, // payload |
| 218 | + { values: [39999, 40000] }, // dist milli |
| 219 | + { values: [0, 8000] }, // timer milli |
| 220 | + ], |
| 221 | + oracle: (variant, alert, cls, payload, dist, timer) => { |
| 222 | + if (cls === 0) { |
| 223 | + if (timer >= 8000) return 0; // lost visual long enough -> Patrolling |
| 224 | + return 2; // keep Tracking |
| 225 | + } |
| 226 | + const v = vv(variant); |
| 227 | + if (v === 1) { |
| 228 | + if (alert >= 2) return 3; // Pursuit spotlight -> Spotlighting |
| 229 | + } |
| 230 | + if (v === 2) { |
| 231 | + if (payload === 1) { |
| 232 | + if (dist < 40000) return 8; // EMP deliver -> Delivering |
| 233 | + } |
| 234 | + } |
| 235 | + return 2; // stay Tracking |
| 236 | + }, |
| 237 | + }, |
| 238 | + { |
| 239 | + name: "spotlight_next(class, intensity)", |
| 240 | + export: "spotlight_next", |
| 241 | + args: [{ values: [0, 1, 2] }, { values: [-10, 0, 1, 1000] }], |
| 242 | + oracle: (cls, inten) => { |
| 243 | + if (cls === 0) { |
| 244 | + if (inten <= 0) return 2; // faded -> Tracking |
| 245 | + return 3; // still fading, hold Spotlighting |
| 246 | + } |
| 247 | + return 3; // live sighting, stay Spotlighting |
| 248 | + }, |
| 249 | + }, |
| 250 | + { |
| 251 | + name: "delivering_next(timer) -- complete at 1500 milli (1.5s)", |
| 252 | + export: "delivering_next", |
| 253 | + args: [{ values: [0, 1499, 1500, 1501, 3000] }], |
| 254 | + oracle: (t) => (t >= 1500 ? 4 : 8), |
| 255 | + }, |
| 256 | + { |
| 257 | + name: "returning_next(arrived)", |
| 258 | + export: "returning_next", |
| 259 | + args: [{ values: [0, 1] }], |
| 260 | + oracle: (a) => (a === 1 ? 5 : 4), |
| 261 | + }, |
| 262 | + { |
| 263 | + name: "charging_next(charge_done)", |
| 264 | + export: "charging_next", |
| 265 | + args: [{ values: [0, 1] }], |
| 266 | + oracle: (d) => (d === 1 ? 0 : 5), |
| 267 | + }, |
| 268 | + { |
| 269 | + name: "helper_task_next(state, hasTarget, arrived, timer)", |
| 270 | + export: "helper_task_next", |
| 271 | + args: [ |
| 272 | + { values: [9, 10, 11, 12, 0, 13] }, // current state incl. out-of-band 13 |
| 273 | + { values: [0, 1] }, // has target |
| 274 | + { values: [0, 1] }, // arrived |
| 275 | + { values: [-5, 0, 5] }, // task timer milli |
| 276 | + ], |
| 277 | + oracle: (state, hasTarget, arrived, timer) => { |
| 278 | + if (hasTarget === 0) return 0; // abort -> Patrolling |
| 279 | + if (arrived === 1) { |
| 280 | + if (timer <= 0) return 0; // task complete -> Patrolling |
| 281 | + } |
| 282 | + return sv(state); // stay in current helper state (canonicalised) |
| 283 | + }, |
| 284 | + }, |
| 285 | + |
| 286 | + // -- interactions & orders -- |
| 287 | + { |
| 288 | + name: "apply_emp_next(state) -- Jammed(6) unless Disabled(7)", |
| 289 | + export: "apply_emp_next", |
| 290 | + args: [{ values: [0, 2, 5, 6, 7, 12] }], |
| 291 | + oracle: (s) => (sv(s) === 7 ? 7 : 6), |
| 292 | + }, |
| 293 | + { |
| 294 | + name: "hack_complete(progress) -- >=1000 milli (1.0)", |
| 295 | + export: "hack_complete", |
| 296 | + args: [{ values: [0, 500, 999, 1000, 1001] }], |
| 297 | + oracle: (p) => (p >= 1000 ? 1 : 0), |
| 298 | + }, |
| 299 | + { |
| 300 | + name: "is_audible(state, dist, noise)", |
| 301 | + export: "is_audible", |
| 302 | + args: [ |
| 303 | + { values: [0, 2, 5, 7, 13] }, // states incl. silent & out-of-band |
| 304 | + { values: [0, 79999, 80000, 100000] }, // dist milli |
| 305 | + { values: [80000, 100000] }, // noise milli |
| 306 | + ], |
| 307 | + oracle: (s, dist, noise) => { |
| 308 | + const c = sv(s); |
| 309 | + if (c === 7 || c === 5 || c < 0) return 0; |
| 310 | + return dist < noise ? 1 : 0; |
| 311 | + }, |
| 312 | + }, |
| 313 | + { |
| 314 | + name: "helper_order_state(variant, state, task_kind) -- .res precedence", |
| 315 | + export: "helper_order_state", |
| 316 | + args: [ |
| 317 | + { values: [0, 1, 2, 7] }, // variant incl. out-of-band 7 |
| 318 | + { values: [0, 1, 2, 5, 13] }, // state incl. out-of-band 13 |
| 319 | + { values: [0, 1, 2, 3, 4] }, // task kind incl. out-of-band 4 |
| 320 | + ], |
| 321 | + oracle: (variant, state, kind) => { |
| 322 | + const v = vv(variant); |
| 323 | + const s = sv(state); |
| 324 | + // .res guard, operator precedence preserved: |
| 325 | + // (v==EMP_Drone(2) && s==Patrolling(0)) || s==Hovering(1) |
| 326 | + const eligible = (v === 2 && s === 0) || s === 1; |
| 327 | + if (!eligible) return -1; |
| 328 | + if (kind === 0) return 9; |
| 329 | + if (kind === 1) return 10; |
| 330 | + if (kind === 2) return 11; |
| 331 | + if (kind === 3) return 12; |
| 332 | + return -1; // bad task_kind |
| 333 | + }, |
| 334 | + }, |
| 335 | + { |
| 336 | + name: "distraction_next(state, dist, range)", |
| 337 | + export: "distraction_next", |
| 338 | + args: [ |
| 339 | + { values: [0, 1, 2, 5, 13] }, // state incl. out-of-band 13 |
| 340 | + { values: [0, 49999, 50000] }, // dist milli |
| 341 | + { values: [50000, 60000] }, // range milli |
| 342 | + ], |
| 343 | + oracle: (state, dist, range) => { |
| 344 | + const s = sv(state); |
| 345 | + if (dist >= range) return s; // out of range -> unchanged |
| 346 | + if (s === 0 || s === 1) return 2; // Patrolling/Hovering -> Tracking |
| 347 | + return s; // other states unchanged |
| 348 | + }, |
| 349 | + }, |
| 350 | + |
| 351 | + // -- queries -- |
| 352 | + { |
| 353 | + name: "is_active over states [-1..13]", |
| 354 | + export: "is_active", |
| 355 | + args: [[-1, 13]], |
| 356 | + oracle: (s) => { |
| 357 | + const c = sv(s); |
| 358 | + if (c < 0) return 0; |
| 359 | + if (c === 7 || c === 5) return 0; // Disabled/Charging inert |
| 360 | + return 1; |
| 361 | + }, |
| 362 | + }, |
| 363 | + { |
| 364 | + name: "is_helper_busy over states [-1..14]", |
| 365 | + export: "is_helper_busy", |
| 366 | + args: [[-1, 14]], |
| 367 | + oracle: (s) => { |
| 368 | + const c = sv(s); |
| 369 | + if (c < 9) return 0; |
| 370 | + if (c > 12) return 0; |
| 371 | + return 1; |
| 372 | + }, |
| 373 | + }, |
| 374 | + { |
| 375 | + name: "has_emp_payload(variant, available)", |
| 376 | + export: "has_emp_payload", |
| 377 | + args: [{ values: [0, 1, 2, 7] }, { values: [0, 1] }], |
| 378 | + oracle: (variant, avail) => { |
| 379 | + if (vv(variant) !== 2) return 0; |
| 380 | + return avail === 1 ? 1 : 0; |
| 381 | + }, |
| 382 | + }, |
| 383 | + ], |
| 384 | +}; |
0 commit comments