surf: wire the dormant wave surfer as TR_MOVEMENT=surf + fix 4 real defects

common_libs/movements/wave_surfer.nim was written in an early session and
never wired to the bot. This connects it exactly like tfil/strafe and fixes
the defects a full read found:

  1. the dodge direction was INVERTED: the perpendicular was built from the
     bot->enemy bearing while GF lives in the enemy->bot frame, so the bot
     moved toward MORE danger. Now built from the wave's origin->bot bearing:
     +90 provably increases GF.
  2. the danger histogram was never reset (resetRound cleared waves only), so
     it was a battle-long static average. Now reset to the uniform prior each
     round.
  3. fire detection tracked only the current target's energy via one scalar;
     now per-enemy (seq[(id,energy)]) so melee target switches cannot invent
     or hide waves.
  4. the wall penalty projected a point from the wave origin, not from the
     bot, making the wall test meaningless. Now projects the bot->candidate
     direction.

Wave speed uses the actual firepower (the one-tick energy drop IS the
firepower, so speed = 20 - 3*drop is exact). Adds TR_SURF_* knobs and
registers them in the env report. Shipped TR_MOVEMENT=tfil default untouched
(test_tfil_commit_env: 30/30 pass; test_env_report: pass).
This commit is contained in:
2026-09-26 00:10:24 +02:00
parent 10723ab5f3
commit 0f5cfe37b2
3 changed files with 259 additions and 95 deletions
+11
View File
@@ -26,6 +26,7 @@ import movements/ram_decision
import movements/the_floor_is_lava
import movements/the_floor_is_lava_ring
import movements/strafe
import movements/wave_surfer
import guns/tm_horizon
import guns/bitbrain_gun
import guns/pattern_matcher
@@ -181,6 +182,7 @@ proc printEffectiveValues(ctx: EnvReportContext) =
let effectiveMovement =
if ctx.movementName == "tfil_ring": "tfil_ring"
elif ctx.movementName == "strafe": "strafe"
elif ctx.movementName == "surf": "surf"
else: "tfil"
emit("TR_MOVEMENT", effectiveMovement, sourceOf("TR_MOVEMENT"))
emit("TR_MOVEMENT_LOG", onOff(MovementLog), sourceOfPresence("TR_MOVEMENT_LOG"))
@@ -293,6 +295,13 @@ proc printEffectiveValues(ctx: EnvReportContext) =
emit("TR_STRAFE_WALL_HOTNESS", $StrafeWallHotness, sourceOf("TR_STRAFE_WALL_HOTNESS"))
emit("TR_STRAFE_WALL_RADIANCE", $StrafeWallRadiance, sourceOf("TR_STRAFE_WALL_RADIANCE"))
# ── movement (WAVE SURFER) ────────────────────────────────────────────────
emit(SurfPrefDistEnv, $SurfPrefDist, sourceOf(SurfPrefDistEnv))
emit(SurfDistBandEnv, $SurfDistBand, sourceOf(SurfDistBandEnv))
emit(SurfWallMarginEnv, $SurfWallMargin, sourceOf(SurfWallMarginEnv))
emit(SurfRadialFracEnv, $SurfRadialFrac, sourceOf(SurfRadialFracEnv))
emit(SurfLogEnv, onOff(SurfLog), sourceOfPresence(SurfLogEnv))
# ── ramming ───────────────────────────────────────────────────────────────
emit("TR_RAM_OPPORTUNITY", onOff(RamOppEnabled), sourceOf("TR_RAM_OPPORTUNITY"))
emit("TR_RAM_OPP_DIST", $RamOppDist, sourceOf("TR_RAM_OPP_DIST"))
@@ -453,6 +462,8 @@ proc knownEnvNames*(): seq[string] =
"TR_STRAFE_HEAT_GRID", "TR_STRAFE_BULLET_CORE", "TR_STRAFE_BULLET_AURA",
"TR_STRAFE_CORRIDOR_HEAT", "TR_STRAFE_WALL_HOTNESS",
"TR_STRAFE_WALL_RADIANCE",
SurfPrefDistEnv, SurfDistBandEnv, SurfWallMarginEnv, SurfRadialFracEnv,
SurfLogEnv,
# harness vars (read by the test framework, inherited by the bot, so they
# must NOT be reported as typos)
"TR_SERVER_JAR", "TR_BATTLE_RUNNER", "TR_BATTLE_RUNNER_DIR",