feat(SAC_LSTM_Bot): action mapping module (#43)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
## actions.nim — map raw network output (4 tanh values) to bot intent fields.
|
||||
##
|
||||
## Note on acceleration vs targetSpeed:
|
||||
## TankRoyale uses setTargetSpeed(), not setAcceleration().
|
||||
## The mapped `acceleration` field is a delta; callers must compute:
|
||||
## newTargetSpeed = clamp(currentSpeed + acceleration, -8.0, 8.0)
|
||||
## and call setTargetSpeed(newTargetSpeed).
|
||||
|
||||
import arraymancer
|
||||
|
||||
const ACTION_DIM* = 4
|
||||
|
||||
type
|
||||
MappedActions* = object
|
||||
turnRate*: float ## degrees/tick, speed-aware; [-10, 10] at speed 0
|
||||
acceleration*: float ## delta speed in [-2, +1]; caller adds to currentSpeed
|
||||
gunTurnRate*: float ## degrees/tick in [-20, 20]
|
||||
firePower*: float ## 0 = don't fire; (0.1, 3.0] = fire with this power
|
||||
|
||||
proc mapActions*(networkOutput: Tensor[float32],
|
||||
currentSpeed: float,
|
||||
gunHeat: float): MappedActions =
|
||||
## networkOutput: [4] tensor of tanh values in [-1, 1].
|
||||
let a0 = networkOutput[0].float
|
||||
let a1 = networkOutput[1].float
|
||||
let a2 = networkOutput[2].float
|
||||
let a3 = networkOutput[3].float
|
||||
|
||||
result.turnRate = a0 * (10.0 - 0.75 * abs(currentSpeed))
|
||||
# asymmetric accel: [-1,1] -> [-2, +1] via (value * 1.5 - 0.5)
|
||||
result.acceleration = a1 * 1.5 - 0.5
|
||||
result.gunTurnRate = a2 * 20.0
|
||||
if a3 > 0.0 and gunHeat <= 0.0:
|
||||
result.firePower = a3 * 2.9 + 0.1
|
||||
else:
|
||||
result.firePower = 0.0
|
||||
Reference in New Issue
Block a user