Files
SirStone 2cc2a3bd87 fix(ModularBot): ram loop prevention, dead-target guards, cleaner logging
- 30-tick cooldown after ghost-stuck/timeout ram exit prevents re-entry loop
- enemy_tracker.update() skips dead bots to prevent same-tick scan resurrection
- TFIL graphics cleared when ramming is active movement
- [config] logs: white base with green-highlighted changes only
- [ram:enter] logs trigger reason and key values on false→true transition
- [death] and [target-invalid] logs retained for diagnostics
2026-09-20 20:44:45 +02:00

57 lines
1.8 KiB
Nim

## Wall-bounce gun: linear extrapolation with arena wall reflection.
## Simulates enemy trajectory tick-by-tick, bouncing off walls like a billiard ball.
## Coordinate system: 0° = East, CCW positive (Tank Royale standard).
import std/math
import gun_harness/gun_interface
type WallBounceGun* = object
debugGraphics*: bool
proc initWallBounceGun*(): WallBounceGun = WallBounceGun(debugGraphics: false)
proc simulateBounce(ex, ey, heading, speed: float, ticks: int,
arenaW, arenaH: float): (float, float) =
## Simulate tick-by-tick with wall reflection. Returns final (x, y).
const margin = BotRadius
var x = ex
var y = ey
var h = heading # radians
for _ in 0..<ticks:
var nx = x + speed * cos(h)
var ny = y + speed * sin(h)
if nx < margin:
nx = margin
h = PI - h
elif nx > 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