juegos

Juegos de terminal de Pancho: Catan (TUI, GUI, web, servidor, PicoCalc), ajedrez, calculadora y minijuegos
git clone https://git.lu3dhn.xyz/juegos.git
Log | Files | Refs

get-stockfish.sh (10735B)


      1 #!/usr/bin/env bash
      2 # ============================================================================
      3 #  bin/get-stockfish.sh  --  Descarga el motor de ajedrez "Stockfish".
      4 # ============================================================================
      5 #
      6 # QUE ES ESTE ARCHIVO:
      7 #   El juego entero esta escrito en bash (texto), pero la inteligencia
      8 #   artificial (la computadora que juega contra vos) necesita un programa
      9 #   externo MUY potente llamado Stockfish. Stockfish es un "motor de ajedrez":
     10 #   le pasas una posicion y te dice cual es la mejor jugada.
     11 #
     12 #   No incluimos a Stockfish dentro del proyecto porque es un archivo binario
     13 #   pesado (mas de 100 MB) y distinto para cada tipo de procesador. En vez de
     14 #   eso, este script lo BAJA de internet y lo guarda en la carpeta ./engine/.
     15 #
     16 #   Solo funciona automaticamente en computadoras x86-64 (las de escritorio y
     17 #   notebooks comunes con Linux). En otros procesadores (por ejemplo una
     18 #   Raspberry Pi o la consola uConsole, que son "aarch64") te dice como
     19 #   instalarlo con el gestor de paquetes del sistema.
     20 #
     21 # COMO SE USA:
     22 #   ./bin/get-stockfish.sh
     23 
     24 # "set -euo pipefail" prende tres modos estrictos de bash. Son MUY utiles para
     25 # que el script no siga adelante cuando algo sale mal:
     26 #   -e            : si CUALQUIER comando falla, cortamos el script enseguida.
     27 #   -u            : si usamos una variable que no existe, es un error (atrapa
     28 #                   errores de tipeo en nombres de variables).
     29 #   -o pipefail   : en una cadena de comandos con "|" (tuberia/pipe), si
     30 #                   cualquiera de los comandos falla, toda la cadena se
     31 #                   considera fallida (sin esto, bash solo mira el ultimo).
     32 set -euo pipefail
     33 
     34 # --- Averiguar en que carpeta esta este script ------------------------------
     35 # Necesitamos saber donde vive el proyecto para guardar el motor en ./engine/.
     36 # Lo armamos de adentro hacia afuera (los $( ) se ejecutan primero):
     37 #   "$0"                  : la ruta con la que se llamo a este script.
     38 #   readlink -f "$0"      : la convierte en una ruta absoluta y real (resolviendo
     39 #                           enlaces simbolicos).
     40 #   dirname ...           : se queda con la carpeta (saca el nombre del archivo).
     41 #   cd ... && pwd         : entra a esa carpeta e imprime su ruta absoluta. Lo
     42 #                           hacemos asi para tener una ruta prolija y completa.
     43 # "$( ... )" se llama "sustitucion de comandos": ejecuta lo de adentro y
     44 # reemplaza todo por el TEXTO que ese comando imprimio.
     45 SCRIPT_DIR="$(cd "$(dirname "$(readlink -f "$0")")" && pwd)"
     46 ROOT="$(dirname "$SCRIPT_DIR")"   # el proyecto es la carpeta que contiene a bin/
     47 ENGINE_DIR="$ROOT/engine"         # aca va a quedar guardado el motor
     48 TARGET="$ENGINE_DIR/stockfish"    # el archivo final del motor
     49 
     50 # --- Datos para la descarga -------------------------------------------------
     51 # "API" es la direccion de GitHub que nos cuenta cual es la ultima version
     52 # publicada de Stockfish.
     53 API="https://api.github.com/repos/official-stockfish/Stockfish/releases/latest"
     54 # Cual de todas las variantes bajar. Usamos la version "baseline" (basica) que
     55 # anda en cualquier procesador x86-64. Una persona avanzada puede pedir una mas
     56 # rapida poniendo la variable de entorno SF_ASSET antes de correr el script.
     57 # "${SF_ASSET:-...}" otra vez significa "usa SF_ASSET, o este valor por defecto".
     58 SF_ASSET="${SF_ASSET:-stockfish-ubuntu-x86-64.tar}"
     59 
     60 # --- Una "funcion" auxiliar -------------------------------------------------
     61 # Una funcion es un bloque de codigo con nombre que podemos reutilizar. Esta,
     62 # "_works", recibe la ruta de un programa (en "$1", el primer argumento que le
     63 # pasamos) y responde si ese programa es realmente Stockfish y funciona.
     64 #
     65 # Como lo verifica: a todo motor de ajedrez se le habla con el protocolo "UCI".
     66 # Si le mandamos la palabra "uci", un motor de verdad responde con "uciok".
     67 #   printf 'uci\nquit\n'  : imprime dos lineas: "uci" y "quit" (\n = salto de
     68 #                           linea). Es lo que le "escribimos" al motor.
     69 #   |                     : la tuberia conecta esa salida con la ENTRADA del
     70 #                           programa "$1" (le mandamos esas dos lineas).
     71 #   2>/dev/null           : descartamos los mensajes de error (no nos importan).
     72 #   grep -q uciok         : busca la palabra "uciok" en la respuesta. "-q" =
     73 #                           modo silencioso: no imprime nada, solo devuelve
     74 #                           exito (0) si la encontro.
     75 # La funcion devuelve el resultado de ese grep: exito si el motor contesto bien.
     76 _works() { printf 'uci\nquit\n' | "$1" 2>/dev/null | grep -q uciok; }
     77 
     78 # --- Si ya esta instalado, no hacemos nada ----------------------------------
     79 # "[[ ... ]]" es la forma de bash de hacer una pregunta de verdadero/falso.
     80 #   -x "$TARGET"  : pregunta si el archivo $TARGET existe y es ejecutable.
     81 # El "&&" significa "Y": las dos condiciones tienen que cumplirse.
     82 if [[ -x "$TARGET" ]] && _works "$TARGET"; then
     83     echo "Stockfish already installed at ${TARGET}."; exit 0
     84 fi
     85 # Quizas ya esta instalado en el sistema (en el "PATH", la lista de carpetas
     86 # donde el sistema busca programas). Si es asi, el juego lo va a encontrar solo.
     87 if command -v stockfish >/dev/null 2>&1 && _works stockfish; then
     88     echo "Stockfish already on your PATH ($(command -v stockfish)). The game will use it."
     89     exit 0
     90 fi
     91 
     92 # --- Chequear el tipo de procesador -----------------------------------------
     93 # "uname -m" dice la arquitectura del procesador (por ejemplo "x86_64" o
     94 # "aarch64"). Solo tenemos descarga automatica para x86_64.
     95 arch="$(uname -m)"
     96 if [[ "$arch" != x86_64 ]]; then
     97     # "cat <<EOF ... EOF" es un "here-document": imprime todo el bloque de texto
     98     # tal cual hasta encontrar la palabra EOF sola en una linea. ">&2" lo manda a
     99     # la salida de errores. Este mensaje queda en ingles (lo lee la persona).
    100     cat >&2 <<EOF
    101 No official prebuilt Stockfish Linux binary for '${arch}'.
    102 Install it with your package manager instead, e.g.:
    103     pacman -S stockfish          # Arch / Artix
    104     sudo apt install stockfish   # Debian / Ubuntu / Raspberry Pi OS
    105     sudo dnf install stockfish   # Fedora
    106 The game auto-detects a 'stockfish' on your PATH.
    107 EOF
    108     exit 1
    109 fi
    110 
    111 # --- Verificar que tengamos las herramientas para bajar y descomprimir ------
    112 # "curl" baja archivos de internet; "tar" abre archivos comprimidos .tar.
    113 command -v curl >/dev/null || { echo "curl is required." >&2; exit 1; }
    114 command -v tar  >/dev/null || { echo "tar is required."  >&2; exit 1; }
    115 
    116 # --- Buscar el link de descarga de la ultima version ------------------------
    117 echo "Finding the latest Stockfish release..."
    118 # Le pedimos a GitHub la info de la ultima version y buscamos el link exacto.
    119 #   curl -fsSL "$API"  : baja el texto de esa pagina (-f falla si hay error de
    120 #                        red, -s silencioso, -S muestra errores igual, -L sigue
    121 #                        redirecciones).
    122 #   grep -oE 'patron'  : "-o" imprime SOLO la parte que coincide (no la linea
    123 #                        entera); "-E" usa expresiones regulares extendidas.
    124 #                        El patron busca una direccion https que termine en el
    125 #                        nombre del archivo que queremos.
    126 #   head -n1           : nos quedamos con la primera coincidencia nomas.
    127 #   || true            : si todo eso falla, devolvemos "exito" igual (true) para
    128 #                        que "set -e" no corte el script aca; mas abajo
    129 #                        chequeamos si "url" quedo vacio.
    130 url="$(curl -fsSL "$API" | grep -oE "https://[^\"]+/${SF_ASSET}" | head -n1 || true)"
    131 # "-n" pregunta si la variable NO esta vacia. Si quedo vacia, avisamos y salimos.
    132 [[ -n "$url" ]] || { echo "Could not find asset '${SF_ASSET}' in the latest release." >&2; exit 1; }
    133 
    134 # --- Bajar y descomprimir en una carpeta temporal ---------------------------
    135 # "mktemp -d" crea una carpeta temporal con nombre unico y nos devuelve su ruta.
    136 # La usamos para no ensuciar el proyecto con archivos intermedios.
    137 tmp="$(mktemp -d)"
    138 # "trap 'comando' EVENTO" programa un comando para que se ejecute cuando pase un
    139 # evento. "EXIT" ocurre cuando el script termina (de cualquier forma). O sea:
    140 # pase lo que pase, al final borramos la carpeta temporal. Es como dejar todo
    141 # limpio antes de irnos.
    142 trap 'rm -rf "$tmp"' EXIT
    143 mkdir -p "$tmp/x"   # subcarpeta donde vamos a descomprimir (mkdir -p no falla si ya existe)
    144 echo "Downloading ${url##*/} ..."   # "${url##*/}" deja solo el nombre del archivo (saca todo hasta la ultima /)
    145 # Bajamos el .tar a la carpeta temporal. "-#" muestra una barrita de progreso.
    146 curl -fL# "$url" -o "$tmp/sf.tar"
    147 # Descomprimimos. "x" = extraer, "f" = desde este archivo, "-C" = hacia esta carpeta.
    148 tar xf "$tmp/sf.tar" -C "$tmp/x"
    149 
    150 # --- Encontrar el binario del motor dentro de lo descomprimido --------------
    151 # El .tar trae el motor MAS un monton de archivos (codigo fuente, documentacion).
    152 # El motor es, de lejos, el archivo mas grande. Asi que buscamos el mas pesado:
    153 #   find "$tmp/x" -type f         : lista todos los archivos (no carpetas).
    154 #   -printf '%s %p\n'             : imprime "tamanio ruta" por cada archivo.
    155 #   sort -rn                      : ordena por numero, de mayor a menor (-r al reves, -n numerico).
    156 #   head -n1                      : nos quedamos con el primero (el mas grande).
    157 #   cut -d' ' -f2-                : corta usando el espacio como separador y se
    158 #                                   queda de la 2da columna en adelante (la ruta),
    159 #                                   descartando el numero de tamanio.
    160 # Importante: buscamos dentro de $tmp/x (donde descomprimimos), NO en $tmp, asi
    161 # el propio archivo .tar (que tambien es grande) no se cuela en la busqueda.
    162 bin="$(find "$tmp/x" -type f -printf '%s %p\n' | sort -rn | head -n1 | cut -d' ' -f2-)"
    163 [[ -n "$bin" ]] || { echo "Could not locate the engine in the archive." >&2; exit 1; }
    164 
    165 # --- Instalar el motor en ./engine/stockfish --------------------------------
    166 mkdir -p "$ENGINE_DIR"     # creamos la carpeta engine/ si no existe
    167 cp "$bin" "$TARGET"        # copiamos el binario encontrado a su lugar final
    168 chmod +x "$TARGET"         # le damos permiso de ejecucion (para poder correrlo)
    169 
    170 # --- Verificar que el motor instalado realmente funciona --------------------
    171 if _works "$TARGET"; then
    172     echo "Stockfish installed to ${TARGET}."
    173     echo "Play the computer with:  ./ches.sh ai"
    174 else
    175     # Algunas variantes necesitan instrucciones modernas del procesador. Si la
    176     # que bajamos no arranca, sugerimos volver a la version basica.
    177     echo "Installed binary did not respond to UCI — your CPU may not support this build." >&2
    178     echo "Try a baseline build:  SF_ASSET=stockfish-ubuntu-x86-64.tar $0" >&2
    179     exit 1
    180 fi