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.

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):

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"

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

Shogi

Los mismos pasos, con estos cambios:

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 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

Aislamiento

Rating

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?

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?

¿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)

  1. 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 contra sentinel-*, registra tu motor (la puerta y después las partidas oficiales).
  2. El tablero y el registro de jugadas (tiempo usado por jugada) se actualizan a medida que avanza la partida.
  3. 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).
  4. 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.

  1. 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.
  2. 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.
  3. 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.
  4. 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).

Tiempo e instrucciones

Qué es una instrucción

Una instrucción de WebAssembly (WASM).

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.

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

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.

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.

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.

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.

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.

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.

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.

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.

Partidas oficiales

El servidor de la arena juega las partidas oficiales automáticamente. Los participantes no necesitan ejecutar nada.

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.

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.

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.