BG2のAIスクリプトの構造等について説明します。
スクリプトの基本構造は以下のようなものです。
IF 条件 THEN RESPONSE #100 アクション END |
この場合、条件が成り立てば100%の確率でアクションを実行します。 アクションや条件は書き並べるとこで複数指定することもできます。 条件の前に ! をつけると逆条件(条件が成り立たなかった時に成立)が指定できます。あとはこれを色々組み合わせ、条件やアクションを色々工夫することで複雑な行動をさせることができます。 IESDPにほぼ全ての機能及び説明が網羅されていますので参考にしてみてください。 |
条件が複雑で多岐にわたる場合の説明です。
例えば、条件Aは必須であるが条件Bか条件Cか条件Dはどれかを満たせば良い時は以下のようになります。
IF 条件A OR(3) 条件B 条件C 条件D THEN RESPONSE #100 アクション END | この場合、条件Aが成り立ち、かつ条件B〜Dのどれか一つが成り立てば100%の確率でアクションを実行します。 |
if( A || (B && C))
という場合です。
IF OR(2) 条件A 条件B OR(2) 条件A 条件C THEN RESPONSE #100 アクション END |
条件Aが成立していれば、2箇所のOR(2) はどちらも成立しますね。また、条件Aが不成立でも条件Bと条件Cが両方成立してる場合も2箇所の OR(2) はどちらも成立します。このように、複雑な条件も全て単純な OR 文の列記に書き下せばOKです。
|
条件が成立した際にとるアクションは、確率指定で分岐させることができます。
IF 条件 THEN RESPONSE #25 アクションA RESPONSE #25 アクションB RESPONSE #25 アクションC RESPONSE #25 アクションD END |
この場合、条件が成り立てば1/4の確率でアクションA〜Dのどれかを実行します。 合計100の必要は無く各数値同士の比率で分岐するようです。 一定確率で何もさせたくない場合は、アクションとして NoAction() を指定します。
|
以下のスクリプトを見て下さい。(条件やアクションはわかり易くする為に日本語表記しています)
IF 敵発見 THEN RESPONSE #100 メッセージ表示「敵がいる」 END IF 敵発見 敵との距離が遠い THEN RESPONSE #100 飛び道具装備 END IF 敵発見 敵との距離が近い THEN RESPONSE #100 近接武器装備 END |
このスクリプトを実行するとどうなるでしょうか。 スクリプトは上から順に流れて行くので、敵が視界に入るとまず「敵がいる」とメッセージを表示します。 そして次に、敵との距離に応じて武器を装備するように見えますが、実際にはそうなりません。 ただひたすらに「敵がいる」と繰り返すだけです。 なぜこうなるのかというと、条件が成立して何かを実行するとスクリプトは再び先頭に戻って処理を再開するからです。 |
Continue()
を使います。
IF 敵発見 THEN RESPONSE #100 メッセージ表示「敵がいる」 Continue() END IF 敵発見 敵との距離が遠い THEN RESPONSE #100 飛び道具装備 END IF 敵発見 敵との距離が近い THEN RESPONSE #100 近接武器装備 END |
これで、(相変わらず喋りつづけますが)きちんと武器を装備するようになります。Continue() は非常に便利で多用しますので覚えておくと良いでしょう。
|
単純にその場の状況を判断して何らかの行動を起こすだけなら不用ですが、凝った事をさせようとするとどうしてもお世話になるものです。
これらを用いて4の例をもうちょっとスマートにしてみましょう。
// A.戦闘状態突入 IF 変数「戦闘状態」が0 敵発見 THEN RESPONSE #100 メッセージ表示「敵がいる」 変数「戦闘状態」に1をセット END // B.臨戦体勢維持 IF 変数「戦闘状態」が1 !敵発見 THEN RESPONSE #100 タイマー「様子見中」に10をセット 変数「戦闘状態」に2をセット END // C.臨戦体勢中に敵再発見 IF 変数「戦闘状態」が2 敵発見 THEN RESPONSE #100 変数「戦闘状態」に1をセット END // D.戦闘終了 IF 変数「戦闘状態」が2 タイマー「様子見中」が経過した THEN RESPONSE #100 変数「戦闘状態」に0をセット END // E.射撃武器に持ち替え IF 敵発見 敵との距離が遠い 変数「射撃武器」が0 THEN RESPONSE #100 飛び道具装備 変数「射撃武器」に1をセット END // F.近接武器に持ち替え IF 敵発見 敵との距離が近い 変数「射撃武器」が1 THEN RESPONSE #100 近接武器装備 変数「射撃武器」に0をセット END |
どうでしょうか。 現在の状態を変数「戦闘状態」として管理しています。 また、戦闘終了まである程度の猶予時間を設ける為にタイマー「様子見中」を入れてみました。 A:「戦闘状態」が0の時敵を発見したらメッセージを発して「戦闘状態」を1にします。 B:「戦闘状態」が1で敵が居なくなったらタイマー「様子見中」を10秒にセットし「戦闘状態」を2にします。 C:「戦闘状態」が2の時敵を発見したら「戦闘状態」を1にします。 D:「戦闘状態」が2のままタイマー「様子見中」が経過したら「戦闘状態」を0にします。 E:敵を発見し、距離が遠く、「射撃武器」が0なら飛び道具を装備して「射撃武器」を1にします。 F:敵を発見し、距離が近く、「射撃武器」が1なら近接武器を装備して「射撃武器」を0にします。 視界に敵が入ると「敵がいる」とメッセージを発します。 敵が物陰に入ったり魔法で消えたりで視界から居なくなっても、10秒間は臨戦体勢を維持しその間は再度発見してもメッセージは発しません。 10秒間敵が居ない状態が続くと戦闘終了とみなして初期状態に戻ります。 また、武器は現在どちらを装備しているかを変数「射撃武器」として保存してみました。 これを条件に用いることで、既に最適な武器を装備しているのにも関わらず装備を繰り返す事によるそれ以降へのスクリプトフローのブロックを防げます。 もう一点、4の例にあった Continue() が消えていることにお気づきでしょうか?書き方を工夫してフローのブロックが起きないようにすれば Continue() 無しでも大丈夫です。実際のスクリプトはこんな感じになります。 コンパイルして動作を確かめてみるのも良いと思います。 |