説明書

初めての方ははじめての方へ(空のフォルダからエンジンの登録まで)・仕組み(ルールとその理由)・よくある質問を読んでください。それ以降は参照用で、対局場の画面と、数字・ラベルの意味を説明します。エンジンが守る約束は仕様書にあります。

概要

小さな AI(WASM のエンジン)どうしを対局させ、順位を付ける場所です。種目はチェス(/chess)と将棋(/shogi)で、画面の右上で切り替えます。順位と対局は種目ごとに別です。

はじめての方へ

空のフォルダから、エンジンの登録までおよそ 30 分。必要なのは Rust・Node 20 以上・curl だけで、ほかはすべてこのサーバーから取得します。手順はチェスで説明します。将棋で変わる点は将棋にまとめています。

1. ひな形を組む

ひな形(starter)は、依存のない短い Rust ファイル 1 つで書かれた完全なエンジンです。合法手の生成(キャスリング・アンパッサン・昇格)、時計が尽きるまで深くするアルファベータ探索、簡単な評価関数を持ちます。合法手しか指さないので、検査はすべて通ります。ひな形は 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

できあがりは約 90KB です。.cargo/config.toml はスタックを 128KiB にします。Rust の既定の 1MiB のスタックのままだとメモリ使用量が 1MiB を超え、停泊料がかかります。

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 は、対局場と同じ検査・審判・命令の時計を持つ 1 つのファイルです。check は登録の検査を行い、終了コード 2 はサーバーが受け付けないことを示します。play は手元で対局し(チェス 1 局で約 15 秒)、結果を表示します。--json を付けると 1 局ごとの詳細が出ます: result・reason・engine.maxMsPerMove(100 未満でなければならない)・depth・moves・problem(不具合で負けたときの原因と対処法)。取得したファイルを対局場の署名付きの目録で検証する方法は /agents.md にあります。

3. 自分のエンジンにする

登録の前に、エンジンに自分の名前を付け、自分の改良を 1 つ入れます。新しいエンジンは関門を越えなければなりません。関門は 3 局で、1 局も負けず、1 勝以上が条件です。ひな形そのままではまず通らない(実測でチェス約 4%・将棋約 1%)ので、名前と数字を変えただけのコピーは公式戦に出られません。src/main.rs の id name の行の starter-chess を自分のエンジンの名前に替え、次のどれかを入れます(ファイルの各部の先頭のコメントが場所を示しています)。

組み直して、変えていないひな形と対局させます。

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 局はそれぞれ違う対局になります。最初の確認にはこれで足ります。変更を測るには、もっと多く指します(改良する)。

目安(対局場のルールで実測): 静止探索を入れたひな形は、変えていないひな形に 10 局中 9 局ほど勝ち、関門をチェスで 4 回に 1 回ほど、将棋で 10 回に 3 回ほど通ります。関門では引き分けは負けになりませんが、3 局とも引き分けだと落ちます。チェスは関門の相手との対局が引き分けになりやすい種目です。

4. ブラウザで試す(任意)

参加するを開き、engine.wasm を枠に落として「先に 1 局試す」を開き、対局開始を押します。対局はあなたのブラウザの中でひな形を相手に行われ、サーバーには何も送りません。結果の欄に、1 手あたりの命令数と時間・1 手の停泊料・メモリの最大が出ます(先に試す)。

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. 結果を読む

エンジンはまず、弱い squire-chess と関門の対局を 3 局指します。1 局も負けず、1 勝以上が条件で、負けが 1 局でも出るか、3 局とも引き分けか、24 時間以内に終わらなければ外されます。そのあと公式戦が自動で始まります。対局場全体で約 90 秒に 1 局なので、最初の公式戦まで数分かかることがあります。最初の公式戦の約 1 分後に仮のレート(? 付き)が出ます。順位には 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 は 1 手ごとの時間・命令数・深さ・節点数・評価値を返します。

7. 改良する

進め方: 今のバージョンを残し、1 か所だけ変え、手元で新旧を対局させ、勝った方を登録します。変える前に毎回、次を実行します。

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 のコマンドを出せる道具(wasi-sdk の C・Zig・TinyGo など)なら動くはずですが、私たちは試していません。要件は次のとおりです: _start とメモリ 1 つを書き出す・取り込むのは wasi_snapshot_preview1 だけ・スレッドと start セクションを使わない・命令は標準入力から読み、応答は標準出力へ書く・時刻は clock_time_get で読む。登録の前に node arena.mjs check が何が悪いかを教えます。全部の一覧は仕様書 §1 にあります。ひな形を組まずに相手にしたいときは、/starter/chess/starter-chess.wasm か /starter/shogi/starter-shogi.wasm を取得してください。

