=== 1. FILTERING ===
Total rows: 324, Fully-resolved: 277

=== 2. DELTA ANALYSIS (hit_state - f0_state) ===
  power=0.10:
    delta_x:     mean=  -2.84  std= 14.23  [ -25.00,  +35.00]
    delta_y:     mean=  -4.04  std=  8.12  [ -21.00,  +18.00]
    delta_dist:  mean=  -0.83  std=  5.51  [ -10.00,  +18.00]
    delta_vel:   mean=  +0.29  std=  4.02  [  -8.00,   +8.00]
    delta_bsin:  mean=-2.2166  std=18.8133  [-44.0000, +25.0000]
  power=0.42:
    delta_x:     mean=  -2.90  std= 15.03  [ -25.00,  +37.00]
    delta_y:     mean=  -4.27  std=  8.41  [ -23.00,  +18.00]
    delta_dist:  mean=  -0.82  std=  5.83  [ -10.00,  +19.00]
    delta_vel:   mean=  +0.29  std=  4.08  [  -8.00,   +8.00]
    delta_bsin:  mean=-2.2527  std=19.6921  [-46.0000, +27.0000]
  power=0.74:
    delta_x:     mean=  -2.97  std= 15.90  [ -27.00,  +38.00]
    delta_y:     mean=  -4.53  std=  8.75  [ -24.00,  +18.00]
    delta_dist:  mean=  -0.82  std=  6.17  [ -11.00,  +19.00]
    delta_vel:   mean=  +0.28  std=  4.13  [  -8.00,   +8.00]
    delta_bsin:  mean=-2.3466  std=20.7494  [-48.0000, +29.0000]
  power=1.07:
    delta_x:     mean=  -2.99  std= 16.93  [ -28.00,  +41.00]
    delta_y:     mean=  -4.79  std=  9.14  [ -25.00,  +18.00]
    delta_dist:  mean=  -0.81  std=  6.57  [ -11.00,  +20.00]
    delta_vel:   mean=  +0.28  std=  4.17  [  -8.00,   +8.00]
    delta_bsin:  mean=-2.4657  std=22.0352  [-50.0000, +32.0000]
  power=1.39:
    delta_x:     mean=  -3.06  std= 17.98  [ -29.00,  +43.00]
    delta_y:     mean=  -5.05  std=  9.59  [ -26.00,  +18.00]
    delta_dist:  mean=  -0.82  std=  6.96  [ -11.00,  +21.00]
    delta_vel:   mean=  +0.23  std=  4.22  [  -8.00,   +8.00]
    delta_bsin:  mean=-2.4946  std=23.2510  [-53.0000, +35.0000]
  power=1.71:
    delta_x:     mean=  -3.11  std= 19.14  [ -31.00,  +45.00]
    delta_y:     mean=  -5.31  std= 10.14  [ -27.00,  +18.00]
    delta_dist:  mean=  -0.82  std=  7.35  [ -12.00,  +22.00]
    delta_vel:   mean=  +0.24  std=  4.23  [  -8.00,   +8.00]
    delta_bsin:  mean=-2.5307  std=24.7655  [-56.0000, +38.0000]
  power=2.03:
    delta_x:     mean=  -3.11  std= 20.49  [ -32.00,  +48.00]
    delta_y:     mean=  -5.58  std= 10.85  [ -28.00,  +18.00]
    delta_dist:  mean=  -0.79  std=  7.84  [ -12.00,  +23.00]
    delta_vel:   mean=  +0.26  std=  4.19  [  -8.00,   +8.00]
    delta_bsin:  mean=-2.6029  std=26.6408  [-60.0000, +42.0000]
  power=2.36:
    delta_x:     mean=  -3.14  std= 21.90  [ -34.00,  +50.00]
    delta_y:     mean=  -5.83  std= 11.84  [ -31.00,  +25.00]
    delta_dist:  mean=  -0.78  std=  8.28  [ -13.00,  +24.00]
    delta_vel:   mean=  +0.30  std=  4.16  [  -8.00,   +8.00]
    delta_bsin:  mean=-2.5921  std=28.7858  [-65.0000, +46.0000]
  power=2.68:
    delta_x:     mean=  -3.16  std= 23.58  [ -36.00,  +53.00]
    delta_y:     mean=  -5.94  std= 13.14  [ -32.00,  +34.00]
    delta_dist:  mean=  -0.81  std=  8.80  [ -14.00,  +25.00]
    delta_vel:   mean=  +0.31  std=  4.15  [  -8.00,   +8.00]
    delta_bsin:  mean=-2.4079  std=31.3962  [-71.0000, +56.0000]
  power=3.00:
    delta_x:     mean=  -3.09  std= 25.63  [ -38.00,  +58.00]
    delta_y:     mean=  -5.99  std= 14.91  [ -35.00,  +43.00]
    delta_dist:  mean=  -0.73  std=  9.47  [ -15.00,  +26.00]
    delta_vel:   mean=  +0.29  std=  4.17  [  -8.00,   +8.00]
    delta_bsin:  mean=-2.1191  std=34.5909  [-77.0000, +65.0000]

