レベル: 初級 Sing Li (westmakaha@yahoo.com), Author, Wrox Press
2004年 6月 29日 「城を防御せよ!土地を占領せよ!ナイト達は勇敢に戦い、敵を撃破するのだ。敵側の脅威的なナイト達を回避しつつも、敵陣を攻め落として敵地を略奪するのだ!」もしも日常的で面白味の無いJavaコードの作成のおかげでここのところ憂鬱な気分になっているのでしたら、ここで中世風味のファンタジーを再現するのもひとつの手かも知れません。Javaプログラミングのスキルに磨きをかけ、Eclipse開発環境をマスターしながら、同時に自分自身の世界に存在する王国を支配できるのです。至高のCodeRulerを使い、一日中一生懸命に頑張れば、スキル習得と領地収得の勝利と栄光は全てあなたのもの。戦争シミュレーションの熱狂者、Sing Liは、究極の王国支配への王道へとあなたをいざないます。
2004 ACM International Collegiate Programming Competition(参考文献を参照)にて登場したCodeRulerは、IBM alphaWorksが提供する最新のファンタジー系ゲーム・シミュレーターの野心作です。このゲームは単純な前提の上で成り立っています。プレイヤーは中世世界の王国の支配者。プレイヤー率いる農民とナイト達は、生存、繁殖、そして繁栄のために、プレイヤーの持つ洗練された戦略的思考、臨機応変な適応能力、そして優れたJavaプログラミングのスキルに全てを任せて委ねます。王国の支配者をシミュレートするJavaコードを書き出すのが、プレイヤーの持つ使命です。このゲーム・シミュレーターはプレイヤーの操作する支配者を最大6体の別の支配者(または同梱されているサンプル支配者)を相手に戦わせ、勝者を決定します。
この記事は、プレイヤーを中世世界の王国支配に導く近道へといざないます。記事はゲーム環境を明らかにし、ルールを説明し、一般的な戦術を考察し、そして既に完全であり直ぐに使用や修正が可能な機能中の支配者のエントリーを2つ提供します。
シミュレーション環境
CodeRulerは、グラフィカルでアニメーションの入ったシミュレーション・ゲーム環境です。中世世界の支配者として、プレイヤーは領地と支配のために他の支配者を相手に戦います。あなたの王国を成すものは、以下の通りです。
- 土地を占領し耕す農民。
- 戦闘に参加でき、敵国の農民、ナイト、そして城を捕獲できるナイト。
- ナイトと農民を生産できる城。占領した土地が広大であれば、生産速度も上昇します。
グラフィカルなゲームの世界
2-Dの王国マップに表現される世界で、ゲームは進行します。(背景にある地形のスケッチはただの壁紙としてしか機能せず、ゲーム性に影響を及ぼしたりゲームの進行に伴い変化しません。)図1は、CodeRulerのゲーム進行の様子を表しています。
図1. CodeRulerのゲーム進行画面
図1は2国間の衝突を表しています。支配者(ゲーム中の駒の戦略的行動を裏側から操作する軍師)は、このゲームの世界の画面には直接登場しません。ゲーム駒(農民、ナイト、そして城)は、シミュレートされた世界(表舞台)の中を動き回る色付きのドットです。駒の形状そして移動可能な方向を示す図解を図2に示します。
図2. CodeRulerのゲーム駒の移動パターン
図2を見れば一目瞭然ですが、ナイト(knight)と農民(peasant)の移動パターンは同じです。ナイトと農民は、それぞれのターンにて8方向のうちの1方向にマス目1つ分だけ移動できます。それぞれの方向には関連番号(Javaコーディングで使用します)が振られています。それぞれの番号にはコード上で使用できる定義済み定数(例: 北西を意味するNW)が与えられています。
コンソール上のスコア表示
図1の右側にステータス・コンソールがあるのがおわかりでしょう。プレイ中の支配者の名前、そして支配者が所属する組織名がコンソールの上の方に表示されます。表示された2つの番号のうち、左側が支配者の現在スコアで右側は農民が占領したマス目の数(占領地の面積)です。図3は、スコア表示の例を示します。
図3. コンソール上のスコア表示
図3を見れば、支配者「#18」はIBM developerWorksに所属しSimple Rulerと呼ばれています。この支配者の現在のスコアは123で、774マス分の土地を王国の支配下に置いています。右上にある赤色の「X」をクリックすることにより、いつでも好きなときにシミュレーションを中断できます。
占領地の概観表示
図1にて示されるステータス・コンソールの中心付近に、ゲーム世界の縮図が表示されているのがおわかりでしょう。図4にて再現されているその縮図を活用すれば、それぞれの支配者の占領状況を一目で把握できます。図4を見れば、青色で表示された支配者がマゼンタ色で示される支配者よりもはるかに広大な土地を占領しているのが一目瞭然です。
図4. 占領地の概観表示
シミュレーション・クロック
図1の右側に表示されるステータス・コンソールの下にあるのは、クロック(時計)です。図5にてその拡大図を示します。
図5. CodeRulerのクロック
太陽は時計の文字盤の周囲を回ります。太陽が一周すれば、対戦終了です。時計が1つ時を刻むたびにシミュレーターのターンが進みます。それぞれのターンで、プレイヤーは支配者として駒の行動を決定します。
戦闘のルール
それぞれの支配者は、ゲーム開始の時点で以下の駒を支配下に置いています。
ゲーム進行中、下記の項目に注意したいものです。
- 自軍の農民を活用し、出来る限り広大な土地を占領しましょう。(一度入手した領地を失わないように。)
- 自軍のナイトが敵軍の農民を出来る限り多く捕獲するようにして、敵側による占領を防ぎましょう。
- 自軍のナイトが、可能な限り多くの敵軍のナイトを相手に闘い、捕獲するようにしましょう。そうすることにより、敵軍の防衛能力が低下します。
- 自軍のナイトで敵軍の城を攻め落としましょう。城はナイトと農民を生産しますので、城がなくてはナイトと農民の数を増やせません。複数の城を所有すれば、農民とナイトを敵軍よりも速く生産する能力を獲得できます。農民とナイトの生産速度を把握するには、補足情報である「新たな農民とナイトを作成そして追加」をご覧ください。
- 戦略的な行動を駆使して、自軍の城が敵軍に占領されるのを阻止しましょう。
|
新たな農民とナイトを作成そして追加
城が農民またはナイトを作成・追加し続ける速度は、占領した土地のマス目の数に依存します。
|
占領地のマス目の数
|
1駒の農民またはナイトを追加するのに必要とされるターン数
| | 124以下 | 作成・追加は無し | | 125 | 14 | | 250 | 12 | | 500 | 10 | | 1,000 | 8 | | 2,000 | 6 | | 4,000を超える | 4 |
|
ゲーム駒を捕獲
ナイトのみが敵軍の農民、城、そしてナイトを捕獲できます。相手が農民または城の場合、ただ単にナイトを相手のマス目に移動すれば相手を捕獲できます。敵軍のナイトを捕獲するには、まず敵ナイトの兵力値を0まで下げなくてはなりません。それぞれのナイトの兵力値は初期値100から始まり、敵側による捕獲行為のたびに15から30の間のランダム数字の分だけ兵力値を失います。(敵がナイトの場合、相手の兵力値を0まで下げてから)敵軍の駒の捕獲を成功させたナイトは兵力値を20ポイント獲得します。
スコアの仕組み
対戦にて勝利を収めるには、戦闘終了の時点にて(対戦参加者の中で)最高得点をスコアしていなくてはなりません。最も広大な土地を占領している支配者が、必ずしもゲームの勝者だとは限りません。このゲームのスコアの仕組みを表1に示します。
表1. 捕獲と関連するスコアの仕組み
| 自軍が捕獲した敵軍の駒の種類 | 敵軍捕獲により自軍に追加される得点数 |
|---|
| 農民 | 4点 | | ナイト | 6点 | | 城 | 15点 |
表2にて示されるとおり、対戦終了時の(自軍の)駒の残数、占領した城の数、そして占領した土地の面積(マス目の数)がスコアに加算されます。
表2. 残存戦力と関連するスコアの仕組み
| 残存戦力の種類 | 加算される点数 |
|---|
| 農民 | 1点 | | ナイト | 2点 | | 城 | 25点 | | 土地 | 10マス毎に1点 |
ゲームの詳細
それぞれのプレイヤーは、支配者をシミュレートするJavaコードを作成します。ゲーム・シミュレーターはプレイヤーの支配者を別の支配者と対戦させ、勝者を決定します。プレイヤーはJavaコード上で農民、ナイト、そして城の行動を指揮します。APIのセットが、自軍そして対戦相手の駒に関する情報を提供します。このAPIを使用して、攻撃的、防御的、そして柔軟な戦略を実装するコードを作成できます。
 |
