移動の仕組みから始めた第一回から10記事以上を費やし、ようやく敵ユニットが勝手に動いてくれるAI処理の構築も最終版です。
おおよその理屈は前回、前々回で書ききってしまいましたし、黙々と処理を作って載せてで突っ走りましょう。
おさらい
AI処理とは「行けるマスの評価」
左に行くと目的地にどれだけ近づいて、攻撃など他のどんな行動がとれるのか。右に行くとどうなるのか……そういった各種ルートを「評価値」という得点に直して比較することがAI処理の実態です。
評価の流れはこんな感じになりそうですね。
- 対象ユニットのAI設定(攻撃するかどうか、目的地はどこか)をCDB・UDBから読み込む
- チェック先の座標と目的地の距離をチェック。ジャストに近いほど評価を小プラス。目的地ジャストなら評価を大プラス
- 攻撃など、なんらかの行動がとれるなら評価を大プラス(攻撃の場合、攻撃可ユニットリストからの参照)
- その行動で発生する数値が大きいほどさらに評価を小プラス(攻撃なら相手の残HPをより小さくできる方が高評価)
なんとか実現できそうな「なんちゃってAI」の挙動
既存のウディタSRPGやFE近作に学びまして、次のようなAIならなんとか作れそうだという結論になりました。
- 特定の地点やユニット(リーダーなど)を目的地とする(動かない=初期位置が目的地)
- 攻撃可能範囲内では倒しやすそうな方を優先して攻撃
- 移動時は2~3ターン(回)分の移動力で考える
また、UDBでのAI設定は「攻撃する?」、「移動する? その場合の目的地は?」といった、することとしないことのフラグの組み合わせだけでも、けっこうバリエーションが作れそうです。
- 【ボス型】攻撃する、絶対に移動しない
- 【迎撃型】攻撃する、目的地「行動圏内の他軍ユニット」
- 【突撃型】攻撃する、目的地「最も近い他軍ユニット」(一度の移動で隣接できなくても)
- 【リーダー護衛型】攻撃する、目的地「自軍リーダー」
- 【集合】攻撃しない、目的地「自軍リーダー」
- 【盗賊・逃走型】攻撃しない、目的地「イベント地点」(宝や村など)
目的地のバリエーションだけでかなり見え方が違ってくることがわかります。簡単なAIづくりの主な仕事は「目的地さがし」と言えそうです。
しかし、201から見ると自分の軍とは所属ナンバー2のことです。ややこしいので、このあたりは次のように呼び分けましょう。
- 《同軍》 所属ナンバーがチェック中ユニットと同じ他ユニット
- 《他軍》 所属ナンバーがチェック中ユニットと違う他ユニット
UDBでAIのパターンを作る
各種フラグを設定する(「攻撃する?」、「目的地はどこ?」)
こんな感じですね。
基本的には、「〇〇する?」に「0=はい/1=いいえ」と設定するだけですが、目的地についてのみ、けっこうなバリエーションが出てきます。
(高確率で必要そうな「村/宝狙う?Y0」と「道具使う?Y0」も用意はしてありますが、今回のAI設定では触れません。村狙いについては、目的地=イベント地点の設定でほぼ同じことができるかと思います)
たとえば、次の動作は設定画似ていても実際の動きは異なるものです
- 自軍リーダーに近づくが、可能なら少し寄り道して他のユニットに攻撃する
- 自軍リーダーに近づくことを最優先する
これを「するorしない」のフラグで表現するために必要なのが、【優先】移動0or行動1……つまり「移動とその他の行動のどちらを優先するのか」という項目です。
また、目的地によっては、数ターンぶんの移動力で見渡してもわからないほど遠くを目指す可能性があります。
これも移動可能範囲内の検索の”前”に検索を済ませておきたいですね。
生存者チェックの要領で、指定の所属の生存ユニットの座標と、AIで動かそうというチェック元ユニットの距離を比較していきます。
(このコモンのさらに上で、AIの目的地設定の解読を行うコモンがあるイメージ)
上のコモンはユニット位置検索の専門。
特定の地点(座標)を目指すケースはまた仕組みが変わってくるでしょうし、ユーザーベースにまた別のイベント設定専用のリストを立てる方がよさそうです。
下でやっていきましょう。
イベント地点として「村」を作る
まずは地形やダメージ床を作る要領で地形のUDBとマップ上に「村」を作りましょう(ついでにいつもの要領で友軍301も登録しています)。
左下の「村」に自軍(プレイヤーキャラ)が到達すれば「村に訪問する」コマンドが増えたり、敵軍の盗賊ユニットがはるばる遠くから襲撃しにいったりするわけです。
マップ(ステージ)ごとに決まった位置・決まった内容のはずですから、上で話した通り「ステージ情報」専用のUDBを作って、適宜読み込むのが手っ取り早そうですね。
”-1”座標は「存在しない」ことを意味します。
上の画像の「村」が(4,8)にあるので、その座標をステージID0のマップでもイベント地点0に指定しましょう。UDBのステージIDは、マップデータ(システムデータベース)のIDと一致させるようにします。
こうすると、「ステージID0のマップのイベント地点0(村)はどこにあったかな?」というとき、「変数+」で現在のマップIDを取得して、その変数の位置を「ステージ情報UDB」から座標を読み込んでくればよいわけです。
AI動作コモンを作っていく
「┃┣AIターン」コモン
内容はこんな感じ。
- 敵軍フェイズなら敵軍設定で「┃┣AIターン」コモン呼び出し
- 友軍フェイズなら友軍設定で「┃┣AIターン」コモン呼び出し
- そのコモン中は生存かつ未行動ユニットを発見したらそのユニット番号を「■AI処理」コモンへ送る
というわけで、未行動者のカウントとほとんど同じようなソースだとわかりますね。
マス(ルート)別評価の下準備
このユニットが実際に移動可能な範囲がどこで、攻撃可能なユニットの番号は座標はどこなのか。これらを知るためのコモンが「┣移動可範囲のチェック」と「┣攻撃可ユニットリストの取得」でした。
実際に設定したUDBのAIフラグを読み取って動くように、書き出し部分を修正してみましょう。
そして、このAIの目的地はどこに設定されているのかを知るために「┣目的地のチェック」というコモンを新設しました。
ここまでで「目的地」と「攻撃可能ユニットのリスト」という2つの文字列変数が得られました。
この情報をもとに、実際に移動可能なマス(ルート)をそれぞれ評価していくことになります。
マス(ルート)別評価の本体
というわけで、あとは「┣移動可範囲のチェック」から「このマス評価して~」と渡された座標に対して、「そこはどれだけ目的地に近いのか」、「そこから行動(攻撃)ができるのか、できたとしてそれがどれぐらい有効なのか」を得点にすればOKです。
これでなんちゃってAIはそれなりに動くようになったはず。あとはUDBのAIの「するorしない」設定をあれこれ変えて、動作確認をしてみてください。
評価の数値も仮組です。移動と行動の優先フラグについても、おそらくもう少し調整が必要です。
- たとえば「自軍リーダーのそばに集まる」AIが、すでに自軍リーダーの右側に隣接しているとします。マスチェックの仕様上、左上の座標を優先するため、右隣に居続けていいのにわざわざ左隣へ移ったりしてしまうはず。これを防ぐには、移動距離が短いほど評価を上げる仕組みが必要です
- 逆に移動距離が長いほど評価をあげるとうまくいくケースもあるでしょう。目的地がかなり遠くにあって、迂回が必要になる状況です。
- 道に沿って移動してもらいたいなら、「道」地形の評価をあげるのもよいですね。「毒の沼」などダメージ床は評価を下げると、さらに賢くなりそうです。
処理負荷(計算量)をおさえるために
マップの使わない範囲に高コスト地形を増やす
実際に戦闘できるように地形を作ってユニットを配置して、何度かテストプレイをしたとします。
30×30サイズのマップでさえマス数は900になりますが、いちどに出撃するユニットは敵味方合わせてもおそらく30前後。
たぶん、実際にユニットたちが歩き回る範囲はマップ(全マス)の50%もないでしょう。「用事のないエリア」が必ず生まれます。用事がなくても、AIは「そこに用事が無いことを確かめる」ため律儀にルートの検索や評価を行ってしまうでしょう。
なので、そういう場所は不自然にならない程度に山や森など消費移動力(コスト)の高い地形を増やしておくと、計算量をいくらか減らすことができそうです(未使用エリアまで移動力計算が延びていくのを抑制する)。
なにもできなくなったらAI設定をゼロにする
盗賊のようにイベント地点を目指すわけでもないユニットは、ほとんどの場合、武器が無くなれば、突っ立っているだけのカカシになります(SFCのFE聖戦などの超賢いAIは自拠点に帰ろうとしますが)。
カカシはできることがありませんが、それでもAIで行動内容を考えさせるとそこそこの処理量が発生してきます。
武器を失うなどして「コイツはカカシになった!」とわかった瞬間に、AI設定を0番(なにもしない)にしてやると、AI処理が実質スキップされるので多少は処理が軽くなるでしょう。
絶対に移動しないユニットの移動力はあらかじめゼロにする
負荷軽減効果という意味では上ふたつには及びませんが、あればあったで親切な機能です。
というのも、FE系のSRPGでは、城をあずかる武将であるボスはたいてい拠点に構えて動いてきません。でもポインターを合わせて移動力を見ると、4,5歩は歩けることがわかっておっかなびっくり近づいたり……
しかしFEもモノによっては「移動力はあるけど、動かない設定だから、移動&武器射程のパネルでも動かないものとして表示しますよ」と処理したりしています。
親切設計で行きたいなら、この仕様もマネするとよさそうですね。
AI設定のIDなどから対象がボスとわかるときは「移動力計算時に移動力をゼロ扱いにする」か「最初からCDB登録の移動力をゼロにしておく」わけです。