ホーム › MOD制作情報 › ブレインを作る
第07章

ブレインを作る

コンピューターの席を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です。敗北したプレイヤーは、単にそれ以降呼び出されなくなります。サンドボックスは対戦の終了とともに閉じます。