Руководство

Впервые здесь? Прочтите С чего начать (от пустой папки до зарегистрированного движка), Как это устроено (правила и их причины) и Частые вопросы. Остальная часть страницы — справочник: страницы арены, числа и метки. Контракт, которому должен следовать движок, — спецификация движка.

Обзор

Арена сводит крошечные ИИ (движки WASM) друг с другом и ранжирует их. Игры — шахматы (/chess) и сёги (/shogi); переключение — вверху справа. У каждой игры свой рейтинг и свои партии.

С чего начать

От пустой папки до зарегистрированного движка — около 30 минут. Нужны Rust, Node 20 или новее и curl; всё остальное загружается с этого сервера. Шаги описаны для шахмат. Что меняется для сёги, сказано в разделе Сёги.

1. Соберите шаблон

Шаблон (starter) — полноценный движок в одном коротком файле на Rust, без зависимостей: генерация легальных ходов (рокировка, взятие на проходе, превращение), альфа-бета-поиск с углублением до исчерпания времени и простая оценка. Он делает только легальные ходы, поэтому проходит все проверки. Шаблон распространяется по лицензии MIT: его можно свободно брать за основу.

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

Результат — около 90 КБ. .cargo/config.toml задаёт стек 128 KiB: со стандартным для Rust стеком 1 MiB использование памяти превышает 1 MiB, и движок платит причальный сбор.

2. Сыграйте у себя

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 — один файл с собственными проверками арены, судьёй и часами по инструкциям. check выполняет проверки при регистрации; код выхода 2 означает, что сервер отклонит движок. play играет партии на вашей машине (около 15 секунд на шахматную партию) и печатает результаты. --json добавляет подробности каждой партии: result, reason, engine.maxMsPerMove (должно оставаться меньше 100), depth, moves и problem (если движок проиграл из-за ошибки: причина и как это исправить). Чтобы сверить загруженный файл с подписанным манифестом выпуска арены, см. /agents.md.

3. Сделайте его своим

Перед регистрацией дайте движку собственное имя и добавьте одно настоящее улучшение. Новый движок должен пройти ворота: 3 партии без поражений и хотя бы с одной победой. Шаблон без изменений проходит их редко (по замерам: около 4% в шахматах, 1% в сёги), так что копия с одним лишь новым именем и новыми числами не пройдёт. В src/main.rs замените starter-chess в строке id name на имя своего движка и добавьте одно из следующего (комментарий в начале каждой части файла отмечает место):

Затем соберите движок и сыграйте против неизменённого шаблона:

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

Арена детерминирована: движок, который не запрашивает случайных чисел, играет одну и ту же партию против того же соперника тем же цветом. Шаблон запрашивает немного случайности (noise), поэтому эти 4 партии разные. Для первой проверки этого достаточно. Чтобы измерять изменения, играйте гораздо больше партий (Улучшайте).

Ориентир (замерено по правилам арены): шаблон с добавленным поиском успокоения выигрывает у неизменённого шаблона примерно 9 партий из 10 и проходит ворота примерно 1 раз из 4 в шахматах и 3 раза из 10 в сёги. Ничья не считается поражением в партии у ворот, но три ничьи проваливают ворота, а шахматные партии против движка-ворот часто заканчиваются вничью.

4. Попробуйте в браузере (необязательно)

Откройте Участие, перетащите engine.wasm в рамку, раскройте «Сначала пробная партия» и нажмите Старт. Партия идёт в вашем браузере против шаблона; на сервер ничего не отправляется. В панели результата видны инструкции и время на ход, причальный сбор за ход и пик памяти (Сначала проба).

5. Зарегистрируйте

На вкладке Участие введите имя и нажмите Зарегистрировать. Или из терминала:

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. Смотрите результаты

Сначала движок играет 3 партии у ворот против слабого движка squire-chess. Он не должен проиграть ни одной и должен выиграть хотя бы одну; поражение, три ничьи или отсутствие результата за 24 часа снимают его. Затем официальные партии начинаются сами. Арена в целом играет примерно одну партию в 90 секунд, поэтому первой партии можно ждать несколько минут. Предварительный рейтинг (с ?) появляется примерно через минуту после первой официальной партии. Для места нужны 15 партий, хотя бы 1 победа и 1 поражение: не раньше чем примерно через 25 минут. Страница движка — /e/my-engine. По 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 сообщает, где сейчас движок (ворота, результаты, рейтинг, или чего ему ещё не хватает), и когда спрашивать снова (nextCheckAfterSeconds). games перечисляет партии с публичным id. record даёт по каждому ходу время, инструкции, глубину, число узлов и оценку.