CodeRulerの立案者
CodeRulerのエンジンの中身そして先進的な戦略に目を通したいのであれば、この裏事情を明かす裏話のような(CodeRulerの製作者であるTim deBoer氏との)インタビューをお読みください。
|
|
ゲームのコンポーネント
CodeRulerと言うゲームは、支配者のコードを作成、デバッグ、そしてテストするためにEclipse IDEを必要とします。(この記事にある「Eclipse: 統合王国開発環境」を参照してください。)
CodeRulerは以下の項目を含みます。
- Eclipse IDEへのプラグインとしての、インタラクティブなゲーム・シミュレーター
- 支配者をコーディングするのに使えるAPIのドキュメント
- 行動、捕獲、そしてスコアのルール一式
- プレイヤー自身の支配者をサンプル支配者に対して戦わせるのに使うローカル環境の戦場
- 公共のトーナメントにプレイヤー自身の支配者を参戦させるため、または独自のトーナメントを設定するための、ネットワーク・メカニズム
シミュレートされた世界の座標システム
ゲームは4,608マス(横72マス x 縦64マス)から出来た世界で成り立っています。マス目は(x,y)の座標システムを基にして番号を振られています。x軸は左から右に、そしてy軸は上から下に伸びます。CodeRulerの世界のレイアウトを、図6にて示します。(0,0)の座標(原点)は、左上のコーナーに位置します。
図6. CodeRulerの世界を表現する座標システム
CodeRuler API、そして継承の階層
ゲーム駒に命令を下す前に、CodeRuler APIを把握する必要があります。APIは非常にオブジェクト指向性が高く、明示的な継承の階層を持ちます。効果的なCodeRulerのコーディングを実行するには、階層の把握が非常に重要となります。継承の階層を、図7で表わします。
図7. CodeRulerの継承の階層
図7の継承ツリーはJavaインターフェースを基にしています。それぞれのゲーム駒はそれ自身と関連するインターフェースを実装しなくてはなりません。農民はIPeasantを実装し、ナイトはIKnightを実装すると言うパターンです。しかしながら、CodeRulerシミュレーターは内蔵された実装を使用しますので、これらのクラスをコーディングする必要はありません。ゲーム駒に関する情報を入手するだけのためにインターフェースに供給されるAPIを使用する必要性を、(支配者として)プレイヤーは持ちます。
IObject インターフェース
IObject インターフェースは、プレイ画面上の全ての駒へのスーパー・インターフェースです。それぞれの駒は、IObject を間接的に実装します。IObjectは、全ての駒の持つ共通の振る舞いを制御します。
-
getRuler(): 駒が所属する支配者
-
getX(), getY(): 駒の現在位置
-
isAlive(): 駒が生きているかどうか(捕獲されていないかどうか)
-
getId(): 全ての駒(農民、ナイト、城)に与えられた固有のID
IObject スーパー・インターフェースには、2つのコンビニエンス・メソッドがあります。これらのメソッドは、戦略的な作戦ではかなり便利で、複雑な三角法の計算に労力を費やすことを回避するのに役立ちます。
-
getDirectionTo() は、画面上で指定された座標へ最も近い方向を計算します。
-
getDistanceTo() は、画面上で指定された座標への距離を計算します。
IPeasantインターフェース
IPeasantインターフェースはIObjectインターフェースに新規の振る舞いを追加しません。支配者のmove()メソッドで農民を動かし、位置を変更できます。農民を使うことにより、土地を占領できます。農民の持つ自動的な振る舞いは、通過する土地を全て占領することです。敵対するナイトは一手で農民を捕獲できます。この場合、兵力値を考慮に入れる計算を伴いません。
ICastleインターフェース
IPeasant インターフェースと同様に、ICastle インターフェースはIObject インターフェースに新規の振る舞いを追加しません。農民またはナイトを次々と生産するのが、城に与えられた自動的な振る舞いです。生産のスピードは、占領している土地の広さに依存します。補足情報「新たな農民とナイトを作成そして追加」で、生産スピードを確認しましょう。
IKnightインターフェース
IKnightインターフェースは、IObjectインターフェースにgetStrength()と言うメソッドを1つ追加します。兵力値が0になると、ナイトは捕獲されます。IKnight インターフェースにあるgetStrength()メソッドを作戦実行時に使えば、ナイトの損失を防ぐことが可能です。ナイトの兵力値計算についての考察をお求めでしたら、前述の「ゲーム駒を捕獲」を参照してください。
図7のインターフェース階層は、シミュレーションの世界(表舞台)で動き回るゲーム駒を表わしています。しかし、支配者はゲーム駒では無く、シミュレーションの世界(表舞台)で動き回ったりしません。IRulerインターフェースが支配者の振る舞いを指定します。
IRulerインターフェース
IRulerインターフェースはIObjectから継承されませんし、その必要もありません。IRulerインターフェースの継承の階層を、図8にて示します。
図8. Irulerインターフェースの継承の階層
IRulerインターフェースは全ての支配者が実装する一般的な振る舞いを指定します。作戦の実装に役立つ通知メソッドを含みます。
-
getPeasants() は、この支配者の支配下に置かれた農民全員のリストを取得します。
-
getKnights() は、この支配者の支配下に置かれたナイト全員のリストを取得します。
-
getCastles() は、この支配者の支配下に置かれた全ての城のリストを取得します。
-
getLandCount() は、支配者が所有する土地のマス目の数をカウントします。
-
getPoints() は、支配者が稼いだ現在スコアを取得します。
-
getRulerName() は支配者の名前を取得します。
-
getSchoolName() は、支配者を作成した者が所属する組織名を取得します。
RulerクラスとMyRulerクラス
ゲームのルールに特定された振る舞いを強制し、IRulerインターフェースの実装を支援するために、図8に示されるとおりCodeRulerはRulerクラスを供給します。このクラスはIRulerメソッドのほとんどにデフォルト実装を提供します。Rulerクラスから継承すべきMyRulerクラスのコンテントを書き出します。Rulerクラスは修正する必要はありませんし、絶対にするべきではありません。
 |
