From 51ebf7698b3e77c24025335ce451c34eb54c7256 Mon Sep 17 00:00:00 2001 From: "Flemming N. Larsen" Date: Sun, 30 Aug 2026 22:37:25 +0200 Subject: [PATCH 1/3] feat: add Vector Rumble bot --- bots/python/Vector/Vector.cmd | 2 ++ bots/python/Vector/Vector.json | 10 ++++++++++ bots/python/Vector/Vector.sh | 10 ++++++++++ bots/python/Vector/src/Vector.py | 28 ++++++++++++++++++++++++++++ tests/test_validate_bot.py | 3 ++- 5 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 bots/python/Vector/Vector.cmd create mode 100644 bots/python/Vector/Vector.json create mode 100644 bots/python/Vector/Vector.sh create mode 100644 bots/python/Vector/src/Vector.py diff --git a/bots/python/Vector/Vector.cmd b/bots/python/Vector/Vector.cmd new file mode 100644 index 0000000..9f7ae9d --- /dev/null +++ b/bots/python/Vector/Vector.cmd @@ -0,0 +1,2 @@ +@echo off +python "%~dp0src\Vector.py" %* diff --git a/bots/python/Vector/Vector.json b/bots/python/Vector/Vector.json new file mode 100644 index 0000000..bdc7cbf --- /dev/null +++ b/bots/python/Vector/Vector.json @@ -0,0 +1,10 @@ +{ + "name": "Vector", + "version": "1.0.0", + "authors": ["Tank Royale Rumble maintainers"], + "description": "A small source-only bot that circles the arena while tracking opponents.", + "platform": "Python", + "programmingLang": "Python 3", + "gameTypes": ["1v1", "melee", "twinduel"], + "license": "Apache-2.0" +} diff --git a/bots/python/Vector/Vector.sh b/bots/python/Vector/Vector.sh new file mode 100644 index 0000000..de68643 --- /dev/null +++ b/bots/python/Vector/Vector.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env sh +set -eu +SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +if [ -n "${RUMBLE_PYTHON:-}" ]; then + exec "$RUMBLE_PYTHON" "$SCRIPT_DIR/src/Vector.py" "$@" +fi +if command -v python3 >/dev/null 2>&1; then + exec python3 "$SCRIPT_DIR/src/Vector.py" "$@" +fi +exec python "$SCRIPT_DIR/src/Vector.py" "$@" diff --git a/bots/python/Vector/src/Vector.py b/bots/python/Vector/src/Vector.py new file mode 100644 index 0000000..40e89bb --- /dev/null +++ b/bots/python/Vector/src/Vector.py @@ -0,0 +1,28 @@ +"""A compact Rumble catalog bot used for the first live ranked 1v1 proof.""" + +import os + + +if os.environ.get("RUMBLE_SMOKE") == "1": + print("RUMBLE_SMOKE_READY Vector") + raise SystemExit(0) + +from robocode_tank_royale.bot_api.bot import Bot + + +class Vector(Bot): + """Sweeps the radar while travelling in a wide arc.""" + + def run(self) -> None: + self.turn_radar_right(360) + while self.running: + self.set_turn_right(30) + self.forward(10_000) + + +def main() -> None: + Vector().start() + + +if __name__ == "__main__": + main() diff --git a/tests/test_validate_bot.py b/tests/test_validate_bot.py index 49c0c96..8477803 100644 --- a/tests/test_validate_bot.py +++ b/tests/test_validate_bot.py @@ -101,7 +101,8 @@ def test_version_increase_supersedes_the_previous_catalog_entry(self) -> None: config_path.write_text(json.dumps(config), encoding="utf-8") self.assertEqual(0, self.run_validator("--generate").returncode) catalog = json.loads((self.root / "bots" / "index.json").read_text(encoding="utf-8")) - self.assertEqual(["superseded", "active"], [entry["status"] for entry in catalog["bots"]]) + orbit = [entry for entry in catalog["bots"] if entry["name"] == "Orbit"] + self.assertEqual(["superseded", "active"], [entry["status"] for entry in orbit]) def test_new_bot_from_another_owner_ignores_unchanged_catalog_entries(self) -> None: self.assertEqual(0, self.run_validator("--generate").returncode) From 5c0dc93d62bc8c168aa715d68946b800aea5eeda Mon Sep 17 00:00:00 2001 From: "Flemming N. Larsen" Date: Sun, 30 Aug 2026 22:50:24 +0200 Subject: [PATCH 2/3] fix: describe Vector accurately and pin the catalog-entry test to Orbit Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Di4MfjnBCVf8N4v8WXq5nk --- bots/python/Vector/Vector.json | 2 +- tests/test_validate_bot.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bots/python/Vector/Vector.json b/bots/python/Vector/Vector.json index bdc7cbf..8ce64fd 100644 --- a/bots/python/Vector/Vector.json +++ b/bots/python/Vector/Vector.json @@ -2,7 +2,7 @@ "name": "Vector", "version": "1.0.0", "authors": ["Tank Royale Rumble maintainers"], - "description": "A small source-only bot that circles the arena while tracking opponents.", + "description": "A small source-only bot that drives in wide arcs across the arena.", "platform": "Python", "programmingLang": "Python 3", "gameTypes": ["1v1", "melee", "twinduel"], diff --git a/tests/test_validate_bot.py b/tests/test_validate_bot.py index 8477803..e681580 100644 --- a/tests/test_validate_bot.py +++ b/tests/test_validate_bot.py @@ -73,8 +73,8 @@ def test_valid_submission_generates_an_active_catalog_entry(self) -> None: result = self.run_validator("--smoke", "--generate") self.assertEqual(0, result.returncode, result.stderr) catalog = json.loads((self.root / "bots" / "index.json").read_text(encoding="utf-8")) - active_entry = next(entry for entry in catalog["bots"] if entry["status"] == "active") - self.assertEqual("Orbit", active_entry["name"]) + orbit = next(entry for entry in catalog["bots"] if entry["name"] == "Orbit") + self.assertEqual("active", orbit["status"]) def test_invalid_license_is_rejected(self) -> None: config_path = self.root / "bots" / "python" / "Orbit" / "Orbit.json" From bf8543c0e34426fb986af07a5cc02d66ab54d54b Mon Sep 17 00:00:00 2001 From: "Flemming N. Larsen" Date: Sun, 30 Aug 2026 22:57:25 +0200 Subject: [PATCH 3/3] feat: let Vector fire on scans --- bots/python/Vector/src/Vector.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bots/python/Vector/src/Vector.py b/bots/python/Vector/src/Vector.py index 40e89bb..5d32a76 100644 --- a/bots/python/Vector/src/Vector.py +++ b/bots/python/Vector/src/Vector.py @@ -8,6 +8,7 @@ raise SystemExit(0) from robocode_tank_royale.bot_api.bot import Bot +from robocode_tank_royale.bot_api.events import ScannedBotEvent class Vector(Bot): @@ -19,6 +20,12 @@ def run(self) -> None: self.set_turn_right(30) self.forward(10_000) + def on_scanned_bot(self, event: ScannedBotEvent) -> None: + """Aim at the detected opponent and fire before continuing the scan.""" + self.turn_gun_right(self.gun_bearing_to(float(event.x), float(event.y))) + self.fire(3) + self.rescan() + def main() -> None: Vector().start()