From a3b4f26b6928de9a324fbf5af42d422c12fb8ba9 Mon Sep 17 00:00:00 2001 From: Davide Cappellini Date: Sun, 20 Sep 2026 01:30:21 +0200 Subject: [PATCH] feat(ModularBot): wall-bounce gun, 8 guns total - Wall-bounce gun: linear extrapolation with arena wall reflection - Simulates enemy tick-by-tick, bouncing off walls (billiard-ball reflection) - 4-iteration convergence on ticksToArrive like circular gun - 8 guns: head-on, linear, circular, tsetlin, guess-factor, pattern, anti-surfer, wall-bounce - Turret: #CCCCCC (silver), bullet: #EEEEEE (white) Co-Authored-By: Claude Sonnet 4.6 --- ModularBot_garage/src/ModularBot.nim | 13 ++++++- common_libs/guns/wall_bounce.nim | 56 ++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 common_libs/guns/wall_bounce.nim diff --git a/ModularBot_garage/src/ModularBot.nim b/ModularBot_garage/src/ModularBot.nim index e99a396..88d92d5 100644 --- a/ModularBot_garage/src/ModularBot.nim +++ b/ModularBot_garage/src/ModularBot.nim @@ -17,12 +17,13 @@ import guns/tsetlin import guns/guess_factor import guns/pattern_matcher import guns/anti_surfer +import guns/wall_bounce import movements/phantom_meteor const botJsonPath = currentSourcePath().parentDir / "ModularBot.json" const DebugVBullets = false const DebugCircular = false -const GunNames = ["HeadOn", "Linear", "Tsetlin", "Circular", "GuessFactor", "Pattern", "AntiSurf"] +const GunNames = ["HeadOn", "Linear", "Tsetlin", "Circular", "GuessFactor", "Pattern", "AntiSurf", "WallBounce"] type ModularBot = ref object of Bot @@ -38,6 +39,7 @@ type guessFactor: GFGun patternMatcher: PatternMatcherGun antiSurfer: AntiSurferGun + wallBounce: WallBounceGun mover: PhantomMeteorModule virtualHits: int virtualMiss: int @@ -75,6 +77,7 @@ method onScannedBot*(bot: ModularBot, e: ScannedBotEvent) = var gfPreds: array[len(PowerBins), GunPrediction] var pmPreds: array[len(PowerBins), GunPrediction] var asPreds: array[len(PowerBins), GunPrediction] + var wbPreds: array[len(PowerBins), GunPrediction] for i 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