diff --git a/ModularBot_garage/src/ModularBot.nim b/ModularBot_garage/src/ModularBot.nim index 9c97f94..4e4ec1d 100644 --- a/ModularBot_garage/src/ModularBot.nim +++ b/ModularBot_garage/src/ModularBot.nim @@ -24,6 +24,7 @@ import guns/displacement import guns/averaged_lead import guns/decay_gf import movements/phantom_meteor +import movements/wave_surfer const botJsonPath = currentSourcePath().parentDir / "ModularBot.json" const DebugVBullets = false @@ -51,6 +52,12 @@ type avgLead: AveragedLeadGun decayGF: DecayGFGun mover: PhantomMeteorModule + waveMover: WaveSurferModule + movementId: int ## 0=phantom, 1=waveSurf + dmgPhantom: float ## rolling damage taken under phantom + dmgWaveSurf: float ## rolling damage taken under waveSurf + roundDmg: float ## damage this round + roundCount: int virtualHits: int virtualMiss: int tick: int @@ -207,21 +214,46 @@ method onScannedBot*(bot: ModularBot, e: ScannedBotEvent) = setGunTurnRate(normDelta) +method onHitByBullet*(bot: ModularBot, e: HitByBulletEvent) = + bot.roundDmg += e.damage + method onRoundEnded*(bot: ModularBot, e: RoundEndedEventForBot) = - discard # Skip detailed logging for now + # Accumulate damage into active movement bucket (exponential decay, α=0.5) + # ponytail: simple EMA; switch to longer window if thrashing becomes a problem + let decay = 0.5 + if bot.movementId == 0: + bot.dmgPhantom = decay * bot.dmgPhantom + (1.0 - decay) * bot.roundDmg + else: + bot.dmgWaveSurf = decay * bot.dmgWaveSurf + (1.0 - decay) * bot.roundDmg + echo "[move] round dmg=", bot.roundDmg, " phantom_ema=", bot.dmgPhantom, " wave_ema=", bot.dmgWaveSurf method onRoundStarted*(bot: ModularBot, e: RoundStartedEvent) = setAdjustGunForBodyTurn(true) setAdjustRadarForBodyTurn(true) setAdjustRadarForGunTurn(true) - setBodyColor("#FF9900") # PhantomMeteor: deep orange/gold setRadarColor("#00CCCC") # RadarLock: cyan/teal setScanColor("#33FFFF") # RadarLock scan arc: bright teal bot.radar.init() bot.hasContact = false bot.tick = 0 - bot.currentGun = -1 # Reset to trigger initial log on first selectShot - bot.mover.resetRound() + bot.currentGun = -1 + bot.roundDmg = 0.0 + inc bot.roundCount + + # Every 3 rounds: switch to lower-damage movement (probe every 3rd round) + # ponytail: simple 3-round probe; add hysteresis if switching thrashes + if bot.roundCount > 2: + bot.movementId = if bot.dmgPhantom <= bot.dmgWaveSurf: 0 else: 1 + + if bot.movementId == 0: + bot.mover.resetRound() + setBodyColor("#FF9900") # PhantomMeteor: deep orange/gold + echo "[move] using phantom_meteor" + else: + bot.waveMover.resetRound() + setBodyColor("#0099FF") # WaveSurfer: blue + echo "[move] using wave_surfer" + echo fmt"[gun] starting: {GunNames[0]}" # tracker fitness persists across rounds (rolling window carries over) @@ -239,8 +271,10 @@ method run*(bot: ModularBot) = go() continue - # Movement harness: oscillate perpendicular to enemy - let (spd, tr) = bot.mover.computeMove(bot.lastState) + # Movement harness: dispatch to active mover + let (spd, tr) = + if bot.movementId == 0: bot.mover.computeMove(bot.lastState) + else: bot.waveMover.computeMove(bot.lastState) setTargetSpeed(spd) setTurnRate(tr) @@ -265,6 +299,7 @@ when isMainModule: decayGF: initDecayGFGun(), radar: RadarLockModule(), mover: initPhantomMeteor(), + waveMover: initWaveSurfer(), currentGun: -1, ) start(bot, botJsonPath)