a3b4f26b69
- 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 <noreply@anthropic.com>
57 lines
1.8 KiB
Nim
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
|
|
discard
|
|
|
|
proc initWallBounceGun*(): WallBounceGun = WallBounceGun()
|
|
|
|
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
|