---
title: "kochess"
url: "https://www.victorfarina.com/proyectos/kochess"
author: "Víctor Fariña"
started: "2026"
updated: "2026-10-02"
---

# kochess

> Juego de ajedrez para Koreader y pensado para el Kobo

Kochess añade un tablero de ajedrez a KOReader: partidas contra Stockfish o entre dos personas, relojes, detección de aperturas y archivos PGN, todo local y sin conexión. Es un proyecto personal en fase de prototipo, escrito en Lua.

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](https://git.wickle.xyz/coffman/kochess.koplugin), que también incluye un vídeo de demostración. El trabajo original del que parte el proyecto es de Baptiste Fouques.