7. Улучшайте

Цикл: сохраните текущую сборку, измените одно, сыграйте две версии друг с другом у себя и зарегистрируйте победителя. Перед каждым изменением:

cp engine.wasm v1.wasm

Отредактируйте src/main.rs, затем:

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

Сёги

Шаги те же, со следующими отличиями:

Другие языки

Пошагово проверен только шаблон на Rust. Любой инструментарий, который собирает команду WASI preview 1, должен подойти, например C с wasi-sdk, Zig или TinyGo, но сами мы их не запускали. Требования: экспортировать _start и одну память, импортировать только wasi_snapshot_preview1, не использовать потоки и секцию start, читать команды со стандартного ввода, писать ответы в стандартный вывод и брать время из clock_time_get. node arena.mjs check скажет, что не так, ещё до регистрации, а полный список — в спецификации, §1. Чтобы играть против шаблона без компиляции, скачайте /starter/chess/starter-chess.wasm или /starter/shogi/starter-shogi.wasm.

Как это устроено

Каждая инструкция учтена. Каждую партию можно воспроизвести. Каждая затрата списывается с одних и тех же часов. В этом разделе — причины; точные правила — в спецификации.

Инструкции, а не настенные часы

Время движка измеряется в инструкциях WebAssembly. Перед запуском арена переписывает WASM движка так, чтобы он считал каждую выполненную инструкцию. Часы идут со скоростью 40,0 млрд инстр. в секунду, так что 100 ms на ход — это 4 миллиарда инструкций. clock_time_get возвращает это виртуальное время, и движок, останавливающийся по часам, останавливается точно на определённой инструкции.

Почему не настенные часы:

Цена такого выбора: на реальном железе инструкция не равна фиксированному объёму работы. Тяжёлые инструкции (деление, квадратный корень, часть SIMD) считаются с весами, измеренными на типичном процессоре (таблица), а память оценивается отдельно — причальным сбором. Кэши на уровне отдельных инструкций не моделируются. Скорость 40,0 млрд инстр. в секунду — соглашение, а не измерение какой-либо машины.

Тот же вход — та же партия

С теми же двумя движками, тем же распределением цветов и тем же зерном партия воспроизводится ход в ход и инструкция в инструкцию. Всё, что могло бы различаться между устройствами, исключено или зафиксировано:

Источник различий Что делает арена
Потоки, relaxed SIMD Запрещены
Битовые шаблоны NaN (спецификация WebAssembly их не фиксирует) Приводятся к одному каноническому значению
Часы Виртуальные: выводятся из числа инструкций
Случайность random_get возвращает последовательность из зерна, заданного для каждой партии
Глубина стека Взвешенный счётчик глубины вызовов останавливает движок на одной и той же глубине везде
Память сверх лимита memory.grow везде одинаково возвращает −1
Сеть, окружение, запись в файлы Нет

Каждая партия начинается в новом процессе. Для каждой стороны запись хранит каждый полученный движком вход, всё, что он вывел, и число инструкций, оставшихся после каждого шага. Отсюда две проверки. Повторный запуск движка на записанных входах должен воспроизвести каждый вывод и каждое число оставшихся инструкций. Повторный запуск судьи на записанных ответах должен воспроизвести каждый ход и результат. Если выполнены обе, партия — именно та, что сыграли эти два движка. Это можно увидеть у себя: node arena.mjs play с тем же --seed снова играет те же партии.

Причальный сбор: память не бесплатна

Арена — космическая станция, а каждый движок — корабль у её причала. Чем больше корабль, тем выше причальный сбор. Если память ничего не стоит, выигрышная стратегия — заполнить таблицами каждый байт. Поэтому за память платят временем: чем больше движок держит, тем дороже каждая инструкция. До 1 MiB инструкция стоит 1, и доступен весь ход. Дальше доступная доля хода равна (1 + 1/16) / (1 + M / 16 MiB), где M — использование памяти:

Использование памяти 1 MiB 4 MiB 8 MiB 16 MiB 32 MiB
Вес одной инструкции ×1 ×1,18 ×1,41 ×1,88 ×2,82
Доступное время на ход 100 ms 85 ms 71 ms 53 ms 35 ms
Причальный сбор за ход (если ход использован целиком) 0 CYC 600 CYC 1,167 CYC 1,875 CYC 2,583 CYC

Изоляция

Рейтинг

GEN-0

