#!/usr/bin/env bash set -euo pipefail # En Croissant + lc0 + Maia + Stockfish setup script # Targets Arch Linux. No sudo required (prerequisites must be pre-installed). APPIMAGE_DIR="$HOME/.local/bin" APPIMAGE_PATH="$APPIMAGE_DIR/en-croissant.AppImage" LC0_BIN="$HOME/.local/bin/lc0" MAIA_WEIGHTS_DIR="$HOME/.local/share/maia" MAIA_BASE_URL="https://github.com/CSSLab/maia-chess/releases/download/v1.0" STOCKFISH_TAR_URL="https://github.com/official-stockfish/Stockfish/releases/latest/download/stockfish-ubuntu-x86-64-avx2.tar" STOCKFISH_DIR="$HOME/.local/share/org.encroissant.app/engines/stockfish" STOCKFISH_BIN="$STOCKFISH_DIR/stockfish-ubuntu-x86-64-avx2" ENGINES_JSON="$HOME/.local/share/org.encroissant.app/engines/engines.json" DESKTOP_FILE="$HOME/.local/share/applications/en-croissant.desktop" info() { printf '\033[1;34m==> %s\033[0m\n' "$*"; } ok() { printf '\033[1;32m -> %s\033[0m\n' "$*"; } skip() { printf '\033[1;33m -> %s (skipped)\033[0m\n' "$*"; } err() { printf '\033[1;31mERROR: %s\033[0m\n' "$*" >&2; } # --------------------------------------------------------------------------- # 1. Check prerequisites # --------------------------------------------------------------------------- info "Checking prerequisites" missing=() for cmd in git meson ninja python3 curl; do command -v "$cmd" &>/dev/null || missing+=("$cmd") done # Check libraries via pacman for pkg in openblas eigen; do pacman -Qi "$pkg" &>/dev/null || missing+=("$pkg") done if (( ${#missing[@]} )); then err "Missing packages: ${missing[*]}" echo "Install them with: sudo pacman -S ${missing[*]}" exit 1 fi ok "All prerequisites found" # --------------------------------------------------------------------------- # 2. Install En Croissant AppImage # --------------------------------------------------------------------------- info "Installing En Croissant AppImage" if [[ -f "$APPIMAGE_PATH" ]]; then skip "Already exists at $APPIMAGE_PATH" else mkdir -p "$APPIMAGE_DIR" # Get latest release AppImage URL from GitHub API appimage_url=$(curl -sL "https://api.github.com/repos/franciscoBSalgueiro/en-croissant/releases/latest" \ | python3 -c "import sys,json; assets=json.load(sys.stdin)['assets']; print([a['browser_download_url'] for a in assets if a['name'].endswith('_amd64.AppImage')][0])") echo " Downloading: $appimage_url" curl -L -o "$APPIMAGE_PATH" "$appimage_url" chmod +x "$APPIMAGE_PATH" ok "Installed to $APPIMAGE_PATH" fi # --------------------------------------------------------------------------- # 3. Build and install lc0 from source # --------------------------------------------------------------------------- info "Building lc0" if [[ -x "$LC0_BIN" ]]; then skip "Already exists at $LC0_BIN" else LC0_BUILD_DIR=$(mktemp -d /tmp/lc0-build.XXXXXX) echo " Cloning to $LC0_BUILD_DIR" git clone --recurse-submodules https://github.com/LeelaChessZero/lc0.git "$LC0_BUILD_DIR/lc0" pushd "$LC0_BUILD_DIR/lc0" >/dev/null INSTALL_PREFIX="$HOME/.local" ./build.sh popd >/dev/null mkdir -p "$HOME/.local/bin" cp "$LC0_BUILD_DIR/lc0/build/release/lc0" "$LC0_BIN" chmod +x "$LC0_BIN" ok "Installed to $LC0_BIN" rm -rf "$LC0_BUILD_DIR" fi # --------------------------------------------------------------------------- # 4. Download Maia weights # --------------------------------------------------------------------------- info "Downloading Maia weights" mkdir -p "$MAIA_WEIGHTS_DIR" for elo in 1100 1200 1300 1400 1500 1600 1700 1800 1900; do file="maia-${elo}.pb.gz" dest="$MAIA_WEIGHTS_DIR/$file" if [[ -f "$dest" ]]; then skip "$file already exists" else echo " Downloading $file" curl -sL -o "$dest" "$MAIA_BASE_URL/$file" ok "$file" fi done # --------------------------------------------------------------------------- # 5. Create Maia wrapper scripts # --------------------------------------------------------------------------- info "Creating Maia wrapper scripts" mkdir -p "$HOME/.local/bin" for elo in 1100 1200 1300 1400 1500 1600 1700 1800 1900; do wrapper="$HOME/.local/bin/maia-${elo}" cat > "$wrapper" <