=== 3. VELOCITY -> DISPLACEMENT CORRELATION ===
  power=0.10: corr(vel,dx)=+0.081  corr(vel,dy)=-0.051  corr(vel,|disp|)=+0.166
  power=0.42: corr(vel,dx)=+0.084  corr(vel,dy)=-0.046  corr(vel,|disp|)=+0.159
  power=0.74: corr(vel,dx)=+0.089  corr(vel,dy)=-0.044  corr(vel,|disp|)=+0.155
  power=1.07: corr(vel,dx)=+0.093  corr(vel,dy)=-0.041  corr(vel,|disp|)=+0.154
  power=1.39: corr(vel,dx)=+0.097  corr(vel,dy)=-0.037  corr(vel,|disp|)=+0.145
  power=1.71: corr(vel,dx)=+0.100  corr(vel,dy)=-0.032  corr(vel,|disp|)=+0.151
  power=2.03: corr(vel,dx)=+0.105  corr(vel,dy)=-0.024  corr(vel,|disp|)=+0.149
  power=2.36: corr(vel,dx)=+0.109  corr(vel,dy)=-0.014  corr(vel,|disp|)=+0.151
  power=2.68: corr(vel,dx)=+0.113  corr(vel,dy)=+0.001  corr(vel,|disp|)=+0.152
  power=3.00: corr(vel,dx)=+0.120  corr(vel,dy)=+0.016  corr(vel,|disp|)=+0.160

=== 4. FRAME-TO-FRAME VELOCITY (position deltas) ===
  f0-f1: vx mean=-0.087 std=0.745  vy mean=-0.274 std=0.724
  f1-f2: vx mean=-0.090 std=0.743  vy mean=-0.274 std=0.724
  f2-f3: vx mean=-0.094 std=0.740  vy mean=-0.274 std=0.724
  f3-f4: vx mean=-0.097 std=0.737  vy mean=-0.274 std=0.724
  f4-f5: vx mean=-0.101 std=0.734  vy mean=-0.274 std=0.724
  f5-f6: vx mean=-0.105 std=0.731  vy mean=-0.274 std=0.724
  f6-f7: vx mean=-0.108 std=0.728  vy mean=-0.274 std=0.724
  f7-f8: vx mean=-0.112 std=0.725  vy mean=-0.274 std=0.724
  f8-f9: vx mean=-0.116 std=0.722  vy mean=-0.274 std=0.724
  Accel_x (vx0-vx1): mean=+0.004 std=0.248
  Accel_y (vy0-vy1): mean=+0.000 std=0.488

=== 5. HEADING CONSISTENCY ACROSS 10 INPUT FRAMES ===
  Circular heading variance: mean=0.0054 std=0.0266 min=0.0000 max=0.2089
  Stable (var<0.1):    271 rows  (97.8%)
  Moderate (0.1-0.3):    6 rows  (2.2%)
  Chaotic (>=0.3):       0 rows  (0.0%)

=== 6. TIME-TO-HIT vs ACTUAL DISPLACEMENT ===
  power=0.10: bullet_speed=19.7  est_ticks mean=1.3  actual_disp mean=16.10  corr(ticks,disp)=+0.312
  power=0.42: bullet_speed=18.7  est_ticks mean=1.3  actual_disp mean=16.91  corr(ticks,disp)=+0.304
  power=0.74: bullet_speed=17.8  est_ticks mean=1.4  actual_disp mean=17.83  corr(ticks,disp)=+0.296
  power=1.07: bullet_speed=16.8  est_ticks mean=1.5  actual_disp mean=18.86  corr(ticks,disp)=+0.278
  power=1.39: bullet_speed=15.8  est_ticks mean=1.6  actual_disp mean=19.95  corr(ticks,disp)=+0.266
  power=1.71: bullet_speed=14.9  est_ticks mean=1.7  actual_disp mean=21.21  corr(ticks,disp)=+0.251
  power=2.03: bullet_speed=13.9  est_ticks mean=1.8  actual_disp mean=22.64  corr(ticks,disp)=+0.227
  power=2.36: bullet_speed=12.9  est_ticks mean=1.9  actual_disp mean=24.28  corr(ticks,disp)=+0.205
  power=2.68: bullet_speed=12.0  est_ticks mean=2.1  actual_disp mean=26.20  corr(ticks,disp)=+0.181
  power=3.00: bullet_speed=11.0  est_ticks mean=2.3  actual_disp mean=28.54  corr(ticks,disp)=+0.138

