戻る

※私個人が利便上使っている用語が存在します。

 AI制作の手引き 序 by ADI
15:52 2011/10/29 ちょっと追記
23:03 2011/06/03 今更間違いに気付く。
20:36 2011/03/05 ちょい
07:04 2011/02/17 用語に今更MUGEN側のAIについて追加
17:07 2010/12/01
・・・
11:23 2009/10/24 必要だったので書き始める。

 ここでいうAIとは、ステート記述を加え、
  キャラクターに自動で動作を行わせるものである。

 AIファイル、というものもあるようですが、制作方法が不明である為、
  ここでは、「AI=自動動作記述」として用いています。
ただし[AI File]は、そのAIファイルを指すため注意すること。

 ここで解説するものはあくまで、「自動動作ステート記述」です。

 必要なものだけを書くよう努めます。
  画像があれば分かりやすいんだろうけど。


 キャラの改変に関しては、キャラの制作者に従う
 それが自分で無い場合は、キャラの制作者が
  どの程度許可を出しているのか確認をすること。
 ダメなら諦める。

 あとAIを制作する際には、バックアップをしっかりと取ること。
 本体のもそうですが、製作途中のものも適度なタイミングで。


 AI制作に必要なもの表。
−2.最低限
  >
  >ある程度の一般教養。
−1.キャラの使用条件他。
  >キャラクターの改変に関してのこと
  >一応バックアップ
 0.ステートに使われている記述の知識
  >ステートの記述がどういう形式か覚える。
  >Triggerの形式について知っておく。

 1.キャラクターの情報
  >技の性能と立ち回り等のメモ
  >ステート番号など技の情報
  >動作設計図
 2.ステート内部の情報
  >Var変数の仕様表
  >-1,-2,-3ステートの位置。
  >Command="*コマンド名*"の位置(修正する為)

 3.MUGENで使うのステートプログラムの詳しい知識
  >Trigger用の情報
  >Varなどの利用



 AI制作をするにあたって逃れられないものが、ステート記述を触れることです。
 キャラによっては必須の知識であり、
  分かっていればより確実な動作なども可能になります。

 AI制作の前に、ステート記述がどういった形式であるのかを
  大雑把ながら解説させていただきます。


 「プログラムする上で一番の障害は処理を知らない事。
  それがありとあらゆるバグやミスに繋がる。
  基礎知識として処理を知ることも然り、
   記述した処理を確認することも然り。」



.ファイルの確認


 まず適当なキャラの定義ファイル、「Defファイル」を開いてください。
 仕様上「*フォルダと同名*.def」という名前だと思います。
  テキストソフト(メモ帳など)で開けるようにしておくと便利です。

 そのファイルに書かれているものを簡単に説明すると
[Info];キャラの名前などの一覧。
Name = "*キャラのシステム名*" ;( Nameで呼び出す名前 )
DisplayName = "*キャラの表示名*" ;( 画面上に現れる名前 )
author = "*制作者名*" ;( AuthorNameで呼び出す名前 )

versiondate = "**" ;割愛
mugenversion = "**" ;割愛
Pal.defaults = "**" ;割愛

[Files];呼び出すファイルの一覧。
cmd = *コマンドファイル名* ; コマンド記述や、-1ステートなどのファイル
cns = *コンスタンツファイル名* ; キャラの定数、Lifeなども設定するファイル
st = *ステートファイル名* ; ステート記述のあるファイル
st2 = *2つ目のステートファイル名* ; 限度はst0〜9まで。
stcommon = *コモンステートファイル名* ; 基礎動作のステート記述ファイル。
; ※これらのファイルは、別々である必要は無い。
; ※例えば、KFMは[cns]と[st]で、同じファイルを指定している。

sprite = ** ;割愛 ・スプライト・画像統合ファイル
anim = ** ; 割愛 ・アニメーション指定ファイル
sound = ** ; 割愛 ・サウンドファイル
Pal1 = ** ; 割愛 ・パレットファイル1
ai = ** ; 本当のAIファイル(※制作方法が不明※)