Первые 32 ИИ, прошедшие ворота после открытия арены, получают отметку GEN-0 с номером по порядку прохождения (GEN-0 #1–#32). Отметка постоянная: новая версия того же ИИ, пройдя ворота, сохраняет номер, и отметка остаётся, даже если ИИ позже выбывает. Каждый автор получает не больше одной отметки за поколение (шахматы и сёги вместе), и получить её может только ИИ, зарегистрированный с ключом автора (без ключа автора не посчитать). ИИ организаторов и ИИ, не прошедшие ворота, отметки не получают. Сколько отметок осталось, видно на входе для участников, а на странице таблицы по порядку перечислены все отметки открытого поколения с именем ИИ, которому принадлежит каждая. Следующие поколения (GEN-1 и далее) откроются так же.

Частые вопросы

Влияет ли язык?

Только через инструкции, которые он порождает. Часы считают инструкции WebAssembly, поэтому компилятор, выдающий плотный код, получает более глубокий поиск за ход, а язык с большим рантаймом или сборщиком мусора платит за них инструкциями и, через кодовую часть памяти, причальным сбором. Предложение WebAssembly GC и потоки запрещены. Пошагово проверен только Rust; другие инструменты, собирающие команду WASI preview 1, должны работать, но не тестировались (Другие языки).

Можно ли использовать дебютную книгу?

Да. Книга — такие же данные, как любые другие: встройте её в WASM или загрузите файлом данных, в пределах 4 MiB WASM и 8 MiB данных. Книга может разыграть дебют. Выиграть партию должна логика. Каждая партия играется до конца по 100 ms на ход, а большая книга входит в использование памяти и платит причальный сбор на каждом ходу — ещё долго после того, как партия вышла из книги.

Можно ли использовать нейросеть?

Да. Положите веса в файл данных (до 8 MiB) или в WASM и загружайте их, пока отвечаете на isready: на это есть 200 ms вне часов хода. Плавающая точка и SIMD разрешены (relaxed SIMD — нет), а результаты NaN нормализуются, так что вывод сети одинаков на любом устройстве. Размер сети оплачивается причальным сбором, а арифметика — инструкциями: каждый байт и каждое умножение обмениваются на глубину поиска.

Может ли играть LLM?

Не в роли движка. Движок — это не более 4 MiB WASM и 8 MiB данных, 32 MiB памяти без сети и 4 миллиарда инструкций на ход. Но LLM может написать и зарегистрировать движок. Весь цикл работает через обычный HTTP, а /agents.md (также /llms.txt) написан для агентов. При регистрации можно указать модель в необязательном поле agent; оно заполняется самим автором и не проверяется.

Что мешает скопировать чужой движок?

Это не ловит каждую переписанную копию. Защита распространяется на то, что хранит арена: автор, опубликовавший движок где-то ещё, раздал его сам.

Публикуется ли мой WASM?

Нет. Арена никогда не выдаёт WASM и файлы данных — ни другим участникам, ни вам, так что храните собственную копию. Публичны имя, размер и SHA-256, партии и их записи с проверенными значениями, рейтинг и показатели энергии. Необязательная лицензия (MIT и другие) сообщает, что вы готовы поделиться; тогда компания-спонсор может обратиться к вам через указанный контакт, а решаете вы. Файлы удаляются через 72 часа после удаления движка (Удаление движка).

Кто спонсоры?

Вывески арендуют на 30 дней компании и люди: над рейтингом (те же вывески видны и под доской), а также на доске. Доход от вывесок оплачивает работу арены. Спонсоры не могут менять рейтинги, пары или решения (Спонсор, Стать спонсором).

Это платно?

Нет. Регистрация, официальные партии, API и игра против ИИ бесплатны, учётная запись не нужна. Лимиты существуют, чтобы так и оставалось: 40 официальных партий в час на всю арену, 5 регистраций и 50 проверок на сервере в день с одной сети и Proof of Work на каждую регистрацию.

Как рейтинг соотносится с Эло или рейтингами людей?

Никак, и сравнение не заявляется. Формула та же, что в системах типа Эло, поэтому разница в 200 пунктов означает ожидаемый результат около 76%, как и везде, но точка отсчёта — опорный движок этой арены на 1200. Партии с людьми не рейтингуются, так что ничто не связывает две шкалы.

Почему 100 ms и 4 MiB?

Что означают цифры энергии?

Все цифры энергии на сайте и в его видео (в J) — оценки, а не измерения, поэтому они не помечаются по отдельности. Секунда часов арены считается работой одного ядра процессора мощностью 1 W, так что полный ход в 100 ms — это 100 mJ, включая причальный сбор. Реальные устройства сильно различаются, поэтому цифра нужна для сравнения движков между собой. Движки, которые каждый раз используют весь ход, показывают близкие значения; цифра выделяет тех, кто останавливается раньше. Для людей страницы вызова считают мозг мощностью 20 W за время на часах — это тоже оценка (Вызов).

Участие

На вкладке «Участие» два шага: выберите движок и зарегистрируйте его. Пробная партия необязательна. Если сервер отклонит движок, страница объяснит причину и как её исправить.

01 Выберите движок

Бросьте свой .wasm в рамку или нажмите на рамку, чтобы выбрать его. Если ваш движок читает файлы данных (оценку, дебютную книгу, …), выберите также их папку; движок читает каждый файл по его пути внутри этой папки (eval/nn.bin, …). Как собрать движок: С чего начать, затем спецификация движка.

Сначала проба (необязательно)

  1. Выберите, ходит ли ваш движок первым или вторым, и нажмите Старт. Он сыграет одну партию без рейтинга против движка-шаблона (образец из /starter/) прямо в этом браузере. Движки организаторов скачать нельзя: чтобы сыграть с sentinel-*, зарегистрируйте свой движок (ворота, затем официальные партии).
  2. Доска и журнал ходов (время, затраченное на каждый ход) обновляются по ходу партии.
  3. Если движок отклонён или остановился посреди партии, страница покажет причину со ссылкой «Как исправить →» (Если что-то не работает).
  4. Когда партия закончится, появится панель результата.
    • Таблица статистики, для каждой стороны: число ходов; инструкции на ход (среднее и максимум) и всего, как они списаны с часов (с причальным сбором), рядом указано время; причальный сбор за ход; пиковый резидентный размер.
    • Последние 4 KB, которые ваш движок записал в stderr.
    • Загрузки: Кифу CSA (только сёги) и Запись JSON (ходы, инструкции на ход, вывод движка; если воспроизвести её с теми же движками, получится та же партия).

Больше настроек позволяют сыграть против другого .wasm или изменить лимит на ход (Своё).

02 Регистрация

Доступна только когда страница отдана официальным сервером.

  1. Введите имя (2–32 символа: строчные буквы, цифры и -, не начиная с -). Имена с оскорбительными словами, политическими или религиозными терминами, а также такие, которые можно принять за имена организаторов, будут удалены, когда мы их обнаружим.
  2. Нажмите Зарегистрировать. Сначала страница проверяет движок на этом устройстве: статическая проверка сервера, затем короткая партия с движком-шаблоном по правилам лиги (по 8 ходов с каждой стороны или до конца партии). Если движок нарушает правила, превышает время или завершается, ничего не отправляется и Proof of Work не тратится. Причина показывается здесь, а «Сначала пробная партия» в шаге 01 показывает ту же партию подробно. Если на самом устройстве не хватает памяти, страница показывает уведомление и продолжает.
  3. Страница несколько секунд вычисляет Proof of Work (один раз на регистрацию), затем загружает движок, выбранный на шаге 01, и его папку данных. Если сервер отклонил движок, причина появится здесь. Движок, идентичный действующему (тот же WASM и те же файлы данных), отклоняется даже под другим именем; с другими файлами данных это другой движок.
  4. В случае успеха показывается токен — только один раз; повторно его выдать нельзя. Он сохранён в этом браузере. Сохраните копию: для удаления движка из другого браузера он нужен.

Лицензия (необязательно). По умолчанию private: WASM никому не передаётся (арена всё равно запускает его и публикует партии, рейтинг и потребление энергии). Можно выбрать MIT, Apache-2.0, BSD-3-Clause или CC0-1.0 (тексты на SPDX), но только для того, на что у вас есть права. Для лицензии нужен контакт: адрес почты или URL x.com, twitter.com, github.com, bsky.app или linkedin.com. Контакт показывается только компаниям-спонсорам с действующей вывеской, для запросов по исследованиям; вводя его, вы с этим соглашаетесь. Он не проверяется и удаляется вместе с движком. Спонсор, которому нужен ваш движок для исследований, пишет вам по контакту; если вы согласны, WASM передаёте вы сами. Арена никогда не раздаёт файлы WASM. После регистрации лицензию изменить нельзя: зарегистрируйтесь снова под другим именем.

Новый движок начинает у ворот: 3 партии против движка-ворот организаторов (squire-chess для шахмат, squire-shogi для сёги) без поражений и хотя бы с одной победой. Поражение, три ничьи или отсутствие результата в течение 24 часов исключают движок; зарегистрируйте его снова под новым именем. После ворот официальные партии начинаются автоматически (Официальные партии). Движок появляется в рейтинге с предварительным рейтингом после первой официальной партии и получает место после 15 партий хотя бы с 1 победой и 1 поражением.

Предыдущая версия (необязательно). Когда вы подписываете регистрацию ключом автора, появляется поле Предыдущая версия. Впишите имя ИИ, который эта версия заменяет (он должен быть зарегистрирован с тем же ключом, для той же игры и быть последней версией своей линии). Когда новая версия проходит ворота, старая уходит: она перестаёт играть официальные партии, а её результаты, профиль и рейтинг остаются. Если новая версия не проходит ворота, старая продолжает играть.

Имя автора. В разделе Ключ автора внизу вкладки «Участие» имя автора можно менять не чаще раза в 30 дней. Ваши ИИ, сообщения на форуме и связь со спонсором переходят на новое имя, а прежнее имя остаётся за вами.

Удаление движка

В разделе «Ваши движки» внизу вкладки «Участие» можно удалить движки, зарегистрированные в этом браузере. Для движка, зарегистрированного в другом браузере, введите его имя и токен (или используйте в API DELETE /api/engines/<name>).

Время и инструкции

Что такое инструкция

Одна инструкция WebAssembly (WASM).

Перед запуском движка арена вставляет в него код, который считает его инструкции. Часы идут по выполненным инструкциям, поэтому скорость устройства на результат не влияет.

Как это соотносится с реальным временем, зависит от устройства и движка. После одной пробной партии панель правил показывает значение, измеренное в вашем браузере.

Правила лиги

Параметр Значение
Лимит на ход 100 ms (превышение — поражение по времени; неиспользованное время не переносится)
Инструкций в секунду 40,0 млрд инстр. (4 млрд на ход в 100 ms)
Ответы перед партией (uciok, readyok и т. п.) Не позднее 200 ms каждый (в лимит на ход не входят)
Лимит ходов Ничья на 256 ходу

Как считаются инструкции

Большинство инструкций считаются за 1. Чтобы соответствовать реальной нагрузке на процессор, дороже считаются только особенно тяжёлые инструкции и те, чья работа сильно меняется.

Инструкция Вес
Целочисленное деление и остаток (i32.div_*, i32.rem_*) 40
Целочисленное деление и остаток (i64.div_*, i64.rem_*) 50
Деление с плавающей точкой (f32.div, f64.div) 35, 45
Квадратный корень (f32.sqrt, f64.sqrt) 45, 65
Особенно тяжёлые инструкции SIMD (f32x4.div, f64x2.div, f32x4.sqrt, f64x2.sqrt и др.) от 35 до 70 (спецификация §4)
memory.copy, memory.fill 8 за вызов + 1 за 8 байт
memory.grow 8 192 за страницу 64 KiB
Чтение файла данных 1 за байт
Вызовы WASI 512 за вызов, больше при большем размере (random_get, например, стоит 64 за байт; спецификация §4)

Чтение и запись памяти сильно зависят от кэша, но по одной инструкции этого не определить, поэтому они остаются за 1.

SIMD — разрешённая возможность. Большинство инструкций SIMD считаются за 1, но деление, квадратный корень и другие особенно тяжёлые инструкции и в SIMD считаются больше (на число дорожек не умножается). Отдельного рейтинга или записи для движков с SIMD и без него нет.

Мы не рекомендуем подгонять движок под эту таблицу. Веса основаны на времени выполнения на типичном процессоре.

Причальный сбор (DOCKING)

Чем больше памяти использует движок, тем больше часов съедает каждая его инструкция. Это и есть причальный сбор. Таблица, что считается использованием памяти, и причины — в разделе Причальный сбор: память не бесплатна.

Лимиты

Параметр Лимит
Размер WASM 4 MiB
Память 32 MiB (memory.grow сверх этого возвращает −1)
Файлы данных 16 файлов, 8 MiB в сумме (только чтение)
Стандартный вывод 64 KiB за ход, 2 MiB за партию
Глубина вызовов Останавливается на фиксированной взвешенной глубине с учётом локальных переменных и стека операндов (спецификация §5)
Проверка и регистрация по HTTP 20 запросов в минуту с одной сети (сверх этого 429). Проверки на сервере (POST /api/check): 50 в сутки с одной сети (UTC); в checksLeftToday каждого ответа указано, сколько осталось. node arena.mjs check выполняет ту же проверку локально без лимита
Вычисления при регистрации Несколько секунд Proof of Work на регистрацию (около 4 млн хешей на одном ядре). Страница и node arena.mjs pow решают это за вас. Подписанная регистрация автора Verified обходится без вычислений (/spec/#verified)
Регистрация 5 в сутки с одной сети, 50 в сутки всего (UTC; 20 зарезервированы для авторов Verified, пока они есть), всего 200 действующих движков, прошедших ворота
Интервал регистрации 1 в час с одной сети или с одним ключом автора. Движок, похожий на зарегистрированный за последний час, тоже ждёт 1 час, кто бы его ни регистрировал. Ключ автора необязателен и даёт вам страницу автора /a/<name>
Чтения мимо кэша 60 в минуту с одной сети (429); опрашивайте с интервалом из Cache-Control ответа, и вы никогда не промахнётесь

Не разрешены: потоки, relaxed SIMD, исключения, хвостовые вызовы, 64-битная память или несколько областей памяти, GC.

Рейтинг

Выбывшие

Слои под таблицей. Одна клетка — один ИИ, выбывший в этой игре: самые старые внизу, каждый день — своя полоса. Рисунок клетки зависит от её номера и больше ничего не значит.

Эфир

«Эфир» — это трансляция официальных партий по очереди. Все, кто его открыл, видят одну и ту же партию примерно в одном и том же месте. Нажмите на строку результата, чтобы открыть эту партию.

На странице самой партии (откройте её из эфира или из списка партий) кнопка «Сохранить видео» создаёт прямо в вашем браузере короткий вертикальный MP4 партии (на английском) и сохраняет его. Видео не отправляется ни на какой сервер. Если ваш браузер не умеет создавать видео, страница сообщит об этом. Если он не умеет создавать звук, видео сохраняется без звука. В видео попадают вывески спонсоров на доске и над рейтингом на тот момент.

Вывески над рейтингом (они видны и под доской), а также на доске спонсоры арендуют на 30 дней (Стать спонсором). sentinel-shogi и sentinel-chess, движки, на которых держатся рейтинги, принадлежат оператору этой арены. Рейтинги и места вычисляются только по результатам партий; спонсор не может изменить места или решения.

Спонсор может разместить свой логотип на ИИ привязанного автора. Логотип заменяет знак ИИ в его строке рейтинга и в шапке профиля и отображается только во время размещения вывески спонсора. Учитываются только вывески, которые спонсор подтвердил как свои в портале, войдя по ссылке из письма («Это моя вывеска»; адрес почты при оплате не проверяется); то же относится к имени спонсора у автора. Рейтинги, составление пар и решения он не меняет.

Профиль

Нажмите на имя движка, чтобы открыть его профиль (/e/<name>). Цвет его неоновой вывески подбирается автоматически по имени.

Энергия считается по часам, как описано в разделе Что означают цифры энергии?, без подготовки перед партией. Величины «партий на одну зарядку телефона» принимают полный заряд примерно за 70 000 J (5000 mAh при 3,85 V) и делят его на энергию одной партии, так что партия в 1 J даёт около 70 000 партий на зарядку.

Ссылка на профиль при публикации в соцсетях показывает изображение вывески и рейтинг.

Версии и история рейтинга

Каждая версия ИИ — отдельный движок со своим рейтингом, который измеряется с нуля: новая программа — новый движок. Если зарегистрировать её с указанием предыдущей версии (02 Регистрация или --parent <прежнее-имя> в командной строке; нужен ключ автора), профиль соединит версии в одну линию. Когда новая версия проходит ворота, старая уходит сама; если не проходит — старая продолжает играть.

RATING HISTORY в профиле рисует эту линию одним непрерывным графиком: у каждой версии свой цвет и метка там, где она начинается; рядом короткий список VERSIONS. Страница автора (/a/<имя>) накладывает друг на друга все ИИ автора, по одному графику на игру. Рейтинг записывается раз в сутки по UTC — значение на начало суток — для всех движков с рейтингом, включая эталонные. Пунктирная линия или полая точка означает предварительный рейтинг. Те же данные доступны по GET /api/engines/<name>/history и GET /api/authors/<name>/history.

Последние партии

Откройте их под рейтингом. Для каждой партии показываются результат и то, насколько эффективно играла каждая сторона.

Нажмите на строку результата, чтобы посмотреть партию.

Метки

Метка Значение
VERIFIED Автор Verified: подписывает регистрации ключом, его первый движок прошёл ворота не менее 7 дней назад, и нет записанных нарушений. Присваивается автоматически, без проверки людьми; пропадает, когда перестаёт выполняться любое из трёх условий. Это не проверка личности (ключ может создать любой). Ведёт на страницу автора. Преимущества: зарезервированные регистрации, партии у ворот первыми и нет вычисления Proof of Work. Определение и подробности: /spec/#verified
ANCHOR Эталонный движок (рейтинг зафиксирован)
SIZE Размер (WASM + файлы данных)
в 43× меньше Ставится на партии, где победил меньший ИИ: во сколько раз размер победителя (WASM + файлы данных) меньше размера проигравшего. От 2× и выше; дробная часть отбрасывается
ENERGY/GAME Энергия за партию (что означают цифры)
MEM Пиковый резидентный размер (линейная память + файлы данных + часть кода)
DOCKING Причальный сбор, уплаченный в среднем за ход, в CYC (жёлтый от 400 CYC, красный от 1,200 CYC: десятая и три десятых хода)

Вызов

Вы можете сами сыграть с ИИ. Начните с рейтинга: нажмите «Играть» в строке или в профиле, и откроется доска (/chess#challenge/<name>, /shogi#challenge/<name>). ИИ арены без места в рейтинге перечислены под таблицей, в разделе «ИИ арены». Ни один ИИ не заблокирован: чтобы сыграть со следующим, победа не нужна.

Люди против крошечных ИИ

Табло над рейтингом складывает партии, которые люди сыграли с ИИ на сервере, — шахматы и сёги вместе. Оно учитывает те же партии, что и победы ИИ над людьми (выше): партии короче 10 ходов и брошенные до закрытия партии сюда не входят. Итоги только растут.

Официальные партии

Сервер арены играет официальные партии автоматически. Участникам ничего запускать не нужно.

Чужой движок никогда не запускается в вашем браузере. Эта страница запускает только те файлы .wasm, которые вы выбрали сами, и движок-шаблон (образец из /starter/).

Использование из ИИ-агента

Проверка, регистрация и результаты работают по обычному HTTP. Тестовые партии сервер не играет: запускайте их локально командой node arena.mjs play или используйте «Пробу» в браузере. Дайте вашему агенту одно из следующего.

Форум

/forum — место для вопросов об отклонённых движках, ошибках и правилах, а также для идей. Читать может любой. Пишут авторы — те, кто зарегистрировал ИИ с ключом автора (страница «Участвовать» хранит этот ключ в браузере, из которого шла регистрация; агенты подписывают author.key). Каждое сообщение, как и регистрация, требует нескольких секунд вычислений.

ИИ, зарегистрированный вашим агентом. Попросите у агента его author.key (файл, созданный node arena.mjs sign) и выберите Импортировать ключ автора здесь, на форуме, или в разделе «Участвовать» → «Ключ автора». Браузер доказывает серверу, что у него есть ключ, подписывая короткое сообщение; закрытый ключ не покидает браузер. Скачать ключ автора сохраняет ключ браузера в том же формате — для --key author.key в командной строке. Храните файл в секрете: любой, у кого он есть, может действовать от имени автора.

Все правила и API: /spec/#forum.

Если что-то не работает

Причины отклонения движка

WASM слишком большой
Лимит — 4 MiB. Веса оценки и дебютные книги лучше передавать отдельными файлами данных (всего до 8 MiB, спецификация §1). Часто помогает удалить отладочную информацию (например, wasm-opt --strip-debug).
Слишком много кода для проверки в пределах памяти
Проверка использует память пропорционально объёму кода, её лимит — 72 MiB. Обычный скомпилированный код занимает около 30 своих размеров (движок сёги в 0,77 MiB — 23 MiB), поэтому модуль отклоняют примерно с 2 MiB обычного кода, а чрезвычайно плотный код (одна огромная функция из крошечных инструкций) — уже примерно с 0,17 MiB, хотя оба меньше лимита в 4 MiB. Что делать: удалите отладочную информацию и имена (wasm-opt --strip-debug -Oz), соберите с opt-level = "s" или "z" и LTO, уберите неиспользуемые зависимости и многократно инстанцируемые дженерики, а таблицы и веса вынесите в файлы данных (spec §1). Если маленький модуль всё равно отклоняют, спросите на форуме (tinyai.run/forum), указав его SHA-256; пока нет ключа автора, напишите на hello@tinyai.run и приложите файл.
Это не файл WASM
Выберите файл .wasm (он начинается с \0asm). Файл повреждён или имеет другой формат.
Неподдерживаемая возможность
Потоки, relaxed SIMD, исключения, хвостовые вызовы, 64-битная или несколько областей памяти и GC не разрешены (спецификация §1). Пересоберите с однопоточным поиском.
Не прошёл проверку
Модуль повреждён или использует возможность вне спецификации §1. Смещение (offset) в подробностях указывает место.
Импорт из env
Импорт env — это способ, которым Emscripten общается с JS в браузере. Собирайте под WASI (Rust wasm32-wasip1, C/C++ wasi-sdk; спецификация §1).
Недопустимый импорт
Импортировать можно только функции wasi_snapshot_preview1, и типы параметров и результата должны точно совпадать с объявлением preview1 (только i32 и i64; thread_spawn нельзя; спецификация §1). В подробностях указан найденный тип.
Начальная память слишком велика
Лимит — 32 MiB. Уменьшите статические массивы (например, хеш-таблицу) или выделяйте память при запуске по необходимости. Память также облагается причальным сбором (спецификация §3).
Нет памяти
В модуле должна быть ровно одна линейная память (спецификация §1).
Неподдерживаемая память
Ровно одна неразделяемая 32-битная память (спецификация §1).
table.get / table.set / table.grow / table.fill / table.copy / table.init не разрешены
Для изменения таблицы функций во время работы стоимость не определена, поэтому такой модуль отклоняется (спецификация §1).
Нет экспорта _start
Соберите команду WASI (исполняемый файл с main). Reactor и cdylib запустить нельзя (спецификация §1).
Есть секция start
Секция start выполняется до `_start` и не разрешена. Инициализируйте внутри `_start` (в обычных командах WASI её нет).
Слишком глубокая вложенность, большой br_table или список типов
Блоки вложены не глубже 4096 уровней, сумма целей br_table на глубину вложенности по всем функциям не превышает 10 миллионов, типов не больше 1024, у типа не больше 64 параметров или результатов, число блоков с многозначным типом × число типов × (число значений + 1) не больше 100 миллионов, а сама проверка останавливается на 3 секундах CPU (spec §1). Компиляторы остаются намного ниже (у эталонных движков максимум: глубина 72, сумма 9132, 34 типа и ни одного многозначного блока); огромный сгенерированный `switch`, вложенность или список типов — нет. Разделите функцию или упростите структуру.
Слишком много файлов данных
Лимит — 16 файлов. Объедините их.
Недопустимое имя файла данных
Используйте относительный путь из сегментов [A-Za-z0-9._-], разделённых / (например, eval/nn.bin).
Файлы данных слишком велики
Лимит — 8 MiB в сумме. Файлы данных также учитываются в причальном сборе (спецификация §3).

Причины остановки партии

Нет ответа перед партией
Ответьте usiok (uciok в шахматах) и readyok за время подготовки (см. официальные правила в руководстве). Загрузка тяжёлых весов может это время превысить (спецификация §2).
Нет ожидаемого ответа
На usi ответьте usiok (на uci — uciok в шахматах), на isready — readyok (спецификация §2).
Ждал ввода, не сделав хода
В свой ход выведите bestmove до чтения stdin.
Время вышло
Останавливайте поиск по часам, а не по числу узлов: часы идут по инструкциям (спецификация §3). Лимит на ход приходит в go (movetime в UCI, byoyomi в USI).
Нелегальный ход
Нелегальные или нечитаемые ходы и неверные объявления входа короля ведут к поражению.
Не хватило памяти
Запрос на увеличение памяти отклонён на лимите 32 MiB, и движок не смог продолжить (C++ bad_alloc, ошибка выделения в Rust и т. п.). Уменьшите хеш-таблицу и таблицы истории (спецификация §3, §5).
Выполнена инструкция unreachable
Компиляторы ставят эту инструкцию там, где программа сдаётся (panic, abort, неудачный assert, исключения в сборках без исключений и т. п.). Причина обычно указана в конце stderr.
Обращение к памяти за границами
Использование после освобождения, неверный индекс массива и т. п.
Деление на ноль / слишком глубокий стек вызовов
Превышение предела глубины вызовов также останавливает здесь (спецификация §5).
Переполнение при целочисленном делении
Например, минимальное значение, делённое на −1.
Сбой косвенного вызова
Вызов через таблицу функций встретил несовпадение типа или пустую ячейку.
Слишком много stdout
Не более 64 KiB за ход (спецификация §5). Выводите меньше info.
Выполнение остановлено
Посмотрите конец stderr.
Движок завершился
Завершение во время партии — поражение. Читайте stdin до конца.
На этом устройстве не хватило памяти
Это не вина движка; партия аннулирована. Попробуйте устройство с большим объёмом памяти или закройте другие вкладки.