ef16dd982d
Generalize the classic-Robocode shim so the hosted bot's main class, jar, extra classpath and data directory are configurable (SHIM_BOT_CLASS / SHIM_BOT_JAR / SHIM_EXTRA_CP / SHIM_DATA), with DrussGT kept as the default so every existing script, fixture and generated bot dir behaves identically. - LegacyBotBridge: generalized bridge (DrussGTBridge kept as an alias). - BotHost: (mainClass, jar, extraJars, dataDir); disableShield -> generic disableStaticBoolean. - ClassicPeer: implement ITeamRobotPeer; synthesize StatusEvent each turn; make move/turnBody/turnGun/turnRadar the immediate (turn-ending) variants; guard re-entrant execute() from event handlers; record delivered events. - make_botdir.sh / run_bridge_battle.sh / run_smoke.sh generalized, legacy invocations unchanged; generated launcher uses a per-process mktemp data dir so concurrent bots/battles cannot clobber one classic data directory. Validated 35 legacy bots against a real Tank Royale battle (2 rounds vs sample SpinBot): 28 usable (27 effective + DrussGT), 5 weak-but-playing, 2 failing. Adds robots.json (manifest) and LEGACY_BOTS.md (how-to, status, missing-API costs). No third-party jar is committed.
151 lines
5.2 KiB
Bash
Executable File
151 lines
5.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Generate a Tank Royale bot directory that boots a classic Robocode robot
|
|
# through the robocode_shim bridge.
|
|
#
|
|
# tools/robocode_shim/make_botdir.sh [TARGET|NAME] \
|
|
# [--class FQCN] [--jar PATH] [--name DISPLAY] \
|
|
# [--version V] [--authors A] [--desc D] [--country CC] [--gametypes G]
|
|
#
|
|
# The first positional argument may be either
|
|
# * a directory path (legacy form, e.g. /tmp/tr_bots/DrussGT), or
|
|
# * a bare bot name, in which case the dir is /tmp/tr_bots/<NAME>.
|
|
# With no arguments at all it reproduces the original DrussGT directory.
|
|
#
|
|
# The generated directory contains only text files (<dir>.json + <dir>.sh); the
|
|
# third-party jars stay outside the repo and are referenced by absolute path.
|
|
#
|
|
# Defaults (so the original no-arg DrussGT invocation is byte-for-byte usable):
|
|
# --class jk.mega.DrussGT
|
|
# --jar $DRUSSGT_JAR (/tmp/drussgt/DrussGT.jar)
|
|
# display name = bot-dir basename, version parsed from the jar name (or 3.1.4159)
|
|
#
|
|
# Data-directory isolation: the generated launcher sets SHIM_DATA to a fresh
|
|
# per-process mktemp directory unless the caller already provided SHIM_DATA /
|
|
# DRUSSGT_DATA. Two bots (or two concurrent battles) therefore can never share
|
|
# or clobber one classic data directory.
|
|
set -euo pipefail
|
|
|
|
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
TARGET=""
|
|
CLASS=""
|
|
JAR=""
|
|
DISPLAY=""
|
|
VERSION=""
|
|
AUTHORS=""
|
|
DESC=""
|
|
COUNTRY="se"
|
|
GAMETYPES="classic,1v1"
|
|
|
|
if [[ $# -gt 0 && "${1}" != --* ]]; then
|
|
TARGET="$1"; shift
|
|
fi
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--class) CLASS="$2"; shift 2;;
|
|
--jar) JAR="$2"; shift 2;;
|
|
--name) DISPLAY="$2"; shift 2;;
|
|
--version) VERSION="$2"; shift 2;;
|
|
--authors) AUTHORS="$2"; shift 2;;
|
|
--desc) DESC="$2"; shift 2;;
|
|
--country) COUNTRY="$2"; shift 2;;
|
|
--gametypes) GAMETYPES="$2"; shift 2;;
|
|
-h|--help) sed -n '2,30p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'; exit 0;;
|
|
*) echo "unknown argument: $1" >&2; exit 2;;
|
|
esac
|
|
done
|
|
|
|
# --- resolve target dir + name (legacy forms preserved) ---
|
|
if [[ -z "$TARGET" ]]; then
|
|
TARGET="/tmp/tr_bots/DrussGT"
|
|
elif [[ "$TARGET" != */* ]]; then
|
|
TARGET="/tmp/tr_bots/$TARGET"
|
|
fi
|
|
DIR_NAME="$(basename "$TARGET")"
|
|
|
|
DRUSSGT_JAR="${DRUSSGT_JAR:-/tmp/drussgt/DrussGT.jar}"
|
|
CLASS="${CLASS:-jk.mega.DrussGT}"
|
|
JAR="${JAR:-$DRUSSGT_JAR}"
|
|
NAME="${DISPLAY:-$DIR_NAME}"
|
|
|
|
# --- defaults that keep the DrussGT case identical to the old script ---
|
|
if [[ -z "$VERSION" ]]; then
|
|
if [[ "$CLASS" == "jk.mega.DrussGT" ]]; then
|
|
VERSION="3.1.4159"
|
|
else
|
|
stem="$(basename "$JAR")"; stem="${stem%.jar}"
|
|
if [[ "$stem" == *_* ]]; then VERSION="${stem##*_}"; else VERSION="1.0"; fi
|
|
fi
|
|
fi
|
|
[[ -n "$AUTHORS" ]] || { if [[ "$CLASS" == "jk.mega.DrussGT" ]]; then AUTHORS="Jacob"; else AUTHORS="unknown"; fi; }
|
|
[[ -n "$DESC" ]] || { if [[ "$CLASS" == "jk.mega.DrussGT" ]]; then
|
|
DESC="Real classic DrussGT running on Tank Royale via the robocode_shim bridge"
|
|
else
|
|
DESC="Classic Robocode robot ${CLASS} running on Tank Royale via the robocode_shim bridge"
|
|
fi; }
|
|
GAMETYPES_JSON="$(printf '%s' "$GAMETYPES" | sed 's/,/\", \"/g')"
|
|
|
|
ROBOCODE_JAR="${ROBOCODE_JAR:-/tmp/robocode/install/libs/robocode.jar}"
|
|
TR_BOT_API_JAR="${TR_BOT_API_JAR:-$HOME/Downloads/sample-bots-java-1.0.2/lib/robocode-tankroyale-bot-api-1.0.2.jar}"
|
|
OUT="${OUT:-$HERE/out}"
|
|
EXTRA_CP="${SHIM_EXTRA_CP:-}"
|
|
EXTRA_LINE=""
|
|
[[ -n "$EXTRA_CP" ]] && EXTRA_LINE="export SHIM_EXTRA_CP=\"$EXTRA_CP\""
|
|
|
|
mkdir -p "$TARGET"
|
|
cat > "$TARGET/$DIR_NAME.json" <<JSON
|
|
{
|
|
"name": "$NAME",
|
|
"version": "$VERSION",
|
|
"authors": ["$AUTHORS"],
|
|
"description": "$DESC",
|
|
"homepage": "",
|
|
"countryCodes": ["$COUNTRY"],
|
|
"gameTypes": ["$GAMETYPES_JSON"],
|
|
"platform": "JVM",
|
|
"programmingLang": "Java 8"
|
|
}
|
|
JSON
|
|
|
|
# The Tank Royale bot API reads bot identity from BOT_* environment variables.
|
|
# When the TR booter launches this directory it supplies them (derived from the
|
|
# .json above), but running this script BY HAND does not - and the API then
|
|
# rejects the handshake with "Required bot property 'name' is missing".
|
|
# Exporting them here makes the script work standalone as well.
|
|
#
|
|
# SHIM_BOT_CLASS / SHIM_BOT_JAR select the hosted classic robot. SHIM_DATA is a
|
|
# fresh per-process directory by default: two bots (or two concurrent battles)
|
|
# can never share or clobber the same classic data directory.
|
|
cat > "$TARGET/$DIR_NAME.sh" <<SH
|
|
#!/bin/sh
|
|
cd "\$(dirname "\$0")"
|
|
|
|
# Hosted classic robot selection - keep in sync with $DIR_NAME.json
|
|
export SHIM_BOT_CLASS="$CLASS"
|
|
export SHIM_BOT_JAR="$JAR"
|
|
$EXTRA_LINE
|
|
: "\${SHIM_DATA:=\${DRUSSGT_DATA:-\$(mktemp -d "\${TMPDIR:-/tmp}/tr_shim_data.XXXXXX")}}"
|
|
export SHIM_DATA
|
|
|
|
# Bot identity - keep in sync with $DIR_NAME.json
|
|
export BOT_NAME="$NAME"
|
|
export BOT_VERSION="$VERSION"
|
|
export BOT_AUTHORS="$AUTHORS"
|
|
export BOT_DESCRIPTION="$DESC"
|
|
export BOT_HOMEPAGE=""
|
|
export BOT_COUNTRY_CODES="$COUNTRY"
|
|
export BOT_GAME_TYPES="$GAMETYPES"
|
|
export BOT_PLATFORM="JVM"
|
|
export BOT_PROG_LANG="Java 8"
|
|
|
|
exec java -cp "$OUT:$ROBOCODE_JAR:$TR_BOT_API_JAR" robocode_shim.LegacyBotBridge
|
|
SH
|
|
chmod +x "$TARGET/$DIR_NAME.sh"
|
|
|
|
echo "bot dir ready: $TARGET"
|
|
echo " $TARGET/$DIR_NAME.json"
|
|
echo " $TARGET/$DIR_NAME.sh"
|
|
echo " class: $CLASS"
|
|
echo " jar: $JAR"
|
|
echo " (classpath: $OUT:$ROBOCODE_JAR:$TR_BOT_API_JAR)"
|