ゲープロ講座セッション3:戦術型SLGの移動アルゴリズム(2)
- 移動アルゴリズムのソースを解析する |
2週間ちょっとのご無沙汰でした、鷹月ぐみなです。前回のアルゴリズム紹介はいかがだったでしょうか。なんとなく移動ルーチンが組めそうだと思いつつも、具体的な実装の仕方がさっぱりな人が多いのではないかと思います。そこで今回は、移動アルゴリズム部の簡単なDelphiサンプルソースを紹介しながら、実際にシステムとして稼動するサンプルアプリケーションを提供しています。今回の内容をマスターしてしまえば、結構SLG制作の道は近づくと思います。技術部分は鷹月のオリジナルなので、フリーで使うことができます。
|
この、人間のもやもやした考えをはっきり文で表現することが「アルゴリズム」、それをプログラムソースに落とし動かす状態にすることが「実装」です。今日はこのルーチンを攻略していきましょう。 まずは、実際に動く部分までは考えずに、単に「ある地点から歩数mvで進める地点を明示する」部分だけのアルゴリズムだけ思い浮かべましょう。なお、マップには「進める箇所」と「進めない箇所」があり、進める部分に関しても平地のように進みやすい場所、荒地のように進みにくい場所が存在します。これは処理を書く前にしっかり規定および仮定しておくべきでしょう。
《規定》
いきなりちょっとした「テクニック」を使っています。岩マスは「進めない」ではなくて、ウェイト10にしておきます。PCは6歩しか歩けないのですから結局進めないマスです。「結局同じじゃない」と思うかもしれませんが、アルゴリズム上ではまったく変わってきます。「問題は単純化すること」はこの世界の原則です。ちなみに上の絵ではPCの歩数は3になっていることを確認しておいてくださいね。真下は荒地のせいで3つ進めない状態なのです。 一つ規定をした上で、以下の移動アルゴリズムを与えます。前回のそれよりさらに単純に、そして分かりやすく具体的になっていますんで、「多少は」安心してくださいね。
《試行》 この結果、マークされた所を光らせてみればめでたく「移動可能地点」がしっかり表示されるはずです。あなたがSLG構築に興味があって、このアルゴリズムに完全に納得していないなら、必ず手で書いて試してみてください。これをトレースと言います。書き方は完全に任せますので。なおその場合、移動歩数が6だと長くなってしまうので、2や3あたりから試してみると良いでしょう。完成予想図が思い浮かばない人も、やはり紙にトレースしましょう。アルゴリズムというものは、頭が明確に理解していない限り、コンピュータに実装させることなんてできるわけがないのです。
この2-5の流れは再帰処理と呼ばれています。ぱっと見では「繰り返し」のように感じますが、単なる繰り返しではありません。一つの流れからいくつもの流れができあがり、またその流れの一つからいくつもの流れを実行しています。具体的に何回3〜5の流れを繰り返しているのかを計算すると……移動歩数がmvで、マップが仮にすべて平地(ウェイト1)とした場合、4×3の(mv−1)乗回となります。mvは暫定的に6としたわけですから、4×3^5 =972回です。最近のコンピュータの性能のことですから、ほんの一瞬で計算してくれますが(MSXのようなマシンを使って、BASICで強引に処理させてみると時間かかりますよ〜)、人間はまじめにやる気はすでにありません。でも人間はこの完成図は予測できます。全部平地とした場合、長さ6のダイヤ(正方菱形)となるはずです。
|
// ユニット上のPCをクリックした時の処理 begin // マップ情報の初期化 for i:=0 to 255 do for j:=0 to 255 do begin GW1.BGf[1,i,j]:=1; mvrec[i,j]:=''; end; // 四方向にアンカーを伸ばす Search(px,py-1,mv,1); Search(px+1,py,mv,2); Search(px,py+1,mv,3); Search(px-1,py,mv,4); // この結果、画面表示ルーチンへ end;
ではプログラムソースを紹介しましょう。この言語環境はDelphi3.1J+TGWですが、アルゴリズムというのは基本的に言語非依存ですから、多少なりプログラム経験のある方は自分の使っている言語での再現が可能なはずです。では解説を始めましょう。上のソースは、先の試行1.と2.とそのまんま一致しています。ただ、プログラムスタイル的に細かくなっています。まず GW1.BGf[1,i,j] ですが、これが最終的に移動可能範囲を表示するためのマップフィルタです。iとjはマップ上のx,y座標を指します。この配列には1(移動不能っぽいですね)か0(移動可能っぽいですね)の情報のどちらかを書きこみます。また、mvrec[i,j] は、マークフラグを指します。ヌル状態はまだ到達していない地点、1は既に到達が確認された地点であることを示します。 // 探索手続きSearch Procedure Search(ax,ay,mv,di); var down,num:integer; begin // すでにチェック済みだったらこれ以上の探索は無意味(Par2-1) if mvrec[ax,ay]<>'' then exit; // 現在の地点にあるマップ情報を取り出して、ウェイトを計算(Par2-2) down:=0; num:=GW1.BGf[0,ax,ay]; if (num=1) then down:=1; if (num=2) then down:=2; if (num=3) then down:=10; // 歩数がマイナスになった地点へは進めないので思考中断(Par2-3) if mv-down<0 then begin exit; end; // マークをします(Par2-4) GW1.BGf[1,ax,ay]:=0; mvrec[ax,ay]:='1'; // さらに現在の位置からアンカーを伸ばす(Par2-5) if di<>3 then Search(ax,ay-1,mv-down,1); if di<>4 then Search(ax+1,ay,mv-down,2); if di<>1 then Search(ax,ay+1,mv-down,3); if di<>2 then Search(ax-1,ay,mv-down,4); end;
これが手続き部分の全てです。3. から5.の試行通りになっていることを確認してください。これら2つの処理の結果、図1のような画面を表示する準備が整うというわけです。プログラム経験者は、「あら、ほんとこれだけでできるんですか〜」と感じるのではないでしょうか。 さて、アルゴリズムは理解できましたでしょうか。ぱっと見程度では分からなくて当然です。それでもアルゴリズムはかなり平易であることは間違いないのです。
|
では、ここから先を読む前に、このlzhファイルをダウンロード、適当なフォルダ内に解凍して、move.exe を実行して暫く試してみてください。Windows95/98/NT上で動作可能です(Machintoshの方ごめんなさい……)。なお、画像のチップ素材は泣く大臣さんのものを、BGMにはみくしぎさんのフリーサウンド「十字架の誓い」を使用させていただきました。 → アプリケーションをダウンロードする(162K) → ソースファイルだけ見たい人はここから |
……というわけで、しばらく動かしてみましたでしょうか。そういう前提でいきます。ソースファイルを見ても分かるように、先のアルゴリズムからもう少し拡張しています。指定地点へ最短距離で移動してくれることをしっかり確認しましょう。これはアルゴリズムには用意していなかった部分ですが、多少の改変で実装できるようになっています。各地点において到達可能か不可能かを示すだけのフラグ mvrec[x,y] があったと思います。これを、「その地点に到達したルートを記録しておく文字列」に変更すればいいのです。そうすれば、後で移動目標地点をクリックした際に、その文字列に書かれたとおりにPCを移動させればいいわけです。ここでポイントとなるのは、手続きArch(先のSearchと同じです)の4番目の引数である、方向情報です。この方向情報を順次加えながら渡していくことによりそれなりに実装できます。細かくソースの解説はしませんので、ソースファイルを各自追ってもらいたいと思います。それでも分からなければメールをお願いします。鷹月がこのコンテンツを「講座」としたのは、読み手からの質問や要望によって、それを反映させて行きたいと思ったからです。あなたがSLG制作を目指していて、ルーチンが分からなかったら聴きましょう。100%回答できるとはいいませんが、ソースおよびアルゴリズムをしっかり理解していただけるように努力しますので。 話を戻しますが、いま加えたルーチンはまだ完全ではありません。最短距離になっていないのです。一歩下に動かそうとすると、なんと「上→右→下→下→左」という奇天烈な動きをしてくれるのです。素直に下に動いてくれないのです。こういう意図しない動きをするのは誰のせいでしょうか。他ならないアルゴリズムの設計者です。コンピューターは、指定した通りにしか動かないのです。そこで、なぜこういった事が起きるのかを考えてみましょう。 原因は手続きの「再帰の順番」にあります。処理の順番は常に上→右→下→左の順番で行なわれます。いまの設定によると、すでに「到達地点までの方法情報が書かれている」場合は書きこまないようになていますので、上→右→下→下→左ではじめて到達した情報が書きこまれて、それを使ってしまうというわけなのです。上書きすれば良いのでは、と思いますが、こうすると逆に、上に動かしたときに「下→左→上→上→右」と動くようになってしまいます。これを解決するために使う方法が、書きこまれている到達移動情報の文字数と、現在までの移動情報の文字数を比較して、少ない方を最短として採用するという仕掛けです。これによって、すべての移動可能地点において、最短で到達できる道筋のみを記録してくれて、後でその通りに動いてくれると言うわけなのです。
|
このサンプルプログラムは、まだ色々と解説しておきたいTipsがありますが、一度に積めこみすぎるのも何ですから、今日はこれくらいにしておきましょう。サンプルを動かして、「お、これが自分でも作れるなら、ひょっとしてこういうゲームの実装も可能なのでは?」と夢膨らませてみるのもいいかも知れません。このSLG講座は最後まではナビゲートはしませんが、十分な「手ほどき」くらいは提供しますので。次回はサンプルの解説の続きかな。それからセッション2で書いていた相手側の索敵・戦闘アルゴリズムへの発展(ケースの洗い出し)へと進めていこうと思います。 感想などお待ちしています。ただし、サンプルプログラムの移植要望だけは受け付けませんのでご了承下さい。(てか、他の言語持ってないってば) - 鷹月ぐみな |
□ Session4:戦術SLGの移動アルゴリズム3 (1999/11/10)
|