## Recency-weighted GF gun: exponential decay on histogram bins. ## decay=0.998/tick gives ~350-tick half-life — adapts to mid-battle strategy shifts. ## Everything else identical to guess_factor.nim. import std/math import gun_harness/gun_interface const GFBins = 31 GFPrior = 0.1 DecayRate = 0.998 # ponytail: single global decay, tune if adaptation too slow/fast type DWave = object fireX, fireY: float fireBearing: float DecayGFGun* = object bins: array[GFBins, float] waves: seq[DWave] cachedTick: int cachedWaveStored: bool proc initDecayGFGun*(): DecayGFGun = result.cachedTick = -1 let center = (GFBins - 1) div 2 for i in 0.. g.bins[best]: best = i best proc predict*(g: var DecayGFGun, state: WorldState, bulletSpeed: float): GunPrediction = if bulletSpeed <= 0.0: return GunPrediction(x: state.enemyX, y: state.enemyY) let dx = state.enemyX - state.selfX let dy = state.enemyY - state.selfY let dist = sqrt(dx*dx + dy*dy) let bearing = arctan2(dy, dx) let mea = arcsin(clamp(8.0 / bulletSpeed, -1.0, 1.0)) if state.tick != g.cachedTick: # Decay all bins once per tick for i in 0.. PI: bearingDelta -= 2.0*PI while bearingDelta < -PI: bearingDelta += 2.0*PI let gf = if mea > 1e-10: clamp(bearingDelta / mea, -1.0, 1.0) else: 0.0 let centerIdx = gfToIndex(gf) for i in 0..