j131 learned movement: real bullet-endpoint resolution (TR_LEARNED_REAL_EVENTS, default off) + exact-geometry Gate A/B (inversion NOT fixed; state still the constraint)
This commit is contained in:
@@ -88,6 +88,66 @@ proc counters(m: LearnedSurferModule): int =
|
||||
if c != 0'u8: inc n
|
||||
n
|
||||
|
||||
proc testRealEvents() =
|
||||
## `TR_LEARNED_REAL_EVENTS`: a wave resolves on the REAL bullet event (exact
|
||||
## origin->endpoint line) instead of the arrival deadline, and is dropped the
|
||||
## moment it resolves (ghost cleanup). Default-off parity is also pinned.
|
||||
const Ex = 400.0
|
||||
const Ey = 100.0
|
||||
const Ux = 400.0
|
||||
const Uy = 300.0
|
||||
|
||||
proc wsAt(tick: int; eEnergy: float): WorldState =
|
||||
WorldState(
|
||||
enemyX: Ex, enemyY: Ey, enemyEnergy: eEnergy,
|
||||
selfX: Ux, selfY: Uy, selfSpeed: 8.0, selfHeading: 0.0,
|
||||
arenaWidth: 800.0, arenaHeight: 600.0, tick: tick,
|
||||
enemies: @[EnemyInfo(id: 1, x: Ex, y: Ey,
|
||||
heading: 180.0, speed: 0.0, energy: eEnergy)])
|
||||
|
||||
# ── parity: with the knob off a real event changes nothing ──────────────
|
||||
putEnv(LearnedLabelEnv, "histogram")
|
||||
putEnv(LearnedRealEventsEnv, "")
|
||||
loadLearnedEnv()
|
||||
var mOff = initLearnedSurfer()
|
||||
discard mOff.computeMove(wsAt(0, 100.0)) # tick 0: baseline energy sample
|
||||
discard mOff.computeMove(wsAt(1, 99.0)) # tick 1: a 1.0 firepower drop
|
||||
check "RE default-off: the fire is detected as a live wave",
|
||||
mOff.liveWaves == 1
|
||||
check "RE default-off: resolveEnemyBullet is a no-op",
|
||||
(not mOff.resolveEnemyBullet(Ux, Uy, degToRad(90.0), 1, 13, true)) and
|
||||
mOff.liveWaves == 1
|
||||
|
||||
# ── ON: the exact origin->endpoint line resolves the wave immediately ────
|
||||
putEnv(LearnedRealEventsEnv, "1")
|
||||
loadLearnedEnv()
|
||||
var mOn = initLearnedSurfer()
|
||||
discard mOn.computeMove(wsAt(0, 100.0))
|
||||
discard mOn.computeMove(wsAt(1, 99.0))
|
||||
check "RE on: the fire is detected as a live wave", mOn.liveWaves == 1
|
||||
# endpoint = our position on the centre line (GF 0 -> bin 15) at ~nominal
|
||||
# (200 px at speed 17 -> ~12 ticks after the fire at tick 1)
|
||||
check "RE on: the real hit endpoint resolves the wave",
|
||||
mOn.resolveEnemyBullet(Ux, Uy, degToRad(90.0), 1, 13, true)
|
||||
check "RE on: the wave is dropped at once (ghost cleanup)", mOn.liveWaves == 0
|
||||
check "RE on: a real resolution is counted", mOn.resolvedReal == 1
|
||||
check "RE on: the exact straight line lands in the centre bin",
|
||||
mOn.glob[15] == 1
|
||||
check "RE on: the real flight time is recorded", mOn.lastFlightErr > -20.0
|
||||
|
||||
# ── ON: an unmatched wave still resolves (as a WALL MISS) at the deadline ─
|
||||
var mMiss = initLearnedSurfer()
|
||||
discard mMiss.computeMove(wsAt(0, 100.0))
|
||||
discard mMiss.computeMove(wsAt(1, 99.0))
|
||||
check "RE on: a wave is pending before any event", mMiss.liveWaves == 1
|
||||
for t in 2..<40: discard mMiss.computeMove(wsAt(t, 99.0))
|
||||
check "RE on: the unmatched wall wave eventually resolves",
|
||||
mMiss.liveWaves == 0 and mMiss.resolvedDead >= 1
|
||||
|
||||
putEnv(LearnedRealEventsEnv, "")
|
||||
putEnv(LearnedLabelEnv, "")
|
||||
loadLearnedEnv()
|
||||
|
||||
proc main() =
|
||||
# 1. concept
|
||||
check "MovementModule concept", isMovementModule(LearnedSurferModule)
|
||||
@@ -170,6 +230,8 @@ proc main() =
|
||||
putEnv(LearnedDecayEveryEnv, "")
|
||||
loadLearnedEnv()
|
||||
|
||||
echo ""
|
||||
testRealEvents()
|
||||
echo ""
|
||||
echo "checks=", checks, " failures=", failures
|
||||
if failures > 0: quit(1)
|
||||
|
||||
Reference in New Issue
Block a user