Diego Molinari

← Todos los casos

Errores que no compilan

El problema

Un juego de cartas multijugador tiene dos problemas que no perdonan.

El primero: el servidor y el navegador tienen que estar de acuerdo sobre las reglas. Si el cliente cree que una carta gana y el servidor cree que pierde, la partida se rompe. La forma habitual de resolverlo es escribir las reglas dos veces y tener cuidado.

El segundo: el cliente no puede recibir las cartas del rival. Si llegan al navegador —aunque la interfaz no las dibuje— cualquiera las lee. La forma habitual de resolverlo es filtrarlas antes de enviar, y tener cuidado.

Los dos se resuelven “con cuidado”. Y el cuidado se agota.

Qué construí

Convite, una plataforma donde cualquier sitio integra juegos con una sola etiqueta <script>. El widget abre en una pantalla de selección, muestra únicamente los juegos que el contrato de ese sitio habilita, y toma los colores de identidad del sitio que lo aloja.

El primer juego es Truco Argentino, mano a mano, a 15 o 30 puntos. Se puede jugar contra otra persona o contra un bot en tres niveles.

Es un monorepo con tres aplicaciones y once paquetes: el motor de reglas, el contrato genérico de juegos, el transporte, el mazo español y la interfaz viven cada uno por separado.

Vista ilustrativa · partida de ejemplo

convite · truco

Nosotros

12

Ellos

9
7
tu turno
3
1
7
12
TrucoEnvidoReal envidoIrse al mazo
Reconstrucción ilustrativa, no una captura. El marcador lleva los puntos en fósforos, como en la mesa. Las cartas del rival están dadas vuelta acá porque también lo están del otro lado: el navegador nunca las recibe — el tipo de la vista que le llega a cada jugador no las admite.

Las decisiones que costaron

Un solo motor, para el servidor y para el navegador. Las reglas viven en un motor puro, sin entrada ni salida, y el mismo código corre en los dos lados. No hay dos implementaciones que puedan discrepar porque no hay dos implementaciones.

El motor no genera azar: recibe el reparto ya hecho. Parece un detalle y cambia todo. Al no tener aleatoriedad adentro, el determinismo deja de ser una promesa y pasa a ser estructural. Y habilita algo que de otra forma no se puede: medir la fuerza de un bot con un torneo reproducible, en lugar de un test que depende de la suerte del reparto.

Las fronteras no se documentan: no compilan. La configuración de TypeScript del motor excluye los tipos de DOM y de Node. Usar document o process ahí adentro no es una advertencia que alguien pueda desactivar un martes apurado: es un error de compilación. La dirección del grafo de dependencias la verifica una herramienta en cada build.

La vista de cada jugador no puede contener información oculta. No por una función que filtra bien, sino porque el tipo de esa vista no admite las cartas del rival. Mandarlas por accidente no es un error que se escape a producción: no compila.

Si alguien se desconecta, la partida sigue. Se abre una ventana de reconexión; si no vuelve, un bot ocupa su lugar. La decisión no es técnica: es acordarse de que del otro lado quedó una persona esperando que no hizo nada malo.

Resultado

Funciona el motor completo, el contrato genérico de juegos, el transporte con autenticación por tenant, el servidor, el lobby con emparejamiento y los bots. Falta el widget embebible.

La próxima incorporación es la administración de accesos: qué juegos habilita cada sitio y desde cuándo hasta cuándo, según su plan.

Y la plataforma está construida para que entren Escoba de 15 y Generala sin tocar el núcleo: el mazo español vive en su propio paquete —no adentro del truco— y el lobby deriva sus modalidades de lo que declara cada juego.