シミュレーターのワーク・フロー
CodeRulerのプレイヤーの視点から見た場合、シミュレーターは以下のワーク・フローを伴います。
- シミュレートされる世界でランダムに選択された王国の位置にて初期設定のゲーム駒を配置する
-
initialize()メソッドの実装を呼び出す
- ターン毎に
orderSubjects()メソッドを呼び出す
getRulerName()メソッドとgetSchoolName()メソッドは、作戦コードを含むべきではありません。シミュレーターはいつでもそれらを呼び出せます。
|
|
MyRulerの実装にて使うべき重要なアクション・メソッドを、Rulerは幾つか提供します。
-
move() は、ゲームの世界にて駒を動かします。
-
capture() は敵軍のゲーム駒を捕獲しようとします。
城の生成モードを変更する幾つかのメソッドをもRulerは実装します。デフォルトとして、プレイヤーの城は農民を生産し続けます。しかし、これらのメソッドを使って、代わりにナイトを製造するように城に命令することも可能です。
-
createKnights() は城にナイトを製造するように命令します。
-
createPeasants() は城に農民を製造するように命令します。
最後に述べますが決して忘れてはならないのは、Rulerクラスの存在理由のひとつとしてプレイヤー自身のMyRuler クラスにて実装しなくてはならない追加的な抽象メソッドを定義することが挙げられます。シミュレーション・エンジンは実行の途中にてそれらのメソッドを呼び出します。
表3にてリストされるメソッドを実装するコードのみを書き出せばよいだけの話です。
表3. 全てのMyRuler実装でのメソッド
|
メソッド
| 説明 |
|---|
getSchoolName()
| プレイヤーの所属するグループまたは組織を識別する25文字以下のストリングを戻します。(元々CodeRulerは大学同士の対戦に向けて開発されましたので、『school(学校)』となっているのです。)支配者を識別するために、これはゲーム進行中に使われます。図1での例として、Simple Rulerの『学校名』はIBM developerWorksです。 |
getRulerName()
| プレイヤーの操作する支配者を固有のものとして識別する25文字以下のストリングを戻します。例えば、図1に登場する支配者のうちの1人は、Simple Rulerの名前で通っています。 |
initialize()
| ゲームの世界に支配者を最初に配置するときに、システムはこのメソッドを呼び出します。ここで必要な初期化を実行します。初期化は1秒間に限られます。初期化にてマシンが実行できる処理の量はCPUの速度と使用中のJava VMに左右されますが、1秒間もあれば大抵のコードの初期化に関するタスクには十分です。遅い入力や出力に依存するかも知れない処理はここでは避けましょう。 |
orderSubjects()
| これはCodeRulerの中核を成します。ターン毎にシステムはこのメソッドを1回呼び出します。ここでは作戦を行使して、このメソッドで何をするかを駒に伝えます。 |
Eclipse: 統合王国開発環境
CodeRulerのシミュレーション環境を実行するには、Eclipse IDE をダウンロードしてインストールします(参考文献を参照)。CodeRulerはEclipse IDEにプラグインとして統合されますので、開発者に優しいEclipse機能を推進します。
EclipseとCodeRulerをインストール
Eclipseをインストールするには、配布物をディレクトリーに落とし込み、eclipse実行可能ファイルを実行します(*nixではeclipseで、Win32システムではeclipse.exe)。バージョン1.4.2以降のJDK/JREがインストールされるべきです。(バージョン1.4.2の方を強く推薦します。なぜならば、CodeRulerはそのVMバージョンで開発そしてテストされたからです。)Eclipseのインストールが終わりましたら、CodeRulerのエンジンをダウンロードしてください(参考文献を参照)。CodeRulerをインストールするには、CodeRuler配布物を<eclipse installation directory>/plugins のディレクトリーに落とし込んでください。そうすれば、 com.ibm.gamesディレクトリーをpluginsディレクトリーの下に作成できます。Eclipseを起動または再起動すれば、CodeRulerプラグインはロードされます。これでCodeRulerを実際に動かす準備が整いました。
CodeRulerのプロジェクトを作成
CodeRulerを使用するには新規プロジェクトをEclipseの中に作成する必要があります。Windows|Preferencesをメインメニューから選択すれば、図9にて示されるようなダイアログ・ボックスが表示されます。
図9. 新規CodeRulerプロジェクトを作成
図9にて示されるとおり、左側のリストにあるIBM Gamesを選択してください。次に、右側にあるGameリスト(プルダウンメニュー)からCodeRulerを選択してください。最後に、OKをクリックしてテンプレートから新規のCodeRulerプロジェクトを作成しましょう。これで独自かつ固有のCodeRulerをコーディングする準備が出来ました。
IDEの左側にあるタブのバーにて、Java Perspective のタブをクリックします。図10にこのタブがあるのがわかります。
図10. EclipseにてJavaパースペクティブを選択
srcノードとデフォルト・パッケージの展開は、図10に示されるように、MyRuler.javaノードを表示します。MyRuler.javaノードをダブルクリックすれば、ソース・コード・エディターは編集のためにファイルを開きます。ここにコードを配置します。
最初の支配者をコーディング
最初に作成する支配者は簡単です。それは全ての農民をランダムに動かします。この支配者のコードをリスト1にて示します。(新たに追加された部分を太字で表記します。)
 |
