diff --git a/SNNBot_garage/src/SNNBot.nim b/SNNBot_garage/src/SNNBot.nim index 3adc2ab..c83a373 100644 --- a/SNNBot_garage/src/SNNBot.nim +++ b/SNNBot_garage/src/SNNBot.nim @@ -249,104 +249,6 @@ proc drawOverlay(bot: SNNBot, myX, myY, gunDir, enemyBearing, targetAngle: float let (tx, ty) = toXY(targetAngle, LINE_LEN) drawLine(myX, myY, tx, ty) - # ── Neuron panel — barcode style (top-left corner at 10,10) ────────────── - const - PX = 10.0 # panel x - PY = 10.0 # panel y - let - panelW = getArenaWidth().float / 2.0 - panelH = getArenaHeight().float / 2.0 - CH = (panelH - PY - 20.0) / 7.0 # row height - LAYER_V = CH * 2.0 # inter-layer gap - IN_W = panelW # input layer spans full panel width - IN_STEP = IN_W / float(N_IN) # spacing between input lines - HID_STEP = IN_W / float(N_HID) # spacing between hidden lines (scales with N_HID) - HID_OFF = 0.0 - - # Input layer: vertical line per neuron, visible when activation > 0 - let inputs = encodeInput(normalizeRelativeAngle(enemyBearing - gunDir)) - setStrokeWidth(1.0) - for i in 0 ..< N_IN: - let alpha = uint8(inputs[i] * 255.0) - if alpha > 0: - let lx = PX + (float(i) + 0.5) * IN_STEP - setStrokeColor(fromRgba(0, 200, 255, alpha)) - drawLine(lx, PY, lx, PY + CH) - - # Hidden layer: vertical line per neuron, visible when membrane > 0 - let hidY = PY + CH + LAYER_V - setStrokeWidth(1.5) - for h in 0 ..< N_HID: - let v = bot.snn.vHid[h].clamp(0.0, THRESH) / THRESH - if v > 0.0: - let lx = PX + HID_OFF + (float(h) + 0.5) * HID_STEP - let alpha = uint8(v * 255.0) - setStrokeColor(fromRgba(255, 140, 0, alpha)) - drawLine(lx, hidY, lx, hidY + CH) - - # Weight lines: input → hidden - var maxAbsWih = 0.0 - for w in bot.snn.wih: maxAbsWih = max(maxAbsWih, abs(w)) - setStrokeColor(fromRgba(180, 220, 255, 180)) - for i in 0 ..< N_IN: - let ix = PX + (float(i) + 0.5) * IN_STEP - let iy = PY + CH - for h in 0 ..< N_HID: - let hx = PX + HID_OFF + (float(h) + 0.5) * HID_STEP - let hy = hidY - let w = bot.snn.wih[i * N_HID + h] - let norm = if maxAbsWih > 0.0: abs(w) / maxAbsWih else: 0.0 - setStrokeWidth(0.5 + norm * 2.5) - drawLine(ix, iy, hx, hy) - - # Output: two small vertical lines for sin/cos channels side-by-side - let outY = hidY + CH + LAYER_V - var sinOut = 0.0; var cosOut = 0.0 - for h in 0 ..< N_HID: - let rate = bot.lastSpikes[h] / float(N_INFER) - sinOut += rate * bot.snn.wSin[h] - cosOut += rate * bot.snn.wCos[h] - let sinV = (sinOut.clamp(-1.0, 1.0) + 1.0) / 2.0 - let cosV = (cosOut.clamp(-1.0, 1.0) + 1.0) / 2.0 - let cx = PX + IN_W / 2.0 - setStrokeWidth(2.0) - if sinV > 0.0: - setStrokeColor(fromRgba(200, 0, 255, uint8(sinV * 255.0))) - drawLine(cx - 4.0, outY, cx - 4.0, outY + CH) - if cosV > 0.0: - setStrokeColor(fromRgba(0, 200, 100, uint8(cosV * 255.0))) - drawLine(cx + 4.0, outY, cx + 4.0, outY + CH) - - # ── Aiming-line legend ──────────────────────────────────────────────────── - const - LEG_X = 10.0 - LEG_SQ = 8.0 - LEG_GAP = 4.0 - LEG_ROW = 14.0 - LEG_PAD = 6.0 - let LEG_Y = getArenaHeight().float - 60.0 - - setFillColor(fromRgba(0, 0, 0, 160)) - fillRectangle(LEG_X - LEG_PAD, - LEG_Y - LEG_PAD, - LEG_SQ + LEG_GAP + 80.0 + LEG_PAD, - 3.0 * LEG_ROW + LEG_PAD) - - setFillColor(GREEN) - fillRectangle(LEG_X, LEG_Y, LEG_SQ, LEG_SQ) - setFillColor(WHITE) - drawText("Enemy bearing", LEG_X + LEG_SQ + LEG_GAP, LEG_Y + LEG_SQ) - - setFillColor(RED) - fillRectangle(LEG_X, LEG_Y + LEG_ROW, LEG_SQ, LEG_SQ) - setFillColor(WHITE) - drawText("Gun direction", LEG_X + LEG_SQ + LEG_GAP, LEG_Y + LEG_ROW + LEG_SQ) - - setFillColor(YELLOW) - fillRectangle(LEG_X, LEG_Y + 2.0 * LEG_ROW, LEG_SQ, LEG_SQ) - setFillColor(WHITE) - drawText("SNN target", LEG_X + LEG_SQ + LEG_GAP, LEG_Y + 2.0 * LEG_ROW + LEG_SQ) - # ── Event handlers ──────────────────────────────────────────────────────────── method onScannedBot*(bot: SNNBot, e: ScannedBotEvent) =