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

protocol.sh (3984B)


      1 #!/usr/bin/env bash
      2 # ============================================================================
      3 #  lib/protocol.sh  --  El "idioma" que hablan dos computadoras y como leerlo.
      4 # ============================================================================
      5 #
      6 # Cuando dos personas juegan en red, sus dos programas se mandan MENSAJES de
      7 # texto, uno por linea. Para entenderse, los dos tienen que usar el mismo
      8 # vocabulario. Eso es un "protocolo": una lista acordada de mensajes posibles.
      9 #
     10 # Estos son todos los mensajes que existen (cada uno ocupa una linea):
     11 #   HELLO <id>      saludo inicial / negociar quien juega cada color
     12 #   HELLO host <tc> del que hace de servidor al que se conecta: ademas lleva el
     13 #                   control de tiempo ("off" o "BASE:INC" en segundos, ej "300:5")
     14 #   HELLO join      del que se conecta al servidor, al conectarse
     15 #   HELLO rejoin    de quien vuelve, al reconectarse a una partida cortada
     16 #   COLOR <w|b>     el lider le dice al otro que color le toca jugar
     17 #   TIME <tc>       modo relay: las blancas avisan el control de tiempo elegido
     18 #   STATE <st>      el lider manda el estado COMPLETO de la partida (posicion,
     19 #                   relojes, etc.) para que el otro arranque igual o se reconecte
     20 #   MOVE <uci>      una jugada, ej "MOVE e2e4" o "MOVE e7e8q" (coronacion)
     21 #   RESIGN          quien lo manda, se rinde
     22 #   DRAW50          quien lo manda, reclama tablas por la regla de 50 movimientos
     23 #   DRAWOFFER       quien lo manda, ofrece tablas de comun acuerdo
     24 #   DRAWYES/DRAWNO  el otro acepta / rechaza la oferta de tablas
     25 #   TIMEOUT         a quien lo manda se le acabo el tiempo (pierde por tiempo)
     26 #   QUIT            quien lo manda salio prolijamente (no es rendicion)
     27 #
     28 # COMO VIAJAN LOS MENSAJES (un poco de tecnica):
     29 #   Usamos un "coprocess" de bash: un segundo programa (ncat) que corre EN
     30 #   PARALELO al nuestro y mantiene la conexion de red abierta. Bash nos da dos
     31 #   "file descriptors" (numeritos que identifican canales de comunicacion) para
     32 #   hablarle: NET_R para LEER lo que llega, NET_W para ESCRIBIR lo que mandamos.
     33 #   Si NET_W esta vacio, quiere decir que no estamos jugando en red.
     34 
     35 NET_R=""   # canal de lectura (por aca nos llega lo que manda el otro)
     36 NET_W=""   # canal de escritura (por aca le mandamos cosas al otro)
     37 
     38 # net_send: mandar un mensaje (una linea de texto) al otro jugador.
     39 net_send() {
     40     # Si no estamos en red (NET_W vacio), no hacemos nada y devolvemos exito.
     41     # Asi el mismo codigo del juego sirve para una partida local sin tocar nada.
     42     [[ -n "$NET_W" ]] || return 0
     43     # "printf '%s\n' "$1"" imprime el mensaje y un salto de linea; ">&$NET_W"
     44     # redirige esa salida hacia el canal de escritura (en vez de a la pantalla).
     45     printf '%s\n' "$1" >&"$NET_W"
     46 }
     47 
     48 # net_recv: esperar y leer UNA linea del otro jugador. Se queda "bloqueado"
     49 # (frenado) hasta que llegue algo. Devuelve 1 (error) si el otro corto (EOF).
     50 net_recv() {
     51     local line
     52     # "read -r -u "$NET_R" line" lee una linea desde el canal NET_R y la guarda en
     53     # "line". "IFS=" antes del read evita que se recorten espacios. Si el read
     54     # falla (no hay mas datos, el otro se desconecto), devolvemos 1.
     55     IFS= read -r -u "$NET_R" line || return 1
     56     printf '%s' "$line"
     57 }
     58 
     59 # net_recv_timeout: igual que net_recv, pero con un LIMITE DE TIEMPO en segundos
     60 # (1er argumento). Es util para no quedarnos esperando para siempre.
     61 # Importante: conserva el codigo de error del read para que quien llama pueda
     62 # distinguir DOS situaciones distintas:
     63 #   - se acabo el tiempo de espera  -> read devuelve un numero MAYOR a 128
     64 #   - el otro se desconecto (EOF)    -> read devuelve 1
     65 # (Esa diferencia es clave para el reloj y para detectar caidas de conexion.)
     66 net_recv_timeout() {
     67     local line rc
     68     IFS= read -r -t "$1" -u "$NET_R" line; rc=$?   # "$?" es el codigo del ultimo comando
     69     (( rc != 0 )) && return $rc                    # si fallo, devolvemos el MISMO codigo
     70     printf '%s' "$line"
     71 }