# Justfile for Migrate Database Changes Workflow # Docs: https://just.systems/man/en/ # ------------------------------------------------------------------------------ # Global settings # ------------------------------------------------------------------------------ # Load Env set dotenv-load set dotenv-required := true # Use zsh set shell := ["bash", "-cu"] BATTLESNAKE_CLI_DIR := ".tools/battlesnake-cli" BATTLESNAKE_CLI_BIN := ".tools/battlesnake-cli/battlesnake" # ------------------------------------------------------------------------------ # Default # ------------------------------------------------------------------------------ # List all Available recipes [private] default: @just --list --unsorted # ------------------------------------------------------------------------------ # Snake Script helpers # ------------------------------------------------------------------------------ run: "{{justfile_directory()}}/main.py" run-snake port="8000" snake="BestBattleSnake": HOST="127.0.0.1" PORT="{{port}}" SNAKE="{{snake}}" DEBUG="false" DEBUG_SERVER="false" "{{justfile_directory()}}/main.py" run-4-snakes base_port="9101" snake="BestBattleSnake": #!/usr/bin/env bash set -euo pipefail pids=() for i in 0 1 2 3; do port="$(({{base_port}} + i))" echo "Starting snake on :$port" HOST="127.0.0.1" PORT="$port" SNAKE="{{snake}}" DEBUG="false" DEBUG_SERVER="false" "{{justfile_directory()}}/main.py" & pids[$i]="$!" done cleanup() { for pid in "${pids[@]}"; do kill "$pid" 2>/dev/null || true done wait || true } trap cleanup EXIT INT TERM wait bench-best-snake iterations="1000": #!/usr/bin/env bash set -euo pipefail PYTHONPATH="{{justfile_directory()}}" python "{{justfile_directory()}}/tests/bench_best_battle_snake.py" --iterations "{{iterations}}" build-battlesnake-cli: #!/usr/bin/env bash set -euo pipefail install_dir="{{justfile_directory()}}/{{BATTLESNAKE_CLI_DIR}}" bin_path="{{justfile_directory()}}/{{BATTLESNAKE_CLI_BIN}}" mkdir -p "$install_dir" if [ ! -f "{{justfile_directory()}}/local-client/go.mod" ]; then echo "Missing local-client source. Run: git submodule update --init --recursive" exit 1 fi ( cd "{{justfile_directory()}}/local-client" go build -o "$bin_path" ./cli/battlesnake/main.go ) "$bin_path" --help > /dev/null echo "Built Battlesnake CLI at $bin_path" battlesnake-cli-version: #!/usr/bin/env bash set -euo pipefail "{{justfile_directory()}}/{{BATTLESNAKE_CLI_BIN}}" --help # ------------------------------------------------------------------------------ # Testing helpers # ------------------------------------------------------------------------------ test-constrictor: build-battlesnake-cli #!/usr/bin/env bash set -euo pipefail BATTLESNAKE_CLI="{{justfile_directory()}}/{{BATTLESNAKE_CLI_BIN}}" "$BATTLESNAKE_CLI" play -W 11 -H 11 --name 'Python Starter Project' --url http://localhost:8000 -g constrictor --browser --minimumFood 0 test-seed: build-battlesnake-cli #!/usr/bin/env bash set -euo pipefail BATTLESNAKE_CLI="{{justfile_directory()}}/{{BATTLESNAKE_CLI_BIN}}" "$BATTLESNAKE_CLI" play -W 11 -H 11 --name 'Python Starter Project' --url http://localhost:8000 -g solo --browser --seed 1713099635738952360 test-local-4 mode="standard" map="standard" base_port="9101" snake="BestBattleSnake" seed="1713099635738952360" browser="true": build-battlesnake-cli #!/usr/bin/env bash set -euo pipefail BATTLESNAKE_CLI="{{justfile_directory()}}/{{BATTLESNAKE_CLI_BIN}}" LOG_DIR="{{justfile_directory()}}/.tools/snake-logs" mkdir -p "$LOG_DIR" pids=() for i in 0 1 2 3; do port="$(({{base_port}} + i))" log_file="$LOG_DIR/snake-$((i+1)).log" echo "Starting snake-$((i+1)) on :$port (log: $log_file)" HOST="127.0.0.1" PORT="$port" SNAKE="{{snake}}" DEBUG="false" DEBUG_SERVER="false" "{{justfile_directory()}}/main.py" > >(tee "$log_file") 2>&1 & pids[$i]="$!" done cleanup() { for pid in "${pids[@]}"; do kill "$pid" 2>/dev/null || true done wait || true } trap cleanup EXIT INT TERM for i in 0 1 2 3; do port="$(({{base_port}} + i))" for _ in $(seq 1 30); do if curl -fsS "http://127.0.0.1:$port" >/dev/null 2>&1; then break fi sleep 0.2 done if ! curl -fsS "http://127.0.0.1:$port" >/dev/null 2>&1; then echo "Snake on :$port did not start correctly. Check logs in $LOG_DIR" exit 1 fi done BROWSER_FLAG="" if [ "{{browser}}" = "true" ]; then BROWSER_FLAG="--browser" fi "$BATTLESNAKE_CLI" play -W 11 -H 11 \ --name "Snake 1" --url "http://127.0.0.1:{{base_port}}" \ --name "Snake 2" --url "http://127.0.0.1:$(({{base_port}} + 1))" \ --name "Snake 3" --url "http://127.0.0.1:$(({{base_port}} + 2))" \ --name "Snake 4" --url "http://127.0.0.1:$(({{base_port}} + 3))" \ -g "{{mode}}" --map "{{map}}" --seed "{{seed}}" $BROWSER_FLAG # ------------------------------------------------------------------------------ # Dataset helpers # ------------------------------------------------------------------------------ export-dataset input="data" output="data/dataset/good_moves.jsonl": python -m server.DatasetExporter --input "{{input}}" --output "{{output}}" curate-dataset input="good_moves-*.jsonl" output="data/dataset/best_moves.jsonl" min_turn="6" late_turn="20" max_safe_options="2" min_score="3" append="false" archive="false" archive_dir="": FLAGS=""; if [ "{{append}}" = "true" ]; then FLAGS="$FLAGS --append"; fi; if [ "{{archive}}" = "true" ]; then FLAGS="$FLAGS --archive-input"; fi; if [ -n "{{archive_dir}}" ]; then FLAGS="$FLAGS --archive-dir {{archive_dir}}"; fi; python -m server.DatasetCurator --input "{{input}}" --output "{{output}}" --min-turn "{{min_turn}}" --late-turn "{{late_turn}}" --max-safe-options "{{max_safe_options}}" --min-score "{{min_score}}" $FLAGS analyze-dataset input="good_moves-*.jsonl" output="": if [ -n "{{output}}" ]; then python -m server.DatasetStats --input "{{input}}" --output "{{output}}"; else python -m server.DatasetStats --input "{{input}}"; fi train-ai input="data/dataset/best_moves.jsonl" rl_input="data/dataset/rl_bootstrap.jsonl" output="models/battlesnake_softmax_v2.json" eval_split="0.2" seed="42" epochs="14" lr="0.08": if [ -f "{{rl_input}}" ]; then python -m server.TrainBattleSnakeAI --input "{{input}}" --input "{{rl_input}}" --output "{{output}}" --eval-split "{{eval_split}}" --seed "{{seed}}" --epochs "{{epochs}}" --lr "{{lr}}"; else python -m server.TrainBattleSnakeAI --input "{{input}}" --output "{{output}}" --eval-split "{{eval_split}}" --seed "{{seed}}" --epochs "{{epochs}}" --lr "{{lr}}"; fi run-trained model="models/battlesnake_softmax_v2.json" port="8000": TRAINED_SNAKE_MODEL="{{model}}" SNAKE="TrainedBattleSnake" PORT="{{port}}" "{{justfile_directory()}}/main.py"