refactor: move adversarial test bots to common_libs/test_framework/adversaries/

This commit is contained in:
2026-09-20 10:49:31 +02:00
parent c0abd4c960
commit 1eaaadf627
28 changed files with 11 additions and 11 deletions
Binary file not shown.
@@ -0,0 +1,11 @@
# Package
version = "0.1.0"
author = "Davide Cappellini"
description = "Reactive wave-surfing adversary — hardest test for TM gun"
license = "MIT"
srcDir = "src"
bin = @["WaveSurfer"]
# Dependencies
requires "nim >= 2.0.0"
requires "tankroyale_botapi >= 1.0.1"
@@ -0,0 +1,11 @@
{
"name": "WaveSurfer",
"version": "0.1.0",
"authors": ["Davide Cappellini"],
"description": "Reactive wave-surfing adversary — hardest test for TM gun",
"homepage": "",
"countryCodes": ["IT"],
"gameTypes": ["classic", "1v1"],
"platform": "Nim",
"programmingLang": "Nim"
}
@@ -0,0 +1,3 @@
#!/bin/sh
cd "$(dirname "$0")"
exec ./WaveSurfer >> /tmp/wavesurfer_stdout.log 2>> /tmp/wavesurfer_stderr.log
@@ -0,0 +1,2 @@
--path:"../common_libs"
switch("outdir", "out")
@@ -0,0 +1,11 @@
{
"name": "WaveSurfer",
"version": "0.1.0",
"authors": ["Davide Cappellini"],
"description": "Reactive wave-surfing adversary — hardest test for TM gun",
"homepage": "",
"countryCodes": ["IT"],
"gameTypes": ["classic", "1v1"],
"platform": "Nim",
"programmingLang": "Nim"
}
@@ -0,0 +1,91 @@
# WaveSurfer — reactive movement adversary with linear prediction gun.
# Monitors enemy energy drops (bullet fire detection), reverses on detected fire.
# Strafes perpendicular to enemy, reverses near walls.
# Purpose: hardest test enemy — tests TM gun's ability to learn reactive movement.
import std/[math, os]
import tankroyale_botapi
const botJsonPath = currentSourcePath().parentDir / "WaveSurfer.json"
const
WALL_MARGIN = 60.0
STRAFE_SPEED = 8.0
BULLET_SPEED = 20.0 - 3.0 * 2.0 # for fire power 2.0
type WaveSurfer = ref object of Bot
strafeDir: float # +1 or -1
lastEnemyEnergy: float
enemyX, enemyY: float
enemyVx, enemyVy: float
enemyDir: float
enemySpeed: float
enemyLastDir: float
method onRoundStarted*(bot: WaveSurfer, e: RoundStartedEvent) =
setAdjustGunForBodyTurn(true)
setAdjustRadarForBodyTurn(true)
setAdjustRadarForGunTurn(true)
bot.strafeDir = 1.0
bot.lastEnemyEnergy = 100.0
bot.enemyX = 0.0
bot.enemyY = 0.0
method onScannedBot*(bot: WaveSurfer, e: ScannedBotEvent) =
# Detect bullet fire: enemy energy dropped by 0.1..3.0
let energyDrop = bot.lastEnemyEnergy - e.energy
if energyDrop > 0.1 and energyDrop <= 3.0:
# Enemy fired — reverse strafe direction immediately
bot.strafeDir *= -1.0
bot.lastEnemyEnergy = e.energy
# Track enemy position and velocity
bot.enemyX = e.x
bot.enemyY = e.y
bot.enemyDir = e.direction
bot.enemySpeed = e.speed
bot.enemyVx = sin(degToRad(e.direction)) * e.speed
bot.enemyVy = cos(degToRad(e.direction)) * e.speed
# Linear prediction: estimate where enemy will be when bullet arrives
let dx = e.x - getX()
let dy = e.y - getY()
let dist = sqrt(dx*dx + dy*dy)
let tof = dist / BULLET_SPEED # ticks of flight
let predX = e.x + bot.enemyVx * tof
let predY = e.y + bot.enemyVy * tof
let bearing = directionTo(getX(), getY(), predX, predY)
let gunDelta = normalizeRelativeAngle(bearing - getGunDirection())
setGunTurnRate(gunDelta.clamp(-MAX_GUN_TURN_RATE, MAX_GUN_TURN_RATE))
if abs(gunDelta) < 5.0 and getGunHeat() <= 0.0:
discard setFire(2.0)
method run*(bot: WaveSurfer) =
while isRunning():
setRadarTurnRate(45.0)
# Strafe perpendicular to enemy
if bot.enemyX != 0.0 or bot.enemyY != 0.0:
let toEnemy = directionTo(getX(), getY(), bot.enemyX, bot.enemyY)
let perpDir = toEnemy + 90.0 * bot.strafeDir
let bodyDelta = normalizeRelativeAngle(perpDir - getDirection())
setTurnRate(bodyDelta.clamp(-MAX_TURN_RATE, MAX_TURN_RATE))
else:
setTurnRate(4.0 * bot.strafeDir)
setTargetSpeed(STRAFE_SPEED)
# Reverse near walls
let x = getX()
let y = getY()
let arenaW = getArenaWidth().float
let arenaH = getArenaHeight().float
if x < WALL_MARGIN or x > arenaW - WALL_MARGIN or
y < WALL_MARGIN or y > arenaH - WALL_MARGIN:
bot.strafeDir *= -1.0
go()
when isMainModule:
var bot = WaveSurfer(strafeDir: 1.0, lastEnemyEnergy: 100.0)
start(bot, botJsonPath)