タイミングの重要性
この支配者をコーディングするとき、タイミングの制約に注意してください。initialize()のメソッドでは、入力/出力では無いコード初期化には十分な時間と言える1秒間に限定されています。1秒間以上の時間を費やせば阻止され、部分的な初期化により痛い目にあうかも知れません。それぞれのターンでは、orderSubjects()メソッドはプレイヤーに0.5秒間の猶予しか与えません。orderSubjects()呼び出しの着信パラメーターは、以前のターンでどれだけの時間を費やしたかを知らせます。タイムリミットを超える時間を費やせば、プレイヤーは失格を言い渡され対戦から退場となります。
|
|
リスト1. orderSubjects()のSimple Ruler実装
import java.util.Random;
...
protected Random rand = new Random();
public String getRulerName() {
return "Simple Ruler";
}
public String getSchoolName() {
return "IBM developerWorks";
}
public void orderSubjects(int lastMoveTime) {
IPeasant[] peasants = getPeasants();
for (int i = 0; i < peasants.length; i++) {
move(peasants[i], rand.nextInt(8) + 1);
}
}
|
リスト1のコードは、1から8の番号をランダムに生成するためにjava.util.Randomを使用します。この番号は農民の移動方向を決定します。全ての農民の配列を取得するためにRulerクラスのgetPeasants()メソッドを使い、農民を移動するためにmove()メソッドを使うことに注目してください。
農民をランダムに移動する行動は、土地の占領につながります。この支配者は敵を捕獲するつもりではありませんので、ナイトを動かすコードを必要としていません。
 |