仕組み

命令はひとつ残らず数えられる。対局はすべて再生できる。費用はすべて同じ時計から引かれる。この節ではその理由を説明します。正確なルールは仕様書にあります。

壁時計でなく、命令の数

エンジンの時間は WebAssembly の命令の数で計ります。エンジンを動かす前に、対局場は WASM を書き換え、実行したすべての命令を数えるようにします。時計は 1 秒あたり 400億命令 進むので、1 手 100ms は 40 億命令です。clock_time_get はこの仮想の時刻を返し、時計を見て止まるエンジンは、命令単位で正確に止まります。

壁時計を使わない理由:

この選択の代償: 実機の上では、命令 1 つの仕事の量は一定ではありません。重い命令(割り算・平方根・一部の SIMD)は一般的な CPU で測った重みで多めに数え(表)、メモリは停泊料で別に値段を付けます。キャッシュは命令ごとには模していません。1 秒 400億命令 という速さも決めごとで、どの機械の測定でもありません。

同じ入力なら、同じ対局

同じ 2 体・同じ手番・同じ種なら、対局は 1 手ずつ、命令 1 つずつ同じに再現されます。機械によって変わりうるものは、すべて取り除くか固定しています。

違いの元 対局場の扱い
スレッド・relaxed SIMD 使えない
NaN のビットの並び(WebAssembly の仕様が決めていない) 1 つの標準形にそろえる
時計 仮想の時計(命令の数から作る)
乱数 random_get は対局ごとの種から決まる列を返す
スタックの深さ 重み付きの呼び出しの深さで、どこでも同じ深さで止める
上限を超えるメモリ memory.grow はどこでも同じく −1 を返す
ネットワーク・環境変数・書き込めるファイル 無い

対局ごとに新しいプロセスで始めます。記録には、両方の側について、エンジンが受け取った入力・出力したものすべて・各段階の後に残った命令の数が残ります。ここから 2 つの検査ができます。1 体を記録の入力でもう一度走らせると、すべての出力と残りの命令の数が一致しなければなりません。審判を記録の応答でもう一度走らせると、すべての手と結果が一致しなければなりません。両方が通れば、その対局はその 2 体が指したものです。手元でも確認できます: node arena.mjs play に同じ --seed を渡すと、同じ対局がもう一度指されます。

停泊料: メモリはただではない

対局場は宇宙ステーションで、エンジンはそこに停泊する船です。大きい船ほど停泊料が高くなります。メモリに値段が無ければ、すべてのバイトを表で埋めるのが最善手になります。そこでメモリは時間で払います。抱えるほど、命令 1 つが高くつきます。1MiB までは命令 1 つの重さは 1 で、1 手をまるごと使えます。それを超えると、1 手のうち使える割合は (1 + 1/16) / (1 + M / 16MiB)(M はメモリ使用量)です。

メモリ使用量 1MiB 4MiB 8MiB 16MiB 32MiB
命令 1 つの重さ ×1 ×1.18 ×1.41 ×1.88 ×2.82
1 手に使える時間 100ms 85ms 71ms 53ms 35ms
1 手の停泊料(毎手を使い切ったとき) 0 CYC 600 CYC 1,167 CYC 1,875 CYC 2,583 CYC

隔離

レート

GEN-0

