Scalatronについて発表しました + 私家翻訳版 Scalatron Game Rules
発表しました
FiS Projectという大学の学生・OB有志でやってるサークルがあるのですが,そこでプログラミング言語Scalaを使ったプログラミングゲームであるScalatronについて発表してきました.
自分自身,Scalaは初心者なのでちゃんと説明できたか不安な所はありますが,発表した感触はおおむね好評でメンバーから「やってみたい」という声も聞けましたし,一応布教には成功できたのかなと思います.
ところで,この手のゲームは人口が増えないとイマイチ盛り上がらないと思います.ですが今のところ英語のドキュメントしかありませんので,このままでは日本では流行らないんじゃないかなぁと思います.そこで,Scalatronのゲームのルールについて和訳したものを公開します.gistにも置いてあります.
まともに英語を勉強したことが無いので間違いが含まれている可能性があります.誤訳などお気づきになりましたら,コメント欄などで指摘していただけると嬉しいです.
他のドキュメントについても,今後順番に和訳していく予定です.
補足訂正 (2012-07-24)
スライド10ページ目で「オブジェクト指向は手続き型の延長線にある」と書きましたが,本来は両者は直行する概念ですので正しくない表現です.
例えば,Common Lispは一般に関数型言語に分類されますが,Common Lispではオブジェクト指向プログラミングの機能を提供する Common Lisp Object System がありますし,オブジェクト指向プログラミング言語が必ずしも手続き型であるとは限りません.
ただ,今回の発表で用いた「オブジェクト指向」とはJavaのような手続き型のオブジェクト指向プログラミング言語のことだけを想定して書いたためこのような表現になってしまいました (言い訳).
私家翻訳版 Scalatron Game Rules
Scalatron について
Scalatron は,プログラミング言語Scalaについてより学びたい,もしくはScalaのプログラミングスキルを磨きたいプログラマのための教材で す.Scalatronは,他者がプログラムした (Scalaで書かれている) ボットを倒す多人数参加・対戦プログラミングゲームである,Scalatron BotWarを主としています.
チュートリアルやソースコードといったドキュメントはコミュニティ資源として意図的にパブリックドメインにしてあります.遠慮なく使用,複製,改良して構いません!
概要
各ボットの振舞いは,入力 (ボットが認識したもの) から出力 (どのように反応するか) を対応付けているコントロール関数を実装したプログラム片によって決められます.ゲームサーバは非プレイヤーキャラクタ(動物)を操作します.
プレイヤーのボットは有害な動物から逃げ,食用となる動物を狩り,有用な植物を収穫し,毒のある植物を避けることによってエネルギーユニット (EU) を集めることが任務です.壁はボットや動物の移動を防げる障害物として存在します.ラウンドの終わりの時点で,回収したエネルギーが最も高いプレイヤーが 勝者となります.
Scalatronゲームサーバはラウンドからラウンドへ継続的に動作します.各ラウンドは設定したステップ数(通常はおよそ10,000ステッ プ,約3分)の間続きます.各ラウンドのはじめに,共通の共有ディレクトリ下のプラグインディレクトリ中にあるJava .jarアーカイブからファクトリがロードされ,ボットのコントロール関数のセットが作成されます.
ゲームが開始すると,各エンティティを制御している各プレイヤーのコントロール関数が周期的に呼び出されます.入力は,エンティティ名,ボットが認 識できるゲーム環境のASCII表現,およびボットが利用可能なエネルギーを含んだ文字列で構成されています.フォーマットは非常にシンプルです.
クレバーな計算をいくつか実行した後,コントロール関数は適切にエンコードされた命令を含む,新しい文字列をサーバに返すことで応答します.命令は,ボットを左に1歩移動させる,新しいミニボットを生成する,といった様々なことをリクエストすることが可能です.
アリーナとエンティティ
アリーナ
-
アリーナは有限の,矩形状のセルの格子で構成されています.アリーナの大きさは開始時に設定可能です.
-
アリーナの完全な大きさはプレイヤーには知らされませんが,ボットのビューよりは大きいことは保証します.
-
アリーナは環状であり,縁で自分自身に戻るようになっているため,ゲームのエンティティからはアリーナは無限に大きいと認識します (つまり,片側からはみ出すともう一方の片側に戻る,アリーナの片側の外を見るともう一方の片側が見える,というようになります).
-
二つのエンティティが同時に同じセルを占有することはできません.したがって,すべての移動は他のエンティティと衝突する制約が課されます.この制約によって,ゲームの世界を (セルごとに一文字を使って) 非常に簡単に表現することができます.
-
座標系の原点は左上です.
プレイヤー
-
ゲーム内では,ファクトリによってインスタンス化されるコントロール関数が,各プレイヤーの代わりを務めます.ファクトリは共通のネットワーク共有ディレクトリ下にある,プレイヤー固有のディレクトリに置かれたプラグインからロードされます.
-
各プレイヤーのコントロール関数は1体のマスターボットと0体以上のミニボットを制御します.
-
プレイヤーが利用可能なコマンドについては"Control Function Protocol"のドキュメントにおいて説明しています.
エンティティタイプ
ゲームには以下のエンティティタイプがあります.各項目の詳細は次節で説明します.
- ボット -- プレイヤーのマスターエンティティ
- ミニボット -- プレイヤーによって制御されるスレーブエンティティ
- フラペット -- 有益な動物 (可動,食用,コンピュータが操作)
- スノーグ -- 有害な動物 (可動,敵性,コンピュータが操作)
- ジュガー -- 有益な植物 (固定,食用)
- トキシフィラ -- 毒性の植物 (固定,有害)
- 壁 -- 固定の障害物
エンティティの詳細
(マスター) ボット
-
マスターボットは1000EUの初期エネルギーを得てスタートします.
-
マスターボットはゲーム環境の限られた範囲を認識します.現状では,ボットのビュー(視界) には以下のセルが含まれます.
- ボットがいるセル
- 各方向15歩の範囲で隣接しているすべてのセル
-
このビューの大きさは31x31セルです.ビューの中心は常にボットがいるセル,すなわち(15,15)の位置になります.
-
ビューの厳密な大きさは,バリアントや将来のゲームのバージョンで変わるかもしれませんが,原則的にビューは常に正方形かつ辺は奇数個のセルの長さをとります.これは解像度に依存しないビューパーザをボットに実装することを可能にするためです.
-
画面に表示されるボットの名前は,それがロードされたプラグインディレクトリの名前です.これはすべてのボットが,プラグインディレクトリの所有者であるプレイヤーに確実に関連付けられるからです.
-
ボットのコントロール関数に渡される
generation
パラメータは常に0です. -
ボットは任意の名前の状態プロパティを保持することが可能です.状態の保持はサーバに移譲しているため,コントロール関数はステートレスです.
-
ボットは以下の動作を行うことができます:
- Move() -- いずれかの方向に一歩移動します
- Spawn() -- ミニボット (スレーブエンティティ) をボットの隣に生成します
- Say() -- 'パンくず'テキストをアリーナに残します
- Status() -- ボットの上に表示する状態メッセージを設定します
- Set() -- ボットが保持する状態パラメータを設定します
- Log() -- 状態パラメータのデバッグ用のログメッセージを書き込みます
コマンドは "Control Function Protocol"のドキュメントで詳しく説明しています.
-
マスターボットは生存や移動にエネルギーを消費せず,死ぬこともありません.
-
マスターボットは,画面上ではボット毎に一意な明色の組合せによる,カラフルな大丸として表されます.
ミニボット
-
ミニボットはマスターボットにより生成され,常にマスターと関連づけられています.マスターボットがミニボットを生成するためには,少なくとも100EUのエネルギーをミニボットに与える必要があります.
-
ミニボットもまた,マスターボットと比べて少し小さい,限られた範囲のゲーム環境を認識します.このミニボットのビューは,現状では以下のセルを含みます:
- ミニボットがいるセル
- 各方向10歩の範囲で隣接しているすべてのセル
-
このビューの大きさは21x21セルです.ビューの中心は常にミニボットがいるセル,すなわち(10,10)の位置になります.
-
周囲を観測することに加えて,ミニボットはマスターボットからの相対位置を認識することが可能です.これはコントロール関数への入力の一部 として提供されます.これにより,ミニボットはエネルギー (例えば,植物や動物から回収したもの) の再吸収・転送等のために親のボットの元へ帰還することができます.
-
ボットが新しいミニボットを生成するとき,この新しいスレーブエンティティに名前を付けることができます.この名前は毎リクエスト時にコントロール関数へと戻されます.コントロール関数はいつでもこのスレーブの名前を変更することができます.
-
ミニボットは,常にそれらを生成したエンティティの
generation
より1つ高いgeneration
の値を持ちます.マスターボットから生成されたミニボットは1のgeneration
を持ち,それらから生成されたミニボットは2のgeneration
を持ちます. -
マスターボットのように,ミニボットは任意の名前付き状態プロパティを保持することが可能です.状態の保持はサーバに移譲しているため,コ ントロール関数はステートレスです.ミニボットの状態プロパティは,それを生成するエンティティから望みの振舞いに関する情報を渡すことで初期化すること ができます.
-
ミニボットは以下の動作を行うことができます:
- Move() -- いずれかの方向に一歩移動します
- Spawn() -- 子のミニボット (N代目のスレーブエンティティ) を生成します
- Explode() -- ミニボットのエネルギーを自爆の威力に変換します
- Say() -- 'パンくず'テキストをアリーナに残します
- Status() -- ボットの上に表示する状態メッセージを設定します
- Set() -- ボットが保持する状態パラメータを設定します
- Log() -- ボット固有のコンテナの中にデバッグ情報を記録します
コマンドのさらなる詳細は Scalatron Protocol のドキュメントで説 明しています.
-
ミニボットはボットの2倍の周期で動作するため,命令の送信や他のボットを狙うといったことを,それらが圏外になる前に行うことができます.
-
ボットとは違って,ミニボットは単に存在するだけで4周期に1EUのエネルギーを消費します.エネルギーを使い果たした場合,それらは消滅します.例として,デフォルトの100EUのエネルギーを持って生成されたミニボットは,ゲームの400ステップ後に消滅します.
-
ボットとは違って,ミニボットは敵のボットやミニボット,動物を攻撃するなどのために,自爆することが可能です.爆発による爆風の半径は実行時にミニボットによって決定され,爆発によって与えたダメージはそのミニボットのマスターボットに勘定されます.
-
画面上では,ミニボットはそれらのマスターボットと同じ明色の組み合わせですが,ずっと小さく表れます.
フラペット (良い動物)
フラペットは臆病ですが栄養価の高い小動物で,アリーナをボットの半分の速さで動き回っています.彼らはボットに狩られると毎回200EUのエネル ギーのボーナスとなります.エネルギーは衝突することで回収できます.つまり,ボットがフラペットのいるセルに踏み込むことで得られます.
フラペットは内気で神経質です.彼らはボットの接近に気づくとすぐに逃げていきます.彼らは限られた視界を持っていますが,ボットより遅いため,比較的確実な餌であります.
ありがたいことに,フラペットが狩られるとすぐに新しいそれがランダムな場所に誕生するため,フラペットは十分な数が常に存在しています.
ボットが活躍していくにつれ,フラペットもまたボットの匂いをよりよく検知し,逃げていきます.下位25%のプレイヤーはフラペットのすぐ近く (6セル) まで接近してようやく気づかれます.上位25%のプレイヤーは遠くの距離 (80セル以上) から気付かれます.
画面上では,フラペットは青い点で表されます.
スノーグ (悪い動物)
スノーグはマヌケですが非常に凶暴な動物で,ボットの肉を探しながらアリーナ内をうろつき回っています.彼らはボットに気づくや否や,噛みつこうとすぐに追いかけてきて,噛みつかれると150EUのペナルティとなります.
スノーグは群れで行動しますが,彼らはボットより遅いです.適切なタイミングで回避行動をとれば,無傷でスノーグの襲撃から逃れることができるでしょう.
スノーグは強大ですが,彼らの生命エネルギーは有限です.7回噛みつかれるた後にスノーグは死にます.とはいえ,スノーグが死ぬとすぐに新しいそれがランダムな場所に誕生するため,スノーグは十分な数が常に存在しています.
ボットが活躍していくにつれ,スノーグもまたボットの匂いをよりよく検知し,襲いかかってきます.下位25%のプレイヤーはフラペットのすぐ近く (6セル)まで接近してようやく気づかれます.上位25%のプレイヤーは遠くの距離 (80セル以上) から気付かれます.
画面上では,フラペットは赤い点で表されます.
ジュガー
ジュガーは栄養のある植物で,アリーナのいたるところに植生しており,ジュガーが摘み取られてもすぐに新しいそれがランダムな場所に生えてくるた め,ジュガーは十分な量が常に存在しています.これらは摘み取る (これに踏み込む) ことで100EUのエネルギーを増加させ,歩き回るボットやミニボットを回復します.
植物が通常そうであるように,これらも動き回ることはありませんが,食べられるまで生えている場所に存在し続けます.
画面上では,ジュガーは緑色の点で表されます.
トキシフィラ
トキシフィラはひどく,不愉快な臭いを放つ毒性の植物で,動き回るボットを刺します.トキシフィラに踏み込むことは,ボットやミニボットを傷つけ,100EUのエネルギーを失うこととなります.
植物が通常そうであるように,これらも動き回ることはありませんが,食べられるまで生えている場所に存在し続けます.
画面上では,トキシフィラは黄色の点で表されます.
壁
壁はゲームの最初から存在し,完全に固定かつ不動で,最後のボットがアリーナに出現した後から存在し続けます.壁にぶつかることは10EUのペナルティとなります.
衝突
エンティティ同士の衝突は,ゲーム内で効果を及ぼします.これは移動の実行と同時にテストされます.移動の順番は (プレイヤー側から見れば) 決まっていません.2つのエンティティが同時に同じセルに移動しようとしたとき,最初に処理された一方は移動し,遅いもう一方は失敗します.
衝突の詳細
注釈:以下の表において,"bonk" はエンティティが衝突して移動が失敗するこ とを意味します.
- マスターボットが ... と衝突
- 自分自身のミニボットのひとつ => ミニボットは消滅, エネルギーはボットへ加算
- 他プレイヤーのマスターボット => bonk
- 他プレイヤーのミニボット => +150, ミニボットは消滅
- ジュガー => +100, 植物は消滅
- トキシフィラ => -100, 植物は消滅
- フラペット => +200, 動物は消滅
- スノーグ => -150, bonk, 動物にもダメージ
- 壁 => bonk, 4周期分行動不能, 10EUを失う
- ミニボットが ... と衝突
- 味方のミニボット => bonk
- 自分のマスターボット => ミニボットは消滅, エネルギーはボットへ加算
- 他プレイヤーのマスターボット => ミニボットは消滅, 保持エネルギーは失う
- 他プレイヤーのミニボット => 両方消滅, 保持エネルギーは失う
- ジュガー => +100, 植物は消滅
- トキシフィラ => -100, 植物は消滅
- フラペット => +200, 動物は消滅
- スノーグ => -150, bonk, 動物にもダメージ
- 壁 => bonk, 4周期分行動不能, 10EUを失う
- フラペットが ... と衝突
- いずれかのプレイヤーのマスターボット => 動物は消滅, ボットは +200 を得る
- いずれかのプレイヤーのミニボット => 動物は消滅, ミニボットは +200 を得る
- ジュガー => bonk
- トキシフィラ => bonk
- フラペット => bonk
- スノーグ => bonk
- 壁 => bonk
- スノーグが ... と衝突
- いずれかのプレイヤーのマスターボット => 動物にダメージ, ボットは -150 を得る
- いずれかのプレイヤーのミニボット => 動物にダメージ, ミニボットは -150 を得る
- ジュガー => bonk
- トキシフィラ => bonk
- フラペット => bonk
- スノーグ => bonk
- 壁 => bonk
爆発
ミニボットは自爆による爆発で他のエンティティにダメージを与えることができます.この爆発の影響は以下のように計算されます:
- energy = 自爆するミニボットの現在のエネルギーレベル
-
blastRadius = Explode() オペコードで指定された, 2 <= x <= 10 の範囲の半径
-
blastArea = blastRadius * blastRadius * Pi
-
energyPerArea = energy / blastArea
-
damageAtCenter = energyPerArea * (-200 EU)
-
distanceFromCenter = 自爆するミニボットから,影響を受けるエンティティまでの距離
-
damageForEntity = damageAtCenter * (1 - (distanceFromCenter / blastRadius))
-
actualDamage = 影響を受けるエンティティが実際に利用可能 (!) なエネルギーで制限された damageForEntity の値
影響を受けるすべてのエンティティのダメージがの総和が,自爆したミニボットを生成したマスターボットへ勘定されます.爆発は,マスターボットによって生成されたボットやマスターボット自身に対してはダメージを与えません.
例A
100EUを保持するミニボットが5セルの半径の爆風をもって自爆したとき:
- blastArea = 5*5*3.14 = 78.5
- energyPerArea = 100/78.5 = 1.274
- damageAtEpicenter = -200*1.274 = 254.7
3セルの距離にいる他のプレイヤーのボット:
- damageForEntity = 254.7*(1-3/5)) = 101.9
ダメージを受けるボットが80EUしか保持していない場合:
- actualDamage = 80 EU
例B
ミニボットが自爆して付近の4エンティティが影響を受けるとき:
- 他プレイヤーのマスターボットに80 EU
- 他プレイヤーのミニボットに50 EU
- 付近のスノーグに40 EU
- 遠くのフラペットに30 EU
ミニボットを生成したマスターボットは200EUを獲得.
戦略
ゲームルールはシンプルで限定されたものではありますが,Scalatron ボットがアリーナで上手くやるためには複雑で多様な戦略を用いる必要があります.あなたの発想を促すため,ここにいくつかの戦略と戦術を例を示します.
ミサイルディフェンス
ビューの中に他プレイヤーのボットを検出したら,ボットはミニボットをミサイルとして使うため Spawn() コマンドを実行します.ミニボットは検出した敵ボットとの相対位置をパラメータ (処理しやすいようにエンコードして,ミニボットの名前の中に設定して,コントロール関数に渡されるパラメータとして使用しす) として受け取り,その位置に向けて(Move() コマンドを発行して目標の方向へ)移動させます.敵ボットに接近したことをミニボットのビューで検出したら,Explode() コマンドを発行し,保持しているエネルギーを爆発力に転換します.もし爆発によって敵ボットにダメージを与えられれば,そのダメージはマスターボットのエ ネルギーとして勘定されます.
フードフェッチャー
食料となるアイテム (フラペットあるいはジュガー) をビューで検出したら,ボットは ミニボットを収穫ドローンとして使うために Spawn() コマンドを実行します.ミニボットは検出した食料アイテムとの相対位置を初期目標位置として受けとり,その位置に向けて移動し,進路にある食料アイテムを 回収しながら接近します.やがてしきい値 (例えば1000EU) に逹っしたら,ミニボットはマスターボットとの相対距離 (コントロール関数に渡されます)を使って帰還し,回収したエネルギーをマスターボットに転送します.
ウォールプランター
ミニボットを他のプレイヤーのボットに対する障害物として,適当な場所に次々に素早く並べていきます.
マインレイヤー
ミニボットを,他のプレイヤーのボットが接近したらただちに自爆するトラップとして設置していきます.
フラペットハーダー
フラペットの群れの周囲にミニボットを展開して,追い込む (herd) ように移動させます.フラペットはミニボットから逃げていくので,マスターボットでこれらを回収します.
スノーグテンプター
1対以上のミニボットを使ってスノーグを引き付けるように歩き回り,他プレイヤーのマスターボットの方へと引き離しておきます.