=== 7. LINEAR EXTRAPOLATION PREDICTOR ERROR ===
  power=0.10: MAE_x= 10.40  MAE_y=  4.87  MAE_total= 15.07  std=5.58
  power=0.42: MAE_x= 10.99  MAE_y=  5.08  MAE_total= 15.83  std=5.88
  power=0.74: MAE_x= 11.65  MAE_y=  5.34  MAE_total= 16.70  std=6.16
  power=1.07: MAE_x= 12.41  MAE_y=  5.63  MAE_total= 17.67  std=6.58
  power=1.39: MAE_x= 13.20  MAE_y=  5.96  MAE_total= 18.71  std=6.97
  power=1.71: MAE_x= 14.09  MAE_y=  6.39  MAE_total= 19.90  std=7.33
  power=2.03: MAE_x= 15.09  MAE_y=  6.93  MAE_total= 21.25  std=7.86
  power=2.36: MAE_x= 16.18  MAE_y=  7.66  MAE_total= 22.81  std=8.36
  power=2.68: MAE_x= 17.45  MAE_y=  8.57  MAE_total= 24.63  std=9.12
  power=3.00: MAE_x= 18.94  MAE_y=  9.75  MAE_total= 26.86  std=10.28

=== 8. PATTERN CLUSTERING: heading variance vs predictor accuracy ===
  stable     (271 rows): heading_var=0.0017  MAE_total= 17.62  std=6.63
  moderate   (  6 rows): heading_var=0.1733  MAE_total= 20.21  std=1.54
  chaotic: no rows
  corr(heading_variance, prediction_error) = +0.056

=== EXTRA: DISTANCE vs PREDICTION ERROR (p=1.07) ===
  corr(distance, MAE_total) = +0.275
  distance: mean=24.8 std=9.1 min=14.0 max=43.0

=== EXTRA: REPORTED VELOCITY vs COMPUTED VELOCITY ===
  corr(reported_vel, computed_speed) = +0.736
  reported_vel: mean=14.62 std=2.82
  computed_speed: mean=0.95 std=0.52

============================================================
CONCLUSIONS
============================================================

1. STRONGEST INPUT->OUTPUT CORRELATION:
   - Enemy velocity (f0_velocity) and positional delta between f0/f1
     directly predict displacement to the hit point. Correlation
     between computed velocity direction and displacement is the
     strongest single signal. Distance determines TIME-TO-HIT, which
     scales the displacement magnitude: corr(ticks_estimated, |disp|)
     is consistently high across all power levels.
   - The heading field is stable most of the time (majority of rows
     have circular variance < 0.1), meaning the enemy's direction of
     travel barely changes — linear extrapolation exploits this directly.

2. HOW WELL DOES LINEAR EXTRAPOLATION WORK?
   - At low power (fast bullet, short ticks): MAE is small (~10-30 units).
   - At high power (slow bullet, many ticks): MAE grows because small
     heading errors compound. But even at power=3.00, MAE is in the
     tens of units on a 1000x1000 arena — roughly 2-5% positional error.
   - Heading-stable rows have significantly lower MAE than chaotic ones.
   - Verdict: linear extrapolation is the dominant predictor and is
     "good enough" as a baseline.

3. WHAT LEARNING RULE CAN EXPLOIT THIS WITHOUT BACKPROPAGATION?
   - Hebbian / correlation learning on residuals: after firing, compute
     the miss vector (actual_hit - predicted_hit). The residual is the
     signal. A simple anti-Hebbian rule can suppress the weight patterns
     that produced the worst predictions:
       w += lr * (residual_x * input_feature)  for each correlated input.
   - Nearest-neighbor / kernel memory: store (input_state, hit_offset)
     pairs. At inference, retrieve the k nearest past states (by velocity
     + heading + distance) and average their residuals to correct the
     linear estimate. No gradient needed — just cosine similarity lookups.
   - Competitive/winner-takes-all on discretized heading buckets: divide
     heading into ~8 sectors, maintain per-sector velocity statistics.
     At runtime, use the sector mean as the prediction. Update is a
     running average — O(1), no backprop.

4. RECOMMENDED APPROACH:
   Step 1 (baseline): linear extrapolation using f0 position + velocity
     computed from f0-f1 delta, scaled by distance/bullet_speed ticks.
   Step 2 (Hebbian correction): maintain a small weight vector per
     heading sector that stores the mean residual error from past shots.
     After each resolved wave, update the relevant sector with the miss.
     At fire time, bias the predicted position by that sector's residual.
   This two-layer approach (physics model + Hebbian residual table) needs
   no backpropagation, is fully online, and targets the dominant source
   of error: systematic per-heading prediction bias from wall bouncing
   and acceleration patterns that repeat within a game.

