refactor: move adversarial test bots to common_libs/test_framework/adversaries/
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,11 @@
|
||||
# Package
|
||||
version = "0.1.0"
|
||||
author = "Davide Cappellini"
|
||||
description = "Fixed movement sequence adversary — tests pattern-matching gun"
|
||||
license = "MIT"
|
||||
srcDir = "src"
|
||||
bin = @["PatternMover"]
|
||||
|
||||
# Dependencies
|
||||
requires "nim >= 2.0.0"
|
||||
requires "tankroyale_botapi >= 1.0.1"
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "PatternMover",
|
||||
"version": "0.1.0",
|
||||
"authors": ["Davide Cappellini"],
|
||||
"description": "Fixed movement sequence adversary — tests pattern-matching gun",
|
||||
"homepage": "",
|
||||
"countryCodes": ["IT"],
|
||||
"gameTypes": ["classic", "1v1"],
|
||||
"platform": "Nim",
|
||||
"programmingLang": "Nim"
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
cd "$(dirname "$0")"
|
||||
exec ./PatternMover >> /tmp/patternmover_stdout.log 2>> /tmp/patternmover_stderr.log
|
||||
@@ -0,0 +1,2 @@
|
||||
--path:"../common_libs"
|
||||
switch("outdir", "out")
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "PatternMover",
|
||||
"version": "0.1.0",
|
||||
"authors": ["Davide Cappellini"],
|
||||
"description": "Fixed movement sequence adversary — tests pattern-matching gun",
|
||||
"homepage": "",
|
||||
"countryCodes": ["IT"],
|
||||
"gameTypes": ["classic", "1v1"],
|
||||
"platform": "Nim",
|
||||
"programmingLang": "Nim"
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
# PatternMover — repeats a fixed movement sequence, head-on firing.
|
||||
# Purpose: test pattern-matching gun.
|
||||
|
||||
import std/[math, os]
|
||||
import tankroyale_botapi
|
||||
|
||||
const botJsonPath = currentSourcePath().parentDir / "PatternMover.json"
|
||||
|
||||
# Sequence: (distance, turn_deg) pairs
|
||||
type Step = tuple[dist: float, turn: float]
|
||||
const STEPS: array[6, Step] = [
|
||||
(100.0, 0.0),
|
||||
( 0.0, 45.0),
|
||||
( 50.0, 0.0),
|
||||
( 0.0, -90.0),
|
||||
( 75.0, 0.0),
|
||||
( 0.0, 30.0),
|
||||
]
|
||||
|
||||
type PatternMover = ref object of Bot
|
||||
stepIdx: int
|
||||
remaining: float # distance left in current move step, or turn degrees
|
||||
inTurn: bool # true while executing a turn sub-step
|
||||
|
||||
method onRoundStarted*(bot: PatternMover, e: RoundStartedEvent) =
|
||||
setAdjustGunForBodyTurn(true)
|
||||
setAdjustRadarForBodyTurn(true)
|
||||
setAdjustRadarForGunTurn(true)
|
||||
bot.stepIdx = 0
|
||||
bot.remaining = STEPS[0].dist
|
||||
bot.inTurn = false
|
||||
|
||||
method onScannedBot*(bot: PatternMover, e: ScannedBotEvent) =
|
||||
let bearing = directionTo(getX(), getY(), e.x, e.y)
|
||||
let gunDelta = normalizeRelativeAngle(bearing - getGunDirection())
|
||||
setGunTurnRate(gunDelta.clamp(-MAX_GUN_TURN_RATE, MAX_GUN_TURN_RATE))
|
||||
if abs(gunDelta) < 10.0 and getGunHeat() <= 0.0:
|
||||
discard setFire(1.0)
|
||||
|
||||
proc advanceStep(bot: PatternMover) =
|
||||
bot.stepIdx = (bot.stepIdx + 1) mod STEPS.len
|
||||
let s = STEPS[bot.stepIdx]
|
||||
if s.dist > 0.0:
|
||||
bot.inTurn = false
|
||||
bot.remaining = s.dist
|
||||
else:
|
||||
bot.inTurn = true
|
||||
bot.remaining = abs(s.turn)
|
||||
|
||||
method run*(bot: PatternMover) =
|
||||
while isRunning():
|
||||
setRadarTurnRate(45.0)
|
||||
|
||||
if bot.inTurn:
|
||||
let s = STEPS[bot.stepIdx]
|
||||
let sign = if s.turn >= 0: 1.0 else: -1.0
|
||||
let rate = min(bot.remaining, MAX_TURN_RATE)
|
||||
setTurnRate(sign * rate)
|
||||
setTargetSpeed(0.0)
|
||||
bot.remaining -= rate
|
||||
if bot.remaining <= 0.0:
|
||||
advanceStep(bot)
|
||||
else:
|
||||
let rate = min(bot.remaining, 8.0)
|
||||
setTargetSpeed(8.0)
|
||||
setTurnRate(0.0)
|
||||
bot.remaining -= rate
|
||||
if bot.remaining <= 0.0:
|
||||
advanceStep(bot)
|
||||
|
||||
go()
|
||||
|
||||
when isMainModule:
|
||||
var bot = PatternMover()
|
||||
start(bot, botJsonPath)
|
||||
Binary file not shown.
@@ -0,0 +1,11 @@
|
||||
# Package
|
||||
version = "0.1.0"
|
||||
author = "Davide Cappellini"
|
||||
description = "Random movement adversary — tests guns against unpredictable movement"
|
||||
license = "MIT"
|
||||
srcDir = "src"
|
||||
bin = @["RandomMover"]
|
||||
|
||||
# Dependencies
|
||||
requires "nim >= 2.0.0"
|
||||
requires "tankroyale_botapi >= 1.0.1"
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "RandomMover",
|
||||
"version": "0.1.0",
|
||||
"authors": ["Davide Cappellini"],
|
||||
"description": "Random movement adversary — tests guns against unpredictable movement",
|
||||
"homepage": "",
|
||||
"countryCodes": ["IT"],
|
||||
"gameTypes": ["classic", "1v1"],
|
||||
"platform": "Nim",
|
||||
"programmingLang": "Nim"
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
cd "$(dirname "$0")"
|
||||
exec ./RandomMover >> /tmp/randommover_stdout.log 2>> /tmp/randommover_stderr.log
|
||||
@@ -0,0 +1,2 @@
|
||||
--path:"../common_libs"
|
||||
switch("outdir", "out")
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "RandomMover",
|
||||
"version": "0.1.0",
|
||||
"authors": ["Davide Cappellini"],
|
||||
"description": "Random movement adversary — tests guns against unpredictable movement",
|
||||
"homepage": "",
|
||||
"countryCodes": ["IT"],
|
||||
"gameTypes": ["classic", "1v1"],
|
||||
"platform": "Nim",
|
||||
"programmingLang": "Nim"
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
# RandomMover — random speed/turn with persistence, head-on firing.
|
||||
# Purpose: test guns against unpredictable movement.
|
||||
|
||||
import std/[math, os, random]
|
||||
import tankroyale_botapi
|
||||
|
||||
const botJsonPath = currentSourcePath().parentDir / "RandomMover.json"
|
||||
|
||||
type RandomMover = ref object of Bot
|
||||
currentSpeed: float
|
||||
currentTurn: float
|
||||
ticksUntilChange: int
|
||||
|
||||
proc newDirection(bot: RandomMover) =
|
||||
bot.currentSpeed = rand(-8.0..8.0)
|
||||
bot.currentTurn = rand(-10.0..10.0)
|
||||
bot.ticksUntilChange = rand(10..20)
|
||||
|
||||
method onRoundStarted*(bot: RandomMover, e: RoundStartedEvent) =
|
||||
randomize()
|
||||
setAdjustGunForBodyTurn(true)
|
||||
setAdjustRadarForBodyTurn(true)
|
||||
setAdjustRadarForGunTurn(true)
|
||||
newDirection(bot)
|
||||
|
||||
method onScannedBot*(bot: RandomMover, e: ScannedBotEvent) =
|
||||
let bearing = directionTo(getX(), getY(), e.x, e.y)
|
||||
let gunDelta = normalizeRelativeAngle(bearing - getGunDirection())
|
||||
setGunTurnRate(gunDelta.clamp(-MAX_GUN_TURN_RATE, MAX_GUN_TURN_RATE))
|
||||
if abs(gunDelta) < 10.0 and getGunHeat() <= 0.0:
|
||||
discard setFire(1.0)
|
||||
|
||||
method run*(bot: RandomMover) =
|
||||
while isRunning():
|
||||
dec bot.ticksUntilChange
|
||||
if bot.ticksUntilChange <= 0:
|
||||
newDirection(bot)
|
||||
|
||||
setTargetSpeed(bot.currentSpeed)
|
||||
setTurnRate(bot.currentTurn)
|
||||
setRadarTurnRate(45.0)
|
||||
go()
|
||||
|
||||
when isMainModule:
|
||||
var bot = RandomMover()
|
||||
start(bot, botJsonPath)
|
||||
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"
|
||||
}
|
||||
+3
@@ -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)
|
||||
Reference in New Issue
Block a user