## Wall-bounce gun: linear extrapolation with arena wall reflection. ## Simulates enemy trajectory tick-by-tick, bouncing off walls like a billiard ball. ## Coordinate system: 0° = East, CCW positive (Tank Royale standard). import std/math import gun_harness/gun_interface type WallBounceGun* = object debugGraphics*: bool proc initWallBounceGun*(): WallBounceGun = WallBounceGun(debugGraphics: false) proc simulateBounce(ex, ey, heading, speed: float, ticks: int, arenaW, arenaH: float): (float, float) = ## Simulate tick-by-tick with wall reflection. Returns final (x, y). const margin = BotRadius var x = ex var y = ey var h = heading # radians for _ in 0.. arenaW - margin: nx = arenaW - margin h = PI - h if ny < margin: ny = margin h = -h elif ny > arenaH - margin: ny = arenaH - margin h = -h x = nx y = ny (x, y) proc predict*(g: var WallBounceGun, state: WorldState, bulletSpeed: float): GunPrediction = let dist = hypot(state.enemyX - state.selfX, state.enemyY - state.selfY) # Iterate ticks estimate 4x to converge var ticks = dist / bulletSpeed for _ in 0..<4: let (px, py) = simulateBounce( state.enemyX, state.enemyY, degToRad(state.enemyHeading), state.enemySpeed, ticks.int, state.arenaWidth, state.arenaHeight) ticks = hypot(px - state.selfX, py - state.selfY) / bulletSpeed let (fx, fy) = simulateBounce( state.enemyX, state.enemyY, degToRad(state.enemyHeading), state.enemySpeed, ticks.int, state.arenaWidth, state.arenaHeight) GunPrediction(x: fx, y: fy) proc onResult*(g: var WallBounceGun, e: FeedbackEvent) = discard # analytical gun — no learning