Kochess es un plugin de KOReader que añade un tablero de ajedrez a la pantalla del lector. Se instala dentro de KOReader, aparece en el menú de herramientas como «Chess Game» y abre un tablero de ocho por ocho casillas con las piezas dibujadas mediante iconos locales. No hay vista web ni recursos externos: cada casilla es un botón del entorno anfitrión.

Se puede jugar contra Stockfish o entre dos personas en el mismo dispositivo, eligiendo por separado qué color controla cada jugador. Kochess no es un producto de KOReader ni de Stockfish: se apoya en el primero como entorno y usa el segundo como motor local. El proyecto continúa un trabajo original de Baptiste Fouques y se publica bajo licencia GPL-3.0 o posterior.

Por qué existe

El problema que resuelve es pequeño y concreto: tener ajedrez dentro del lector, sin conexión, sin cuentas y sin nada que interrumpa la partida. Todo ocurre en el dispositivo: las reglas, las aperturas, los archivos PGN y el motor. Kochess no consulta ningún servicio externo.

Lo que hace interesante el proyecto son las restricciones. Una pantalla de tinta electrónica refresca despacio y tiene pocos colores, el dispositivo es pequeño, y aun así hay un motor de ajedrez real calculando jugadas mientras la interfaz sigue respondiendo. Casi todas las decisiones del código salen de ahí.

Estado

Es un prototipo en desarrollo. El último commit del repositorio es del 15 de enero de 2026, con la incorporación de números y letras en los bordes del tablero, y el historial registrado termina en esa fecha.

Qué hace hoy

Tablero y reglas

  • Mostrar un tablero de ocho por ocho con piezas blancas y negras y coordenadas en los bordes.
  • Seleccionar una pieza tocando su casilla y después la casilla de destino; la casilla seleccionada se marca oscureciendo el fondo.
  • Validar las jugadas con la biblioteca local: enroques, capturas al paso, promociones, jaque mate y posiciones de tablas.
  • Preguntar por la pieza de promoción con un diálogo de dama, torre, alfil o caballo.
  • Avisar con un diálogo cuando la partida termina en mate.
  • Reiniciar la partida desde la barra superior.

Motor

  • Lanzar Stockfish como proceso local y comunicarse con él mediante el protocolo UCI.
  • Enviar la posición y la secuencia de jugadas y aplicar la bestmove que devuelve el motor.
  • Ajustar el nivel de habilidad entre 0 y 20.
  • Mostrar la evaluación en centipeones y las posiciones de mate, traducidas a textos como ventaja ligera, clara o decisiva.
  • Elegir tiempos de reflexión aproximados de 0,3, 1,5, 3 o 5 segundos, además de un hilo y un tamaño de tabla hash fijados en el arranque.

Relojes

  • Un reloj por color, con tiempo inicial e incremento por jugada, formato de horas, minutos y segundos, y pausa o reinicio al cerrar o reiniciar la partida.

PGN, aperturas y evaluación

  • Historial de jugadas en notación algebraica estándar, desplazado para mantener visible el final.
  • Guardar la partida actual como .pgn, eligiendo carpeta y nombre; por defecto, la carpeta Games del plugin.
  • Cargar un PGN con el selector de rutas de KOReader, que reconstruye la posición y muestra su estado final.
  • Detectar la apertura comparando la secuencia de jugadas con aperturas.json y mostrar su nombre y su código ECO, escogiendo la coincidencia más larga.

Cómo está hecho

El punto de entrada es main.lua, que registra la acción en el menú de KOReader, instala los iconos del plugin y construye la pantalla de juego. A partir de ahí el trabajo se reparte entre varios archivos:

  • board.lua: dibuja el tablero, muestra las piezas y aplica las jugadas.
  • settingswidget.lua: ajustes de jugadores, nivel del motor, tiempo de reflexión y controles de tiempo.
  • timer.lua: los relojes de ambos colores.
  • uci.lua: lanza el motor y habla UCI con él.
  • utils.lua: comunicación por pipes, lectura no bloqueante y callbacks con la programación de KOReader.
  • chess.lua: reglas, movimientos legales, notación SAN, FEN, PGN, promociones, enroques, capturas al paso y estados de partida.
  • aperturas.json, engines e icons: la tabla de aperturas, el binario del motor y los iconos de piezas y casillas.

La parte que menos se parece a un plugin Lua habitual es la del motor. Kochess lo ejecuta como proceso separado, conecta sus entradas y salidas mediante pipes y las atiende con fork, execvp y poll a través de FFI, procesando respuestas como uciok, readyok, info y bestmove. Es una decisión poco común en Lua, pero encaja con el Linux que hay debajo de KOReader.

El historial registra que el binario incluido para Kobo se actualizó a Stockfish 15 en enero de 2026, y ese binario ocupa alrededor de 48 MB. El README todavía menciona Stockfish 11, así que esa referencia está desactualizada. La lógica de ajedrez procede de chess.lua, una biblioteca Lua derivada de chess.js.

El repositorio incluye una suite de pruebas Busted para esa biblioteca, con casos de perft, generación de movimientos, jaque mate, tablas, promoción, enroque y notación algebraica. Cubren la lógica del ajedrez, no el plugin completo: la interfaz, el motor, los relojes y el flujo de PGN no tienen pruebas equivalentes visibles.

Lo que me parece interesante contar

El tablero en tinta electrónica

Cada casilla es un botón de KOReader y cada pieza un icono. La selección se comunica oscureciendo el fondo de la casilla en lugar de con animaciones o colores vivos, que en esta pantalla no existen. Es un ejemplo concreto de cómo adaptar una interfaz de juego a un refresco lento y a una paleta reducida.

Una jugada completa contra Stockfish

  1. Se toca una pieza y después la casilla de destino.
  2. La biblioteca local valida y aplica la jugada.
  3. La notación SAN entra en el historial.
  4. Cambia el reloj activo.
  5. Kochess envía al motor la posición y la secuencia de movimientos.
  6. Stockfish responde con una bestmove.
  7. Kochess traduce esa jugada UCI a su representación interna y actualiza el tablero.

El recorrido sirve para ver cómo se separan reglas, presentación, reloj y motor en piezas que no se pisan entre sí.

Hablar con un proceso externo

El motor no es una función que se llama y devuelve un valor: es un proceso que se lanza, escribe cuando puede y tarda lo que tarda. La interfaz tiene que seguir respondiendo mientras tanto, y por eso utils.lua lee de los pipes sin bloquear y encola callbacks. Decisiones como el tiempo de reflexión fijo, en lugar de dejar que el motor administre el reloj de la partida, salen de esa misma arquitectura.

Dos informaciones que se parecen poco

La apertura y la evaluación aparecen juntas en pantalla, pero se obtienen de formas distintas. El nombre y el código ECO se reconocen buscando una coincidencia entre la secuencia de jugadas y una tabla local; la evaluación la calcula Stockfish para la posición actual. Una es recuperación, la otra es cálculo.

La promoción de peón

Cuando un peón alcanza la última fila, la jugada no se aplica al tocar el destino: se abre un diálogo con cuatro piezas y la decisión vuelve a la pantalla principal. Es un caso donde la interacción necesita un paso extra antes de modificar el tablero.

Código y créditos

El código está en el repositorio público de Kochess, que también incluye un vídeo de demostración. El trabajo original del que parte el proyecto es de Baptiste Fouques.