CodeRulerの『禁じ手』リスト
ゲームにて勝利を収めるには賢い作戦は確かに重要なのですが、ゲームのエンジンを乗っ取るためにJava言語の機能を小賢しく悪用したり別の悪質な方法で勝ったりする行為をCodeRulerは推奨しません。コードの『禁じ手』を以下のリストに連ねます。
- コンストラクターを定義
- 初期化ブロックを使用
- スレッドを作成
- プロセスを作成
- ファイルへの書き込み
- JDBCを使用
- GUIコンポーネントを作成するために、SwingまたはAWTを使用
- ネットワークまたは類似するシステム・フィーチャーへのアクセス
- シミュレーターの内部を発見そして歩くために、リフレクションとイントロスペクションを使用
全ての公共で開催される対戦とトーナメントでは、そのようなハッカーまがいの裏技に頼るような人は失格を言い渡され競技から除外されます。カスタムJavaSecurityManagerは、そのような行為をほとんど見逃しません。
|
|
最初の対戦にて戦闘開始
最初の戦いに赴く前に、ツールバーのSave(保存)ボタンをクリックするかメニューから File >Saveを選択することにより、新規に編集された支配者を保存しましょう。保存の行為は、コードをコンパイルします。次のステップに進む前に、スペルミスや構文エラーを修正しましょう。
図11に示されるとおり、CodeRulerに特定された5つのアイコン・ボタンに気付くはずです。
図11. Eclipseツールバー内の統合されたCodeRulerボタン
表4は、図11のボタンの機能を左から右へと順番に説明します。
表4. CodeRulerボタンの機能
|
ボタン | 説明 |
|---|
| サンプルを相手に実行 | このボタンを使い、プレイヤー自身が選ぶサンプルの支配者を相手に自軍の支配者をテストします。 | | サンプルを相手にデバッグ | このボタンを使い、プレイヤー自身が選ぶサンプルの支配者を相手に自軍の支配者をテストします。デバッグ・モードで自軍の支配者を実行し、プレイヤー自身が設定したブレークポイントで停止します。 | | 別のチームを相手に実行 | コードをサブミットした後、別のチームの支配者がダウンロードされます。このボタンを使うことにより、別のチームの支配者を相手に自軍の支配者をテストします。 | | 別のチームを相手にデバッグ | 別のチームの支配者を相手に自軍の支配者をテストする間、IDEのデバッグ・モードで自軍の支配者を実行します。 | | コードをサブミット | これで自軍の支配者をサブミットしてください。これまでに他のチームによりサブミットされた全ての支配者の暗号化されたバンドルのダウンロードをもします。 |
最初の実験では、プレイヤーが最初に作成した支配者はサンプルの支配者のみを相手に実行します。(図11でハイライト(選択)されている)最初のボタンのみを使うことをそれは意味します。このボタンをクリックすれば、CodeRulerは起動されプレイヤー自身の支配者をロードします。図12にて示されるとおり、対戦相手を選択することができます。
図12. 対戦相手を選択
「Do Nothing Ruler」を追加してみましょう。プログラムを実行し、自軍の農民がランダムに動き回って土地を占領するのを観察してください。この対戦は楽勝なはずです。
次に、Random Rulerを試してみましょう。この支配者はプレイヤー自身の支配者とほぼ同一の振る舞いを示します。両軍の土地を占領する能力の平均値は、ほぼ同等です。
他のサンプル支配者を対戦相手として選べば、プレイヤー自身が作成したSimple Rulerは多分負けるでしょう。他のサンプル支配者の大半は、プレイヤーの駒を積極的に捕獲しようとします。プレイヤーのSimple Rulerに新たな攻略能力を追加しなくてはならぬ模様です。
攻撃的な支配者を作成
修正された支配者のコードを、リスト2にて示します。追加項目を赤、青、緑のハイライトで表わします。
リスト2. 積極的な敵軍捕獲に向けて修正されたSimple Ruler
import com.ibm.ruler.*;
import java.awt.Point;
import java.util.Random;
import java.util.Vector;
public class MyRuler extends Ruler {
public String getRulerName() {
return "Simple Ruler";
}
public String getSchoolName() {
return "IBM developerWorks";
}
public void initialize() {
}
protected Random rand = new Random();
protected Vector enemies = new Vector();
public void orderSubjects(int lastMoveTime) {
IPeasant[] peasants = getPeasants();
IKnight[] knights = getKnights();
for (int i = 0; i < peasants.length; i++) {
move(peasants[i], rand.nextInt(8) + 1);
}
enemies.clear();
IPeasant[] otherPeasants = World.getOtherPeasants();
IKnight[] otherKnights = World.getOtherKnights();
ICastle[] otherCastles = World.getOtherCastles();
for (int i=0; i<otherPeasants.length; i++) {
enemies.add(otherPeasants[i]);
}
for (int i=0; i<otherKnights.length; i++ ){
enemies.add(otherKnights[i]);
}
for (int i=0; i<otherCastles.length; i++) {
enemies.add(otherCastles[i]);
}
int size = knights.length;
for (int i = 0; i < size; i++) {
IKnight curKnight = knights[i];
if (!enemies.isEmpty()) { IObject curEnemy = (IObject) enemies.remove(0);
moveAndCapture(curKnight, curEnemy);
}
else
break; } // of outter for
}
public void moveAndCapture(IKnight knight, IObject enemy) {
if ((enemy == null) || !enemy.isAlive())
return;
// find the next position in the direction of the enemy
int dir = knight.getDirectionTo(enemy.getX(), enemy.getY());
Point np = World.getPositionAfterMove(knight.getX(), knight.getY(), dir);
if (np == null)
return;
if ((np.x == knight.getX()) & (np.y == knight.getY())) {
move(knight, rand.nextInt(8) + 1); return;
}
// capture anything that is in our way
IObject obj = World.getObjectAt(np.x, np.y);
if ((obj != null) & (obj.getRuler()!= this))
capture(knight, dir);
else
move(knight, dir);
}
}
|
 |
