feat(ModularBot): 6 guns, pattern matcher, melee modules, adversarial bots

- New guns: guess-factor (GF histogram), pattern-matcher (movement tape replay)
- New modules: minimum-risk melee movement, spinning melee radar
- New test bots: PatternMover, RandomMover, WaveSurfer
- Fixed: FeedbackEvent now carries actualX/actualY for proper GF learning
- Fixed: TM gun warmup gating + directional residuals
- Fixed: circular gun integrated formula + multi-bin omega cache
- Fixed: oscillator wall-bounce lockout
- Fixed: phantom meteor perpendicular body orientation
- 6/6 battle wins across all enemy types
This commit is contained in:
2026-09-20 00:59:53 +02:00
parent 254c7dc997
commit 1ed7797cb6
184 changed files with 80149 additions and 21 deletions
BIN
View File
Binary file not shown.
+11
View File
@@ -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
View File
@@ -0,0 +1,3 @@
#!/bin/sh
cd "$(dirname "$0")"
exec ./PatternMover >> /tmp/patternmover_stdout.log 2>> /tmp/patternmover_stderr.log
+2
View File
@@ -0,0 +1,2 @@
--path:"../common_libs"
switch("outdir", "out")
+11
View File
@@ -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"
}
+75
View File
@@ -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)