;[Arcade];アーケードモード用ファイル
;割愛

 MUGENがこのファイルから必要なファイルを読み込むことで、
  キャラクターを動かせる状態にしてくれるわけです。

 AI制作で使うことになるのは、[Cmd][Cns][St][St*番号*][stcommon]のファイル。
 まず、Stのファイルをテキストソフトで開きましょう。

 ちなみに「;」←この記号は、「それより右側をシステムと認識しませんよ〜」というもの。
; 補足説明や、なんであるかの記名に使われています。
; 通称はコメントアウト

 あとファイルの記述が多いと、メモ帳などでは処理が重くなりますので、
  使いやすい高性能なテキストソフトで記述編集する方がスムーズに進むかと。
 特に特定文章の色を変えるなどの機能があると、記述のミスなどが気づきやすいです。

 またフォントや基本色なども見やすいものに変えておく方が良いです。
 私の場合、等幅(文字がそれぞれ同じ幅)の「MSゴシック」にサイズ10で通してます。

.まず見てみる


 ステートファイルを開きましたら検索機能で[StateDef と検索をかけます。
 そして、その下に続くのが「ステート記述」です。

 ステート記述は、
[Statedef ***];***番のステート記述・開始
Type = **;オプション

[State ***];ステートコントローラー記述・開始
Type = **;命令・ステートコントローラー名
Value= **;内容・パラメーター(ステートコントローラーによって記述が異なる)
Trigger1 = **;条件・トリガー。「0」か「0でない」かで判断している。

; ステートコントローラー(Type = **)とは「どんな処理をさせるか」という命令、
;  パラメーター( Value = **他 )は「どのように処理をするか」という内容、
;  トリガー( Trigger** = ** )とは「どんな時に処理をさせるか」という条件です。

[State ***];ステコン開始+ 直前のステートコントローラー記述の終わり
Type = **;
TriggerAll = **;
Trigger1 = **;
Trigger2 = **;
Value = **; (Type以外の位置は同ステートコントローラー内ならどこでも良い。)

[Statedef ***];***番のステート記述の開始+ 直前のステコン記述・ステート記述の終わり
Type = **;オプション
;以下略
 という風に記述が行われています。
 キャラクターのステートは、こうしたものがズラリと並んで構成されています。
  反対に言えば、構成しているものはほとんどこれだけです。


 そして、キャラクターは常に1つのステート番号を持ち、
  そのステート番号と同じ番号のステートを呼び出して、処理を行っていきます。
 例えば200番のステートにいるなら[StateDef 200]の処理を行うというわけです。

 ステートとは「○○番の仕事」で、ステートコントローラーは「仕事の命令」
  パラメーターは「注文内容」、トリガーは「実行のタイミング」という感じ。

 主な基本動作のステートは「0番の立ち待機(ニュートラルポーズ)」に、
  「20番の歩き動作」や「40番のジャンプ始動」などなどがあります。
 それらの動作も基本的にステート記述で制御されているのです。

 ステートコントローラーの内容や、トリガー用の情報などは、
  >このサイト( http://homotaro.s44.xrea.com/mugen.htm )<の
  >このページ(ステートコントローラー一覧(HTML))
  >このページ(トリガー情報の索引)
 などを参照しましょう。※外部サイト。私のサイトではありません。※
 ちなみにトリガー情報はTrigger***=以外、パラメータなどでも使えるものもあります。

 ステート記述を図にするとこう
┌ステート***([StateDef ****])────・・・

| ┌ステートコントローラー([State ****])──┐
| │Type = *ステートコントローラー名*;命令名 |
| | ├パラメータ───────────┐  |
| │ |Value= *命令値*;命令で異なる  |  |
| │ |Value以外のことも        |  |
| │ └────────────────┘  |
| │┌トリガー(Trigger*** =)──────┐  |
| ||Trigger*** = *条件式*;トリガー  |  |
| || 条件式に使うための情報があり、 |  |
| || それを組み合わせることで使う。 |  |
| |└─────────────────┘  |
| └─────────────────────┘

| ┌ステートコントローラー([State ****])──┐
| │Type = *ステートコントローラー名*;命令名 |
| | ├パラメータ───────────┐  |
| │ |Value= *命令値*;命令で異なる  |  |
| │ └────────────────┘  |
| │┌トリガー(Trigger*** =)──────┐  |
| ||Trigger*** = *条件式*;トリガー  |  |
| |└─────────────────┘  |
| └─────────────────────┘

| ┌[State ****](ステートコントローラー)──┐
| │Type = *ステートコントローラー名*;    |
| |Trigger*** = *条件式*;          |
| │Value= *命令値*;             |
| └─────────────────────┘

└───・・・
┌[StateDef ****](ステート***)───・・・
■以下略

 あとはステートを眺めながら分からないものは先ほどのサイトで確認し、
  ステートがどういうものか、まず見て慣れましょう。
 大体こういうものだと見慣れてから、作ることに慣れる作業へ移ります。
 一応その5で例を出して解説してますが。

 次にステートがどう読み込まれているのかを説明します。

.参照処理

 M.U.G.E.Nのステートの処理は、
 基本処理
  ↓
 1Pキャラ (-3ステート) → -2ステート → (-1ステート) → 現在の番号のステート
  ↓
 2Pキャラ (-3ステート) → -2ステート → (-1ステート) → 現在の番号のステート
  ↓
  次のユニット     ※一応、状況によって順番が前後することも。

 という順番で参照がおこなわれ、全てのステート処理が終わってから
  フレームが進み、MUGEN本体の処理が行われ、またステートの処理が行われます。
( フレーム(F):ゲーム内の時間単位。処理の1周分が1フレーム。基本60Fで約一秒。
  一秒に60回画像を変えたりするので、動いている、動かしているように見えるわけです。 )

 細かい所はかなり省いてますが、大体こんな感じだと覚えてください。

 新しく出てきた「-xステート」とは、常に行う処理のステート。
 ■-2ステートは「常時監視ステート」 >毎フレーム、参照を行います。
 ■-3ステートと-1ステートは「常時監視ステート」
  >毎フレーム、相手にステートを奪われていなければ、参照を行います。
 ステートを奪われている状況というのは「投げ技」などを受けている時です。
 その場合、参照は「→ -2ステート → 現在の番号のステート →」という形になります。


 ちなみに同じステートの中では、
  上から順番に一つ一つトリガー・条件の真偽と、
  ステートコントローラーの処理が行われています。


 Defファイルを見て、次はCmdのファイルを開いてください。
 ダブルクリックで開けない場合は、テキストソフトを開いてドラッグ&ドロップ。

 そのCmdファイルにはコマンドの情報が記されていますが、とりあえず割愛。

 Cmdファイルを開いたら検索機能で、[Statedef -1] と検索してください。
 そこから下にあるものが-1ステート、主に「コマンドを動作に反映させる記述」です。

 ほぼ全てのステートコントローラー記述が Type = ChangeState で、
  トリガーに Command="***" といった記述が含まれているはず。
 「ある状況で***というコマンドが入力された時、Value=**のステートへ移行する」
  という記述。キャラクター操作の制御は、ほとんどがここで行われているわけです。

 -1ステートは後々も使っていくので、場所を覚えておきましょう


.AIと-1ステート
 AIでも、この-1ステートの記述されている条件を基本とし、
  「コマンドの条件」を「技の出す状況の条件」に変える形になります。
 といっても、そのままそっくりコピーして記述を変えるのは不便なので、
  トリガーグループを分解して使うことになりますが。
 ちなみに「ChangeState」はあくまで単なる命令であり、処理もパラメーター(Value)に従うだけ。
  そのため同じ番号へのChangeStateはいくつでも記述することができます。

 つまり、-1ステート(もしくは-3ステート)などに、
  ChangeStateのステートコントローラーを並べることで自動で動くようにするのが、
  ここでいうAI記述の基本になります。


 ですが、-1ステート以外でコマンド制御されている動作や、
  ステートで制御されていない動作もあり、
  全てが全てここで制御されているわけではありません。

 まず-1ステート以外でコマンド制御されている動作とは、
  Command="***"という記述はあくまで「トリガー用の情報の1つ」であり、
  -2ステートや-3ステート、通常のステートにも使えるものです。

 次に、厄介なステートで制御されていない動作は、
  「レバー方向による動作」の歩き・屈み・ジャンプ・ガードの始動です。
  この動作は-3ステートよりも前の「基本処理」で行われています。
 ちなみにダッシュは「レバー二回というコマンド」を使って-1ステートで制御されています。

 AIではCommandを制御できない為、AIをつける際は、
  Commandのある条件記述、全てをAIにも使えるよう変えなければなりません。
 「common1.cns」などの他から記述を引っ張ってくる必要のある場合もあります。
 レバー方向による動作はちょっとした記述でいくらか制限できますが、完璧には困難です。

.試してみる
 小難しい話を並べては分かりにくいと思いますので、
  実際に記述をすることでどう動くのかを見てみましょう。

 まず、-1ステートから「Type = ChangeState」で「Value = 200」の記述を探します。
 ある場合はそのステートコントローラーを、なければ適当な技の記述を1つ、
  -1ステートの先頭にコピーし、Command="***" を消しましょう。

Trigger1 = Command = "***"
 その記述の、Trigger1の行がCommandの1つしかない場合は、
Trigger1 = 1 ;無条件・真
 Commandを、0以外の数字に変えます。

Trigger*** = Command = "***" ;
Trigger*** = Command = "***" && Command = "***" ;
Trigger*** = Command = "***" || Command = "***" ;
 上記以外のCommandだけで構成されている行は、その行を削除。

Trigger*** = Command = "***" && *条件式* ;
Trigger*** = *条件式* || Command = "***" ;
 Command以外の条件式が含まれている場合も、
Trigger*** = *条件式* || 1;無条件・真
 Commandを、0以外の数字に変えます。

 Commandを削除する事でコマンドを入力する必要がなくなった状態、
  常にコマンドを入力しているのと同じような状態になります。

 保存をしたらM.U.G.E.Nを起動し、トレーニングで、そのキャラクターを選びましょう。
 既に起動していて、そのキャラクターで一度試合画面に入っている場合は、
  試合画面で「Shift+F4」を押せば試合をリセットし、ファイルを再度読み込み直してくれます。

 すると、その技を出せる状態になったとき自動でその技が出ます。
 特に地上の通常技などであれば、何度も何度も連打するはずです。


 AIはそうした、Commandを抜いた記述へCommandの代わりに、
  「いつ打つか」という状況の条件などを加える形で、制御することになります。

 例えば、先ほどの記述に
TriggerAll = P2BodyDist X < 30 ;相手との距離:極めて近い〜後ろの方
 という記述を加えると、「極めて近い時」という条件が加わり、
TriggerAll = P2StateType = A ;相手の状態:空中
 という記述を加えると、「相手が空中」という条件が加わります。

 こうした様々な条件式を組み合わせることによって、
  AIをより思い通りに動かしていくことになります。

 例として記述したものは消しておきましょう。

 説明を見るよりも、使って覚えるものですが一応。

.Triggerの説明
 と、何度もTriggerが出てきましたが、最初に説明しましたとおりTriggerとは条件のこと。
 Triggerに使う条件式は先ほど紹介したサイトを参照していただくとして、
  Trigger自体の仕様を説明いたします。

 まず、Triggerに使えるものは、TriggerAllTrigger*数値*です。
 Triggerの数の上限は不明。Allでも同じ番号でも、幾つあっても処理されます。
 しかし Trigger1 は、全てのステートコントローラーに1つ以上なければいけません。

TriggerAll = ** ;トリガーオール(ALLはなくてもよい)
TriggerAll = ** ;   1.条件式は当てはまっているなら真,1、間違いなら偽,0を返す
Trigger1 = ** ;トリガー1(1つ以上必要)
Trigger1 = ** ;    2.Triggerは偽(0)と真(0以外)を判別する。
Trigger2 = ** ;トリガー2
Trigger2 = ** ;    3.Allと同じ番号のTriggerが全て真の時、命令を処理する。
Trigger3 = ** ;
Trigger4 = ** ;    4.Triggerの番号は、1から順番に書かなければいけない。
Trigger5 = ** ;
Trigger6 = ** ;    5.トリガーが真で無かった場合、次の記述を参照する。
Trigger7 = ** ;
Trigger... ;トリガー番号の上限数値も不明。

;Triggerの番号が途切れていたりする場合は、途切れるところまで読み込まれます。


 トリガーは命令を実行するための条件で、
  条件はALL(あれば)と、番号のどれかが合うことで満たされます。

TriggerAll = *条件A*
Trigger1 = *条件B*
Trigger2 = *条件C*
Trigger2 = *条件D*
 この場合、A(TriggerAll)B(Trigger1)が真になるか、
  もしくは、A(TriggerAll)CD(Trigger2)が真になることで
  条件が満たされ、命令が処理されるわけです。

 そして、ABのまとまり・ACDのまとまりを、私はトリガーグループと呼んでいます。
 先の例をトリガーグループでまとめた条件式にすると、
 ◇トリガーグループ1
Trigger*** = *条件A* ; TriggerAll
Trigger*** = *条件B* ; Trigger1
 ◇トリガーグループ2
Trigger*** = *条件A* ; TriggerAll
Trigger*** = *条件C* ; Trigger2
Trigger*** = *条件D* ; Trigger2
 ということになります。

 トリガーグループはどれも「必要な条件」であり、
  AIの技の記述を行う場合は、こうしたトリガーグループに分解しすることで、
  必要な条件だけを抜き出します。


 ちなみに条件式は上限はあるものの、1行一つに限定されているわけではありません。
 理論演算子と呼ばれる記号の、「 && 」や「 || 」などを用いることで、
  一行に複数の条件式をまとめることもできます。

 例えば、先ほど出した条件式も、「 &&(AND) 」を使えば
TriggerAll = *条件A*
Trigger1 = *条件B*
Trigger2 = *条件C*
Trigger2 = *条件D*
 ↑から↓にできます。
TriggerAll = *条件A*
Trigger1 = *条件B*
Trigger2 = *条件C* && *条件D* ;> 条件C+条件D
 そこへ、さらに「 ||(or) 」を使うことで、
TriggerAll = *条件A*
Trigger1 = *条件B* || *条件C* && *条件D* ;> 条件B または 条件C+条件D
 というようように、Triggerをまとめることも出来ます。
 ちなみに||と&&が同じ行で使われている場合、優先度は&&が高い為、
  &&で条件式をまとめてから、||で分かれます。

 さらに囲った条件を優先する「 ( ) 」を使うことで、
Trigger1 = *条件A* && ( *条件B* || *条件C* && *条件D* );> A+( B または C+D )
 という一行に
TriggerAll = *条件A*
Trigger1 = *条件B*
Trigger2 = *条件C*
Trigger2 = *条件D*
 この4行のTriggerたちをまとめる事もできます。

 勿論まとめられるのだから分解も出来るわけで、反対に
Trigger1 = ( *条件A* || *条件B* ) || *条件C* && *条件D*
 といった記述は、
Trigger1 = ( *条件A* || *条件B* )
Trigger2 = *条件C* && *条件D*
 や
Trigger1 = *条件A*
Trigger2 = *条件B*
Trigger3 = *条件C*
Trigger3 = *条件D*
 という風に分解することが出来ます。
 トリガーグループに分解するときは、
  このように条件式自体を一度バラすと分かりやすいかもしれません。


 例えば以下のような記述
;※KFMのCmdファイルからの引用。
[State -1, Crouching Strong Punch]
type = ChangeState
value = 410
triggerall = command = "y"
triggerall = command = "holddown"

trigger1 = statetype = C
trigger1 = ctrl

trigger2 = (stateno = 400) || (stateno = 430)
trigger2 = (time > 9) || (movecontact && time > 5)


 このステートコントローラーのトリガーは、
triggerall = command = "y" && command = "holddown" ;コマンド記述
 と
trigger1 = statetype = C && ctrl ;始動条件
 と
trigger2 = (stateno = 400) || (stateno = 430)
trigger2 = (time > 9) || (movecontact && time > 5)

 で構成されています。

 さらにそこからTrigger2を砕いてみると。
trigger2 = (stateno = 400) || (stateno = 430)
trigger2 = (time > 9) || (movecontact && time > 5)
 ( || )&&( || )ですので、
trigger2 = (stateno = 400) ;A
trigger2 = (time > 9) || (movecontact && time > 5) ; ( || )
trigger3 = (stateno = 430) ;B
trigger3 = (time > 9) || (movecontact && time > 5) ; ( || )
 ↓で、
trigger2 = (stateno = 400) ;A
trigger2 = (time > 9) ;C
trigger3 = (stateno = 400) ;A
trigger3 = (movecontact && time > 5) ;D
trigger4 = (stateno = 430) ;B
trigger4 = (time > 9) ;C
trigger5 = (stateno = 430) ;B
trigger5 = (movecontact && time > 5) ;D
 という4通りの組み合わせに分解することができます。

 そしてトリガーグループは、
; 1◇グループ1
Trigger1 = command = "y" && command = "holddown";コマンド記述
Trigger1 = StateType = C && Ctrl ;Trigger1 のまとまり
; 2◇グループ2−1−1
Trigger2 = command = "y" && command = "holddown";コマンド記述
Trigger2 = stateno = 400 && time > 9 ;Trigger2 の前半+前半
; 3◇グループ2−1−2
Trigger3 = command = "y" && command = "holddown";コマンド記述
Trigger3 = stateno = 400 && movecontact && time > 5 ;Trigger2 の前半+後半
; 4◇グループ2−2−1
Trigger4 = command = "y" && command = "holddown";コマンド記述
Trigger4 = stateno = 430 && time > 9 ;Trigger2 の後半+前半
; 5◇グループ2−2−2
Trigger5 = command = "y" && command = "holddown";コマンド記述
Trigger5 = stateno = 430 && movecontact && time > 5 ;Trigger2 の後半+後半
 の5種類になるわけです。
 先ほどのトリガー記述を、これに差し替えたとしても、
  条件は全く同じである為、処理に変化はありません。

 つまり、このいずれもが「技の前提条件」として機能し、
  どれか1つでも当てはまっているのであれば、
  元の条件にも当てはまっている状態だと分かります。

 AIを制作する際には、このようにトリガーグループを分解して、
  コマンド記述だけ削除し「技の前提条件」として組み込みます。
 もっと言えば、AIも「技の前提条件」には注意しなければいけません


 例えば、パワーゲージを使うゲージ技で、ゲージ量の条件を忘れた場合、
  ゲージが無い状態でもそれを使ってしまう、という事態が起こります。
 状態の記述が甘いと、出来ないはずなのに技をキャンセルしてしまったり、
  酷い場合には空中浮遊してしまったり、動作を不自然にくりかえしたりなど。

 それを防ぐためにまず技の前提条件を付けてから、
  その他もろもろの条件をつけることになります。


 ちなみに条件式のStateNo=[xx,xxx]などの[xx,xxx]といった記述は
  「xx以上からxxx以下までの数値のいずれか」という数値の指定方法です。
 こちらもそのいずれかでStateNo = xxxと指定すれば、トリガーグループとして機能します。
 ただし、StateNo!=[xx,xxx]の場合は、「xxからxxxの数値でない」という条件です。

 また***=[xx,xx]のバリエーションとして(xx,xxx)や、[xx,xxx)、(xx,xxx]があります。
 これは()側の数値は「( xxよりも大きい」「xxx )よりも小さい」という指定です。
 []のxx以上xxx以下とは、xxの数値を含まないという点だけ違います。

 もちろん、それと同様にTime>5というような条件は、
  「Timeが5より大きい」のならトリガーグループとして機能します。(Time=7など)
 その他、MoveContactなどのように単体で書かれている条件の数値は、
  その数値が「0以外(真)」ならOKです。(MoveContact>5など ※Dos版は不可
  あと!MoveContactの場合は、MoveContact=0でなければいけません。



.記述ついて、蛇足
 慣れてから、注意することですが。

 トリガーはつないでいくだけで作っていくと、
  Triggerの量が膨大になり、見辛くなってしまいます。
 かと言って全てを&&などでまとめてしまっても、見づらいです。

 トリガーの分類などで行なども適度にまとめるよう意識しましょう
 また複雑なトリガーは、横に「 ; 」を打って何を意味するトリガーか
  説明などを書いておくと、忘れてしまったときなどに助かります。



 ■Triggerの細かい処理の図解(読まなくてもいい。)
( Trigger*数値*をTriggerXと記載 )
 Triggerの真と偽を判定する。
 ├Triggerが真(数値0以外)の場合
 | ├TriggerAllである。
 | | └↑次のTriggerXを参照する。(最初に戻る↑)
 | |
 | └TriggerXである。
 |   ├処理していないTriggerXがある。
 |   | └↑次のTriggerXを参照する。(最初に戻る↑)
 |   └処理していないTriggerXが無い
 |     └●参照を終え、ステートコントローラーを実行する●
 |
 └Triggerが偽(数値0)の場合
   ├TriggerAllである
   | └×参照を終え、次のステートコントローラーの参照を行う×
   |
   └TriggerXである
     ├処理していない次の番号のTriggerX+1がある。
     | └↑次にTriggerX+1を参照する。(最初に戻る↑)
     └処理していない次の番号のTriggerX+1が無い。
       └×参照を終え、次のステートコントローラーの参照を行う×
 ●トリガーが真と判定された時
 └ステートコントローラーのパラメーターを参照する。


 ステート記述のことを大体説明しましたので、あとは
  >このサイト(※外部サイト。私のサイトではありません。※)<の
  >このページ(ステートコントローラー一覧)
  >このページ(トリガー情報の索引)
 などを参照しながら、制作することになります。

 ですがまだ、AIそのものに関しては説明していません。
 次の項ではAIに関する情報を説明していきますが、
  ここで説明したステートの知識も度々必要になります。



 >その1へ


  私の使っている用語についてメモ
※共通語ではないかと。

  ■*○○* ****(〜〜が入る)
 ◇*○○*は、○○に書かれたものが入る、代替文。
  ****も同様で、何かしらの文章か数値を入れる。
 ◇なぜ*(アスタリスク)で挟んでいるのかといえば、打ちやすかったから。
 ◇ちなみに、乗算(かけ算)を行う場合も*を使いますが、
  数式との違いは前後から読み取ってください。

  ■CNS(Constants,Cnsファイル)・ステートプログラム
 ◇ステートの記述されたファイルまた、ステート記述の方式。
 ◇これが分かるようになると、AI制作がグッと楽になる。
 ◇決まった呼び方が無い為、M.U.G.E.Nのキャラクターで使われているプログラム、
  ステートコントローラーとトリガーで構成される方式がCNSと呼ばれたりします。
 ◇cnsはConstants(コンスタンツ)、「定数」の略称ですが、
  CNSといえば、大体ステートプログラムだと伝わるはずです。

  ■ステート(State)
 ◇命令文のまとまりの1つ、または命令文。
 ◇[StateDef ****]でその****番のステートが始まり、
  ファイルの終了、もしくは次の[StateDef ****]でステートが終わる。
 ◇同番号のステートが複数ある場合先に読み込まれる方が優先される。
  ファイル順の優先度はst > st0 > st1〜番号順 となっている。
 ( ちなみにCommon1.cns(MUGEN側のファイル)の優先度は最低。 )
 ◇0以上の数字の他、-1,-2,-3ステートが存在する。
 ◇ステートコントローラーが1つも存在しない場合などは、エラーを返す。
 ◇参照は、-3 → -2 → -1 → 現在のStateNo の順で行われる。
   ステート内の参照は言わずもがな上から順に。
 ◇相手のステートを参照させられている場合は、-2 → 現在のState。
  >-2ステートは毎F処理を行う「常時監視ステート」
  >-1,-3ステートは「準常時監視ステート」という感じです。
 ◇ステートコントローラーでChangeStateなどを行うと、
   それより下のステート記述の参照を飛ばす。

  ■ステートコントローラー
 ◇命令文、またその命令。
 ◇[State ****]で始まり、ファイルの終了か次の[State ****]で終わる。
  ****には何が入ってもいいが、分かりやすく見やすいものが望ましい。
 ◇構文のエラーを起こしている場合、****がエラー時に表示される為、
  例として[State *番号*, *数字もしくは名前*]などが特定しやすい。
 ◇Type = *ステートコントローラー名*とTrigger1 = *条件式*を必須とし、
  またステートコントローラーによって他にも必須な数値がある。
 ◇AIで使うことになるコントローラーは基本的に ChangeState だけ。
  加えてVarsetやVaradd。凝ったものになるとHelperなども使うようになる。

  ■トリガー(Trigger)
 ◇ステートコントローラーの条件、また条件式。
 ◇TriggerAll = 、Trigger1 = 、Trigger*数値* = などで始め、
  情報から作った条件式をその右に書き、条件の真偽を判断させ、
  トリガーグループが真になった時、ステートコントローラーの命令を処理します。
 ◇条件式は、トリガー以外でも数値を扱う箇所で使えます。
  条件式は真で1を、偽で0を返します。上手く使えると便利です。
 ◇条件式を、数値の形式でおいた場合、0が偽、0以外が真になります。
 ◇条件式の前に!を置くと「〜でない」。偽を真に、真を偽に反転させます。
 ◇ちなみに一行の文字数限度は256字くらいまでらしいです。書き過ぎないよう注意。

  ■トリガーグループ
 ◇同じ数値Triggerと、TriggerAllをあわせたもの。条件のパターン。
 ◇TriggerAll+Trigger1の全体をトリガーグループ1などと呼んでいます。
 ◇ || (〜または〜)がある場合は、グループ1−2だとか、かな。
 ◇AIでは、Commandのこれを分割して記述することになりますし、
  難しいことではないので、覚えておきましょう。
 ◇トリガーの性質についてはとりあえず割愛。



  ■MUGEN側のCPU,AI
 ◇Cnsで管理されたAIではなくMUGEN側のAIのこと。私限定の呼び方かな。
 ◇Arcadeモードなどの相手やWatchモードの両方、TeamモードのSimulの相方などは
  最初からCPU,AIが管理しており、デバッグキーのCtrl+1などで起動・停止も可能。
  TrainingモードではTraining MenuのDummy ControlをAIにすることで起動する。
 ◇CPU,AIが起動している場合は「プレイヤーがコマンド入力のできず、
   MUGEN側が無作為にコマンド入力処理を行なっている状態」になる。
 ◇そのせいで予期せぬAI動作の温床になっているのだが、
  それらの仕組みを理解していれば制御は可能。

 ◇後で説明するがCnsで監視しているAIは、CPU,AIの特性を応用した
  「人間には不可能なコマンド入力を感知して起動する方式」が多い。
 ◇そうしたCnsで管理しているAIは一度AIが起動すると
  処理の関係上、試合中にプレイヤー操作へ戻すことはできない。


戻る