feat(ModularBot): pluggable bot with 4 guns, phantom meteor movement, radar harness
- Gun harness: virtual bullet tracker, rolling fitness, auto-selector - Guns: head-on, linear (extrapolation), circular (integrated formula), tsetlin machine (learning) - Movement: phantom meteor gravity engine (danger histograms, phantom bullets, fire detection) - Radar: harness + radar_lock adapter - Color-coded modules: turret/bullet color per gun, body per movement, scan per radar - Beats Target, SpinBot, Crazy, TrackFire in 10-round battles
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
## 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): (GunId, int, float) =
|
||||
## Returns (gunId, powerBinIdx, power) — the shot to take this tick.
|
||||
let gunId = t.bestGun()
|
||||
let (binIdx, power) = t.bestPower(gunId)
|
||||
result = (gunId, binIdx, power)
|
||||
Reference in New Issue
Block a user