From c90874affd4a0283f6355f0db7c0ad2743af7f3d Mon Sep 17 00:00:00 2001 From: Davide Cappellini Date: Sun, 20 Sep 2026 12:36:09 +0200 Subject: [PATCH] =?UTF-8?q?refactor(movement):=20extract=20ram=20to=20harn?= =?UTF-8?q?ess=20=E2=80=94=20phantom=20meteor=20dodge-only,=20rammer=20mod?= =?UTF-8?q?ule=20via=20harness=20decision?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- ModularBot_garage/src/ModularBot.nim | 31 ++++++++++++++++++++++-- common_libs/movements/phantom_meteor.nim | 16 ------------ 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/ModularBot_garage/src/ModularBot.nim b/ModularBot_garage/src/ModularBot.nim index 5575499..9818f32 100644 --- a/ModularBot_garage/src/ModularBot.nim +++ b/ModularBot_garage/src/ModularBot.nim @@ -26,6 +26,7 @@ import guns/averaged_lead import guns/decay_gf import guns/knn_gun import movements/phantom_meteor +import movements/rammer import movement_harness/virtual_bodies as mvb import movement_harness/bullet_shadows import targeting/enemy_tracker @@ -71,6 +72,8 @@ type decayGF: DecayGFGun knnGun: KNNGun mover: PhantomMeteorModule + rammer: RammerModule + isRamming: bool moveTracker: VirtualBodyTracker virtualHits: int virtualMiss: int @@ -85,7 +88,8 @@ proc printConfig(bot: ModularBot, changed: string = "") = let gunColor = if changed == "gun" or changed == "all": CLR_CHANGE else: CLR_RST let radarColor = if changed == "radar" or changed == "all": CLR_CHANGE else: CLR_RST let radarName = if bot.radarMode == 0: "radar_lock" else: "melee_scan" - echo CLR_ROUND & "[config]" & CLR_RST & " " & gunColor & "gun=" & gunName & CLR_RST & " | " & CLR_MOVE & "move=phantom_meteor" & CLR_RST & " | " & radarColor & "radar=" & radarName & CLR_RST & " | enemies=" & $bot.enemyTracker.allAlive().len & " target=#" & $bot.currentTargetId + let moveName = if bot.isRamming: "rammer" else: "phantom_meteor" + echo CLR_ROUND & "[config]" & CLR_RST & " " & gunColor & "gun=" & gunName & CLR_RST & " | " & CLR_MOVE & "move=" & moveName & CLR_RST & " | " & radarColor & "radar=" & radarName & CLR_RST & " | enemies=" & $bot.enemyTracker.allAlive().len & " target=#" & $bot.currentTargetId proc buildState(bot: ModularBot, ex, ey, espeed, eheading, eenergy: float): WorldState = var ei: seq[EnemyInfo] @@ -142,6 +146,7 @@ method onRoundStarted*(bot: ModularBot, e: RoundStartedEvent) = bot.radar.init() bot.mover.resetRound() bot.enemyTracker.resetRound() + bot.isRamming = false bot.hasContact = false bot.tick = 0 bot.currentGun = -1 @@ -205,7 +210,28 @@ method run*(bot: ModularBot) = go() continue - let (spd, tr) = bot.mover.computeMove(bot.lastState) + # Ram decision — harness decides, not the movement module + let ws = bot.lastState + let ramDist = hypot(ws.enemyX - ws.selfX, ws.enemyY - ws.selfY) + let ramFinisher = ramDist < 300.0 and ws.enemyEnergy < 20.0 and ws.selfEnergy > ws.enemyEnergy + let ramOpportunity = ramDist < 80.0 and ws.selfEnergy > ws.enemyEnergy + 10.0 + let ramDesperation = ws.selfEnergy < 5.0 and ws.enemyEnergy < 5.0 and ramDist < 150.0 + let shouldRam = ramFinisher or ramOpportunity or ramDesperation + + if shouldRam and not bot.isRamming: + bot.isRamming = true + let tag = if ramDesperation: "desperation" elif ramFinisher: "finisher" else: "opportunity" + echo CLR_MOVE & "[ram:" & tag & "] dist=" & $int(ramDist) & + " selfE=" & $int(ws.selfEnergy) & " enemyE=" & $int(ws.enemyEnergy) & CLR_RST + bot.printConfig("move") + elif not shouldRam and bot.isRamming: + bot.isRamming = false + bot.printConfig("move") + + let (spd, tr) = if shouldRam: + bot.rammer.computeMove(ws) + else: + bot.mover.computeMove(ws) setTargetSpeed(spd) setTurnRate(tr) @@ -399,6 +425,7 @@ when isMainModule: radar: RadarLockModule(), meleeScan: initMeleeScan(), mover: initPhantomMeteor(), + rammer: initRammer(), moveTracker: mvb.initVirtualBodyTracker(1), currentGun: -1, ) diff --git a/common_libs/movements/phantom_meteor.nim b/common_libs/movements/phantom_meteor.nim index fee0992..590e215 100644 --- a/common_libs/movements/phantom_meteor.nim +++ b/common_libs/movements/phantom_meteor.nim @@ -218,22 +218,6 @@ proc computeMove*(m: var PhantomMeteorModule, ws: WorldState): MoveCommand = else: enemyVecs.add enemyPos - # ── Ram override ───────────────────────────────────────────────────────────── - let ramDist = dist(botPos, enemyPos) - let ramFinisher = ramDist < 300.0 and ws.enemyEnergy < 20.0 and ws.selfEnergy > ws.enemyEnergy - let ramOpportunity = ramDist < 80.0 and ws.selfEnergy > ws.enemyEnergy + 10.0 - let ramDesperation = ws.selfEnergy < 5.0 and ws.enemyEnergy < 5.0 and ramDist < 150.0 - if ramFinisher or ramOpportunity or ramDesperation: - let tag = if ramDesperation: "desperation" elif ramFinisher: "finisher" else: "opportunity" - echo CLR_CYAN & "[ram:" & tag & "] dist=" & $int(ramDist) & - " selfE=" & $int(ws.selfEnergy) & " enemyE=" & $int(ws.enemyEnergy) & CLR_RST - let headingRad = arctan2(enemyPos.y - botPos.y, enemyPos.x - botPos.x) - let desiredDeg = radToDeg(headingRad) - var delta = desiredDeg - ws.selfHeading - while delta > 180.0: delta -= 360.0 - while delta < -180.0: delta += 360.0 - return (speed: 8.0, turnRate: delta.clamp(-10.0, 10.0)) - # Advance simulation m.engine.tickPhantoms() m.engine.tickWaves(botPos)