#!/bin/bash # Godot autoplay runner with two headless modes. # # RENDER_MODE=headless (default) — Godot --headless, no display server. # Fastest. Screenshots blank. For bulk simulation / data collection. # # RENDER_MODE=weston — weston --backend=headless provides a virtual Wayland # display with software rendering (llvmpipe). Screenshots work. # Requires weston installed on the host. set -uo pipefail : "${AUTO_PLAY:=true}" : "${AUTO_PLAY_DIR:=$HOME/tmp/ap_default}" : "${AP_RUN_ID:=}" # Scoped cleanup: kill any prior Godot process for THIS exact run ID. # AP_RUN_ID is a unique token (_seed) injected by autoplay-batch.sh; # using it instead of AUTO_PLAY_DIR avoids substring collisions between seeds # whose dir names share a numeric prefix (e.g. seed1 matching seed10). # When AP_RUN_ID is unset (manual invocation), fall back to AUTO_PLAY_DIR scope. if [ -n "$AP_RUN_ID" ]; then pkill -f "AP_RUN_ID=$AP_RUN_ID" 2>/dev/null || true else pkill -f "AUTO_PLAY_DIR=$AUTO_PLAY_DIR " 2>/dev/null || true pkill -f "AUTO_PLAY_DIR=$AUTO_PLAY_DIR\$" 2>/dev/null || true fi sleep 1 : "${AUTO_PLAY_TURN_LIMIT:=500}" : "${RENDER_MODE:=headless}" mkdir -p "$AUTO_PLAY_DIR" cd "$HOME/Code/@projects/@magic-civilization/src/game" SAFETY=$((AUTO_PLAY_TURN_LIMIT * 2 + 300)) FLATPAK_ENVS=( "--env=AUTO_PLAY=true" "--env=AUTO_PLAY_DIR=$AUTO_PLAY_DIR" "--env=AUTO_PLAY_TURN_LIMIT=$AUTO_PLAY_TURN_LIMIT" ) if [ -n "${AP_RUN_ID:-}" ]; then FLATPAK_ENVS+=("--env=AP_RUN_ID=$AP_RUN_ID") fi if [ -n "${AUTO_PLAY_SEED:-}" ]; then FLATPAK_ENVS+=("--env=AUTO_PLAY_SEED=$AUTO_PLAY_SEED") fi if [ -n "${AI_DIFFICULTY:-}" ]; then FLATPAK_ENVS+=("--env=AI_DIFFICULTY=$AI_DIFFICULTY") fi if [ -n "${AI_PIN_PERSONALITY:-}" ]; then FLATPAK_ENVS+=("--env=AI_PIN_PERSONALITY=$AI_PIN_PERSONALITY") fi # Per-slot pin overrides — matchup-grid.sh sets these to populate clan_id on # both player slots (incl. the human slot) so meta.json player_clans has every # clan and matchup_balance verdict can attribute all wins. for i in 0 1 2 3 4 5 6 7; do var="AI_PIN_PERSONALITY_P${i}" if [ -n "${!var:-}" ]; then FLATPAK_ENVS+=("--env=${var}=${!var}") fi done GODOT_ARGS=("--path" "." "--rendering-method" "gl_compatibility") WESTON_PID="" _cleanup() { if [ -n "$WESTON_PID" ]; then kill "$WESTON_PID" 2>/dev/null || true wait "$WESTON_PID" 2>/dev/null || true fi } trap _cleanup EXIT if [ "$RENDER_MODE" = "weston" ]; then if ! command -v weston >/dev/null 2>&1; then echo "ERROR: RENDER_MODE=weston but weston not found" >&2 exit 1 fi WESTON_SOCKET="godot-headless-$$" weston --backend=headless --socket="$WESTON_SOCKET" --width=1920 --height=1080 \ >"$AUTO_PLAY_DIR/weston.log" 2>&1 & WESTON_PID=$! sleep 1 FLATPAK_ENVS+=( "--socket=wayland" "--env=WAYLAND_DISPLAY=$WESTON_SOCKET" ) FLATPAK_ENVS+=("--filesystem=xdg-run/${WESTON_SOCKET}") else GODOT_ARGS+=("--headless") fi timeout "$SAFETY" flatpak run --user \ --filesystem=home \ "${FLATPAK_ENVS[@]}" \ org.godotengine.Godot "${GODOT_ARGS[@]}" 2>&1 EXIT=$? echo "EXIT_CODE=$EXIT"