ブレインを作る
コンピューターの席を1つプレイする.oabrain。フォルダー、マニフェストの全キー、タグ、レベル、全視界、スクリプトが動く場所、予算、停止したときに起きること。
この章はdocs/brains/oabrain-standard.md、docs/brains/authoring.md、docs/playing-with-brains.mdの要約です。規範となるのはこれらのドキュメントです。
ブレインとは
既定はエンジン本来のコンピューターで、それはエンジンの中にあり続けます。ブレインがプレイするのはコンピューターの席1つで、それもプレイヤーが設定した席だけです。ブレインのIDが空なら、それは内蔵コンピューターを意味します。ブレインのない席、合わないブレイン、停止したブレインの席は、どれも同じ内蔵コンピューターがプレイします。ClassicはLuaで書かれ、内蔵コンピューターと同じようにプレイします。これは内蔵コンピューターを記述したもので、置き換えるものではありません。
スクリプトを実行するのはコンピューターを席に着かせたマシンだけなので、ほかのプレイヤーは何もインストールする必要がありません。ほかのプレイヤーのマシンは、その席のユニットをミラーするだけです。録画を再生するときは、スクリプトを実行しません。ブレインはLuaのソースとデータで、ネイティブコード、ファイル、ネットワーク、時計を持ちません。全視界はマニフェストのフラグです。ブレインはこれを設定でき、ネットワーク対戦でも使え、席にはそのフラグが表示されます。
パッケージ
ブレインは1つの.oabrainファイル、またはそのファイルを展開したフォルダーです。マニフェストはMODプロファイルと同じ厳格なYAMLで、ドキュメントは1つ、最上位は1つのマッピング、アンカーとブロックスカラーは使えません。パッケージの最上位にはoabrain.yamlを置きます。その隣に置けるファイルは、次のいずれかです。このリストにないファイルは拒否されます。
my-brain.oabrainプレイヤーが入手するファイル├─ oabrain.yaml必須 マニフェスト。最大256 KiB├─ brain.luaエントリスクリプト。既定の名前はbrain.lua。entryで別のものを指定でき、そのファイルはパッケージ内にある必要がある├─ lua/そのほかのLuaソース。requireが読むのはこれらのファイルだけ。各部分は小文字、数字、_├─ nets/マニフェストが指定するネットワーク。nets/と、.oannで終わる名前├─ data/データ表1つ。1階層まで。.csv、.tdf、.json、.txt├─ icon.png画像。iconで指定したときだけ。そのキーがなければ、このファイルはリスト外├─ README.md最上位のメモ。ゲームは読み込まない└─ LICENSE最上位のライセンス。licenceという名前と、サブフォルダー内のreadmeはリスト外比較ではASCII文字の大文字と小文字を区別しません。ただし、規格がバイトの一致を求める箇所は除きます。entryが別のファイルを指定しているとき、brain.luaはリスト外になります。Luaファイル1つは最大1 MiBです。アイコンは正方形のPNGで、1辺は最大256ピクセル、サイズは最大256 KiBです。OAは、ブレインをBrains/の下の、マニフェストのIDのフォルダーにインストールします。
マニフェスト
読み取り側は違反しているルールをすべて集めます。1つでも違反があれば、マニフェストは変更されずに残ります。規格にないキーは拒否されます。プロファイルのキーはMODに書くものです。ミューテータのキーは、ミューテータのキーとして拒否されます。バージョンは引用符で囲んでください。ただの1.0は数値になります。星印も引用符で囲んでください。ただの星印はYAMLのエイリアスになります。
| キー | 必須 | 内容 |
|---|---|---|
oabrain | はい | 形式。整数の1。1.0や、引用符で囲んだ1は拒否されます。 |
id | はい | 小文字のケバブケースで1〜64バイト。先頭や末尾のハイフン、連続したハイフンは使えません。Brains/の下のフォルダー名です。 |
name | はい | 1〜64バイトで、制御文字は使えません。プレイヤーに表示される名前です。 |
version | はい | 引用符で囲み、1〜3個の部分からなる、ミューテータと同じ形式のバージョン("2.0"など)。ただの数値は拒否されます。2、2.0、2.0.0は等しいものとして比べられます。 |
author | はい | マッピング。nameは必須で1〜128バイト。emailは任意です。 |
description | はい | 必須。1〜2,000バイト。改行は使えますが、それ以外の制御文字は拒否されます。最初の行を200バイトで切ったものが概要です。 |
homepage | いいえ | httpかhttpsのアドレス。 |
icon | いいえ | パッケージ最上位の画像icon.pngだけ。それ以外は拒否されます。 |
tags | はい | 下の9つのタグから1〜4個。重複は不可。 |
works-with | はい | 1〜32個の条件で、同じIDは2回使えません。星印はすべてのMODとベースゲームを意味し、その場合はそれが唯一の項目になります。ta-3.1cはMODなしのベースゲームです。それ以外のIDはMODで、バージョン範囲を付けることもできます。 |
requires | いいえ | engineとexpansionsだけです。engineは範囲で、「>」で始まる場合は引用符で囲みます。expansionsは1〜16個のバンドルIDです。ブレインはミューテータを必要条件にできません。 |
levels | はい | 1〜6個のレベル。各マッピングは、id、name、difficultyのちょうど3つです。 |
fullAwareness | いいえ | trueかfalse。省略するとfalseです。引用符で囲んだtrueは拒否されます。 |
networks | いいえ | 1〜16個。それぞれid、file、sha256のちょうど3つ。fileはnets/と、.oannで終わる名前。sha256は引用符で囲んだ64桁の小文字の16進数です。 |
options | いいえ | 最大16個で、ミューテータのオプションと同じルール。トグルはtrueかfalse、数値は数値、選択肢はそのテキストです。me.optionsで読みます。 |
strings | いいえ | 最大16言語。各言語にname、description、options、labels、levelsを入れられます。 |
entry | いいえ | パッケージ最上位のLuaファイルで、名前は小文字、数字、_。省略するとbrain.luaです。 |
9つのタグ
タグはこの9つのいずれかで、バイト単位で比較されます。共通のタグルールを満たしていても、4個を超えていれば、それ自体が独立した問題として扱われます。9つにないタグは拒否されます。
| キー |
|---|
classic |
economy |
rush |
turtle |
air |
naval |
learned |
teaching |
experimental |
レベルと難易度
levelsは1〜6個のマッピングのリストです。それぞれid、name、difficultyのちょうど3つで、すべて必須です。idは1〜32バイトの小文字のケバブケースで、重複は不可。nameは制御文字を含まない1〜64バイト。difficultyはeasy、medium、hardのいずれかで、バイト単位で一致する必要があります。
この3つの名前は、値0、1、2にあたります。レベルを選んだ席は、その値を収入ルールに使います。ゲームがすでに使っているのと同じ難易度です。
全視界
fullAwarenessはtrueかfalseです。省略するとfalseです。このフラグを持つブレインは、内蔵コンピューターと同じく、霧の中の席には見えないユニットまで見え、建設地点の確認に配置するプレイヤーを必要としません。このフラグはネットワーク対戦でも使えます。ライブラリにはTotal Annihilation本来のコンピューターと同じく、マップ上の全ユニットが見えると表示されます。フラグはマニフェスト自身のもので、パッケージのIDによって与えられるものではなく、Classicだけに与えられるものの1つでもありません。
ブレインが動く場所
パッケージが必要なのは、コンピューターを席に着かせたマシンだけで、スクリプトを実行するのもそのマシンだけです。席とは、そのマシンのコンピューターのことです。人間の席は拒否されます。game.modeはskirmish、campaign、networkのいずれかです。
| 状況 | 実行されるもの |
|---|---|
| スカーミッシュ | このマシンがプレイする各コンピューターの席のうち、プレイヤーがブレインを設定した席。IDが空なら内蔵コンピューターです。 |
| キャンペーンのミッション | キャンペーンの席は、プレイヤーが設定した既定のブレインに従います。ミッションがその既定を無視することはありません。 |
| ネットワーク対戦 | コンピューターの席を持つマシンが、全視界も含めてブレインを実行します。ほかのマシンは実行しません。 |
| 後でロードしたセーブデータ | セーブデータは各席のブレインを記録しています。パッケージがない場合やバージョンが違う場合にどうなるかは、規格に書かれています。 |
| 録画の再生 | 録画にはブレインの情報がテキストで保存されます。再生は記録されたパケットを適用するもので、ブレインを席に着かせず、フックも呼びません。 |
| デスマッチまたはトーナメント | 起動時にコンピューターは席に着きません。 |
席がプレイするブレインは、シミュレーションハッシュの入力に含まれません。どのブレインを席に着かせたかだけが違う2つの対戦は、同じ対戦状態ハッシュを保ちます。MODのai.*ハックの値は、そのハッシュが対象とするMODプロファイルの一部なので、変わらずすべてのマシンに届きます。
ランタイムの予算
ブレインは1つのサンドボックス内でLuaとして実行されます。2つのブレインが、モジュール、グローバル変数、予算を共有することはありません。スクリプトはファイル、時計、環境変数、プロセス、ネットワークを持ちません。チャンクはすべてテキストとして読み込まれます。pcallやxpcallで、使い切ったフェーズを生き延びさせることはできません。ターンとは、ユニットの巡回処理の後、席のコントローラー処理の時点で行われる、貯めた予算を使う1回の呼び出しです。フックが出した命令は次のティックで有効になります。
| 予算 | 値 |
|---|---|
| load、fits、start、save、reportでの命令数 | 50,000,000 |
| 1ティックで加わる命令数 | 2,000,000 |
| 貯められるティック数(現在のティックを含む) | 30。そのため残高は60,000,000から始まる |
| Luaのメモリ | 64 MiB(67,108,864バイト)。フェーズ間でリセットされない |
| ネットワークのメモリ | 64 MiB。Luaの上限とは別 |
| 実時間:ターン以外のフェーズ(ミリ秒) | 10,000 |
| 実時間:1ターン(ミリ秒) | 250 |
| 文字列1つ(バイト) | 65,536 |
ブレインが停止するとき
ブレインが停止するのは、フックかタイマーでのエラー、命令数の上限の使い切り、実時間の安全上限、Luaのメモリ上限、65,536バイトを超える文字列、席が拒否する読み込みのいずれかが起きたときです。失敗したターンは、そのターンが戻る前にサンドボックスを閉じ、フックを消去します。失敗したターン自体はプレイ済みとして数えられます。次の命令ティックにはフックがないので、内蔵コンピューターがそれを引き継ぎます。拒否された、開始に失敗した、または合わないブレインはフックを持たないので、最初から内蔵コンピューターがプレイします。通知にはマニフェストの名前と、160バイトで切った理由が使われます:
- `{brain} stopped ({reason}); the engine plays this seat on`
- `{brain} could not start ({reason}); the engine plays this seat`
- `{brain} does not fit this game ({reason}); the engine plays this seat`
席に固有の理由がない場合、理由はthe brain could not be seatedです。敗北したプレイヤーは、単にそれ以降呼び出されなくなります。サンドボックスは対戦の終了とともに閉じます。