NPCのAIプログラミング
こんにちは。開発担当のマットです。
ゲームが大好きです。
パソコンゲームと最初に出会ったのは子供の頃でした。
父親の事務所にあったパソコンにMS-DOSゲームライブラリーというものがあって、楽しく遊んでいたことを覚えています。
ライブラリーには色々なゲームがありましたが、その中でもシミュレーションゲームが特に好きでシムシティのようなゲームに何時間も費やしていました。
遊んできたたくさんのゲームの中で、大きな印象があったのが2001年発のBlack&Whiteです。
ちょっと珍しい設定ですが、このゲームは村の神様として遊びます。
雨を降らしたり、火災を起こしたり、雷を落としたり、様々な神秘的な奇跡を起こすことによって崇拝してもらうゲームです。
でも、一番面白いと思っていたのはゲームの中の村人達でした。
ゲーム用語で、このようなキャラクターは「直接制御できないキャラクターNPC(ノンプレイヤーキャラクター)」といいます。
このゲームの一番の魅力はこのNPC達のAIでした。
なぜなら他のゲームと違って、ある程度自由に動いたりすることができたからです。
村の婦人達が妊娠したり、子供達が遊んで走り回ったり、皆が怖いことから隠れたりして、見るだけでも十分面白いシミュレーションでした。
AIとは何?
AIはArtificial Intelligenceの省略です。
日本語では、「人工知能」と訳されています。
ゲームのAIは「知能」の意味が曖昧で中々定義しにくいですが、環境に反応して目的を果たそうとするものはAIと言っていいかと思います。
上記で取り上げたBlack&Whiteの例では、村人達の目的は単純に無事に幸せに生きて子供を残すことだけでしたが、そのことでゲームに個性が生まれて楽しく遊ぶことができました。
この記事で紹介するAIの例
この記事では、上記のようなAIプログラムの基本を説明したいと思います。
実際のコードは使いませんが、AIの基盤がわかるとプログラミング言語を1つでも知っていれば、誰でもAIスクリプトを書くことに挑戦できると思います。
上記のゲームと同様で自由勝手に動く人間(NPC)のAIの例で進めたいと思います。
何らかの設定が必要なので、「無人島に流された」という設定を使いたいと思います。
ゲームAIの分解
AIのプログラムは5つの段階に分けることができます。
- Sensing – 感知する
- Conditions – 条件を生成する
- State – 状態を選択する
- Schedule – (適切であれば)新たなスケジュールを選択する
- Task – タスクを実行する
定期的にスクリプトをコールして、これらの段階を順番に実行していきます。
1. Sensing – 感知する
まず一番最初にするのは「感知」です。
NPCはただの人間で全知の超能力者ではありません。
そのNPCは何を見えるか、何を聞こえるかをリストアップし、もしNPCの近くにココナッツの木やビーチで歩いているカニがいたら、それらをNPCの感知リストに載せる。
逆に島の反対側にいるイノシシは見えないし聞こえないので、感知リストには載せません。
2. Conditions – 条件を生成する
次は感知したものリスト一覧で様々な「条件」を生成する。
例えばカニが見えるので「食物が見えるか」の条件をtrueと定義する。
同じくココナッツが見えるので「水分が見えるか」の条件もtrueと定義できる。
その反面イノシシのような獣は感知していないので「危険な動物がいる」の条件をfalseと定義する。
3. State – 状態を選択する
次はNPCの状態を選択する。
まずは「通常」ですが、もし近くにいる危険な動物を感知したら「危険な動物がいる」という条件がtrueになります。
もちろん危険動物が近くにいると振る舞いが変わるので、NPCの状態(State)が「通常」ではなくて「注意深い」になります。
「注意深い」になっている間は、音を立てずに忍足で歩くなど行動が変わります。
一つの状態の種類だけだと足りないかもしれないので、さらに分けることができます。
例えば「心理の状態」と「健康の状態」など。
4. Schedule – スケジュールを選択する
スケジュールとは一つの目標のことです。
上記で定義した条件と状態の元で決めます。
例えば水分が近くにあって喉が乾いている場合、水分を取りに行くというスケジュールを決定する。
基本的にスケジュールが決定されたら、そのスケジュールを最後までする。*1
つまり水分を取りに行っている途中、お腹が空いてもスケジュールは変更しません。
まず水分を獲得してから食料を取りに行けばいい。*2
しかし「割り込み条件」(Interruption)という特別な条件が成立したら、途中であってもスケジュールを変更する。
例えば蛇に噛まれた場合は水分獲得をやめてケガを治療するスケジュールに切り替えるべき。
*1: これは柔軟なルールです。途中で再検証すべきスケジュールもあると思います。
*2: ただし「餓死しそう」のような「割り込み条件」が成立したらスケジュールを変更すべきです。
5.Task -タスクを実行する
スケジュールは一つか複数のタスクで成り立っています。
例えばココナッツの水分を獲得するのに、以下のタスクがある。
- 木まで歩く
- 木を登る
- ココナッツを取る
- 木を降りる
- ココナッツを割る
- 飲む
「割り込み条件」によってスケジュールが変わらない限り、これらのタスクを1つ1つ順番にやり遂げるだけです。
まとめ
ゲームを開発する際、気の利いたAIが必要で欠かせない場合がたくさんあります。
プログラマーとして「あ!動いた!」の瞬間が一番楽しいと思うので、実際に動き回るバーチャルな人間のようなNPCをコーディングすることはとても楽しいです。
興味がある方は実際にプログラムでも書いてみるのはいかがでしょうか。