はじめてのゲームAI

WEB+DB PRESS Vol.68にのっていた記事「はじめてのゲームAI」の記事を自分なりにまとめたメモです。

はじめてのゲームAI

AIの基本原理

AIを考える上で欠かすことのできないものは、

  • 外部の環境との関わり

です。

AIには、外部との関わりなしで動作するものもあります。例えば、出現してもプレイヤーお構いなしで直線移動するような敵です。

これはこれで動作のパターンを覚えて撃ち落とすという楽しみもあるのでOKなのですが、パターンを覚えてしまうと、簡単に倒せる・避けられるので、そういった敵ばかりでは退屈ですよね。

そこで、ぱっと思いつくのが、プレイヤーを狙って動く敵ですね。このAIは、プレイヤーが避けても追いかけてくるので、プレイヤーは近づかれないように、何とかしてその敵を倒す必要が出る面白さが生まれます。

ここでは「プレイヤー」という外部環境との関わりですが、ゲームによってはフィールドにある障害物を利用したり、仲間と連携して動作する敵、など色々な外部要素が考えられると思います。

そのような外部とどう関わっているかを考えることで、AIの行動のバリエーションが増え、面白いゲームになる、というわけです。

インフォメーション・フロー

インフォメーション・フローとは、AIの環境との関わりをフローにしたものです。

AIは外部環境の認知するという入力を受けて、外部環境への影響を与えるという出力を行います。

この入力を「感覚器」、出力を「効果器」と呼びます。

感覚器から得た情報をAI内部では、

  • 認識→意思決定→動作生成

という過程を経て、効果器から出力します。(この3つの過程にはそれぞれ記憶領域が影響します)

例えば、「プレイヤーを追いかける敵」というAIを過程を細かく噛み砕けば、

  1. プレイヤーがいる方角を認識する(認識)
  2. プレイヤーを追いかけるという意思を決定する(意思決定)
  3. プレイヤーの方角に向けて座標を (x,y) 移動する(動作生成)

という処理を行なっていることとなります。

プログラム的には、認識と意思決定は「条件式(IF文)」により行われ、動作生成は行動パラメータ(例えば座標の移動・弾の生成)の変化により行われます。

簡単にまとめると、AIとは、「条件式」と「行動」により決まることとなります。

エージェント・アーキテクチャの6つの型

エージェント・アーキテクチャとは、環境の存在を切り離し、環境に対してどう反応するかを定義したアーキテクチャとなります。

エージェント・アーキテクチャには以下の6つの型が存在します。

  • ルールベース
  • ステートベース
  • ビヘイビアベース
  • タスクベース
  • ゴール指向
  • ユーティリティベース

という6つの型を定義しています。

ここではルールベース、ステートベースのAIを紹介したいと思います。

ルールベース

ルールベースのAIとは、条件式のみで動作するAIです。

例えば、

  • 近くにプレイヤーがいたら、○○する
  • HPが低くなったら、○○する
  • 一定時間経過したら、○○する

という感じです。

「その環境に適合した条件」と「対応する動作」というルールを記述するだけなので、実装が簡単で分かりやすいです。条件に影響する要素が少なく、条件が単純になっていれば非常に効果的です。

ただし、条件の数が増えると処理が複雑になり、いずれ「競合」という問題が発生します。

競合とは、「2つ以上のルールの条件が同時に成立」し「動作が共存できない」状況です。

例えば、

  • プレイヤーを見つけたら近づく
  • プレイヤーを見つけたら離れる

というルールは、同時に満たすことが可能でかつ動作が共存できないため、競合が発生します。

これを解消するためには

  • 条件が同時に満たされないようにする
  • 動作を共存できるようにする
  • 動作にプライオリティをつける

ことが必要となります。

プライオリティによる競合の解消

ここではプライオリティによる解消方法を見ていきます。

プライオリティによる競合の解消方法には、以下の4つのパターンがあります。

  1. 静的プライオリティ
  2. 動的プライオリティ
  3. ランダム
  4. 交互に選択する

1は予めそれぞれのルールに評価点をつけておき、どちらの動作を優先するかを定義しておくものです。

2は状況を評価して、動的に評価点を設定して、評価の高い動作を行うものです。

3は乱数で動作を決定するものです。

4は動作Aと動作Bが競合した場合、最初はA次はBというように交互に動作を選択します。

まとめ

ルールベースは以下のような特徴を持っていることとなります。

  • ルールベースは、「条件」とそれに対応する「動作」からなるAI
  • ルールベースは分かりやすく記述が容易
    • 環境が限定的であるほど作りやすい
    • ゲームの要素が少ないシンプルなゲームで特に有効
  • ルールが増えると「競合」が発生する
  • 「競合」を解消するには「プライオリティ」をつける
  • さらにルールが増え「競合」が増えると「プライオリティ」の順番が見えづらくなる
    • 最悪、使われないルールが生まれる危険性がある

ステートベース

ステートベースのAIとは、複数の状態が存在し、一定の条件で状態が遷移するAIのことです。ルールベースのAIよりも複雑なことが可能で、実装もそれほど難しくないので非常によく使われています。

例えば、迷宮内の秘宝を守るモンスターのAIとして、

  • 待機:何もしない。休憩する
  • 偵察:プレイヤーを探すために迷宮を巡回する
  • 追跡:プレイヤーを発見
  • 警戒:プレイヤーが存在した場所を調べる

という4つの状態を持たせます。

通常は、「待機」「偵察」という状態を繰り返します。ですが、プレイヤーを発見すると「追跡」状態に遷移しプレイヤーが逃げたとしても、「警戒」状態に遷移しプレイヤーいた場所を巡回します。その後、何も見つからなかったら再び「待機」「偵察」に戻る、というAIです。

ちなみにこのような複数の状態を持つAIを、有限状態機械(ステートマシン・FSM)と呼びます。

より複雑なFSM

FSMは、複数の状態を遷移することで条件の切り離しを行ったルールベースのAIとも言えます。これにより複雑なことができるようになったのですが、これも状態が増えると管理が大変になります。結局状態の遷移はgoto文で切り替わっているようなものなので、スパゲッティコード化した状態遷移により条件が満たされずに使用しない状態が生まれる危険性が大いにあります。

これを回避するには、状態を階層化します。

例えば、

  • 待機
  • 攻撃
  • 逃走

という3つの状態を持つAIに、「積極的に攻撃する」「消極的に攻撃する」という状態をもたせる場合、

「攻撃」状態のサブシステムとしてこれらを配置します。

これにより、攻撃する前に引き金を引く、という初期動作を共通化したり、大量に被弾したら攻撃動作を終了して「逃走」に遷移する、というように流れがスッキリします。

まとめ

ステートベースの特徴をまとめると以下のようになります。

  • ステートベースは、ルールベースに複数の状態と状態遷移を持たせたもの
  • 状態を持たせることで行動の方針が明確になる
  • ただし状態が増えると複雑化する
    • どこからどの状態に遷移したなどが見えにくくなるとバグが生まれやすくなる
    • 使用されない状態が発生することもある
  • 複雑化を解消するには状態を階層化する
    • 階層化することで処理を共通化したり、流れが明確になる
    • ただし階層化も限度がある