feat(BNNBot): 10-tick sliding window of enemy data + self state — 870 bits total
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# BNNBot — binary encoding data collector.
|
||||
# Radar lock on enemy, converts each scan to a 44-bit BinaryVector, prints it.
|
||||
# Radar lock on enemy, encodes a 10-tick sliding window (870 bits), prints it.
|
||||
# No aiming, no firing — pure scan visualization for BNN research.
|
||||
|
||||
import std/[math, os, strutils]
|
||||
@@ -11,56 +11,73 @@ const botJsonPath = currentSourcePath().parentDir / "BNNBot.json"
|
||||
|
||||
type
|
||||
BNNBot = ref object of Bot
|
||||
hasContact: bool
|
||||
hasContact: bool
|
||||
enemyBearing: float
|
||||
lastEnemyX: float
|
||||
lastEnemyY: float
|
||||
hasLastPos: bool
|
||||
velocity: float # signed velocity (from heading + speed)
|
||||
heading: float # enemy heading (degrees)
|
||||
distance: float
|
||||
tick: int
|
||||
prevVec: BinaryVector
|
||||
hasPrev: bool
|
||||
lastEnemyX: float
|
||||
lastEnemyY: float
|
||||
hasLastPos: bool
|
||||
velocity: float
|
||||
heading: float
|
||||
distance: float
|
||||
tick: int
|
||||
prevVec: BinaryVector
|
||||
hasPrev: bool
|
||||
frameBuffer: array[WINDOW_SIZE, array[FRAME_BITS, uint8]]
|
||||
bufferCount: int
|
||||
|
||||
method onScannedBot*(bot: BNNBot, e: ScannedBotEvent) =
|
||||
let bx = getX(); let by = getY()
|
||||
bot.enemyBearing = directionTo(bx, by, e.x, e.y)
|
||||
bot.distance = distanceTo(bx, by, e.x, e.y)
|
||||
bot.heading = e.direction
|
||||
bot.velocity = e.speed # signed: positive = forward, negative = reverse
|
||||
if bot.hasLastPos:
|
||||
discard # velocity from e.speed is more accurate; position delta kept for future use
|
||||
bot.lastEnemyX = e.x
|
||||
bot.lastEnemyY = e.y
|
||||
bot.hasLastPos = true
|
||||
bot.hasContact = true
|
||||
bot.velocity = e.speed
|
||||
bot.lastEnemyX = e.x
|
||||
bot.lastEnemyY = e.y
|
||||
bot.hasLastPos = true
|
||||
bot.hasContact = true
|
||||
|
||||
let arenaW = getArenaWidth().float
|
||||
let arenaH = getArenaHeight().float
|
||||
let enemyX = e.x
|
||||
let enemyY = e.y
|
||||
let scan = ScanData(
|
||||
bearing: bot.enemyBearing,
|
||||
distance: bot.distance,
|
||||
velocity: bot.velocity,
|
||||
heading: bot.heading,
|
||||
myWallN: arenaH - by,
|
||||
myWallS: by,
|
||||
myWallE: arenaW - bx,
|
||||
myWallW: bx,
|
||||
enemyWallN: arenaH - enemyY,
|
||||
enemyWallS: enemyY,
|
||||
enemyWallE: arenaW - enemyX,
|
||||
enemyWallW: enemyX,
|
||||
myEnergy: getEnergy(),
|
||||
enemyEnergy: e.energy,
|
||||
canFire: getGunHeat() <= 0.0,
|
||||
let arenaW = getArenaWidth().float
|
||||
let arenaH = getArenaHeight().float
|
||||
let enemyX = e.x
|
||||
let enemyY = e.y
|
||||
|
||||
let frame = EnemyScanFrame(
|
||||
bearing: bot.enemyBearing,
|
||||
distance: bot.distance,
|
||||
velocity: bot.velocity,
|
||||
heading: bot.heading,
|
||||
enemyWallN: arenaH - enemyY,
|
||||
enemyWallS: enemyY,
|
||||
enemyWallE: arenaW - enemyX,
|
||||
enemyWallW: enemyX,
|
||||
enemyEnergy: e.energy,
|
||||
)
|
||||
let vec = encode(scan)
|
||||
let hamming = if bot.hasPrev: hammingDistance(bot.prevVec, vec) else: 0
|
||||
let encoded = encodeFrame(frame)
|
||||
|
||||
# Shift buffer: 0..8 → 1..9, newest at index 0
|
||||
for i in countdown(WINDOW_SIZE - 1, 1):
|
||||
bot.frameBuffer[i] = bot.frameBuffer[i - 1]
|
||||
bot.frameBuffer[0] = encoded
|
||||
|
||||
if bot.bufferCount < WINDOW_SIZE:
|
||||
inc bot.bufferCount
|
||||
if bot.bufferCount < WINDOW_SIZE:
|
||||
return # still filling
|
||||
|
||||
let selfState = SelfState(
|
||||
myWallN: arenaH - by,
|
||||
myWallS: by,
|
||||
myWallE: arenaW - bx,
|
||||
myWallW: bx,
|
||||
myEnergy: getEnergy(),
|
||||
canFire: getGunHeat() <= 0.0,
|
||||
)
|
||||
let selfEncoded = encodeSelf(selfState)
|
||||
let vec = encodeFullVector(bot.frameBuffer, selfEncoded)
|
||||
|
||||
let hamming = if bot.hasPrev: hammingDistance(bot.prevVec, vec) else: 0
|
||||
let similarity = if bot.hasPrev: TOTAL_BITS - hamming else: 0
|
||||
let overlap = if bot.hasPrev: popcount(bitwiseAnd(bot.prevVec, vec)) else: 0
|
||||
let overlap = if bot.hasPrev: popcount(bitwiseAnd(bot.prevVec, vec)) else: 0
|
||||
echo align($bot.tick, 4), " ", formatBinary(vec), " ", hamming, " ", similarity, " ", overlap
|
||||
bot.prevVec = vec
|
||||
bot.hasPrev = true
|
||||
@@ -74,6 +91,7 @@ method onRoundStarted*(bot: BNNBot, e: RoundStartedEvent) =
|
||||
bot.hasLastPos = false
|
||||
bot.tick = 0
|
||||
bot.hasPrev = false
|
||||
bot.bufferCount = 0
|
||||
setTargetSpeed(0.0)
|
||||
setTurnRate(0.0)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user