## Gun selector — picks best gun×power, computes aim angle, gates firing. ## Fires highest power with acceptable hit rate when gun is aimed within ## threshold and gunHeat == 0. import std/math import gun_interface import virtual_bullets const AimThresholdDeg* = 2.0 ## max angle error to fire; ponytail: tune per bot proc aimAngle*(selfX, selfY, targetX, targetY: float): float = ## Absolute bearing in degrees (0=East, CCW+) toward (targetX, targetY). result = radToDeg(arctan2(targetY - selfY, targetX - selfX)) proc shouldFire*(currentGunDir, targetAngle, gunHeat: float): bool = ## Returns true when gun is close enough and cool enough to fire. var delta = (targetAngle - currentGunDir) mod 360.0 if delta > 180.0: delta -= 360.0 elif delta < -180.0: delta += 360.0 abs(delta) <= AimThresholdDeg and gunHeat <= 0.0 proc selectShot*(t: VirtualTracker, targetId: int = -1): (GunId, int, float) = ## Returns (gunId, powerBinIdx, power) — the shot to take this tick. ## Pass targetId to pick the best gun for that specific enemy. let gunId = t.bestGun(targetId) let (binIdx, power) = t.bestPower(gunId, targetId) result = (gunId, binIdx, power)