多彩なWorldオブジェクト
徹底的な支配者のコーディングにのめり込む前に、Worldオブジェクトの文書の勉強に時間を割くのを忘れないでください。作戦を実装するのに便利な数多くの静的メソッドを、そのオブジェクトは含みます。例えば、getLandOwner()を使って誰がとあるマス目の土地を所有しているかを知ることができ、getObjectAt()を使ってとある座標に位置するゲーム駒を識別できます。それから、getOtherPeasants()、getOtherKnights()、getOtherCastles()、そしてgetOtherRulers()を使って、敵軍(農民、ナイト、城、支配者)を発見できます。
|
|
リスト2にて緑色の文字で示されるコードに見覚えがあるはずです。(リスト1を参照してください。)
赤字で示されるコードは、シミュレーションの世界にて生きている敵軍のゲーム駒から成るVectorを設定します。情報を得るためにWorldオブジェクトを使用しているのに注目してください。(World.getOtherPeasants()のことです。)
青字で示されたコードは自軍のナイト全ての間でループし、生きている敵軍のゲーム駒に向けてそれぞれのナイトを動かします。ナイトは付近にいる可能性のある敵軍の駒を捕獲します。それはmoveAndCapture()メソッドを使って移動と捕獲を実行します。
moveAndCapture()メソッドは、指定されたナイトを指定された敵軍の駒に向けて移動します。ナイトが「どつぼにはまった」場合に、WorldオブジェクトのgetPositionAfterMove()メソッドを使い、ナイトにランダムな行動をさせます。WorldオブジェクトのgetObjectAt()メソッドを使い、行く先を邪魔する敵軍の駒の有無を確認したり(敵軍の駒があれば)捕獲したりもします。
この新規のSimple Rulerを、サンプルの支配者を相手に試してみましょう。大抵の敵軍を相手に善戦することに気付くことでしょう。当然、まだまだ改善の余地はあります。訓練として、以下のとおりにコードを修正するのもよいでしょう。
- 自軍のナイトの数が少なくなった場合に、ナイトを製造するように城に命令する。
- より効率良くナイトに標的を割り当てる。
- より効率良く土地を占領するように、農民をプログラミングする。
- 敵軍の捕獲行為を回避するように、農民をプログラミングする。
- 農民とナイトの数が少なくなった場合に、防御的な生存作戦行動に移行するようにする。
まとめ
単純で実践的なロボットの様な支配者や洗練された作戦を基にしたゲームプレイの法則に裏付けされた軍師を採用するなど、CodeRulerのプレイ方法には様々なやり方があり、全てはプレイヤー次第です。現実の世界と同様に、最も洗練された作戦行動や込み入ったコーディングが必ずしも確実な連戦連勝の方程式を意味するとは限りません。実を言いますと、一部のチャンピオン支配者達は、最も単純かつ洗練されたゲリラ戦法を展開します。もしも戦略的な設計とJava開発のために生きていると自信を持って言えるのでしたら、是非ともCodeRulerをお奨めします。
ダウンロード | 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|
| Sample code for two simple rulers | j-coderuler.zip | | HTTP |
|---|
参考文献
著者について  | 
|  | Sing LiはWrox Pressから出版されている多数の本の著者で、Professional Apache Tomcat 、Early Adopter JXTA 、Professional Jini などを執筆しています。技術雑誌に頻繁に寄稿しており、P2P発展に関する熱心なエバンジェリスト(伝道者)でもあります。コンサルタント兼ライターであるSingの連絡先はwestmakaha@yahoo.comです。 |
記事の評価
|