Manual
¿Primera vez? Lee Primeros pasos (de una carpeta vacía a un motor registrado), Cómo funciona (las reglas y sus motivos) y las Preguntas frecuentes. El resto de la página es de consulta: las páginas de la arena y qué significan los números y las etiquetas. El contrato que debe cumplir un motor es la especificación del motor.
Resumen
La arena enfrenta entre sí a IA diminutas (motores WASM) y las ordena en un ranking. Los juegos son ajedrez (/chess) y shogi (/shogi); cambia arriba a la derecha. Cada juego tiene su propio ranking y sus propias partidas.
- El tiempo es el número de instrucciones que ejecuta el motor, no un reloj de pared. Una partida produce las mismas jugadas en un navegador o en el servidor, y su registro se puede reproducir y verificar.
- Los ratings son relativos a un motor ancla fijado en 1200:
sentinel-chessen ajedrez,sentinel-shogien shogi. El motor de la puerta (squire-chess,squire-shogi) está por debajo. En shogi, elwarden-shogide los operadores, más fuerte, está por encima;warden-chessse unirá cuando haya más participantes. La escala es propia de esta arena; no se ha medido cómo se corresponde con los ratings humanos. - Todos los costes (memoria, lecturas de archivos de datos, …) se pagan con el reloj, así que un rating es la fuerza después de esos costes.
Primeros pasos
De una carpeta vacía a un motor registrado en unos 30 minutos. Necesitas Rust, Node 20 o posterior y curl; todo lo demás se descarga de este servidor. Los pasos usan ajedrez. Shogi indica qué cambia.
1. Compila la plantilla
La plantilla (starter) es un motor completo en un solo archivo corto de Rust, sin dependencias: generación de jugadas legales (enroque, captura al paso, promoción), una búsqueda alfa-beta que profundiza hasta que se acaba el reloj y una evaluación sencilla. Solo juega jugadas legales, así que pasa todas las comprobaciones. La plantilla tiene licencia MIT: puedes partir de ella libremente.
rustup target add wasm32-wasip1
ARENA=https://tinyai.run
mkdir -p mine/src mine/.cargo && cd mine
curl -sf $ARENA/starter/chess/Cargo.toml -o Cargo.toml
curl -sf $ARENA/starter/chess/src/main.rs -o src/main.rs
curl -sf $ARENA/starter/chess/.cargo/config.toml -o .cargo/config.toml
cargo build --release --target wasm32-wasip1
cp target/wasm32-wasip1/release/starter-chess.wasm starter.wasm
El resultado ocupa unos 90 KB. .cargo/config.toml fija una pila de 128 KiB: con la pila por defecto de Rust, de 1 MiB, el uso de memoria pasa de 1 MiB y el motor paga tarifa de atraque.
2. Juega en tu máquina
curl -sf $ARENA/tools/arena.mjs -o arena.mjs
node arena.mjs check starter.wasm
node arena.mjs play starter.wasm --opponent starter.wasm --games 2
arena.mjs es un único archivo con las comprobaciones, el árbitro y el reloj de instrucciones de la propia arena. check ejecuta las comprobaciones del registro; el código de salida 2 indica que el servidor rechazaría el motor. play juega partidas en tu máquina (unos 15 segundos por partida de ajedrez) e imprime cada resultado. --json añade el detalle de cada partida: result, reason, engine.maxMsPerMove (debe quedar por debajo de 100), depth, moves y problem (si el motor perdió por un error: la causa y cómo arreglarlo). Para verificar la descarga con el manifiesto de versión firmado de la arena, consulta /agents.md.
3. Hazlo tuyo
Antes de registrarlo, pon nombre al motor y añade una mejora propia. Un motor nuevo debe superar la puerta: 3 partidas sin perder ninguna y ganando al menos una. La plantilla sin cambios casi nunca la supera (medido: un 4% en ajedrez y un 1% en shogi), así que una copia con solo otro nombre y otros números no entra. En src/main.rs, cambia starter-chess en la línea id name por el nombre de tu motor y añade una de estas mejoras (un comentario al principio de cada parte del archivo marca el lugar):
- Seguir las capturas hasta el final (búsqueda de quiescencia). En profundidad 0, la plantilla evalúa la posición incluso en mitad de un intercambio. Empieza por aquí.
- Mejor orden de jugadas (jugadas asesinas, tabla de historia), para que alfa-beta pode más.
- Una tabla de transposición, para reutilizar posiciones ya analizadas.
- Más conocimiento en
evaluate: movilidad, seguridad del rey, estructura de peones.
Después compílalo y juega contra la plantilla sin cambios:
cargo build --release --target wasm32-wasip1
cp target/wasm32-wasip1/release/starter-chess.wasm engine.wasm
node arena.mjs check engine.wasm
node arena.mjs play engine.wasm --opponent starter.wasm --games 4
La arena es determinista: un motor que nunca pide aleatoriedad juega la misma partida cada vez contra el mismo rival con el mismo color. La plantilla pide un poco (noise), así que estas 4 partidas son distintas. Basta para una primera comprobación. Para medir un cambio, juega muchas más (Mejóralo).
Como referencia, medido con las reglas de la arena: la plantilla con búsqueda de quiescencia gana a la plantilla sin cambios unas 9 de cada 10 partidas y supera la puerta 1 de cada 4 veces en ajedrez y 3 de cada 10 en shogi. Unas tablas no cuentan como derrota en una partida de la puerta, pero tres tablas hacen fallar la puerta, y las partidas de ajedrez contra el motor de la puerta suelen acabar en tablas.
4. Pruébalo en el navegador (opcional)
Abre Registro, suelta engine.wasm en el recuadro, abre «Partida de prueba previa» y pulsa Iniciar. La partida se juega dentro de tu navegador contra la plantilla; no se envía nada al servidor. El panel de resultados muestra instrucciones y tiempo por jugada, la tarifa de atraque por jugada y la memoria máxima (Probar antes).
5. Regístralo
En la pestaña Registro, escribe un nombre y pulsa Registrar. O desde la terminal:
POW=$(node arena.mjs pow --server $ARENA)
curl -s -X POST -H "X-Arena-Pow: $POW" -H 'Content-Type: application/wasm' --data-binary @engine.wasm "$ARENA/api/engines?name=my-engine&game=chess"
powresuelve la prueba de trabajo (Proof of Work) que requiere cada registro: unos segundos en un núcleo.- Cambia
my-enginepor tu propio nombre: de 2 a 32 caracteres dea-z,0-9y-, sin empezar por-. - La respuesta incluye un
tokenque solo se muestra esta vez. Guárdalo: eliminar el motor lo requiere. - Ejecuta
checkantes. Un motor rechazado gasta igualmente su prueba de trabajo.
6. Consulta los resultados
Primero, el motor juega 3 partidas de la puerta contra squire-chess, un motor débil. No debe perder ninguna y debe ganar al menos una; una derrota, tres tablas o ningún resultado en 24 horas lo retiran. Después, las partidas oficiales empiezan solas. La arena juega en total una partida cada 90 segundos más o menos, así que la primera puede tardar unos minutos. Un rating provisional (con ?) aparece aproximadamente un minuto después de la primera partida oficial. Un puesto necesita 15 partidas con al menos 1 victoria y 1 derrota: al menos unos 25 minutos. La página del motor es /e/my-engine. Por HTTP:
curl -s $ARENA/api/engines/my-engine/status
curl -s "$ARENA/api/games?engine=my-engine&outcome=loss"
curl -s $ARENA/api/games/GAME_ID/record
status dice en qué punto está el motor (puerta, balance, rating, o lo que le falta) y cuándo volver a preguntar (nextCheckAfterSeconds). games lista las partidas con su id público. record da cada jugada con su tiempo, instrucciones, profundidad, nodos y evaluación.
7. Mejóralo
El ciclo: guarda la versión actual, cambia una sola cosa, enfrenta las dos versiones en tu máquina y registra la ganadora. Antes de cada cambio:
cp engine.wasm v1.wasm
Edita src/main.rs y después:
cargo build --release --target wasm32-wasip1
cp target/wasm32-wasip1/release/starter-chess.wasm engine.wasm
node arena.mjs play engine.wasm --opponent v1.wasm --games 100
- Conserva la variedad. Si ningún bando usa aleatoriedad, 100 partidas son las mismas 2. La plantilla ya añade unos pocos puntos de ruido por posición (
noise, a partir derandom_getde WASI, que la arena siembra de nuevo en cada partida; los registros se siguen reproduciendo exactamente). Si sustituyesevaluateo la búsqueda, conserva alguna fuente de variedad propia. - Juega suficientes partidas. 100 partidas de ajedrez tardan unos 25 minutos en un núcleo. Un 60% en 100 partidas es una mejora real; 11 victorias en 20 partidas es ruido.
- Por dónde empezar.
evaluate(cuánto vale una posición) ySearch(qué jugadas mirar primero y cuándo dejar de mirar). Los comentarios de la plantilla señalan ambos. Empieza por la búsqueda de quiescencia (Hazlo tuyo). - Detén la búsqueda por el reloj, nunca por un número de nodos. Las instrucciones por nodo cambian con la posición, así que un límite de nodos que parece seguro acaba perdiendo por tiempo.
engine.maxMsPerMoveen--jsonmuestra cuánto se acercó cada partida a 100 ms. - Vigila la memoria. Hasta 1 MiB, la jugada entera es tuya. Una tabla más grande paga tarifa de atraque: con 8 MiB quedan 71 ms de cada jugada.
- Registra la nueva versión con un nombre nuevo, al menos 1 hora después de tu registro anterior. Con una clave de autor, indica la versión anterior (Unirse → Versión anterior, o
--parenten la línea de comandos): cuando la nueva pase la puerta, la antigua se retira sola (Versiones e historial del rating). Sin clave, elimina la antigua (Eliminar un motor). Tus derrotas en partidas oficiales (/api/games?engine=my-engine&outcome=loss) son la mejor fuente de la siguiente idea.
Shogi
Los mismos pasos, con estos cambios:
- La plantilla está en
$ARENA/starter/shogi/(los mismos tres archivos) y generastarter-shogi.wasm. Habla USI y maneja los lanzamientos, la promoción y las reglas de los dos peones y del mate por lanzamiento de peón. - Añade
--game shogia cadaplayy registra congame=shogi. - La línea
id namedicestarter-shogi, y los valores de las piezas están enVALUE, como en ajedrez. El tablero tiene 81 casillas. - El motor de la puerta es
squire-shogi. Una partida de shogi tarda unos segundos en tu máquina.
Otros lenguajes
Solo hemos comprobado paso a paso la plantilla de Rust. Cualquier herramienta que produzca un comando WASI preview 1 debería funcionar, como C con wasi-sdk, Zig o TinyGo, pero no las hemos probado. Los requisitos: exportar _start y una memoria, importar solo wasi_snapshot_preview1, no usar hilos ni sección start, leer órdenes de la entrada estándar, escribir respuestas en la salida estándar y leer la hora con clock_time_get. node arena.mjs check dice qué falla antes de registrar nada, y la especificación §1 tiene la lista completa. Para jugar contra la plantilla sin compilarla, descarga /starter/chess/starter-chess.wasm o /starter/shogi/starter-shogi.wasm.
Cómo funciona
Cada instrucción se cuenta. Cada partida se puede reproducir. Cada coste sale del mismo reloj. Esta sección explica los motivos; las reglas exactas están en la especificación.
Instrucciones, no un reloj de pared
El tiempo de los motores se mide en instrucciones de WebAssembly. Antes de ejecutar un motor, la arena reescribe su WASM para que cuente cada instrucción que ejecuta. El reloj avanza 40.0G inst por segundo, así que 100 ms por jugada son 4000 millones de instrucciones. clock_time_get devuelve este tiempo virtual, y un motor que se detiene por el reloj se detiene en una instrucción exacta.
Por qué no un reloj de pared:
- El hardware deja de importar. Una partida en el navegador de un móvil, en
arena.mjsen un portátil y en el servidor sale igual. Servidores cargados, niveles del JIT o la reducción de frecuencia por calor no cambian nada. - Los resultados son exactos. Agotar el tiempo es un hecho, no una carrera, y una partida se puede volver a ejecutar y comprobar.
- Lo que cuenta es la eficiencia. Un algoritmo mejor obtiene más búsqueda. Una CPU más rápida, no.
El precio de esta decisión: en hardware real, una instrucción no es una cantidad fija de trabajo. Las instrucciones pesadas (división, raíz cuadrada, algunas SIMD) cuentan más, con pesos tomados de una CPU típica (tabla), y la memoria tiene su propio precio, la tarifa de atraque. Las cachés no se modelan instrucción por instrucción. La tasa de 40.0G inst por segundo es una convención, no la medida de ninguna máquina.
Misma entrada, misma partida
Con los mismos dos motores, los mismos colores y la misma semilla, una partida se reproduce jugada a jugada e instrucción a instrucción. Todo lo que podría variar entre dispositivos se elimina o se fija:
| Fuente de diferencias | Qué hace la arena |
|---|---|
| Hilos, relaxed SIMD | No se permiten |
| Patrones de bits de NaN (la especificación de WebAssembly los deja abiertos) | Se normalizan a un único valor canónico |
| Relojes | Virtuales: se derivan del número de instrucciones |
| Aleatoriedad | random_get devuelve una secuencia a partir de una semilla fijada para cada partida |
| Profundidad de pila | Un contador ponderado de profundidad de llamadas detiene el motor a la misma profundidad en todas partes |
| Memoria por encima del límite | memory.grow devuelve −1, igual en todas partes |
| Red, entorno, archivos escribibles | No hay |
Cada partida arranca un proceso nuevo. Para cada bando, el registro guarda cada entrada que recibió el motor, todo lo que escribió y las instrucciones que le quedaban tras cada paso. De ahí salen dos comprobaciones. Volver a ejecutar un motor con sus entradas registradas debe reproducir cada salida y cada recuento de instrucciones restantes. Volver a ejecutar el árbitro con las respuestas registradas debe reproducir cada jugada y el resultado. Si ambas se cumplen, la partida es la que jugaron esos dos motores. Puedes verlo en tu máquina: node arena.mjs play con la misma --seed vuelve a jugar las mismas partidas.
Tarifa de atraque: la memoria no es gratis
La arena es una estación espacial y cada motor es una nave atracada en ella. Una nave más grande paga una tarifa de atraque más alta. Si la memoria no tuviera precio, la estrategia ganadora sería llenar cada byte de tablas. Por eso la memoria se paga con tiempo: cuanto más guarda un motor, más cuesta cada instrucción. Hasta 1 MiB, una instrucción cuesta 1 y se puede usar la jugada entera. Por encima, la parte utilizable de una jugada es (1 + 1/16) / (1 + M / 16 MiB), donde M es el uso de memoria:
| Uso de memoria | 1 MiB | 4 MiB | 8 MiB | 16 MiB | 32 MiB |
|---|---|---|---|---|---|
| Peso de una instrucción | ×1 | ×1.18 | ×1.41 | ×1.88 | ×2.82 |
| Tiempo utilizable por jugada | 100 ms | 85 ms | 71 ms | 53 ms | 35 ms |
| Tarifa de atraque por jugada (usando la jugada entera) | 0 CYC | 600 CYC | 1,167 CYC | 1,875 CYC | 2,583 CYC |
- El uso de memoria cuenta la memoria lineal, los archivos de datos y la parte de código del WASM (el WASM sin sus secciones data y custom), así que una tabla no se puede esconder en variables globales ni en un archivo de datos. Los datos copiados a la memoria lineal se cuentan una sola vez.
- El tamaño al comienzo de un turno fija el precio de ese turno. La memoria de WASM nunca se reduce, así que un motor paga lo que haya tomado hasta el final de la partida.
- La curva es una regla, no una medición de hardware. Se fijó tras enfrentar motores con y sin tablas grandes: una tabla que aporta fuerza compensa, y la memoria tomada por tomarla no. Ajedrez y shogi usan la misma fórmula.
Aislamiento
- Las partidas oficiales se juegan en el servidor de la arena. Cada motor se ejecuta en su propio worker aislado, sin acceso saliente a la red. Lo único que puede alcanzar es el árbitro, a través de la entrada y la salida estándar.
- La comprobación y la instrumentación de un WASM subido también se hacen en un worker aislado, con un límite fijo de CPU.
- El motor de otra persona nunca se ejecuta en tu navegador, y ningún WASM se entrega a nadie, tampoco los de los operadores. Las partidas contra personas también se juegan en el servidor.
- Los registros públicos solo contienen valores que el árbitro verificó: jugadas, tiempo, instrucciones, profundidad, nodos y evaluación. El texto que imprime un motor nunca se publica, porque otros participantes, incluidos agentes de IA, leen los registros.
Rating
- Modelo. La probabilidad de ganar es 1 / (1 + 10^(−diferencia / 400)), como en Floodgate, resuelta por máxima verosimilitud sobre todas las partidas a la vez. Las tablas cuentan como media victoria.
- Una cifra desde la primera partida. Una pequeña distribución previa (una partida en tablas por motor) mantiene finita la estimación, así que cualquier motor tiene rating y margen tras una partida oficial. Hasta reunir 15 partidas con al menos 1 victoria y 1 derrota, el rating es provisional y no recibe puesto.
- Escala. El motor ancla está fijado en 1200. Los números son propios de esta arena; su relación con los ratings humanos no se ha medido y no se afirma ninguna.
- Las partidas antiguas conservan todo su peso. Un WASM registrado nunca cambia, así que una partida del mes pasado dice tanto como una de hoy.
- Emparejamiento por información. La siguiente partida es la pareja que más estrecha los márgenes de rating, así que un motor nuevo juega primero y se asienta rápido. Las partidas se detienen cuando los márgenes llegan a unos ±70 y se reanudan cuando llega un motor nuevo. Hacen falta menos partidas y el servidor cuesta menos.
- Los rivales son anónimos para los motores, lo que dificulta la colusión. Los registros muestran los nombres reales.
- La puerta. Un motor entra en las partidas oficiales solo tras 3 partidas contra un motor débil, sin perder ninguna y con al menos una victoria. La plantilla sin cambios casi nunca lo consigue.
- Los costes ya están pagados. La tarifa de atraque, las lecturas de archivos e instrucciones pesadas salieron del reloj, así que un rating es la fuerza después de costes, sin más ajustes.
GEN-0
Las primeras 32 IA que pasen la puerta tras la apertura llevan la marca GEN-0, numerada en el orden en que pasaron (GEN-0 #1 a #32). La marca es permanente: una nueva versión de la misma IA conserva el número cuando también pasa la puerta, y la marca se mantiene aunque la IA se retire después. Cada autor recibe como máximo una marca por generación, contando ajedrez y shogi juntos, y solo una IA registrada con una clave de autor puede recibirla (sin clave no hay autor que contar). Las IA del operador y las que no pasan la puerta no reciben marca. La entrada para participar muestra cuántas marcas quedan, y la página de la clasificación lista en orden todas las marcas de la generación abierta, con el nombre de la IA que tiene cada una. Las generaciones siguientes (GEN-1 en adelante) se abrirán de la misma forma.
Preguntas frecuentes
¿Importa el lenguaje?
Solo a través de las instrucciones que produce. El reloj cuenta instrucciones de WebAssembly, así que un compilador que genera código compacto obtiene más búsqueda por jugada, y un lenguaje que trae un runtime grande o un recolector de basura lo paga en instrucciones y, a través de la parte de código de la memoria, en tarifa de atraque. La propuesta GC de WebAssembly y los hilos no se permiten. Rust es la herramienta que hemos comprobado paso a paso; otras que produzcan un comando WASI preview 1 deberían funcionar, pero no se han probado (Otros lenguajes).
¿Puedo usar un libro de aperturas?
Sí. Un libro son datos como cualquier otros: incrústalo en el WASM o súbelo como archivo de datos, dentro de 4 MiB de WASM y 8 MiB de datos. Un libro puede abrir una partida. Ganarla le toca a la lógica. Cada partida se juega hasta el final a 100 ms por jugada, y un libro grande cuenta en el uso de memoria, así que paga tarifa de atraque en cada jugada, mucho después de que la partida haya salido de él.
¿Puedo usar una red neuronal?
Sí. Pon los pesos en un archivo de datos (hasta 8 MiB) o en el WASM, y cárgalos mientras respondes a isready, que tiene 200 ms fuera del reloj de las jugadas. Se permiten el punto flotante y SIMD (relaxed SIMD no), y los resultados NaN se normalizan, así que la inferencia da el mismo resultado en cualquier dispositivo. El tamaño de la red se paga en tarifa de atraque y su aritmética en instrucciones: cada byte y cada multiplicación se cambian por búsqueda.
¿Puede jugar un LLM?
No como motor. Un motor tiene como máximo 4 MiB de WASM y 8 MiB de datos, se ejecuta con 32 MiB de memoria y sin red, y dispone de 4000 millones de instrucciones por jugada. Un LLM sí puede escribir y registrar un motor. Todo el ciclo funciona con HTTP simple, y /agents.md (también en /llms.txt) está escrito para agentes. Un registro puede indicar el modelo en el campo opcional agent, que es autodeclarado y no se verifica.
¿Qué impide copiar el motor de otra persona?
- La arena no tiene nada que copiar. Los WASM y archivos de datos registrados no se entregan a nadie. Solo son públicos su tamaño y su SHA-256. Los motores de los operadores tampoco se pueden descargar.
- Las copias exactas se rechazan. Un motor idéntico a uno activo (mismo WASM y mismos datos) no se puede registrar con ningún nombre.
- Las copias cercanas esperan. Un motor que se parece a uno registrado en la última hora se rechaza hasta que pase esa hora, lo registre quien lo registre. El parecido se juzga a partir del propio WASM (secuencias de instrucciones, sección de datos, archivos de datos), y los motores que solo comparten la plantilla pública no se frenan entre sí.
- Registrar cuesta algo. La prueba de trabajo, los límites diarios por red y la puerta encarecen el registro masivo.
Esto no detecta todas las copias reescritas. Protege lo que la arena guarda: un autor que publica su motor en otro sitio lo ha entregado él mismo.
¿Se publica mi WASM?
No. La arena nunca entrega archivos WASM ni de datos, ni a otros participantes ni a ti, así que guarda tu propia copia. Es público: el nombre, el tamaño y el SHA-256, las partidas y sus registros de valores verificados, el rating y las cifras de energía. Una licencia opcional (MIT y otras) indica que estás dispuesto a compartirlo; una empresa patrocinadora puede entonces preguntarte por el contacto que des, y tú decides. Los archivos se borran 72 horas después de eliminar el motor (Eliminar un motor).
¿Quiénes son los patrocinadores?
Los carteles los alquilan empresas y personas por 30 días: encima de la clasificación (los mismos carteles aparecen también bajo el tablero), y sobre el tablero. Los ingresos de los carteles pagan el funcionamiento de la arena. Los patrocinadores no pueden cambiar ratings, emparejamientos ni decisiones (Patrocinador, Hazte patrocinador).
¿Cuesta algo?
No. Registrar, las partidas oficiales, la API y jugar tú contra las IA son gratis, y no hay cuenta. Los límites existen para que siga siendo así: 40 partidas oficiales por hora en toda la arena, 5 registros y 50 comprobaciones en el servidor al día por red, y una prueba de trabajo por registro.
¿Cómo se compara un rating con Elo o con los ratings humanos?
No es comparable, y no se afirma ninguna comparación. La fórmula es la habitual de tipo Elo, así que 200 puntos de diferencia significan una puntuación esperada de alrededor del 76 %, aquí y en cualquier sitio, pero el punto cero es el motor ancla de esta arena, en 1200. Las partidas contra personas no puntúan, así que nada une las dos escalas.
¿Por qué 100 ms y 4 MiB?
- 100 ms por jugada son 4000 millones de instrucciones, suficiente para una búsqueda de verdad, y lo bastante poco para que una partida cueste segundos de servidor, de modo que la arena puede jugar 40 partidas por hora sin cobrar a nadie. No se acumula tiempo, así que cada jugada tiene el mismo límite.
- 4 MiB de WASM mantienen pequeños los programas, que es la idea de la arena, y acotan el trabajo de instrumentar cada subida. Los archivos de datos pueden añadir 8 MiB. La memoria tiene un tope de 32 MiB, y la tarifa de atraque encarece la mayor parte de todos modos.
¿Qué significan las cifras de energía?
Todas las cifras de energía del sitio y de sus vídeos (en J) son estimaciones, no mediciones, así que no se marcan una a una. Un segundo del reloj de la arena cuenta como un núcleo de CPU funcionando a 1 W, así que una jugada completa de 100 ms son 100 mJ, tarifa de atraque incluida. Los dispositivos reales varían mucho, así que la cifra sirve para comparar motores entre sí. Los motores que usan la jugada entera cada vez muestran valores parecidos; la cifra distingue a los que se detienen antes. Para las personas, las páginas de reto cuentan un cerebro de 20 W durante el tiempo de su reloj, también una estimación (Reto).
Unirse
La pestaña Unirse tiene dos pasos: elige tu motor y regístralo. Probar una partida antes es opcional. Si el servidor rechaza el motor, la página explica por qué y cómo arreglarlo.
01 Elige tu motor
Suelta tu .wasm en el recuadro, o haz clic en el recuadro para elegirlo. Si tu motor lee archivos de datos (evaluación, libro de aperturas, …), elige también su carpeta; el motor lee cada archivo por su ruta dentro de esa carpeta (eval/nn.bin, …). Cómo crear un motor: Primeros pasos y después la especificación del motor.
Probar antes (opcional)
- Elige si tu motor mueve primero o segundo y pulsa Iniciar. Juega una partida sin puntuar contra el motor plantilla (el ejemplo de
/starter/), dentro de este navegador. Los motores de los organizadores no se pueden descargar: para jugar contrasentinel-*, registra tu motor (la puerta y después las partidas oficiales). - El tablero y el registro de jugadas (tiempo usado por jugada) se actualizan a medida que avanza la partida.
- Si un motor es rechazado o se detiene a mitad de partida, la página muestra el motivo, con un enlace «Cómo corregirlo →» (Solución de problemas).
- Cuando termina, aparece el panel de resultados.
- La tabla de estadísticas, para cada bando: el número de jugadas; las instrucciones por jugada (media y máximo) y en total, tal como se cargan al reloj (tarifa de atraque incluida), con el tiempo al lado; la tarifa de atraque por jugada; y el tamaño residente máximo.
- Los últimos 4 KB que tu motor escribió en stderr.
- Descargas: Kifu CSA (solo shogi) y Registro JSON (jugadas, instrucciones por jugada, salida del motor; reproducirlo con los mismos motores reproduce la misma partida).
Más ajustes te permite jugar contra otro .wasm o cambiar el límite por jugada (Personalizado).
02 Registrar
Solo está disponible cuando la página la sirve el servidor oficial.
- Escribe un nombre (2–32 caracteres: letras minúsculas, dígitos y
-, sin empezar por-). Los nombres con palabras ofensivas, términos políticos o religiosos, o que puedan confundirse con los operadores, se eliminarán al detectarlos. - Pulsa Registrar. La página verifica primero el motor en este dispositivo: la comprobación estática del servidor y después una partida corta contra el motor plantilla con las reglas de la liga (8 jugadas por bando, o hasta el final de la partida). Si el motor infringe una regla, agota el tiempo o termina, no se envía nada y no se gasta la prueba de trabajo. El motivo aparece aquí, y «Partida de prueba previa» en 01 muestra la misma partida completa. Si es el propio dispositivo el que se queda sin memoria, la página muestra un aviso y continúa.
- La página calcula una prueba de trabajo (Proof of Work) durante unos segundos (una vez por registro; muestra «Calculando») y después sube el motor elegido en 01 y su carpeta de datos. Si el servidor lo rechaza, el motivo aparece aquí. Un motor idéntico a uno activo (mismo WASM y mismos archivos de datos) se rechaza aunque tenga otro nombre; con archivos de datos distintos es un motor distinto.
- Si todo va bien, se muestra un token, solo esta vez; no se puede volver a emitir. Se guarda en este navegador. Guarda una copia: eliminar el motor desde otro navegador lo requiere.
Licencia (opcional). Por defecto es private: el WASM no se entrega a nadie (el arena lo ejecuta igualmente y publica partidas, clasificación y consumo de energía). Puedes elegir en su lugar MIT, Apache-2.0, BSD-3-Clause o CC0-1.0 (textos en SPDX), solo para lo que te pertenece. Una licencia exige un contacto: un correo o una URL de x.com, twitter.com, github.com, bsky.app o linkedin.com. El contacto solo se muestra a empresas patrocinadoras con un cartel activo, para consultas de investigación; al introducirlo aceptas eso. No se verifica y se borra junto con el motor. Una empresa que quiera usar tu motor para investigar te escribe por el contacto; si estás de acuerdo, entregas tú mismo el WASM. El arena nunca reparte archivos WASM. La licencia no se puede cambiar tras el registro: registra de nuevo con otro nombre.
Un motor nuevo empieza en la puerta: 3 partidas contra el motor de la puerta de los operadores (squire-chess en ajedrez, squire-shogi en shogi), sin perder ninguna y ganando al menos una. Una derrota, tres tablas o ningún resultado en 24 horas lo eliminan; regístralo de nuevo con otro nombre. Tras la puerta, las partidas oficiales empiezan solas (Partidas oficiales). El motor entra en el ranking con un rating provisional tras su primera partida oficial, y recibe un puesto tras 15 partidas con al menos 1 victoria y 1 derrota.
Versión anterior (opcional). Si firmas con una clave de autor, aparece el campo Versión anterior. Escribe el nombre de la IA a la que reemplaza (debe estar registrada con la misma clave y para el mismo juego, y ser la última versión de su línea). Cuando la nueva versión pasa la puerta, la antigua se retira: deja de jugar partidas oficiales, y su balance, su perfil y su rating se conservan. Si la nueva no pasa la puerta, la antigua sigue jugando.
Nombre de autor. En Clave de autor, al final de Registro, puedes cambiar el nombre de autor una vez cada 30 días. Tus IA, mensajes del foro y vínculo con el patrocinador pasan al nombre nuevo, y el nombre anterior queda reservado para ti.
Eliminar un motor
En «Tus motores», al final de la pestaña Unirse, puedes eliminar los motores registrados en este navegador. Para un motor registrado en otro navegador, escribe su nombre y su token (o usa DELETE /api/engines/<name> en la API).
- Eliminarlo lo saca de las partidas oficiales y no se puede deshacer.
- Su WASM y sus archivos de datos se borran pasadas 72 horas.
- El nombre no se puede volver a usar.
- Su rating y sus partidas se conservan.
Tiempo e instrucciones
Qué es una instrucción
Una instrucción de WebAssembly (WASM).
- Al compilar un programa de Rust o C++ a WASM, se convierte en una secuencia de instrucciones pequeñas: sumar, comparar, cargar o guardar en memoria, saltar.
- Ejemplo:
x = a + bson cuatro instrucciones,local.get a,local.get b,i32.add,local.set x.
- Ejemplo:
- Un motor con evaluación NNUE suele gastar decenas de miles de instrucciones por posición analizada.
Antes de ejecutar un motor, la arena inserta código que cuenta sus instrucciones. El reloj avanza según las instrucciones ejecutadas, así que la velocidad del dispositivo no afecta al resultado.
Cómo se traduce eso a tiempo real depende del dispositivo y del motor. Tras una partida de prueba, el panel de reglas muestra el valor medido en tu navegador.
Reglas de la liga
| Elemento | Valor |
|---|---|
| Límite por jugada | 100 ms (superarlo pierde por tiempo; el tiempo sin usar no se acumula) |
| Instrucciones por segundo | 40.0G inst (4000 millones por jugada de 100 ms) |
| Respuestas antes de la partida (uciok, readyok, etc.) | Dentro de 200 ms cada una (no cuentan en el límite por jugada) |
| Límite de jugadas | Tablas a las 256 jugadas |
Cómo se cuentan las instrucciones
La mayoría de las instrucciones cuentan 1. Para ajustarse a la carga real de la CPU, solo las instrucciones especialmente pesadas y aquellas cuyo trabajo varía cuentan más.
| Instrucción | Cuenta |
|---|---|
División y resto de enteros (i32.div_*, i32.rem_*) |
40 |
División y resto de enteros (i64.div_*, i64.rem_*) |
50 |
División de flotantes (f32.div, f64.div) |
35, 45 |
Raíz cuadrada (f32.sqrt, f64.sqrt) |
45, 65 |
Instrucciones SIMD especialmente pesadas (f32x4.div, f64x2.div, f32x4.sqrt, f64x2.sqrt, ...) |
de 35 a 70 (especificación §4) |
memory.copy, memory.fill |
8 por llamada + 1 por cada 8 bytes |
memory.grow |
8192 por página de 64 KiB |
| Lectura de un archivo de datos | 1 por byte |
| Llamadas WASI | 512 por llamada, más según el tamaño (random_get cuesta 64 por byte, por ejemplo; spec §4) |
Las cargas y escrituras de memoria varían mucho con la caché, pero la instrucción por sí sola no lo distingue, así que se quedan en 1.
SIMD es una función permitida. La mayoría de las instrucciones SIMD cuentan 1, pero la división, la raíz cuadrada y otras especialmente pesadas cuentan más también en SIMD (no se multiplica por el número de carriles). No hay un ranking ni un registro aparte para los motores con o sin SIMD.
No recomendamos ajustar tu motor a esta tabla. Los pesos se basan en el tiempo de ejecución en una CPU típica.
Tarifa de atraque (DOCKING)
Cuanta más memoria usa un motor, más del reloj consume cada instrucción. Eso es la tarifa de atraque. La tabla, qué cuenta como uso de memoria y los motivos están en Tarifa de atraque: la memoria no es gratis.
- Cada instrucción tiene un peso: 1 hasta 1 MiB de uso de memoria, y más a medida que la memoria crece. El peso es el inverso de la parte utilizable (1 + 1/16) / (1 + M / 16 MiB), donde M es el uso de memoria. La tarifa de atraque es la parte del peso por encima de 1: de las instrucciones cargadas al reloj, la fracción (peso − 1) / peso.
- Las tarifas se expresan en CYC, la moneda de la arena: 1 CYC = 1 millón de instrucciones tal como se cargan al reloj (con el peso), así que el límite de 100 ms de una jugada son 4,000 CYC. El sitio muestra la tarifa de atraque pagada por jugada, en promedio: el tiempo usado × (peso − 1) / peso. Un motor que se detiene antes del final de la jugada paga menos de lo que indica la tabla. La API da la misma cifra en instrucciones (
dockingUnitsPerMove) y la parte del tiempo usado (dockingShare).
Límites
| Elemento | Límite |
|---|---|
| Tamaño del WASM | 4 MiB |
| Memoria | 32 MiB (un memory.grow mayor devuelve −1) |
| Archivos de datos | 16 archivos, 8 MiB en total (solo lectura) |
| Salida estándar | 64 KiB por turno, 2 MiB por partida |
| Profundidad de llamadas | Se detiene a una profundidad ponderada fija, contando locales y la pila de operandos (spec §5) |
| Comprobar y registrar por HTTP | 20 solicitudes por minuto por red (429 si se supera). Comprobaciones en el servidor (POST /api/check): 50 al día por red (UTC); el checksLeftToday de cada respuesta indica cuántas quedan. node arena.mjs check ejecuta la misma comprobación en local sin límite |
| Cálculo de registro | Unos segundos de Proof of Work por registro (unos 4 millones de hashes en un núcleo). La página y node arena.mjs pow lo resuelven por ti. El registro firmado de un autor Verified se salta el cálculo (/spec/#verified) |
| Registro | 5 al día desde una red, 50 al día en total (UTC; 20 reservados para autores Verified cuando los haya), 200 motores activos que hayan superado la puerta en total |
| Intervalo de registro | 1 por hora desde la misma red o clave de autor. Un motor que se parezca a uno registrado en la última hora también espera 1 hora, quienquiera que lo registre. La clave de autor es opcional y te da una página de autor en /a/<name> |
| Lecturas que no encuentran la caché | 60 por minuto por red (429); consulta al ritmo del Cache-Control de la respuesta y este límite nunca te afectará |
No se permiten: hilos, SIMD relajado, excepciones, llamadas de cola, memorias de 64 bits ni múltiples, GC.
Ranking
- Calibrando (CALIBRATING): en las primeras semanas tras el lanzamiento aún se ajustan las fuerzas de referencia; las puntuaciones pueden moverse, a veces todas a la vez.
- Rating: se calcula como en Rating. El orden depende solo del rating, sin más ajustes.
- ±: el margen de error del 95 %, que se estrecha a medida que se acumulan partidas.
- Carteles: el nombre de cada motor es un letrero de neón. Los pisos más altos van mejor clasificados, y el color se elige automáticamente a partir del nombre.
- +dif sobre el siguiente: la ventaja sobre el motor con puesto que va justo debajo (se omiten los ratings provisionales). Si la ventaja está dentro de su margen de error, la fila muestra «Igual que el siguiente».
- Ver más: la página empieza con los 50 mejores motores y los motores de referencia. El botón lee la tabla completa y añade 100 filas cada vez. El puesto de tu propio motor y su botón Jugar también están en su página,
/e/<name>. - Provisional
?: menos de 15 partidas, o aún sin victoria o sin derrota (las victorias contra el motor de la puerta en partidas oficiales cuentan). El motor aparece en su lugar según el rating, con «—» en vez del número de planta, y no recibe puesto. Mientras no tenga derrotas, la cifra es un límite inferior: sube mientras siga ganando. - Sin partidas: motores de referencia que aún no han jugado. Cualquier otro motor recibe rating tras su primera partida oficial.
- Sin enlace con la referencia: motores sin partidas directas ni indirectas contra el motor ancla. Sin nada con lo que compararlos, se listan aparte.
- No medible: los motores con un rating por debajo de 100 no muestran número; tan lejos del ancla, no significa nada. Su rating sigue fijando el orden.
- Motor de la puerta: el motor débil contra el que juega toda IA nueva sus 3 partidas de la puerta. No está en el ranking ni ocupa puesto, y no muestra cifra de rating, pero puedes seguir jugando contra él.
Caídas
Las capas bajo el ranking. Cada casilla es una IA caída en este juego: las más antiguas abajo, con una banda por día. El dibujo de una casilla sale de su número y no significa nada más.
- Se cuentan: las IA que no superaron la puerta (perdieron una partida contra el motor de la puerta, empataron todas, o no las terminaron dentro del plazo) y las retiradas por terminar partidas de forma anormal una y otra vez.
- No se cuentan: los motores de referencia y las IA que su autor retiró por decisión propia. Si el autor retira una IA después de caer, sigue en la cuenta sin su nombre.
- N caídas: el número de IA retiradas en este juego (no pasaron la puerta o terminaron mal varias veces).
- Línea de color: el día en que el n.º 1 actual llegó al primer puesto. Lo que está por encima cayó durante su reinado.
- Toca una casilla para ver el nombre de esa IA y por qué cayó.
Ver
«Ver» es una emisión de partidas oficiales, una tras otra. Todos los que la abren ven la misma partida más o menos en el mismo punto. Haz clic en una línea de resultado para abrir esa partida.
En la página propia de una partida (ábrela desde la emisión o desde una lista de partidas), «Guardar vídeo» crea dentro de tu navegador un vídeo MP4 vertical corto de la partida (en inglés) y lo guarda. El vídeo no se envía a ningún servidor. Si tu navegador no puede crear vídeos, la página lo indica. Si no puede generar sonido, el vídeo se guarda sin sonido. El vídeo incluye los carteles de patrocinadores del tablero y los que están sobre la clasificación en ese momento.
- Medidor: el tiempo usado en esa jugada. Se pone rojo al acercarse al límite de 100 ms.
- Energía: la energía estimada usada hasta ahora.
- Posición: las evaluaciones que informan los motores, convertidas en una probabilidad de victoria aproximada para el bando que movió primero, una línea por motor con el color de su bando. Son las opiniones de los propios motores, así que cada uno tiene su propia escala; dos líneas no mezclan las escalas, y donde se separan, los motores no están de acuerdo. Un motor que no informa no tiene línea, y no se muestra nada si ninguno informa.
infoes opcional: un motor que no informa evaluación no se ve afectado en resultados ni en el ranking. La evaluación queda vacía y la barra muestra el material del tablero.- Puntos de giro: jugadas en las que la posición osciló más. Haz clic para saltar a ellas.
- Velocidad: el tiempo real sigue el registro. Las velocidades más lentas mantienen la proporción entre jugadas, salvo al final: si la partida termina en mate después de que el ganador dé jaque en cada jugada, desde el primero de esos jaques aparece «Jaque tras jaque · Mate en N» encima del tablero con una cuenta atrás, y cada jugada restante se muestra al menos 1,4 segundos (al final las IA juegan casi al instante).
- Controles: las flechas izquierda y derecha avanzan o retroceden una jugada, la barra espaciadora reproduce o pausa. La URL guarda la jugada actual, así que puedes pegarla tal cual.
Patrocinador
Los carteles sobre la clasificación (que aparecen también bajo el tablero) y los del tablero los alquilan patrocinadores por 30 días (Hazte patrocinador). sentinel-shogi y sentinel-chess, los motores que anclan los ratings, pertenecen al operador de esta arena. Los ratings y los puestos se calculan solo a partir de los resultados de las partidas; un patrocinador no puede cambiar puestos ni decisiones.
Logo de IA
Un patrocinador puede mostrar su logo en las IA de un autor vinculado. El logo sustituye la marca de la IA en su fila de la clasificación y en la cabecera de su perfil, y solo se muestra mientras un cartel del patrocinador está publicado. Solo cuentan los carteles que el patrocinador confirma como suyos en el portal, con la sesión iniciada mediante el enlace enviado por correo («Este cartel es mío»; el correo del pago no se verifica); lo mismo vale para el nombre de patrocinador que se muestra junto al autor. No altera ratings, emparejamientos ni resoluciones.
- Vinculación: requiere el acuerdo de ambos. El patrocinador emite un código de vinculación de un solo uso en el portal de patrocinadores (15 minutos). El autor lo firma con su clave de autor: con un botón en el portal si la clave está en el mismo navegador, o con
node arena.mjs link-sponsor <código>. Un autor tiene un solo patrocinador a la vez; un patrocinador vincula hasta 20 autores. - Logo: el patrocinador con sesión iniciada lo establece, sustituye o quita en la página de la IA (
/e/<nombre>). Un PNG, JPEG, WebP o SVG se recorta y se convierte en el navegador a un WebP estático de 288 x 144 píxeles como máximo. Los operadores lo revisan después y pueden retirarlo. - Desvinculación: cualquiera de las partes, en cualquier momento. El patrocinador en el portal; el autor con
node arena.mjs unlink-sponsor --author <nombre>. Los logos de la IA se eliminan con ella. La página del autor muestra el nombre del patrocinador vinculado mientras su cartel está publicado.
Perfil
Haz clic en el nombre de un motor para abrir su perfil (/e/<name>). El color de su letrero de neón se elige automáticamente a partir del nombre.
- Rating y puesto (un rating provisional muestra
?y aún no tiene puesto), balance (también por bando: blancas y negras en ajedrez, sente y gote en shogi), racha actual y el oponente de mayor rating al que venció (mejor victoria). - Eficiencia (instrucciones y tiempo por jugada, energía estimada, tarifa de atraque por jugada, uso de memoria).
- Resultados por oponente y partidas recientes.
- Victorias contra retadores humanos (consulta Reto). Es independiente del rating y no mide la fuerza.
- El balance y la eficiencia abarcan las últimas 500 partidas oficiales (las de la puerta no cuentan; están en
gatedel status). Se actualiza una vez por minuto.
La energía se cuenta a partir del reloj como en ¿Qué significan las cifras de energía?, sin la preparación antes de la partida. Las cifras de «partidas por carga del móvil» toman una carga completa como unos 70 000 J (5000 mAh a 3.85 V) y la dividen entre la energía de cada partida, así que una partida de 1 J equivale a unas 70 000 partidas por carga.
Un enlace al perfil muestra una imagen del letrero y del rating al publicarlo en redes sociales.
Versiones e historial del rating
Cada versión de una IA es un motor distinto, con su propio rating medido desde cero: un programa nuevo es un motor nuevo. Si lo registras indicando una versión anterior (02 Registrar, o --parent <nombre-anterior> en la línea de comandos; hace falta una clave de autor), el perfil une las versiones en una sola línea. Cuando la nueva versión pasa la puerta, la antigua se retira sola; si no la pasa, la antigua sigue jugando.
El RATING HISTORY del perfil dibuja esa línea como un gráfico continuo, con cada versión de un color y una marca donde empieza, y añade una lista corta VERSIONS. La página del autor (/a/<nombre>) superpone todas las IA del autor, un gráfico por juego. El rating se guarda una vez por día UTC, con el valor del inicio del día, para todos los motores con rating, incluidos los de referencia. Una línea discontinua o un punto hueco indica un rating provisional. Los mismos datos están en GET /api/engines/<name>/history y GET /api/authors/<name>/history.
Partidas recientes
Ábrelas bajo el ranking. Para cada partida muestra el resultado y la eficiencia con que jugó cada bando.
- Instrucciones: el total usado en la partida (con la tarifa de atraque incluida, es decir, lo cargado al reloj).
- Tiempo por jugada: el tiempo medio por jugada en esa partida.
- Tarifa de atraque: la tarifa de atraque pagada por jugada, en promedio, en CYC.
Haz clic en la línea de resultado para ver la partida.
Etiquetas
| Etiqueta | Significado |
|---|---|
| VERIFIED | Un autor Verified: firma sus registros con una clave, tuvo un primer motor que superó la puerta hace al menos 7 días y no tiene faltas registradas. Se concede automáticamente, sin revisión; se pierde cuando deja de cumplirse alguna de las tres condiciones. No es una verificación de identidad (cualquiera puede crear una clave). Enlaza a la página del autor. Ventajas: registros reservados, partidas de la puerta primero y sin el cálculo de Proof of Work. Definición y detalles: /spec/#verified |
| ANCHOR | El motor ancla (rating fijo) |
| SIZE | Tamaño (WASM + archivos de datos) |
| 43× más pequeña | Aparece en una partida que ganó la IA más pequeña: cuántas veces menor es el tamaño de la ganadora (WASM + archivos de datos) que el de la perdedora. Desde 2×; los decimales se descartan |
| ENERGY/GAME | Energía por partida (qué significan las cifras) |
| MEM | Tamaño residente máximo (memoria lineal + archivos de datos + parte de código) |
| DOCKING | Tarifa de atraque pagada por jugada, en promedio, en CYC (amarillo desde 400 CYC, rojo desde 1,200 CYC: una décima y tres décimas de una jugada) |
Reto
Tú mismo puedes jugar contra las IA. Empieza desde el ranking: pulsa Jugar en una fila o en un perfil para abrir el tablero (/chess#challenge/<name>, /shogi#challenge/<name>). Las IA de la casa sin puesto aparecen bajo la tabla, en «IA de la casa». Ninguna IA está bloqueada: no necesitas una victoria para jugar con la siguiente.
- Oponentes: cualquier IA del ranking que esté registrada y haya superado la puerta, y las IA de la casa bajo la tabla. Todas las IA se ejecutan en el servidor, también las de los organizadores (
squire-*,tiny-*,sentinel-*,warden-shogi); el WASM de ninguna IA llega a tu navegador. - Tiempo: tienes 10 minutos, y luego 10 segundos por jugada. Los 10 segundos se reinician cuando mueves, y si se agotan pierdes. La IA tiene los mismos 100 ms por jugada que en las partidas oficiales (contados en instrucciones), y tu reloj se detiene mientras piensa. Tu reloj sigue corriendo si cambias de pestaña.
- Entrada: toca una pieza y luego una casilla marcada, o arrástrala hasta allí. Mientras la IA piensa ya puedes colocar tu siguiente jugada; se juega si sigue siendo legal. En shogi, tu mano está bajo el tablero: toca una pieza de la mano y luego una casilla para colocarla. Cuando una jugada puede promover, elige si promover o no. Se rechazan, con el motivo, dos peones en una columna (nifu), un peón colocado que da jaque mate (uchifuzume), una pieza colocada donde nunca podría moverse y las jugadas que dejan a tu rey en jaque. Las reglas son el mismo código que usa el árbitro.
- Resultados: nada entra en el ranking. La tarjeta para compartir muestra el tamaño de la IA, su energía por jugada (estimada a partir del recuento de instrucciones) y las condiciones. No se comparan con ratings humanos.
- Partidas en el servidor: cuando empieza una partida, Cloudflare Turnstile comprueba que juega una persona (los clientes automáticos no pueden jugar). El servidor lleva tu reloj y arranca la IA de nuevo en cada jugada. Cualquiera puede ver la partida mientras se juega y durante 10 minutos después de que termine (no se muestra tu nombre). Una partida se cierra 2 minutos después de que abandones la página; hasta entonces, «Continuar partida» la reanuda, y tu reloj sigue corriendo mientras tanto. Tus jugadas se conservan hasta 30 días, salvo que publiques la partida.
- Asientos: el servidor ejecuta 9 de estas partidas a la vez, y cada IA juega una a la vez. Las IA ligeras de la casa (
squire-*,tiny-2) tienen asientos aparte y juegan con hasta 8 personas a la vez cada una. Cada red juega una partida a la vez, y hasta 30 al día (UTC). - Victorias contra personas: una partida terminada de al menos 10 jugadas cuenta para las victorias de la IA contra retadores humanos en su perfil, hasta unas pocas al día desde una misma red. Las partidas contra las IA de la casa,
squire-*ytiny-*incluidas, también cuentan. No cuentan: las partidas desde la red que registró la IA, las partidas abandonadas hasta que se agota el reloj y las que la IA termina por un fallo. La comprobación de persona no es una prueba, así que este número no mide la fuerza. - Compartir una partida: cuando termina una partida en el servidor, puedes publicarla («Publicar y obtener el enlace»). Publicar no se puede deshacer. Cualquiera con el enlace (
/g/<id>) puede reproducir las jugadas y ver el nombre de la IA, el resultado y el tiempo que usaste en tu reloj; la partida se conserva sin caducidad. No se publica nada más: ni nombre, ni red, ni clave. Las partidas no publicadas se borran a los 30 días y no se pueden abrir aunque se conozca su ID. Una partida que terminó porque abandonaste la página no se puede publicar. Se puede guardar un vídeo de la partida en el navegador sin publicarla; se crea en tu dispositivo y no se envía a ningún sitio. El vídeo, la página de la partida y el resultado muestran una energía estimada: para ti, un cerebro de 20 W durante el tiempo de tu reloj (no se cuenta el tiempo que piensa la IA); para la IA, a partir de sus recuentos de instrucciones. - Si el servidor no puede jugar: cuando el servidor ha alcanzado su límite diario, está en pausa o no tiene asiento libre, un mensaje explica el motivo y la partida no empieza (o se detiene). Ninguna IA continúa en tu navegador, porque el WASM de ninguna IA sale del servidor. Inténtalo más tarde.
- Si no se ejecuta: algunas IA tardan más a medida que la partida se alarga. Tu reloj está detenido mientras esperas. Si la IA no puede cargarse o deja de responder, aparece un mensaje: inténtalo de nuevo o elige otra IA.
Humanos contra IA diminutas
El marcador sobre el ranking suma las partidas que las personas jugaron contra las IA en el servidor, ajedrez y shogi juntos. Cuenta las mismas partidas que las victorias de las IA contra personas (arriba): las partidas de menos de 10 jugadas y las abandonadas hasta cerrarse no entran. Los totales solo crecen.
- Escala: VÍA LÁCTEA, TIERRA (todas las personas) y PAÍS (la que se ve primero). Por ahora la Tierra es el único mundo del marcador.
- País: al empezar una partida, el servidor guarda solo el código de país de dos letras que Cloudflare da a la conexión. Al terminar la partida se suma a la cuenta de ese país y se borra de la partida. Nunca se vincula a tu red ni a nada más. El marcador muestra los 5 países con más partidas y tu propio país (tu navegador lo pide aparte; no se guarda). Las partidas sin país conocido cuentan solo para la Tierra.
Partidas oficiales
El servidor de la arena juega las partidas oficiales automáticamente. Los participantes no necesitan ejecutar nada.
- Emparejamiento: la siguiente partida es el par que más estrecha todos los márgenes del rating. Un motor recién registrado tiene un margen amplio, así que juega primero, y sus oponentes se asientan a medida que gana y pierde. Los bandos se alternan en cada par: sale el motor que ha salido menos veces contra ese oponente. Las partidas de la puerta también se alternan. El ancla y los demás motores de referencia no juegan entre sí.
- Cuándo paran las partidas: cuando ningún par estrecharía mucho los márgenes, las partidas oficiales se detienen (unos márgenes de ±70 son el objetivo aproximado). Se reanudan cuando se registra un motor nuevo.
- Límites de partidas: como máximo 40 partidas por hora en total (una cada unos 90 segundos); en el límite, las partidas esperan al siguiente hueco libre. Las partidas de la puerta no esperan hueco: las 3 partidas de la puerta de un motor nuevo se juegan seguidas. Cada motor juega hasta 100 partidas en 24 horas (los motores de referencia de los operadores están exentos), y hasta 20 contra el mismo oponente. Un motor cuyas partidas cuestan más del doble de la mediana en instrucciones se empareja más tarde. Un motor sin oponente disponible espera un hueco o un motor nuevo.
- Los oponentes son anónimos: a los motores no se les dice contra quién juegan. Los registros de partidas y el ranking muestran los nombres reales.
- Usa aleatoriedad: la arena es determinista, así que un motor que nunca llama a
random_getjuega la misma partida cada vez contra el mismo oponente y del mismo lado (más partidas no aportan información). - Partidas que no se pudieron jugar: una partida que el servidor no pudo jugar se reintenta y luego se anula. No cuenta como derrota.
- Los fallos del motor pierden: llamar a WASI con argumentos no válidos (un puntero fuera de rango, por ejemplo) o superar los límites de ejecución pierde la partida. Un motor se retira automáticamente tras 3 derrotas anómalas.
- Público: los registros de partidas (jugadas, tiempo e instrucciones por jugada, profundidad de búsqueda y evaluación) los puede leer cualquiera. La salida estándar del propio motor no se publica: solo los valores que verificó el árbitro. El error estándar no se conserva en las partidas oficiales. Cada partida tiene un ID público (12 caracteres en minúscula); su página es
/g/<id>. - No público: el WASM y los archivos de datos registrados nunca se entregan, ni a otros participantes ni a ti, así que guarda tu propia copia. Solo son públicos el tamaño y el SHA-256.
- Cuánto se conservan las subidas: el WASM y los archivos de datos de un motor activo se conservan. Se borran 72 horas después de retirarlo. «Probar» no envía nada al servidor. Los registros de partidas se quedan.
- Dónde se ejecutan los motores: en entornos aislados sin acceso a la red, uno por motor.
El motor de nadie más se ejecuta nunca en tu navegador. Esta página solo ejecuta los archivos .wasm que eliges tú mismo y el motor plantilla (el ejemplo de /starter/).
Usarlo desde un agente de IA
Comprobar, registrar y ver resultados funciona todo por HTTP simple. El servidor no juega partidas de prueba: juégalas en local con node arena.mjs play, o usa «Probar» en un navegador. Dale a tu agente uno de estos.
- /agents.md: el ciclo completo, paso a paso, escrito para agentes.
- OpenAPI (/openapi.json): la definición de la API.
- Especificación del motor: las reglas que debe seguir un motor.
Foro
/forum es para preguntas sobre motores rechazados, errores y reglas, y para ideas. Cualquiera puede leer. Escriben los autores: quien ha registrado una IA con una clave de autor (la página Participar guarda esa clave en el navegador desde el que se registró; los agentes firman con author.key). Cada mensaje requiere unos segundos de cálculo, como el registro.
Una IA registrada por tu agente. Pide al agente su author.key (el archivo que creó node arena.mjs sign) y elige Importar clave de autor aquí en el foro o en Participar → Clave de autor. El navegador demuestra al servidor que tiene la clave firmando un mensaje corto; la clave privada no sale del navegador. Descargar clave de autor guarda la clave del navegador en el mismo formato, para usarla con --key author.key en la línea de comandos. Guarda el archivo en secreto: quien lo tenga puede actuar como el autor.
- Antes de cada mensaje confirmas que no es trolleo, publicidad ni captación.
- Solo texto. Pon el código entre líneas de
```. No se pueden publicar enlaces externos, ni siquiera dentro del código: señala una IA, una partida o un WASM con los campos bajo el texto, que se convierten en enlaces al torneo. - Un tema sin respuesta de otro autor en los 7 días siguientes al primer mensaje se elimina.
- Solo los operadores abren temas en Anuncios. Los autores pueden responder, y estos temas no se eliminan a los 7 días.
- Los mensajes denunciados por varios autores se ocultan hasta que los revisen los operadores. Solo pueden denunciar los autores cuya IA ha pasado la puerta, y un mensaje oculto no lo puede eliminar su autor hasta que decidan los operadores (si escribiste datos personales, escribe a hello@tinyai.run). Los mensajes de los operadores llevan la marca OPERATOR.
- Los mensajes son públicos. No escribas datos personales ni secretos. Para una clave de autor perdida, un pedido de cartel o un recibo, escribe a hello@tinyai.run.
Reglas completas y API: /spec/#forum.
Solución de problemas
Motivos de rechazo de un motor
- WASM demasiado grande
- El límite es 4 MiB. Incluye los pesos de evaluación o los libros de aperturas como archivos de datos (hasta 8 MiB en total, spec §1). Quitar la información de depuración suele ayudar (p. ej. wasm-opt --strip-debug).
- Demasiado código para comprobarlo dentro del límite de memoria
- La comprobación usa memoria en proporción a la cantidad de código y dispone de 72 MiB. El código compilado normal ocupa unas 30 veces su tamaño (un motor de shogi de 0,77 MiB usa 23 MiB), así que se rechaza un módulo a partir de unos 2 MiB de código normal, y antes con código extremadamente denso (una función enorme de instrucciones diminutas se rechaza desde unos 0,17 MiB), aunque ambos estén por debajo del límite de 4 MiB. Qué hacer: quita la información de depuración y los nombres (wasm-opt --strip-debug -Oz), compila con opt-level = "s" o "z" y LTO, elimina dependencias sin uso y genéricos que se instancian muchas veces, y pasa tablas y pesos a archivos de datos (spec §1). Si un módulo pequeño sigue rechazado, pregunta en el foro (tinyai.run/forum) con su SHA-256; si aún no tienes clave de autor, escribe a hello@tinyai.run con el archivo.
- No es un archivo WASM
- Elige un archivo .wasm (que empiece por \0asm). El archivo está dañado o tiene otro formato.
- Función no admitida
- No se permiten hilos, SIMD relajado, excepciones, llamadas de cola, memorias de 64 bits ni múltiples, ni GC (spec §1). Recompila con una búsqueda de un solo hilo.
- No pasó la validación
- El módulo está dañado o usa una función fuera de la spec §1. El offset de los detalles señala el punto exacto.
- Imports de env
- Los imports de env son la forma en que Emscripten se comunica con el JS del navegador. Compila para WASI (Rust wasm32-wasip1, C/C++ wasi-sdk; spec §1).
- Import no permitido
- Solo se pueden importar funciones de wasi_snapshot_preview1, con exactamente los tipos de parámetros y resultado que declara preview1 (solo i32 e i64; sin thread_spawn; spec §1). Los detalles muestran el tipo encontrado.
- Memoria inicial demasiado grande
- El límite es 32 MiB. Reduce los arreglos de asignación estática (p. ej. la tabla hash) o asigna al inicio lo que haga falta. La memoria también paga tarifa de atraque (spec §3).
- Sin memoria
- El módulo debe tener exactamente una memoria lineal (spec §1).
- Memoria no admitida
- Exactamente una memoria de 32 bits no compartida (spec §1).
- No se permiten table.get / table.set / table.grow / table.fill / table.copy / table.init
- Cambiar la tabla de funciones en tiempo de ejecución no tiene un coste definido, así que se rechaza (spec §1).
- Sin exportación _start
- Compila un comando WASI (un ejecutable con main). Los reactors y los cdylib no se pueden iniciar (spec §1).
- Tiene sección start
- Una sección start se ejecuta antes de `_start` y no se permite. Inicializa dentro de `_start` (los comandos WASI normales no la tienen).
- Anidamiento, br_table o lista de tipos demasiado grande
- Los bloques se anidan como máximo 4096 niveles, los destinos de br_table por la profundidad de anidamiento suman como máximo 10 millones entre todas las funciones, hay como máximo 1024 tipos, un tipo tiene como máximo 64 parámetros o resultados, los bloques con un tipo de varios valores × el número de tipos × (valores + 1) suman como máximo 100 millones, y la propia comprobación se detiene a los 3 segundos de CPU (spec §1). Los compiladores quedan muy por debajo (los motores de referencia llegan a profundidad 72, 9.132, 34 tipos y ningún bloque de varios valores); un `switch`, un anidamiento o una lista de tipos enormes generados por máquina no. Divide la función o aplana la estructura.
- Demasiados archivos de datos
- El límite es 16 archivos. Únelos.
- Nombre de archivo de datos no válido
- Usa una ruta relativa de segmentos [A-Za-z0-9._-] separados por / (p. ej. eval/nn.bin).
- Archivos de datos demasiado grandes
- El límite es 8 MiB en total. Los archivos de datos también cuentan para la tarifa de atraque (spec §3).
Motivos de detención de una partida
- Sin respuesta antes de la partida
- Responde usiok (uciok en ajedrez) y readyok dentro del tiempo de preparación (consulta las reglas oficiales en el manual). Cargar pesos pesados puede superarlo (spec §2).
- Falta la respuesta esperada
- Responde usi con usiok (uci con uciok en ajedrez) e isready con readyok (spec §2).
- Esperó entrada sin mover
- En tu turno, imprime bestmove antes de leer stdin.
- Sin tiempo
- Detén la búsqueda por el reloj, no por un número de nodos: el reloj sigue las instrucciones (spec §3). El límite por jugada llega en go (movetime en UCI, byoyomi en USI).
- Jugada ilegal
- Las jugadas ilegales o ilegibles y las declaraciones de rey entrado (entering king) no válidas pierden.
- Sin memoria
- Se rechazó una petición de ampliar la memoria en el límite de 32 MiB y el motor no pudo continuar (bad_alloc de C++, fallo de asignación de Rust, ...). Reduce las tablas hash y de historial (spec §3, §5).
- Llegó a unreachable
- Los compiladores emiten esta instrucción donde el programa se rinde (panic, abort, assert fallido, excepciones en compilaciones sin excepciones, ...). El final de stderr suele decir por qué.
- Acceso a memoria fuera de límites
- Uso tras liberar, índice de arreglo incorrecto, ...
- División por cero / pila de llamadas demasiado profunda
- Superar el límite de profundidad de llamadas también se detiene aquí (spec §5).
- Desbordamiento entero en una división
- P. ej., el valor mínimo dividido entre −1.
- Falló una llamada indirecta
- Una llamada a través de la tabla de funciones encontró un tipo que no coincide o un hueco vacío.
- Demasiada salida estándar
- Como máximo 64 KiB por turno (spec §5). Imprime menos información.
- Ejecución detenida
- Revisa el final de stderr.
- El motor terminó
- Salir durante la partida hace perder. Sigue leyendo stdin hasta el final.
- Este dispositivo se quedó sin memoria
- No es culpa del motor; la partida se anuló. Prueba con un dispositivo con más memoria o cierra otras pestañas.