MUGEN ( フォント環境:MS ゴシック 標準 サイズ10 )   AIの基本 byADI  ※初歩の追加メモ  ※各個をまとめよう・・・。  [AI製作の手引き/AI00.html]の方をどうぞ。 23:01 2011/06/03※Triggerについて、間違いがありました。  >参照されません。 17:57 2009/10/27 0:28 2009/10/25 最後の方に追加。 11:00 2009/10/15 ちょくちょく。 5:00 2009/10/10 ちょいちょい。 0:35 2009/10/07 ちょいちょい 14:49 2009/10/03 -1,-2,-3ステートの検証。 14:28 2009/09/30 まだ・・・。 20:34 2009/09/24 まだ足りない。 17:44 2009/09/25 書き続けてたら長すぎると気づく。どうしよ。 23:51 2009/09/25 まだ途中。  AIを制作する時、キャラクターの制作者が自分で無い場合、   どの程度許可を出しているのか確認をすること。  細かい所は、他の方の説明書をご覧になってください。   大雑把にメモを取っているだけです。  ちなみにたびたびでてくる「そうした所」とか「そういう所」は、   「そういう場所」です。うん。  リダイレクトの調整だとかは、その説明以外省略。  また、[Varの初歩]、[AIの初歩]、に書かれているもの、   格闘ゲームの基本などの話もだいぶ割愛している為、   それらが必要な場合そちらの閲覧をどうぞ。 ■■■準備0・下準備  しっかりとキャラの確認を行う。  キャラの性能を知り、技の性能などをメモ。  その際キャラの技のStateNoも調べてメモしておく。 ( コンボなどもメモしておく。 )  そして、AIの書いていく場所を決める。  ステートの説明になるが、 [Statedef xxx]←これがxxxの番号の記述を始める記述。  同じ番号のStaetDef記述は、一箇所にしか使わないこと。(=一箇所に纏めること)  通常は[Statedef 0]以上だが、特殊なステートが3種類ある。 [Statedef -1];Cmd記述などの入っているステート。自身のステート中、毎フレーム参照を行う。 [Statedef -2];常時監視ステート、毎フレーム参照を行う。相手のステートを参照中でも処理を行う。 [Statedef -3];準常時監視ステート、自身のステート中、毎フレーム参照を行う。(-1と同じ) ( 相手のステートというのは、技が特殊な動作を必要とする場合、   自分の中に記述されている参照し、その特殊な動作を行わせる為にある。 )  ※ 処理は -3ステート → -2ステート → -1ステート → 現在のステートの処理 ※  ※ ステート内でChangeStateの命令が行われた場合、そのChangeStateの記述よりも下側の参照を行わない。 ※  ※ ChangeStateの有無に関わらず、-3,-2,-1の順番だけは変化しない。(※ただし上記の通り参照しないことがある) ※  ※( 状態としては、-3,-2でChangeStateを行っても、「StateNoが変わっている」だけである。 ) ※  ※ ヘルパーはType=Player(※なるべく使わない)の時-3,-2ステートを読み込み、  ※ KeyCtrl=1の時-1ステートを読み込む仕様である。  そして、AIは処理タイミングの関係上-3か-1に記述する事となる。  また、ChangeStateを行う関係上、基本的な記述の下側に書かなければいけない。 できれば  Cmd記述だけをすぐ見れるよう、メモファイルへコピペ。   (Cmd記述は基本的に[Statedef -1]の中に書かれている。)  キャラの動作などの大体の立ち回りをメモしておく。  Var管理メモの作成、AI用変更メモの作成。 ■■■準備1・AIフラグ処理  AI専用キャラにしない場合は、   AIフラグの為に、Cmd記述へ条件を追加する。 Trigger*** = !Var(*AIフラグVar*) ;AIフラグ無し  という記述をCmdファイルにある Command="**コマンド名**" の条件記述に追加。  そうすることで「コマンドでの操作を封印」し、MUGEN自体の操作をほぼ遮断する。  そのほかのステートにもCommand記述の含まれている場合もある為、   全てのステートファイルで「Command」を検索しそれを追加する。  Trigger~~の数値は、Command条件と同じ番号(もしくは同じAll)  ただし、移動動作(0〜199 5000〜5999)などは例外。無闇に触れないことが望ましい。  ※ただし、これだけではMUGEN本体側で処理の行われている動作を制限できない。  ※主に移動関係でレバー系の動作であると思われる。( ガード・前後の移動・ジャンプなど。 )  ※それらを制御したい場合、0〜199の記述を変えなければならなくなる。  AIフラグを立てる方法は、   分からなかったら先人の知恵を借りよう。 ■■■作成1・記述の設計  どこで何をさせるのか、の設計。 1.Varsetなどの雑多処理( 使うのが早い方を上に。 ) 2.防御関連( ガード動作より反撃動作を上に。 ) 3.特殊動作関連( 起き攻めや待ちなどの特殊条件動作。 ) 4.コンボ関連( 重要なコンボを上に ) 5.通常動作関連( 近・中・遠距離・対空などの始動動作。 )  くらいに、自分は分けている。必要な分、適当に分ける。  通常動作はどの距離で何をするのかと言ったことを書き出しておくと楽。  細かい動作のことについては割愛。 ■■■作成2・記述に書く条件  AIの【基本は「動作命令」と「条件記述」の二つ一組】である。  何を使わせるのか、いつ使わせるのか。  以下細かい説明(細かいことはそういう所を参照。説明も状況によって当てはまらないこともある。)  「;◇」などとその右側は説明。  条件式があっている事を「真」、あっていない事を「偽」と呼ぶ。  条件式は数値の「0」か「1」かを返しているだけである為、 Trigger*** = 0; 0があれば無条件に偽、 Trigger*** = 1; 1単体は無条件に真とできる。(※ 0以外であればなんでも構わない) ;◆トリガーの説明。(必要になったら読めば良い) [State a];◇1つの記述を始め。(また、前の記述の終わり。) Type = Null;◇命令(属性)の名前。処理数値は、それぞれ異なる為、そうした所を参照。 ;◇ TriggerAll = 1 ;◇以下条件全てに、同じ条件を加える。1よりも前に書く事。 ;◇ Trigger1 = 1 ;◇ ● Trigger1 は最低1つ以上必要 ● Trigger1 = 0 ;◇Trigger*数字* は同じ数字のTriggerとTriggerAllが全て真である場合、命令された処理を行う。 ;◇ Trigger2 = 1 ;◇Trigger2以降は、それよりも上側の数字の条件式が合っていない時に、参照する。 Trigger2 = 1 ;◇( Triggerは上側から1行ずつ参照され、「真」である場合その次の条件式があれば参照する。 ) Trigger2 = 1 ;◇( Trigger*数字*で「偽」がでた場合、次の数字を参照する。 ) Trigger2 = 1 ;◇( その時次の数字が無い場合、もしくはTriggerAllの場合次の命令文へと向かう。 ) ;◇ Trigger3 = 1 ;◇この条件式例の場合、Trigger2の条件式全てが「真」である為、 Trigger3 = 0 ;◇ Trigger3以降は参照されず、命令された処理が行われる。 ;◇ Trigger5 = 1 ;◇ ● Trigger*数字*は、1から順番にいれないといけない ● Trigger6 = 1 ;◇数字が飛んでいたりする場合は処理が行われない。 Trigger4 = 1 ;◇順番がごっちゃになっている場合は、処理は行われるが、参照は上から行われている。 ;◇ ;◇ちなみに、TriggerAllで偽が出た場合、その記述条件の参照を終了し、次の記述の参照をする。 ;◇またChangeStateなどの「ステート移行」の処理が行われた場合、それより下の記述を参照しない。 ;◇( あくまで移行の処理が行われた場合。移行しない限り毎F参照は行われる。 ) ;◇以降、面倒なのでTrigger*数値*の纏まりを、トリガーグループと呼ぶ。 ;◆ChangeStateの説明 ;◇ChangeState ステート変更。AIとしてはいわゆる「動作命令」 [State xxx, yyy];◇xxxには適当な番号。, yyyには名前(全角可)があれば。無ければ[State xxx] Type = ChangeState ;◇命令(属性):ステート変更 Value = zzzz ;◇zzzzに移行するステート(Cmd記述準拠) TriggerAll = **** ;◇移行するステートのCmdにある条件記述(複数行に及ぶことも多々) ;◇Command=""を除いたALL+1やAll+数値、1つのトリガーグループの条件式を纏めたもの。 ;◇ちなみにこれらはただの命令文である為、数の制限は無く、複数に分けても良い。 TriggerAll = Alive && RoundState = 2 && Var(*AIフラグ*) ;◇AI最低限の記述 ;◇Alive はK.O.されているかどうか。( !Aliveで倒れている ) ;◇RoundState=2 は試合中であること。( 試合開始から相手をKOするまで間。 ) ;◆条件 ;◇◇◇基本 Trigger1 = Ctrl ;◇基本操作が行えるかどうか(レバーでの移動動作などの受付) Trigger1 = Power >= xxxx ;◇パワーゲージ量がxxxx以上である。 Trigger1 = Random < xxx ;◇確率(xxx/1000の確率 動作を固定させない為) Trigger1 = StateType = S ;◇立ち Trigger1 = StateType = C ;◇屈み Trigger1 = StateType = A ;◇空中 Trigger1 = StateType != A ;◇空中でない( L、倒れ状態も含む ) Trigger1 =(P2BodyDist X = [xx,xxx]) ;◇反応距離 xx〜xxxまで (単位は大体1ピクセル?) Trigger1 =(P2BodyDist Y = [yy,yyy]) ;◇反応高さ yy〜yyyまで Trigger1 = BackEdgeBodyDist < xx ;◇壁までの距離(記述・xx未満) ;もちろん、応じて使い分ける。 ;◇◇◇コンボ・追撃用 Trigger1 = StateNo = xxxx ;◇xxxxステート内 Trigger1 = MoveGuarded ;◇攻撃がガードされた時 Trigger1 = MoveGuarded && P2StateType = S ;◇立ちガードされた時 Trigger1 = MoveGuarded && P2StateType = C ;◇屈みガードされた時 Trigger1 = MoveHit ;◇攻撃がヒットした時(ガードされていない時) Trigger1 = PrevStaetNo = xxxx;◇xxxxステート直後のステート内。 Trigger1 = P2MoveType = H ;◇相手くらい中・追撃用 Trigger1 = P2StateType = L ;◇相手倒れ中・起き攻め用(簡易) Trigger1 = P2StateType != L ;◇相手倒れ中でない・起き攻め中暴発封じ Trigger1 = P2StateNo = xxxx ;◇相手がxxxxステート内。(ガードなどの察知) ;◇実際に動かして確認をすること。 ;◇◇◇遅延・タイミング Trigger1 = Time > xx ;◇同じステート内でxxフレーム経ってから。(フレームは1秒60Fが基本) Trigger1 = EnemyNear,Time > xx ;◇相手が同じステート内でxxフレーム経ってから。 Trigger1 = EnemyNear,AnimTime < xx ;◇相手のアニメーションの終わりまでxxフレーム以内。 ;◇目押し、遅延処理他に用いる。 TimeはChangeStateが行われたときリセットような状態。 Trigger1 = EnemyNear,Vel X = [xx,xx] ;◇接近に対する迎撃用記述。 ;◇ >0ならば接近してくる。 <0なら後退している。 ;◇P2BodyDist X = [xx*(EnemyNear,Vel X*発生F数),xxx*(EnemyNear,Vel X*発生F数)] ;◇ というような記述で、相手の動きに対応する攻撃もできるが、 ;◇  Velは状況によって激変する為、極めて少ない発生F数でのみ用いるくらい。 ;◇◇◇ガード関係 Trigger1 = InGuardDist ;◇相手が指定したガード可能範囲の中。 ;◇ガードは記述を間違えると全くしなくなる為、要確認。 ;◇◇◇反撃・迎撃用 Trigger1 = P2MoveType = A ;◇相手が攻撃動作中 Trigger1 = EnemyNear,Vel X > x ;◇相手が向かってきているかどうか。 ;◇記述は、相手の横の速度が 1F x pixel 以上の分かを確認する。 ;◇Velは、内部で処理を行ってくれる速度だが、 ;◇ 動いていても、Pos制御である場合はVelの数値が無いことを留意。 ;◇ 基本動作の速度は大体1~6程度。(キャラによってかなり差がある。) ;◇条件式中の、「=」は等号、「!=」は不等号を表しているが、 Trigger1 != 0 ;◇と言ったような記述はできない。ただ、 Trigger1 = !0 ;◇というように「条件式の前に!を置く」ことはできる。 ;◇!を手前に置かれた条件式は「式の真なら偽」「式の偽なら真」という結果を返す。 ;◇また数値からの真偽は「0(偽)」か「0以外(真)」である。( =0 か !=0 ) ;◇数値場合は「 > >= = != =< < 」や「 =[xx,xx] 」などを用いることができる。 ;◇等号式、不等号式は基本と同様。 ;◇ =[xx,xx] は、左側の数値から右側の数値までを表す。 ;◇ ( ※記述は左より右の数値が大きくなければならない。 ) ;◆情報のリダイレクト ;◇記述例でだしていた Trigger1 = EnemyNear,xxx = xx ;◇相手のxxxがxxである ;◇の「 EnemyNear, 」部分は「リダイレクト」と呼ばれるもので特定の対象を参照する記述。 ;◇リダイレクトの対象が居ない場合、デバッグ表示でエラーが出る為、注意するに越した事は無い。 ;◇ よく使うことになるもの ;◇EnemyNear, は一番近い相手(生死問わず) ;◇EnemyNear(0), も同様。 EnemyNear(1), で二番目に近い相手。 ;◇ たまに使いうるもの ;◇PlayerID(*ID数値*), 特定のIDの者を参照 ;◇Target(*HitID数値*), 特定のHitIDのターゲット(当てた相手)を参照。( Target,で技を問わず ) ;◇Partner, パートナーを参照。 ;◇ 相手のタッグを考慮した場合、使いどころの難しいもの。 ;◇Enemy, はIDの若い方の相手(通常、開始左側(1P側)は2P、開始右側(2P側)は1Pを参照する) ;◇Enemy(0), も同じ。 Enemy(1),で2番目の相手。( 1P側で4P、2P側で3P という具合) ;◇ ( 試合中はリダイレクトの対象が変わらない為、それが必要なシステムには使いうる。 ) ;◇ ヘルパー関係を使う場合に使うもの ;◇Parent, ヘルパーを呼び出した「親」を参照(親が居ないと参照不可) ;◇Root, ヘルパーを呼び出した大本、「本体」を参照(親をたどる為、親が居ないと参照不可) ;◇Helper(*ヘルパーID*), 特定のヘルパーIDを持つヘルパーを参照(居ない場合参照不可) ;◇ ※ヘルパーは自身の呼び出したヘルパーしか参照できません。 ;◇ 数の確認 ;◇NumEnemy = xx 相手の数。(Helperは数えない) ;◇NumHelper = xx 自分の呼び出したヘルパーの数。 ;◇NumHelper(*ヘルパーID*) = xx 自分の呼び出した特定ヘルパーIDのヘルパーの数。 ;◇NumPartner = xx 相方の数。(自分や、Helperは数えない) ;◇NumTarget = xx ターゲットの数。( ターゲットとは、自分が攻撃を当てた相手。 ) ;◇NumTarget(*HitID*) = xx 特定HitIDのターゲットの数。 ;◇ 有無の確認 ;◇PlayerIDExist(*ID番号*) 特定IDのキャラクターが存在するかどうか Trigger1 = NumPartner = 1 ;◇確認 Trigger1 = Partner,*** ;◇リダイレクトの使用。 ;◇◇◇記述応用 ;◇ EnemyNear, ;◇条件式を用いて EnemyNear(!(EnemyNear,Alive||NumEnemy=1)), で生きている最も近い相手。 ;◇ NumEnemy=1は相手が一人である。 EnemyNear,Aliveは最寄の相手が生きているかどうか。 ;◇ !で真偽を反転させている為、相手が一人・もしくは最寄の相手が生きているなら0を返し、 ;◇ 相手が一人でなく、また最寄の相手が生きていない時だけ1を返すようにしている。 ;◇( ただし記述量が膨れ上がるため、通常はVarで管理を行う。EnemyNear(Var(*フラグ*)), ) ;◇ 防御機構用 Trigger1 = Enemy,MoveType != A && Enemy(!(NumEnemy=1)),Movetype != A && InGuardDist ;◇一人目の相手が攻撃中でない + (相手が二人以上なら)二人目が攻撃中でない 状態で、 ;◇ InGuardDist である状態、という条件式。相手が本体以外での攻撃を行っていると判断できる。 ;◇Guard.DistはMovetype=Aでしか発生しないため、攻撃中でないのにGuard.Distがあると言う状態は ;◇ 基本的なキャラクターが相手ならば飛び道具しかないと、考えることができる。 ;◇( あるいはP2MoveType!=Aも加え、PlayerタイプのHelperが最寄でないかを確認する。 ) Trigger1 = Enemy,xxx && Enemy(!(NumEnemy=1)),xxx ;◇この記述なら相手がタッグでも双方を参照可能。 ;◇加えて、相手が一人なら両方とも同じ相手を参照する為、エラーが出ない。 ;◇◇◇ちなみに Trigger1 = P2xxx = xx;◇相手のxxxがxxである。 ;◇のP2は「 自分の中で取得している相手の情報 」であり、種類が限られている。 ;◇ この場合のP2は「StateNo=5150でない最も近い相手。(居なければ最も近い相手?)」で取得できる情報は ;◇P2BodyDist X :自分の前の衝突判定から、相手の前の衝突判定までの距離。 ;◇P2Dist X :自分の中心から、相手の中心まで。 ;◇P2BodyDist Y P2Dist Y :自分と相手との高さ。(相手が上ならマイナス・自分が上ならプラス側) ;◇P2Life :相手の体力数値 ;◇P2MoveType :相手のMoveType属性 ;◇P2Statetype :相手のStatetype属性 ;◇P2StateNo :相手のStateNo ;◇ Name情報としては ;◇P1Name :自分のName ;◇P2Name :相手のName ;◇P3Name :パートナーのName ;◇P4Name :二番目に近い相手のName ;◇ といった種類がある。( リダイレクトと異なり、対象が居なくともエラーを返さない。 ) ;◇ ;◇「自分の中で取得している情報」である為、リダイレクトで ;◇EnemyNear,P2MoveType=H といった記述の「相手の,対象のMoveType」も可能。 ;◇Helperなど細かい処理を行う場合は、Root,P2BodyDist Xなども必要となってくる。 ;◇ ;◇ちなみに、P2はPlayerタイプのヘルパーも感知するが、注意が必要なのはキャラ制作側だと思う。 ;◇あと、StateNo=5150はKOステート。 ;◆応用 && と || ;◇例でもたびたび使われていた記述。 ;◇「 && 」は「〜に加えて〜」 「 || 」は「〜または〜」という記述 Trigger1 = *条件1−1* Trigger1 = *条件1−2* ;◇例えば↑は↓と同義。 Trigger1 = *条件1−1* && *条件1−2* ;◇ TriggarAll = *前提条件* Trigger1 = *条件1* Trigger2 = *条件2* ;◇↑と↓も、ほぼ同じ処理である。(例外有り) Triggar1 =( *前提条件* ) && ( *条件1* || *条件2* );◇「 () 」はその内部で処理を行う。 ;◇( *前提条件* と ( *条件1*もしくは*条件2* ) ) ;◇ Trigger1 = *条件1* && *条件2* || *条件3* ;◇&&の優先度が高い為、1,2と3を入れ替えても同じ ;◇また↑と↓も、同じである。( *条件1*と*条件2* もしくは *条件3* ) Trigger1 = *条件1* && *条件2* Trigger2 = *条件3* ;◇ ;◇これらの記述を使うことで、トリガーグループを統合し、記述の量を抑えられる。 ;◇使いどころは難しいが、同じようなものに「 ^^ 」というものがある。 ;◇ これは、「 〜と〜 のどちらかが真である」という記述。 ;◇例えば Trigger1 = *条件1* && !*条件2*;◇条件1が真であり、条件2が真でない。 Trigger2 = !*条件1* && *条件1*;◇条件1が真でなく、条件2が真である。 ;◇ という記述を Trigger1 = *条件1* ^^ *条件2*;◇条件1と条件2のどちらかが真である。 ;◇ に置き換えられるが、使いどころは難しい。 ;◆Varset他の説明  Varの初歩は[Varの初歩]を参照。よって割愛。  Varは情報を保持できる為、それを利用した使い方をする。  ◇AIのVarの使い道の例  .本体の使っているVarは、キャラクター状態状況の把握、コマンド処理などに。   >特殊モード時限定などの技制限処理。(Cmd記述に準拠)   >特殊ゲージなどの管理、技制限処理。(Cmd記述に準拠)   >攻撃の強弱などの技ステート内のコマンド判定。(AI用に書き換えの必要あり。)   >技制限処理に使われていない、特殊状態の確認。(技の性質の変わる状態など。)  .新しくAIの動作の条件などに。   >AIフラグ。AIレベルなどの設定項目。   >特定のコンボを決めるために状況判断を付加させる。   >特定の状況が続いた場合に、反応を起こす。  あるいは、  .条件記述は長いが何度も用いるものをVar(**)に収める記述圧縮など。  ※ Cmd記述にそうした項目がない限り、制限処理に用いられているVarを変更してはいけない。  ※ 使用するVarが重複しないよう、全てのファイルを調べ、使用しているVarを確認し  ※  使用していないものも含めて、表にしておくこと。(AI用に使うVarはそこへ追加する。) ;◇◇◇条件側 TriggerAll = Var(*特殊モード・特殊状態フラグ*) ;◇フラグの形が0or1の場合 TriggerAll = Var(*特殊モード・フラグ数値*) = xx ;◇フラグが特定数値の場合。 TriggerAll = Var(*特殊ゲージ*) ;◇特殊ゲージが0でない。(※0未満、マイナスでも反応する) Trigger*** = Var(*特殊ゲージ*) > xx ;◇特殊ゲージがxx以上。(ゲージ管理) ;◇AILvなどについては[AILv論](HTML)を参照。割愛 ;◇大体は、通常の数式処理と同じような状態。 ;◇◇◇代入(変数をVarへ入れる) ;◇ Varset 代入 [State xxx, yyy] Type = Varset ;◇命令:VarSet Value = xxx ;◇代入数値(セットする数値) V = xx ;◇代入場所(使用するVarスロット) Trigger1 = *条件式* ;◇無ければTrigger1=1だけでも入れる。 ;◇Varsetは、元々の数に関わらず、設定した代入の数値を入れる。 ;◇フラグ系統ではこれが基本となる。 ;◇Vは、FVに変える事でFvar(**)を使用可能。 ;◇それ以外に、 [State a] Type = Varset var(**) = xxx ;◇Varの**スロットへxxxを代入する。 Trigger1 = *条件式*; ;◇と言った代入場所と数値を合わせた記述もできる。 ;◇ただし● var fvar は小文字にすること ●。 大文字だとなぜかエラーを起こす。 ;◇これらの記述の場合、代入ができるのは一度に1つまで。 ;◇ Varadd 加算・減算 [State a] Type = Varadd Value = xxx ;◇増減させる数値 V = xx ;◇数値を増減させるスロット。 Trigger1 = *条件式* ; ;◇Valueの数値は0で変化無し、1以上で加算、-1以下で減算。 ;◇条件が合っているとき増加させ、一定量を超えたとき反応させる、など。 ;◇ちなみにVarSetであっても var(**) = Var(**)+xx で増減の処理は可能。 ;◇処理数値=条件式 Value = *条件式* という記述を用いた場合は、 ;◇ 条件式が合っていれば(真であれば)「1」 ;◇ 条件式が合っていなければ(偽なら)「0」が処理に用いられる。 ;◇ := 条件式・代入記述 Trigger*** = Var(**):=xx ;◇この行が参照された時、Var(**)へxxを代入する。 ;◇その行のトリガーが参照された場合、代入する。 ;◇トリガー参照の順番については、;◆トリガーの説明。を参照。 ;◇なお、この記述は[数値]と同じである為、真偽判定はその数値に寄る。 Trigger1 = Var(**):= 1 ;◇!0真。 Trigger1 = Var(**):= 0 ;◇ 0偽。参照はされるため代入される。 Trigger2 = Var(**):= 3 ;◇!0真。前のトリガーグループが偽だった為、参照され代入される。 Trigger2 = Var(**):= 0 ;◇ 0偽。参照はされるため代入される。 Trigger2 = Var(**):= 5 ;◇!0真だが、前のトリガーが偽なので参照されない。 Trigger3 = Var(**):= 7 ;◇!0真。前のトリガーグループが偽だった為、参照され代入される。 Trigger4 = Var(**):= 9 ;◇!0真。前のトリガーグループが真だった為、参照されない。 ;◇上記の例の場合、最終的に代入されている数値は、Trigger3で代入した7。 ;◇ Var(**) := xx || 1 という記述であれば代入数値に関わらず、真にでき、 ;◇ Var(**) := xx && 0 という記述であれば代入数値に関わらず、偽にできる。 ;◇そうした代入数値に関係ない記述が基本かもしれない。 ;◇なお、トリガー参照で書いたとおり、TriggarAllが偽の場合、次の条件は参照されない。 ;◇その為、Var(**)=0から TriggarAll = Var(**)=1 Trigger1 = Var(**):=1 Trigger2 = 1 ;◇こういった記述をしても、TriggerAllが偽の為、trigger1は参照されない。 ;◇また、TriggerAllが参照されるのは最初の一度だけであり、Var(**)=0から、 TriggerAll = Var(**) = 0 ;◇Var(**) = 0で真 Trigger1 = Var(**):=1 ;◇真 Trigger1 = 0 ;◇偽 Trigger2 = 1 ;◇真 ;◇こうした記述でも、Trigger2でのTriggerAllは既に真を返している為、 ;◇  Var(**)=1 になりながら、処理は行われる。 ;××××××××××××××××××××××××23:02 2011/06/03 ;××××××××××××××××××××××××間違いでした。 ;×××××××××××××××××××××××× ;◇その他、Triggerの情報は番号が順不同であっても、番号が飛んでおらず、 ;◇ 同トリガーグループで偽が出ていないかぎり、上側から真偽判定の処理を行う。 ;◇( 処理は トリガーの番号がどこまで続いているか→上から情報の処理 のようだ ) Trigger1 = 0&&Var(**) := 0 ;◇偽。Varを0に。 Trigger3 = 1||Var(**) = 1 ;◇偽。手前でVarが0になっているので、偽。 Trigger2 = 0&&Var(**) := 1 ;◇偽。Varを1に。 Trigger3 = 1||Var(**) := 2 ; 既にTrigger3は偽を返している為、参照されない。 Trigger4 = 0&&Var(**) = 1 ;◇偽。Trigger3が偽を返している為、参照される。 ;◇ こうした例を出してはいるが、なるべく● 上から順に番号をふる ●事をオススメする。 ;×××××××××××××××××××××××× ;××××××××××××××××××××××××実際には「トリガー番号の若い方から参照します。」 ;×××××××××××××××××××××××× >>>>>正しくはこちら ;◇Triggerの情報は番号が順不同であっても若い番号から順に処理します。 Trigger1 = 0&&Var(**) := 0 ;◇偽。Varを0に。 Trigger3 = Var(**) = 1 ;◇真。↓のTrigger2で1を代入している為。 Trigger2 = 0&&Var(**) := 1 ;◇偽。Varを1に。 Trigger3 = 1||Var(**) := 2 ;◇真。Varを2に。 Trigger4 = 0&&Var(**) := 1 ; 偽。Trigger3が真を返しているので参照されない。 ;◇見やすさを考えて● 上から順に番号をふる ●事をオススメする。 ;◇注意点としては、 [State a] Type = Null;◇命令:何もしない Trigger1=Var(**):= xx ;◇TypeがNullでも、なんであってもトリガーが参照されさえすれば、代入は行われる事。 ;◇その為、こうした記述を用いている場合、TypeにNull;を入れてるよりも、 TriggerAll = 0 ;◇無条件の偽 を条件記述の先頭に入れる方が良い。 ;◇使い道としては「コマンド判定処理」 ;◇技内にコマンドによる強弱判定がある技の条件の最後に、 Trigger*** = 1||Var(*判定Var*):=*強弱判定数値* ;◇トリガーグループが複数あれば全ての後ろに ;◇と記述して、技側は「その判定がある場合判定方法を変える」と言った記述の変更を行う。 ;◇Commandの隣に「 || 」で置くような形の場合は、 ;◇ 記述の先頭で毎回そうしたVarのリセットを行うという感じでも良い、かな。 ;◇( AIフラグで記述を分けていても、AIフラグが無い場合は常に0とする。 ) ;◇同様の形でそれ以外としては、コンボなどの為の制御変数など。 ;◇他には「記述圧縮」として [State a] Type=Varset var(**)=xx Trigger1=1 [State a] Type=Varset var(**)=xx Trigger1=1 ;◇ を [State a] Type=Null Trigger1=1||var(**):=xx Trigger1=var(**):=xx ;◇ という風に圧縮したりできる。(主にコンフィグ一覧などに。) ;◇細かい条件がある場合は [State a] Type=Null Trigger1=*条件* Trigger1=0&&var(**):=xx Trigger2=*条件* Trigger2=0&&var(**):=xx ;◇ という風に 0&& をつけてトリガー番号1つ1つを変えれば、 ;◇ 条件が合っても合わなくても次のトリガーグループの参照は行ってくれる。 ;◇うまく用いれば記述を大幅な圧縮も可能。 ;◇ただし、一律に多くのVarをセットする必要がある場合のみになるが。 ;◇◇◇その他の使用方法 ;◇一応いくらでも使い道はある。ただし、Varのスロットも無尽蔵ではないため注意。 ;◇ リダイレクト用 [State a] Type = Varset var(**) = !(EnemyNear,Alive||NumEnemy=1) Trigger1 = 1 ;◇EnemyNear(Var(**)),xxx といったリダイレクト用の記述圧縮。 ;◇条件式の返す数値は「 真で1 偽で0 」である為、それを利用した代入ができる。 ;◇ 反撃反応用 [State a] Type = VarAdd var(**) = 10 ;◇ 10 はAILvVarでもよい。 Trigger1 = Enemy,MoveType=A || Enemy(!(NumEnemy=1)),MoveType=A;◇相手が攻撃中(どちらか、でも) Trigger2 = MoveType = H || StateType = L ;◇自分がくらい中、もしくは倒れ中 Trigger3 = EnemyNear,P2MoveType = H ;◇相手の対象がくらい中 Trigger4 = EnemyNear,P2StateType = L ;◇相手の対象が倒れ中 ;◇この間に反撃用行動の記述。 ;◇Var(**)の数値を基準に反応を行わせる。 [State a] Type = Varset var(**) = 0 ;◇リセット数値。 Trigger1 = P2MoveType = H || MoveType = A ;◇相手がくらい中、もしくは自分が攻撃中。 Trigger2 = P2Movetype = I && Movetype = I ;◇相手も自分も、くらい状態でも攻撃状態でもなく、 Trigger2 = P2BodyDist X != [xx,xxx];◇(xxxには反応範囲可能を入れる)反応可能範囲外 またより複雑なものとしては、Varに相手情報などを入れて処理を行う「記憶システム」などもある。 それの簡易版として特定の条件がそろった時、Var数値を変動させ、それを動作に反映させるなど。 (ガード状態からガード以外のくらい状態になったら数値を上昇させ、ガードの確率を下げる、など。) ;◇ 統一された確率 [State a] Type = Varset var(**) = Random Trigger1 = 1 ;◇Randomは、毎回異なる数値を返す為、技振りに用いると単純な確率になり下のほうほど使わなくなる ;◇その為、統一された確率を用いることで、絶対にいずれかを行わせることができる。 ;◇◇◇ヘルパー  ※● よく分からない場合は、手を出さない事 ●※  ● ヘルパーは、合計数に【限度】があります。  ● その為、多くても●3つ程度●に抑え、  ●  必要でなければ使わないようにしましょう。  本体だけではできないことをやらせるのがヘルパー。   ヘルパーは本体とは別個の体と変数を有している。  代表例は、InGuardDistの補助と、変数の増設。  長くなりそうな為、詳しくは割愛。  その中で、「呼び出した親」の変数を変える記述がある。 [State a] Type = ParentVarSet ;◇親のVarへ代入する。 Value = *** ;◇代入する数 V = ** ;◇代入するスロット( 記述方法はType = VarSetと同様。 ) Trigger1 = *条件式* [State a] Type = ParentVarAdd ;◇親のVarを増減させる。 Value = *** ;◇増減数 V = ** ;◇増減させるスロット( 記述方法はType = VarAddと同様。 ) Trigger1 = *条件式*  こうした記述を用いることで、本体の変数を変化させるという事も可能。 ;◆オプション IgnoreHitPause = 1 ;◇ヒットポーズ中にも処理を行う。 ;◇ ヒットポーズ中とは、攻撃が当たった時の僅かな停止時間。(コンボの入力猶予など) ;◇この記述を加えるのは、ChangeStateならこの記述のある技。 ;◇Varなどの処理であれば、そうした状況でも処理しなければらならない場合。 ■■■確認 ;◇ 動作確認の処理 TriggerAll = Alive && RoundState = 2 && Var(*AIフラグ*) ;◇AI最低限の記述 ;◇「 ; 」はコメントアウトと言って、「それ以降を処理情報として読み込まない」 TriggerAll = Alive && RoundState = 2 && ;◇ Var(*AIフラグ*) ;◇AI最低限の記述 ;◇このように、AIフラグをコメントアウトすることで、AIフラグが無くとも反応を起こすようになる。 ;◇確認が終わった場合は、コメントアウトを削除して、AIフラグの管理を戻す。 ;◇試合中に「 Shift + F4 」を押すことで試合をリセットし、Cnsファイルなども読み直します。 ;◇ 数値の確認 ;◇デバッグ表示で数値を表示させる。(記述は、-2,ステートに置く。) [State a];◇デバッグ Type = DisplayToClipBoard Trigger1 = 1 Text = "P2BodyDist X=%f, \t P2Dist Y=%f, \nVel X=%f, \t EN_Vel X=%f, \t Bebd=%d" Params = P2BodyDist X, P2Dist Y, Vel X, (EnemyNear,Vel X),BackEdgeBodyDist IgnoreHitPause = 1 ;◇ 相手との衝突判定の距離 相手との高さの差異 ;◇ 自分の速度 相手の速度 後ろまでの距離 ;◇といった表示を行います。 ;◇Var変数を確認する場合。 [State a];◇デバッグ Type = DisplayToClipBoard Trigger1 = 1 Text = "Var(*1*)=%d, \t Var(*2*)=%d, \t Var(*3*)=%d, \nFvar(*4*)=%f, \t Fvar(*5*)=%f" Params = Var(*1*),Var(*2*),Var(*3*),Fvar(*4*),Fvar(*5*) IgnoreHitPause = 1 ;◇特定のVarを見る場合のもの。*数字*は見たいVarの数に変更すること ;◇Varのみ [State a];◇デバッグ Type = DisplayToClipBoard Trigger1 = 1 Text = "Var(*1*)=%d, \t Var(*2*)=%d, \t Var(*3*)=%d, \nVar(*4*)=%d, \t Var(*5*)=%d" Params = Var(*1*),Var(*2*),Var(*3*),var(*4*),var(*5*) IgnoreHitPause = 1 ;◇Fvarのみ [State a];◇デバッグ Type = DisplayToClipBoard Trigger1 = 1 Text = "Fvar(*1*)=%f, \t Fvar(*2*)=%f, \t Fvar(*3*)=%f, \nFvar(*4*)=%f, \t Fvar(*5*)=%f" Params = Fvar(*1*),Fvar(*2*),Fvar(*3*),Fvar(*4*),Fvar(*5*) IgnoreHitPause = 1 ■■■作成3・記述例  どういう動作を、どういう状況で使うか。  「自分の反応をさせたい状況はどういった情報から参照できるのか」   という風に考えて、作成していく。  例えば、「対空」は、   「相手が自分の上側に居る」 = P2Dist Y < 0 ;◇相手が自分よりも上側   「自分は地上にいる」 = Statetype != A ;◇自分が空中でない   「コンボ中ではない」 = P2Movetype != H ;◇相手がくらい中でない  そしてこうした記述に加えて、「技のリーチ」や、「確率・頻度」を加える。 [State a, 対空攻撃] Type = ChangeState Value = **** ;◇対空攻撃ステート TriggerAll = Alive && RoundState = 2 && Var(*AIフラグ*) ;◇AI最低限の記述 TriggerAll = **** ;◇技の前提条件(Cmd記述に準拠) ;◇想定条件 Trigger1 = P2Dist Y < -20 ;◇相手が自分より20以上上側。 Trigger1 = StateType != A ;◇自分が地上 Trigger1 = P2MoveType!= H ;◇相手がくらい中でない。 ;◇技性能 Trigger1 = P2Dist Y = [-yyy,-yy] ;◇どの程度の高さまで届くか。 Trigger1 = P2BodyDist X = [xx,xx] ;◇どの程度の距離まで届くか。 ;◇確率 Trigger1 = Random < xxx ;◇どの程度の確率で動作を行うか。 Trigger1 = PrevStateNo != **** ;◇連続して同じ攻撃を使わない。(戻る手前のStateNoを指定。)  技性能の攻撃範囲については、相手の移動距離を考慮して、   発生フレームが遅い場合はやや広め、早い場合はやや狭く指定すること。  また、範囲ギリギリの指定はしないこと。  キャラによっては衝突判定より当たり判定が小さいこともある。  確率は「ランダムの要素が一切無ければ全く同じ試合を行う為」です。  MUGENのCPUが起動状態であればキーのランダム要素はありますが、   それすらも無い状態、VSモードなどでキャラのAIを強制起動にし、   MUGENのCPUAIを起動しない状態にすると、Random以外の乱数要素はありません。  その為既存キャラでも、Randomなどを固定数値に変えたキャラ同士で戦わせると、   何度でも一定の演舞を確認することが出来るはずです。 ( システム上は「Randomが無い=一定の処理」でなければいけない為。 )  ただ同キャラ戦の場合、処理の順番の差で両者の反応は異なりますが。  記述が甘いと、おかしい動作をする。   何かしら不具合のある動作を行った場合は、前提条件を見直して確認すること。   ずっと反応する場合は、条件が足りない。(もしくは、範囲が広すぎる)   全く反応しない場合は、条件が多すぎる。(もしくは、範囲が狭すぎる)  記述の順番はキチンと考えること。   ChangeState の処理が行われると、そのフレーム中はそれより下の処理が行われない。  その為、優先する記述を先に書いていくことになる。  基本的には、  >Var処理 ( 欠かせない+ChangeStateを行わない為最上位 )  >防御関係  ( 攻撃動作を優先すると、防御がほとんど行われなくなる。 )    >反撃  ( 切り返しなど。ガード優先だと攻撃をしなくなる為 )    >ガード  >コンボ関係 ( タイミング自体が異なる為、コンボの優先順位は特に無し。 )  >通常動作    >ぶっぱ ( 低確率で。 )    >行動  という感じの並びになる。 ( ちなみに、記述がどれだけ長くても、フレームはその記述を処理した後に進みます。   記述が長くなると、重くはなるかもしれませんが、動作が遅れるという事はありえません。 ) ;記述例( ※動作の確認はしてない。 ) ;Varメモ(このままでは使えない。) Var(*AIフラグ*) AIフラグ Var(*1*) EnemyNear(Var(*1*)),用 Var(*2*) ランダム統一数値(割り振り用) Var(*3*) ガード上下管理 ;◇◇◇Var処理 ;◇Var処理1 [State adi, AI flag] Type = Varset var(*AIフラグ*) = 1 ; Trigger1 = *適当な* [State adi, VarSet] Type = Null; Trigger1 1 || Var(*1*) := !(EnemyNear,Alive||NumEnemy=1) ;◇EnemyNear(Var(*1*))用。 Trigger1 1 || Var(*2*) := Random ;◇ランダム統一用 ;◇◇◇ ;◇反撃 ;◇ 反撃反応用 [State adi, Counter] Type = ChangeState Value = **** ;◇カウンター攻撃 TriggerAll = Alive && RoundState = 2 && Var(*AIフラグ*) ;◇AI最低限の記述 TriggerAll = Ctrl ;◇(基本、技の前提条件にある) TriggerAll = **** ;◇技の前提条件(Cmd記述に準拠) TriggerAll = P2MoveType != H ;◇相手がくらい状態でない。 Trigger1 = P2MoveType = A ;◇相手が攻撃状態。 Trigger2 = StateNo = 140 || PrevStateNo = 140 ;◇ガード終了ステート中・ステート後 Trigger3 = PrevStateNo = [5000,5099] ;◇くらい動作後(倒れ含まず) ;◇ガード制御VarSet [State adi, Guard Varset] Type = Null TriggerAll = Var(*3*) := 0 ;◇フラグリセット Trigger1 = !InGuardDist ;◇InGuardDist外ならフラグは0 Trigger2 = StateType = A && Var(*3*) := 1 ;◇基本フラグ Trigger3 = Var(*3*) := 2 + (P2StateType != C) ;◇フラグ(副) 相手屈みで立ち・それ以外屈み Trigger3 = Var(*2*) < 900 ;◇90%(基本的に↓側) Trigger3 = Var(*3*) := 2 + (P2StateType = C) ;◇フラグ(主) 相手屈みで屈み・それ以外立ち ;Var(*3*) = 0 ;リセット ;Var(*3*) = 1 ;基本(空中用) ;Var(*3*) = 2 ; 立ち ;Var(*3*) = 3 ; 屈み ;◇地上ガード [State adi, Guard] Type = ChangeState Value = 130 + (Var(*3*)=3);◇ガードステートへ 基本立ち(130)・屈みフラグで屈み(131) TriggerAll = Alive && RoundState = 2 && Var(*AIフラグ*) ;◇AI最低限の記述 TriggerAll = Ctrl && InGuardDist ;◇ガードの条件 TriggerAll = Statetype != A ;◇地上ガードの条件 Trigger1 = Var(*3*) ;◇ガードフラグあり。 ;◇空中ガード [State adi, Air Guard] Type = ChangeState Value = 132 ;◇空中ガードステートへ TriggerAll = Alive && RoundState = 2 && Var(*AIフラグ*) ;◇AI最低限の記述 TriggerAll = Ctrl && InGuardDist ;◇ガードの条件 TriggerAll = Statetype = A ;◇空中ガードの条件 Trigger1 = Var(*3*) = 1 ;◇ガードフラグ・空中 ;◇◇◇コンボ ;◇目押しコンボ(攻撃動作終了後、次の攻撃に入る。) [State adi, Attack after Attack End];◇英語わからない。 Type = ChangeState Value = **** ;◇つなぐ攻撃 TriggerAll = Alive && RoundState = 2 && Var(*AIフラグ*) ;◇AI最低限の記述 TriggerAll = Ctrl ;◇(基本、前提条件にある) TriggerAll = **** ;◇技の前提条件(Cmd記述に準拠) Trigger1 = P2MoveType = H ;◇相手がくらい状態である。 Trigger1 = PrevStateNo = **** ;◇その前のステート ; ※ !Ctrlの( StateNo *** && AnimTime = 0(動作の終わり) )は、Ctrlより1F早く始動します ※ ;◇キャンセルコンボ(動作を中断して次の攻撃に入る。チェーンコンボなど。) [State adi, Attack by Attack Cancel];◇英語わからない。 Type = ChangeState Value = **** ;◇つなぐ攻撃 TriggerAll = Alive && RoundState = 2 && Var(*AIフラグ*) ;◇AI最低限の記述 TriggerAll = MoveContact ;◇攻撃を当てた(基本、前提条件にあるもの) TriggerAll = StateNo = **** ;◇当てた攻撃(基本、前提条件にあるもの) TriggerAll = **** ;◇技の前提条件(Cmd記述に準拠) Trigger1 = P2MoveType = H ;◇相手がくらい状態。 ;◇ 対ガードの条件 ;◇Trigger1 = MoveGuarded && P2StateType = S ;◇攻撃ガードされた+相手立ち状態。 ;◇Trigger1 = MoveGuarded && P2StateType = C ;◇攻撃ガードされた+相手屈み状態。 ;◇ ヒット後の条件 ;◇Trigger1 = MoveHit ;◇攻撃が直撃した。 ;◇Trigger1 = MoveHit && P2StateType = A ;◇攻撃が直撃し、相手が浮いた。 ;◇ 相手吹き飛び中(?)の条件 ;◇Trigger1 = P2StateType = A && P2MoveType = H ;◇相手が空中くらい状態。 ;◇Trigger1 = P2StateType = A && P2MoveType = H && P2StateNo!=[120,159] ;◇相手が空中くらい状態で、ガードでない ;◇◇◇通常動作 ;◇通常攻撃 [State a, Attack] Type = ChangeState Value = **** ;◇攻撃ステート TriggerAll = Alive && RoundState = 2 && Var(*AIフラグ*) ;◇AI最低限の記述 TriggerAll = **** ;◇技の前提条件(Cmd記述に準拠) Trigger1 = **** ;◇想定状況の条件 Trigger1 = **** ;◇技性能を考慮した条件 ;◇ここらへんは例に出した通り。 ;◇基本動作 [State a, Crouch] Type = ChangeState Value = 11 ;◇屈み固定ステート TriggerAll = Alive && RoundState = 2 && Var(*AIフラグ*) ;◇AI最低限の記述 TriggerAll = Ctrl && StateType != A ;◇前提条件 Trigger1 = P2MoveType = 0 ;◇相手が立ちステート ;◇基本動作ステート一覧 ;◇ 0:立ち ;◇ 11:屈み ( 10:立ちから屈み 12:屈みから立ち ) ;◇ 20:歩き ( 前後はコマンド判定 AIで制御したい場合は要記述改変 ) ;◇ 40:ジャンプ ( 同上 ) ;◇ 45:空中ジャンプ ( 空中ジャンプの限度数は自身のVarで管理しなければいけない。 ) ;◇100:ダッシュ ( 動作終了はコマンド判定。 ) ;◇105:バックダッシュ ( バックステップでない場合、ダッシュと同様かと。 ) ;◇110:115空中ダッシュなど?  ;◇ 行動によっては、1フレームだけといったことも可能であり、 ;◇  動作がガクガクするといった状態になることもありうる。 ;◇ また移動を「遠:前 近:後」というふうに記述すると、前後を繰り返してしまうことも。  こういった記述を用いて、動作の始動を行わせる事になる。 ( 動作ステート内でコマンド判定が行われている場合はそれらの記述を調整する。 )  動作は随時確認し、キチンと反応するかを調べておくこと。  複数の箇所を纏めて確認しようとすると、どこが間違っているか分からなくなる場合がある。 ■■■調整・実践調査( 文章だけ )  そのキャラクターと同様の性能を持っているキャラと対戦させる、   もしくは手操作で対戦し、実践での動作を確認する。  何度も、また複数のキャラの相手をさせ、どこか動作に改良点が無いかを調べる。  コンボに不良がないか、どこか動作が抜けていないか、そうした点から、   「攻撃を受けるとき」を確認し不用意な受け方をしていないか、など。  ● 動作の設計や、調整は個々人に委ねる。 ●  例えば、格闘ゲームの基本がなっていない状態、特に無闇な攻撃や、   そこから攻撃を受けるような状態は修正をするべきである。 ( 例えば遠距離からの突進技が、ガードで反撃確定する場合はたまにしか使わせないなど。 )  また複数のタイプの相手と戦って、「ハマり」がおきていないかなども調べ、   動作の見直しや、条件の見直し、新しい動作の追加などを考慮する。 ( ハマり:同じような攻撃方法に対して対応できていない事が繰り返される。 )  パターンの緩和には動作の選択肢を増やし、低確率で別の動作をせる。  動作しすぎによるガードの甘さには動作の確率を減らしガードできるタイミングを増やす。  相手のガードをなかなか崩せない場合は、固めの選択肢増やすか、   ガードされ続け崩すこともできなければ様子見を行う、など。  足りない部分を補い、様々な状況に応えうるよう調整することになるが、   調整方法だとかは、設計構築と同様、個々人で考え行うことになる。  【負けることには理由がある。】 なぜ負けたのか考え、調整する。  勝ったとしても、どこか改善点は無いか探し、調整する。  ただし、AIの限界は考慮と技術の限界である為、極めて難い。  その為、適度な目標を作って、調整するといい。 ( 〜〜に勝ち越せる・〜〜に勝てる・〜〜と五分 のように。 )  また強さばかりでなく、様々な考慮も行うべきである。 ( 例えば、特殊ガード全開などは相手を選ぶように、    その場合は、レベル制なども考慮に加える。 )  ◇魅せに関しては  [魅せに関する話]を参照。  強いばかりがAIではない。 ■■■「システム」について  条件記述を複合させてVarなどを管理し、特殊な反応を返させるシステム全般。  ぶっちゃけると応用編。  「特定な状態になったとき変数を操作し、その変数を動作の条件に加える。」  基本のChangeStateの記述1つだけで動作させるものを単式と呼ぶとすれば、   Varsetなどで変数管理をしChangeStateの条件に加えるものを複式と呼べるだろう。  例で出してた反撃反応用の記述も複式にあたる。  AIフラグなどは「基本条件」であり、それを変動させどうこうというわけでない。   AIレベルも変動式であれば、変動の為の条件を有している為、複式と呼びうる。  とかなんとか。  記憶システムは条件→記憶→条件→動作であるので複式  特定条件になった場合に数値を変動させ、行動に反映させれば大体複式。  複式の利点は「柔軟性」を持たせられることにある。  変数を記憶することで、その状態を察知し、管理することができます。  別の言い方をすれば、   「その状態を察知しないかぎり、その行動を行わない」という管理も可能です。  極端な例としては「ゲージがマックスで使い放題な状態かどうか」を判定すること。  黒カラーなどであればそのカラーであることを感知すればいいのですが、   F3や記述の追加などで、本体に装備されていないゲージの増加を行っている場合、   超必殺技の「ゲージ量が最大」だけではゲージを使いすぎて困る可能性がある。  だからと言って、そうした特殊な状態を知ることのできる条件記述はありません。  そうした時に「1Fでゲージが異常な量増加する」といった条件で変数を変動させ、   それが何度かある場合にその状態が確定、ゲージ技を遠慮なく使わせるといったものです。 ■■■■■■■■■■■■■■■ ■■■対アーマーの考慮  ステート強制的に維持し、相手に奪われもされないアーマー。  その為、例えば相手が浮くことが前提の技や、   ステートを奪ってどうこうと言った投げ技などが効かない。  そうした行動を減らし、アーマーに有効な攻撃などを行うとか。なんとか。 ■■■AI用擬似コマンド操作の案  CommandによってVarを管理し、技の強弱などが変わる技の場合。   それぞれの条件式の最後に「 := 」でVarSetを行い、   技側はそれに順ずるよう変えるといいでしょう。 TriggerAll = ** Trigger1 = ** Trigger1 = ** Trigger1 = 1|| Var(*判定用Var*):= ; Trigger2 = ** Trigger2 = 1|| Var(*判定用Var*):= ;  ※ただし、-3ステートでの記述の場合は-2,-1ステートで、  ※ -2ステートの場合は-1ステートで「判定のリセット」を行う場合、  ※ 「判定がリセットされて」 処理が行われる為注意しましょう。 ( ChangeState はあくまで「ステート番号の変更」と「そのステートでの処理の中断」だけ。 ) ■■■AI用擬似レバー操作の案  Varの1つの桁を用いる。  テンキー並びで5を中心のニュートラル(何もしない)状態というような状態  789    8が上のみ  456 4が後のみ 6が前のみ  123    2が下のみ  という具合で、  (Var(**)=[7,9]);上要素  (Var(**)%3 = 1);後ろ要素  (Var(**)%3 = 0);前要素  (Var(**)=[1,3]);下要素  と言った参照方法もできる。  こうした「擬似レバー」を作り、ジャンプのステート記述へ、  「AIフラグ起動中擬似レバーに上要素が無い場合、立ち状態へ戻す」  というような記述をすることで、内部レバー操作の拒否を行う事もできなくはない。  ただし、制御を間違えると大変なことになる為注意すること。 ( あと、PrevStateNoが使いにくくなる。 )  AI専用ステートでの移動などの制御を行う場合、   基本動作を条件とした行動を行わせているキャラが反応しづらくなる為、   注意はしておくこと。 ■■■レバー動作封印  調査した結果、レバーによる動作は-3ステートよりも前に行われていると判明。  ただし、これを使うことによるバグを詳しくは調べていない。 ;AI用レバー封印 [State adi, Stop the Direction Move 1] Type = ChangeState Value = 0 ;強制立ち TriggerAll = Var(*AIフラグVar*) TriggerAll = PrevStateNo = 0;直前が立ちステート。 TriggerAll =(StateType = S || StateType = C) && Ctrl && !Time ;Time=0 Trigger1= StateNo = 20 ;左右(歩き) Trigger2= StateNo = 40 ;上(ジャンプ) Trigger3= StateNo = 10 ;下(屈み) Trigger4= StateNo = 120 ;ガード始動 Ctrl=1  ※立ちステートからのみ。  これをAI記述の最後に記述することで、   AI動作が無い+レバーによる動作で反応をし、   むりやり通常のステートへと戻してくれる。  ただし、キャラクターによっては思いも寄らぬ動きをしかねないため注意。  空中ジャンプの制限はこちら。 [State adi, Stop the Direction Move 2];※不具合あるかも Type = ChangeState Value = 50 ;強制空中動作 TriggerAll = Var(*AIフラグVar*) TriggerAll = StateType = A && Ctrl && !Time ;Time=0 Trigger1= PrevStateNo = 50 ;空中待機? Trigger1= StateNo = 45 ;空中ジャンプ Ctrl=1 ■■■没。 ;◇ 状況判定他 [State a] Type = Null TriggerAll = *リセット制限条件* TriggerAll = Var(**):=0;◇リセット TriggerAll = Alive && RoundState = 2 && Var(*AIフラグ*);◇AI最低限記述 Trigger1 = 0 && Var(**):=1;◇準備 Trigger2 = Var(**) = 1 && *条件* Trigger2 = 0 && Var(**):=x;◇特殊限定動作用 Trigger3 = Var(**) = 1 && *条件* Trigger3 = 0 && Var(**):=x;◇特殊限定動作用 Trigger4 = Var(**) = 1 Trigger4 = 0 && Var(**):=19;◇通常動作用引継ぎ ;◇0をリセット、1と19は引継ぎ、2から18は限定された動作の為の空き。 [State a] Type = Null TriggerAll = Var(**) = 19;◇引継ぎ分 ;◇距離 Trigger1 = P2BodyDist X=[-400,-10] ;◇対後ろ側 Trigger1 = 0 && Var(**):= 20 ;◇00 Trigger2 = P2BodyDist X = [-10,80] ;◇対近距離 ( 通常技の長さ程度に調整すること ) Trigger2 = 0 && Var(**):= 24 ;◇04 Trigger3 = P2BodyDist X = [80,150] ;◇対中距離 Trigger3 = 0 && Var(**):= 28 ;◇08 Trigger4 = P2BodyDist X =[150,400] ;◇対遠距離 Trigger4 = 0 && Var(**):= 32 ;◇12 ;◇空中・対空のプラス分 Trigger5 = P2Dist Y <-10 ;◇対空(正確には対上方) Trigger5 = 0 && Var(**):=Var(**)+1 ;◇+1 Trigger6 = StateType = A ;◇空中 Trigger6 = 0 && Var(**):=Var(**)+2 ;◇+2(対空なら+3) ;◇起き攻め用 Trigger7 = P2StateType = L;◇相手倒れ Trigger7 = 0 && Var(**):=36+(P2BodyDist X >= 80)+(P2BodyDist X >= 150) ;◇近16・中17・遠18 ;◇その他 Trigger8 = ;*その他*;◇空き Trigger8 = 0 && Var(**):= 39;◇空き ;◇・表・ Var(**)>19 && Var(**)%20 = xx ;◇xxの部分。 ;◇ 00 後ろ側 01対空・後ろ側 02空中・後ろ側 03対空空中後ろ側(対空+1 空中+2) ;◇ 04 近距離 05対空・近距離 06空中・近距離 07対空空中近距離(対空+空中= +3) ;◇ 08 中距離 09対空・中距離 10空中・中距離 11対空空中中距離 ;◇ 12 遠距離 13対空・遠距離 14空中・遠距離 15対空空中遠距離 ;◇ 16相手倒れ近17 同・中距離 18 同・遠距離 19空き [State a] Type = Null TriggerAll = Var(**) = [20,39];◇引継ぎ Trigger1 = *条件* ;◇特殊状態1 Trigger1 = 0 && Var(**):=Var(**)+20 ;◇40~ Trigger2 = *条件* ;◇特殊状態2 Trigger2 = 0 && Var(**):=Var(**)+20 ;◇60~ Trigger3 = *条件* ;◇3 Trigger3 = 0 && Var(**):=Var(**)+20 ;◇80~ ;◇複数モードや、特殊状態モードを必要とする場合に。 ;◇ Floor(Var(**)/10) = x ;か、 ;◇ ( Var(**) = [xx,xx] ) ;で、モード判定 ;Var(**)>19 && Var(**)%20=で、通常動作用の条件を参照