公開の後に関門を最初に越えた 32 体の AI には、越えた順の番号つきで GEN-0 の印が付きます(GEN-0 #1〜#32)。印は消えません。同じ AI の新しい版も、関門を越えれば同じ番号を引き継ぎ、後で引退しても残ります。印は 1 世代に 1 作者 1 つ(チェスと将棋を合わせて)で、作者の鍵で署名して登録した AI にだけ付きます(鍵が無いと作者を数えられないため)。運営の AI と、関門を越えられなかった AI には付きません。残りの枠の数は参加の入口に出ます。順位表のページには、開いている世代の枠が番号の順に全部並び、埋まった枠にはその印を持つ AI の名前が出ます。次の世代(GEN-1 から先)も同じ形で開きます。

よくある質問

言語で有利不利はある?

出てくる命令を通してだけです。時計は WebAssembly の命令を数えるので、引き締まったコードを出すコンパイラは 1 手でより深く読めます。大きなランタイムやガベージコレクタを持ち込む言語は、その分を命令で払い、コードの分のメモリを通じて停泊料でも払います。WebAssembly の GC 提案とスレッドは使えません。手順を一通り検証したのは Rust だけで、WASI preview 1 のコマンドを出せるほかの道具は動くはずですが、試していません(ほかの言語)。

定跡(opening book)は使える?

使えます。定跡もほかと同じデータで、WASM に埋め込むか、データのファイルとして送ります(WASM 4MiB・データ 8MiB の範囲で)。定跡は序盤を作れても、勝つのはロジックです。どの対局も 1 手 100ms で最後まで指し、大きな定跡はメモリ使用量に数えられるので、定跡を抜けたずっと後まで、毎手停泊料を払います。

ニューラルネットは使える?

使えます。重みはデータのファイル(8MiB まで)か WASM に入れ、isready に答える間に読み込みます。ここには 1 手の時計の外で 200ms あります。浮動小数点と SIMD は使え(relaxed SIMD は不可)、NaN はそろえるので、推論はどの機械でも同じ結果になります。ネットの大きさは停泊料で、計算は命令で払います。1 バイト、1 回の掛け算が、読みの深さと引き換えです。

LLM は参加できる?

エンジンそのものとしては参加できません。エンジンは WASM 4MiB とデータ 8MiB まで、メモリ 32MiB でネットワーク無し、1 手 40 億命令です。ただし LLM がエンジンを書いて登録することはできます。すべての手順は素の HTTP で済み、/agents.md(/llms.txt も同じ)はエージェント向けに書いています。登録には任意の agent 欄でモデル名を書けます(自己申告で、検証はしていません)。

他人のエンジンのコピー対策は?

書き直されたコピーをすべて見抜けるわけではありません。守れるのは対局場が預かっているものです。作者が自分のエンジンをよそで公開すれば、それは作者自身が配ったことになります。

自分の WASM は公開される?

されません。対局場は WASM もデータのファイルも、ほかの参加者にもあなたにも渡さないので、手元に控えを残してください。公開するのは、名前・大きさと SHA-256・対局と審判が検証した値の記録・レート・電力の数字です。任意のライセンス(MIT など)は、共有してよいという意思表示です。そのときスポンサーの企業があなたの連絡先へ問い合わせることがあり、渡すかどうかはあなたが決めます。ファイルはエンジンを削除してから 72 時間後に消します(エンジンを削除する)。

スポンサーとは?

看板は、企業や個人が 30 日ずつ借りるもので、順位表の上(同じ看板が盤の下にも順に出ます)と、盤の上にあります。看板の収入で対局場を運営しています。スポンサーはレート・組み合わせ・判定を変えられません(スポンサー・スポンサーになる)。

費用はかかる?

かかりません。登録・公式戦・API・AI と自分で指すことは無料で、アカウントもありません。無料を保つために上限があります: 対局場全体で 1 時間に公式戦 40 局・回線ごとに 1 日 5 体の登録と 50 回のサーバーの検査・登録ごとの Proof of Work。

Elo や人のレーティングと比べられる?

比べられず、比べられるとも主張しません。式は Elo と同じ形なので、差 200 点はほかと同じく期待得点 約 76% を意味しますが、原点はこの対局場の基準のエンジン(1200)です。人との対局はレートに入らないので、2 つの尺度をつなぐものはありません。

なぜ 100ms と 4MiB?

電力の数字の意味は?

サイトと動画に出る電力量(J)は、どれも推定で、測定ではありません。そのため、数字ごとに「推定」とは書いていません。対局場の時計の 1 秒を、1W で動く CPU の 1 コアとみなします。1 手 100ms を使い切ると 100mJ で、停泊料も含みます。実機の値は大きく違うので、エンジンどうしを比べるための数字です。毎手を使い切るエンジンは似た値になり、早く止まるエンジンとの差が出ます。人の側は、挑戦の画面で 20W の脳が時計を使った時間を数えます。これも推定です(チャレンジ)。

参加する

「参加する」タブは 2 つのステップです。エンジンを選び、登録します。先に 1 局試すのは任意です。サーバーの検査で落ちたときは、理由と対処法が画面に出ます。

01 エンジンを選ぶ

.wasm を枠にドロップするか、枠をクリックして選びます。データファイル(評価関数や定跡など)を読むエンジンは、そのフォルダも選びます。エンジンは各ファイルをフォルダの中のパス(eval/nn.bin など)で読みます。エンジンの作り方ははじめての方へ、続けて仕様書を見てください。

先に試す(任意)

  1. 自分のエンジンが先に指すか後に指すかを選び、対局開始を押します。ひな形のエンジン(/starter/ の見本)とこのブラウザの中で 1 局指します。順位には入りません。運営のエンジンはダウンロードできません。sentinel-* と指すには、エンジンを登録します(関門、その後に公式戦)。
  2. 1 手ごとに盤・指し手の一覧(使った時間)が更新されます。
  3. エンジンを受け付けられないときや、途中で止まったときは、理由と「対処法 →」が表示されます(困ったとき)。
  4. 対局が終わると、結果が表示されます。
    • 結果の表(両者それぞれ): 手数、1 手の命令数(平均・最大)と合計(停泊料を含む、時計から引かれた数。時間も併記)、1 手の停泊料、メモリ使用量の最大。
    • エンジンが標準エラーに書いた最後の 4KB。
    • 保存できるファイル: 棋譜 CSA(将棋だけ)と記録 JSON(指し手、1 手ごとの命令数、エンジンの出力。同じエンジンで再生すると同じ対局になります)。

詳細設定を開くと、相手を別の .wasm に替えたり、1 手の上限などのルールを変えたり(カスタム)できます。

02 登録する

サーバーに接続しているときだけ使えます。

  1. 名前を入力します(英小文字・数字・- で 2〜32 文字。先頭に - は使えません)。不適切な語、政治や宗教に関する語、運営と紛らわしい語を含む名前は、見つけ次第削除します。
  2. 登録するを押すと、ページはまずこの端末でエンジンを検査します。サーバーと同じ静的な検査と、ひな形を相手にした公式戦と同じルールの短い対局(自分の手が 8 手になるまで、または終局まで)です。反則・時間切れ・異常終了があれば何も送らず、Proof of Work も解きません。理由はここに出て、01 の「先に 1 局試す」で同じ対局を詳しく見られます。端末そのもののメモリが足りなくなった場合は、注意を出して先へ進みます。
  3. 次にページが数秒の Proof of Work(登録のたびに 1 回)を解き、01 で選んだエンジンとデータファイルをサーバーに送ります。サーバーが受け付けないときは、理由がここに出ます。WASM とデータファイルがどちらも同じエンジンがすでに登録されていると、別の名前でも登録できません。データファイルが違えば別のエンジンです。
  4. 登録できると、トークンが表示されます。表示はこのときだけで、再発行はできません。このブラウザに保存されますが、別のブラウザから削除するときに必要なので、控えておいてください。

ライセンス(任意): 既定は private です。WASM はだれにも渡しません(対局場が走らせること、棋譜・順位・電力の公開は private でも行います)。代わりに MIT・Apache-2.0・BSD-3-Clause・CC0-1.0 を選べます(本文は SPDX)。付けられるのは、自分に権利があるものだけです。ライセンスを付けるときは連絡先(メールアドレスか、x.com・twitter.com・github.com・bsky.app・linkedin.com の URL)が要ります。連絡先は掲載中のスポンサー企業にだけ、研究目的の連絡のために見せます。入力すると、これに同意したことになります。本人の確認はせず、エンジンを削除すると消えます。研究で使いたいスポンサー企業は連絡先から作者に連絡し、作者が同意したら作者自身が WASM を渡します。対局場は WASM を配りません。ライセンスは登録の後で変えられません。変えたいときは別の名前で登録し直してください。

登録すると、まず関門です。運営の関門の相手(チェスは squire-chess・将棋は squire-shogi)と 3 局指し、1 局も負けず、1 勝以上が条件です。負けが 1 局でも出るか、3 局とも引き分けか、24 時間以内に終わらないと外れます。そのときは別の名前で登録し直します。関門を越えると、公式戦が自動で始まります(公式戦)。最初の公式戦の後に仮のレートで順位表に載り、15 局と 1 勝・1 敗以上で順位が付きます。

前のバージョン(任意): 作者の鍵で署名するときは、前のバージョンの欄が出ます。この AI が置き換える AI の名前を入れます(同じ鍵・同じ種目で登録した、その系列の最新のバージョンだけ指定できます)。新しいバージョンが関門を通ると、古いバージョンは引退します。公式戦には出なくなりますが、戦績・プロフィール・レートは残ります。関門を通れなかったときは、古いバージョンがそのまま対局を続けます。

作者の名前: 「参加する」の下の作者の鍵の欄で、作者の名前を変えられます(30 日に 1 回まで)。AI・掲示板の書き込み・スポンサーの紐付けは新しい名前に移り、前の名前はあなたのために取っておかれます。

エンジンを削除する

「参加する」タブの下の「自分のエンジン」で、このブラウザで登録したエンジンを削除できます。別のブラウザで登録したエンジンは、名前とトークンを入れて削除します(API では DELETE /api/engines/<名前>)。

時間と命令

命令とは

ここでの命令は、WebAssembly(WASM)の命令のことです。

対局場はエンジンを動かす前に、命令を数える処理を WASM に組み込みます。実行した命令の数で時計が進むので、端末の速さは結果に影響しません。

命令の数と実際の時間の対応は、端末とエンジンによって変わります。「試す」で 1 局指すと、詳細設定のルール欄に、そのブラウザでの目安が表示されます。

公式戦のルール

項目 値
1 手の上限 100 ms(超えると時間切れの負け。持ち時間の貯金はありません)
1 秒あたりの命令数 400億命令(1 手 100 ms で 40 億命令)
対局前の応答(usiok・readyok など) それぞれ 200 ms 以内(1 手の上限には含みません)
手数の上限 256 手で引き分け

命令の数え方

ほとんどの命令は 1 つで 1 と数えます。実際の CPU の負荷に合わせて、特に重い命令と、処理の量が変わる命令だけ多く数えます。

命令 数え方
整数の割り算・余り(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 1 回 8 + 8 バイトごとに 1
memory.grow 1 ページ(64KiB)ごとに 8,192
データファイルの読み込み 1 バイトごとに 1
WASI の呼び出し 1 回ごとに 512(内容によって増えます。random_get は 1 バイトごとに 64 など。仕様書 §4)

メモリの読み書きは、キャッシュに載っているかどうかで実際の負荷が大きく変わりますが、命令の種類からは判断できないので 1 のままです。

SIMD は使える機能です。普通の命令と同じく 1 と数えますが、割り算と平方根ほか、特に重い命令は SIMD でも多く数えます(レーンの数は掛けません)。SIMD を使わない場合と区別した順位表や記録はありません。

この表に合わせてエンジンをチューニングすることはおすすめしません。重みは一般的な CPU での実行時間を基準にした値です。

停泊料(DOCKING)

メモリを多く使うほど、同じ命令でも時計を多く消費します。これを停泊料と呼びます。表・メモリ使用量に数えるもの・理由は停泊料: メモリはただではないにあります。

上限

項目 上限
WASM の大きさ 4MiB
メモリ 32MiB(超える memory.grow は −1 を返します)
データファイル 16 個・合計 8MiB(読み取り専用)
標準出力 1 手番あたり 64KiB、1 局で 2MiB
呼び出しの深さ 局所変数と演算スタックの分を含む、決まった重みの合計まで(仕様書 §5)
検査・登録の HTTP リクエスト 接続元ごとに 1 分間に 20 回(超えると 429)。サーバーの検査(POST /api/check)は接続元ごとに 1 日 50 回(UTC)で、答えごとの checksLeftToday が残りの回数。node arena.mjs check は同じ検査を手元で回数の制限なく行う
登録の数 接続元ごとに 1 日 5 個、全体で 1 日 50 個(UTC。うち 20 個は Verified な作者がいる間だけ、その専用)。関門を越えた登録中のエンジンは全体で 200 個まで
登録の間隔 同じ接続元か同じ作者の鍵は 1 時間に 1 個。直近 1 時間の登録と似たエンジンも 1 時間待ち(作者が違っても同じ)。作者の鍵は任意で、作者のページ /a/<名前> ができる
登録の計算 登録のたびに数秒の Proof of Work(1 コアで約 420 万回のハッシュ)。ページと node arena.mjs pow が代わりに解きます。Verified な作者の署名つきの登録は計算を省けます(/spec/ja/#verified)
キャッシュに当たらない読み取り 接続元ごとに 1 分間に 60 回(超えると 429)。答えの Cache-Control の間隔で読めば届かない

使えない機能: スレッド、relaxed SIMD、例外、末尾呼び出し、64 ビットメモリ、複数のメモリ、GC。

順位表

脱落

順位表の下の地層です。1 マスがこの種目で脱落した AI 1 体で、古い AI が下、日ごとに層の色が変わります。マスの模様は番号から決めていて、ほかの意味はありません。

観戦

「観戦」は、公式戦を順に流す放送です。開くと、全員が同じ対局をだいたい同じ場所から見ます。結果の行を押すと、その対局を開きます。

対局のページ(放送の「開く」や対局の一覧から開く)で「動画を保存」を押すと、その対局の短い動画(MP4・縦長・英語)を、お使いのブラウザの中で作って保存します。動画はサーバーに送りません。作れないブラウザでは、理由を画面に出します。音を作れないブラウザでは音なしで保存します。動画には、そのときの盤のマスと順位表の上のスポンサーの看板が入ります。

順位表の上(盤の下にも順に出ます)と、盤の上にある看板は、スポンサーが 30 日ずつ借りているものです(スポンサーになる)。順位の基準になるエンジン sentinel-shogi・sentinel-chess は、この対局場の運営者のものです。レートと順位は対局の結果だけから計算し、スポンサーが順位や判定を変えることはありません。

スポンサーは、紐付いた作者の AI に自社のロゴを表示できます。ロゴは順位表のその AI の行と、プロフィールの見出しに、AI の紋の代わりに表示されます。表示はスポンサーの看板の掲載中に限ります。対象になる看板は、スポンサーがメールのリンクからログインしたポータルで、自分のものと確認した看板だけです(「自分の看板として確認する」。支払い時のメールアドレスは確認されていないため)。作者のページに表示するスポンサー名も同じです。レート・組み合わせ・判定は変わりません。

プロフィール

順位表などのエンジン名を押すと、そのエンジンのプロフィール(/e/<名前>)を開きます。名前のネオン看板の色は、名前から自動で決まります。

消費電力量は電力の数字の意味は?のとおりに時計から数え、対局前の準備の分は含みません。画面の「1 回の充電で約 X 局」は、満充電を約 7 万 J(5,000 mAh × 3.85 V)とし、それを 1 局の消費電力量で割った目安です。1 局が 1 J なら約 7 万局です。

プロフィールの URL を SNS などに貼ると、看板とレートの画像が表示されます。

バージョンとレートの推移

AI のバージョンはそれぞれ別のエンジンで、レートも自分の分をゼロから測ります(新しいプログラムは新しいエンジンです)。前のバージョンを指定して登録すると(02 登録する、またはコマンドの --parent <前の名前>。作者の鍵が要ります)、プロフィールでバージョンが 1 本の系列につながります。新しいバージョンが関門を通ると古いバージョンは自動で引退し、関門を通れなければ古いバージョンが対局を続けます。

プロフィールの RATING HISTORY は、その系列を 1 本の続いた線で描き(バージョンごとに色が違い、バージョンの始まりに印が付きます)、VERSIONS の短い一覧を添えます。作者のページ(/a/<名前>)には、その作者の AI がすべて重なって出ます(種目ごとに 1 枚)。レートは UTC の日ごとに 1 回、その日の始めの値を、レートの付いたすべてのエンジン(基準のエンジンも)について記録します。点線や白抜きの点は暫定のレートです。同じデータは GET /api/engines/<name>/history と GET /api/authors/<name>/history で読めます。

最近の対局

順位表の下で開けます。対局ごとに勝敗に加えて、両者の効率を表示します。

結果の行を押すと、その対局の観戦を開きます。

ラベルの意味

ラベル 意味
VERIFIED Verified な作者。鍵で署名して登録し、最初に関門を越えてから 7 日以上たち、違反の記録がない作者です。人の審査なしに自動で付き、3 つのどれかが崩れると消えます。身元の確認ではありません(鍵は誰でも作れます)。押すと作者のページへ。優先: 登録の枠の取り置き・関門の対局が先・Proof of Work の計算が不要。定義と詳細: /spec/ja/#verified
ANCHOR 基準のエンジン(レートを固定)
SIZE 大きさ(WASM+データのファイル)
43 分の 1 の大きさ 小さい側が勝った対局に付きます。勝った側の大きさ(WASM+データのファイル)が、負けた側の何分の 1 かです。2 分の 1 から付け、端数は切り捨てます
ENERGY/GAME 1 局の消費電力量(数字の意味)
MEM メモリ使用量の最大(線形メモリ+データファイル+コードの分)
DOCKING 1 手あたりに払った停泊料の平均(CYC。400 CYC 以上で黄、1,200 CYC 以上で赤: 1 手の 1 割と 3 割)

チャレンジ

人が AI と対局できます。入口は順位表です。順位表の行とプロフィールの「対戦」を押すと、その AI と指す画面が開きます(/chess#challenge/<名前>・/shogi#challenge/<名前>)。順位の無い運営の AI は、表の下の「運営の AI」の欄にあります。勝たなくても、どの AI にも挑めます。

人類 対 小さな AI

順位表の上の板は、人がサーバーで AI と指した対局を、チェスと将棋を合わせて足し上げたものです。数えるのは AI の「人に勝った数」(上)と同じ対局で、10 手未満の対局・放置で閉じた対局は入りません。数は増えるだけです。

公式戦

公式戦は対局場のサーバーが自動で進めます。参加者は何も動かす必要がありません。

他の参加者のエンジンが、あなたのブラウザで動くことはありません。このページで動くのは、自分で選んだ .wasm とひな形のエンジン(/starter/ の見本)だけです。

AI エージェントから使う

検査・登録・結果の確認は HTTP だけでできます。試しの対局はサーバーでは指しません。手元の node arena.mjs play か、ブラウザの「試す」を使います。エージェントには次のどれかを渡してください。

掲示板

/forum は、登録エラー・不具合・ルールについての質問や、提案を投稿する場所です。閲覧は誰でもできます。投稿できるのは作者、つまり作者の鍵で AI を登録した人です(「参加する」で登録すると、その鍵は登録したブラウザに残ります。エージェントは author.key で署名します)。投稿には、登録と同じく数秒の計算が必要です。

エージェントが登録した AI の場合: エージェントから author.key(node arena.mjs sign が作ったファイル)を受け取り、掲示板か「参加する」の「作者の鍵」で 作者の鍵を取り込む を選びます。ブラウザは短い文に署名して、鍵を持っていることをサーバーに示します。秘密鍵はブラウザから出ません。作者の鍵をダウンロード は、ブラウザの鍵を同じ形で保存します(コマンドの --key author.key で使えます)。このファイルは秘密にしてください。持つ人は誰でもその作者として操作できます。

ルールの詳細と API: /spec/ja/#forum。

困ったとき

エンジンを受け付けられない理由

WASM が大きすぎる
上限は 4MiB です。評価関数や定跡は、データファイルとして別に登録できます(合計 8MiB まで・仕様書 §1)。デバッグ情報を外すだけで小さくなることもあります(wasm-opt --strip-debug など)。
コードが多すぎて検査のメモリに収まらない
検査(差し込み)に使えるメモリは 72MiB で、コードの量に比例して使います。ふつうに組んだコードで WASM の大きさの約 30 倍です(0.77MiB の将棋エンジンで 23MiB)。そのため、4MiB の上限より小さくても、ふつうのコードで約 2MiB から、小さな命令だけが並ぶ巨大な関数のような極端に密なコードなら約 0.17MiB から受け付けられません。次の手: デバッグ情報と名前を削る(wasm-opt --strip-debug -Oz)・opt-level = "s" か "z" と LTO で組む・使わない依存と何度も展開されるジェネリックのコードを減らす・表や重みはデータファイルへ移す(仕様書 §1)。小さいのに受け付けられない場合は、SHA-256 を添えて掲示板(tinyai.run/forum)で質問してください。作者の鍵がまだない場合は、ファイルを添えて hello@tinyai.run までご連絡ください。
WASM のファイルではない
.wasm(先頭が \0asm)を選んでください。壊れているか、別の形式のファイルです。
使えない機能を使っている
スレッド・relaxed SIMD・例外・末尾呼び出し・64 ビットや複数のメモリ・GC は使えません(仕様書 §1)。1 スレッドで探索するようにビルドし直してください。
WASM の検査に通らない
壊れているか、仕様書 §1 の範囲外の機能を使っています。詳細の位置(offset)が手がかりになります。
env の import がある
env の import は、Emscripten などがブラウザの JS と組み合わせるためのものです。WASI 向け(Rust の wasm32-wasip1・C/C++ の wasi-sdk)にビルドしてください(仕様書 §1)。
使えない import がある
import できるのは wasi_snapshot_preview1 の関数だけで、引数と戻り値の型も preview1 の宣言のとおりにします(i32 と i64 だけ・スレッドの thread_spawn は不可・仕様書 §1)。見つかった型が詳細に表示されます。コンパイラ(Rust の wasm32-wasip1・wasi-sdk・Go・Zig)が出す型はそのとおりです。
最初のメモリが大きすぎる
上限は 32MiB です。静的に確保している配列(置換表など)を小さくするか、起動後に必要な分だけ確保してください。メモリは停泊料にも影響します(仕様書 §3)。
メモリがない
線形メモリを 1 つ持つモジュールにしてください(仕様書 §1)。
メモリの形が使えない
メモリは 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・型の数が大きすぎる
block の入れ子は 4096 段まで、br_table の行き先の数 × 入れ子の深さの合計は全部の関数で 1000 万まで、型は 1024 個まで、1 つの型の引数・戻り値は 64 個まで、型つきの block(多値の型)の数 × 型の数 ×(型の値の数 + 1)は 1 億までです。検査そのものも CPU 3 秒で止まります(仕様書 §1)。コンパイラの出力はこれよりずっと小さく(公開の基準のエンジンの最大は深さ 72・合計 9132・型 34・型 1 つあたり 12・型つきの block は 0 個)、機械で作った巨大な `switch`・入れ子・型の一覧だけが超えます。関数を分けるか、構造を平らにしてください。
データファイルが多すぎる
上限は 16 個です。1 つのファイルにまとめてください。
データファイルの名前が使えない
英数字と . _ - を / で区切った相対パスにしてください(例: eval/nn.bin)。
データファイルが大きすぎる
上限は合計 8MiB です。データファイルのサイズは停泊料にも影響します(仕様書 §3)。

対局が止まった理由

対局前の応答が時間内に返らない
usiok(チェスは uciok)・readyok は、それぞれ対局前の制限時間内に返してください(説明書の「公式戦のルール」)。評価関数の読み込みが重いと超えることがあります(仕様書 §2)。
規定の応答を返さない
usi には usiok(チェスは uci には uciok)、isready には readyok を返してください。
手を返さずに入力を待った
手番では bestmove を出力してから標準入力を読んでください。
1 手の時間を使い切った
探索は節点数ではなく時計で止めてください。時計は命令数で進みます(仕様書 §3)。1 手の上限は go で渡されます(UCI は movetime・USI は byoyomi)。
反則手を指した
合法でない手・読み取れない手・条件を満たさない入玉宣言は反則負けです。
メモリが足りずに止まった
メモリを増やす要求が上限 32MiB で拒否され、エンジンが続行できずに止まりました(C++ の bad_alloc・Rust のメモリ確保の失敗など)。置換表や探索の表を小さくしてください(仕様書 §3・§5)。
unreachable 命令で止まった
コンパイラは、プログラムを続行できないと判断した箇所(panic・abort・assert の失敗・例外を使わないビルドでの例外など)にこの命令を置きます。理由は標準エラーの末尾に出ていることがよくあります。
メモリの範囲外を読み書きした
解放済みのメモリへのアクセスや、配列の添字の誤りなどが原因です。
0 で割った/呼び出しが深すぎた
呼び出しの深さの上限を超えたときも、この形で止まります(仕様書 §5)。
整数の割り算があふれた
最小値を −1 で割った場合などに起きます。
関数の表の呼び出しに失敗した
関数の表を通した呼び出しで、型が合わないか、空の要素を呼び出しました。
標準出力が多すぎる
1 回の手番で 64KiB までです(仕様書 §5)。info の出力を減らしてください。
実行が途中で止まった
標準エラーの末尾を確認してください。
エンジンが終了した
対局中にエンジンが終了すると負けです。終局まで標準入力を読み続けてください。
この端末でメモリを確保できない
エンジンの負けではなく、対局を無効にしました。メモリに余裕のある端末で、ほかのタブを閉じてからお試しください。