MUGENのこととかいろいろ
未分類 | AI関連 | パレット | ポトレ | キャラ紹介 | MUGEN以外 | AI講座的なもの | その他 | キャラ | 
名の無限
≪2017.08  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30  2017.10≫
プロフィール

名無し/Nanashi

Author:名無し/Nanashi
MUGENのAIをつくったり

あと自分が他所で名前出すときはこの呼び名に統一します。
他の方が呼ぶ分には名無しで構いません。

公開中のブツのリストなど

AI講座一覧

このブログはリンクフリーです。お気軽にどうぞ。

↓バナー


最新記事
Twitter
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
FC2カウンター
FC2カウンター
現在の閲覧者数:
検索フォーム
リンク
ブロとも申請フォーム
QRコード
QRコード
--.--.-- --
スポンサーサイト
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

スポンサー広告    Top↑

2010.03.20 Sat
シンプルなヘルパーリダイレクト
ChangeStateループを使ったヘルパーリダイレクトについて記事にしてみようと思ってましたが、

書いてるうちにループを使わないでヘルパーリダイレクトする方法がティンときたのでコッチを記事にしてみました




ヘルパーリダイレクトとはそのまま「相手のヘルパーをリダイレクト(参照)」することです。

既存のリダイレクトキーで可能かのように思えますが、
"Enemy,(helper,hitdefattr,SCA) = "のような「リダイレクトキーワードを組み合わせた記述ができない」ことから
普通のリダイレクトキーのみでは不可能になっています。


ではどうするかと言うと、PlayerIDを利用します

PlayerIDとは場に出現したキャラ・ヘルパーに自動で振り分けられているIDを参照するリダイレクトキーで、

「PlayerID(〇〇),」のように〇〇にIDの数値を指定すれば、敵味方関係なくそのIDの持ち主を参照することができます。


つまり!
相手のヘルパーのIDをなんとか知ることが出来たなら、
「PlayerID(相手ヘルパーのID),」を使うことでヘルパーリダイレクトが実現するってことです




すると問題なのはどうやってあいてのヘルパーのIDを知るか?ですが、

PlayerIDは「場に出現した順番どおりの数値で与えられる」という特性があります

この特性から考えると、
相手がヘルパーAを1回出して、その後他に誰もヘルパーを出さずにまた相手がヘルパーBを出したとして、
ヘルパーAの次に場に出現したヘルパーBのIDは、ヘルパーAのIDに1足したものになっているはずです。


このように、特性からなんとか相手のヘルパーのIDを予測して、それが正しいか確かめていくのがヘルパーリダイレクトの基本?のようですw




IDをいくつも調べる必要があるし、ヘルパーは1フレ中に複数出現することもあるので
よく見るヘルパーリダイレクトはChangeStateのループを利用していることが多いですが、

「ヘルパーが出た順にIDが振り分けられるのなら、相手のヘルパーが出た瞬間のフレームを感知すれば
 直後に自分でヘルパーを出して、そのIDから1引いた数が相手ヘルパーのIDじゃね?」


と思いついたので、(たぶん)よりシンプルなこっちを採用しました
色々試して、ちゃんとリダイレクトできてるので間違ってはないと思う…

ちなみに相手が1フレで複数ヘルパーを出した場合を考えて、ID-20まで調べるようにしています
1フレ中に20もヘルパー出すなんてなかなかないと思うけどw

というわけで以下、実際にヘルパーリダイレクトを使った飛び道具検出の記述です。projも検出してますが





;-1ステートに================================================

[State -1, ];相手のprojもしくはhelperが増えた瞬間ヘルパー呼び出し
type=helper
triggerall = !ishelper
triggerall = !NumHelper(40005)
triggerall = NumEnemy
trigger1 = var(33) <= 0 ; 以下,監視で代入しといた値より相手のprojやhelperが大きい時
trigger1 = Enemy(0),numproj > 0 ;
trigger2 = var(34)< Enemy(0),numhelper ;
trigger3 = var(35) <= 0 ;
trigger3 = Enemy(numenemy=2),numproj > 0 ;
trigger4 = var(36) < Enemy(numenemy=2),numhelper ;
helpertype=normal
name = "P-H"
stateno = 40005
ID = 40005
pos = 0,9999
keyctrl = 1
pausemovetime = 2147483647
supermovetime = 2147483647
persistent = 0

[State 30006, 飛び道具監視];上の処理の後に相手のprojとhelperの最新の数を代入する
type = null
triggerall = !ishelper
triggerall = NumEnemy
trigger1 = var(33) := Enemy(0),numproj
trigger2 = var(34) := Enemy(0),numhelper

[State 30006, 飛び道具監視タッグ二人目用]
type = null
triggerall = !ishelper
triggerall = NumEnemy
trigger1 = var(35) := Enemy(numenemy=2),numproj
trigger2 = var(36) := Enemy(numenemy=2),numhelper


;============================================


;ヘルパーのステート====================================

[Statedef 40005];飛び道具検出用
type = A
ctrl = 0
anim = 0
movetype = I
physics = N
sprpriority = 1

;保険等---------------------
[State 40005]
type = SelfState
trigger1 = !IsHelper
Value = 0
[State 40005]
type = assertspecial
trigger1 = 1
flag = invisible
[State 40005]
type = NotHitBy
value = SCA
trigger1 = 1
;----------------------------

[State 40005];スイッチリセット
type = parentvarset
trigger1 = 1
var(47)=0

[State 40005, 検出P];相手projが存在するときスイッチON
type = parentvarset
triggerall = NumEnemy
trigger1 = Enemy(0),numproj > 0
trigger2 = Enemy(numenemy=2),numproj > 0
var(47)=1

[State 40005, 検出H];相手ヘルパーが攻撃判定を持つときスイッチON
type = parentvarset
triggerall = NumEnemy
trigger1 = playerIDexist(ID-1)=1 ;このヘルパーの1つ前のプレイヤーIDが存在するとき。
trigger1 = (playerID(ID-1),hitdefattr = SCA,AA,AT,AP || playerID(ID-1),movetype = A) && playerID(ID-1),teamside != root,teamside && playerID(ID-1),ishelper
trigger2 = playerIDexist(ID-2)=1 ;このヘルパーの2つ前のプレイヤーIDが存在するとき。以下同様
trigger2 = (playerID(ID-2),hitdefattr = SCA,AA,AT,AP || playerID(ID-2),movetype = A) && playerID(ID-2),teamside != root,teamside && playerID(ID-2),ishelper
trigger3 = playerIDexist(ID-3)=1
trigger3 = (playerID(ID-3),hitdefattr = SCA,AA,AT,AP || playerID(ID-3),movetype = A) && playerID(ID-3),teamside != root,teamside && playerID(ID-3),ishelper
trigger4 = playerIDexist(ID-4)=1
trigger4 = (playerID(ID-4),hitdefattr = SCA,AA,AT,AP || playerID(ID-4),movetype = A) && playerID(ID-4),teamside != root,teamside && playerID(ID-4),ishelper
trigger5 = playerIDexist(ID-5)=1
trigger5 = (playerID(ID-5),hitdefattr = SCA,AA,AT,AP || playerID(ID-5),movetype = A) && playerID(ID-5),teamside != root,teamside && playerID(ID-5),ishelper
trigger6 = playerIDexist(ID-6)=1
trigger6 = (playerID(ID-6),hitdefattr = SCA,AA,AT,AP || playerID(ID-6),movetype = A) && playerID(ID-6),teamside != root,teamside && playerID(ID-6),ishelper
trigger7 = playerIDexist(ID-7)=1
trigger7 = (playerID(ID-7),hitdefattr = SCA,AA,AT,AP || playerID(ID-7),movetype = A) && playerID(ID-7),teamside != root,teamside && playerID(ID-7),ishelper
trigger8 = playerIDexist(ID-8)=1
trigger8 = (playerID(ID-8),hitdefattr = SCA,AA,AT,AP || playerID(ID-8),movetype = A) && playerID(ID-8),teamside != root,teamside && playerID(ID-8),ishelper
trigger9 = playerIDexist(ID-9)=1
trigger9 = (playerID(ID-9),hitdefattr = SCA,AA,AT,AP || playerID(ID-9),movetype = A) && playerID(ID-9),teamside != root,teamside && playerID(ID-9),ishelper
trigger10= playerIDexist(ID-10)=1
trigger10= (playerID(ID-10),hitdefattr = SCA,AA,AT,AP || playerID(ID-10),movetype = A) && playerID(ID-10),teamside != root,teamside && playerID(ID-10),ishelper
trigger11= playerIDexist(ID-11)=1
trigger11= (playerID(ID-11),hitdefattr = SCA,AA,AT,AP || playerID(ID-11),movetype = A) && playerID(ID-11),teamside != root,teamside && playerID(ID-11),ishelper
trigger12= playerIDexist(ID-12)=1
trigger12= (playerID(ID-12),hitdefattr = SCA,AA,AT,AP || playerID(ID-12),movetype = A) && playerID(ID-12),teamside != root,teamside && playerID(ID-12),ishelper
trigger13= playerIDexist(ID-13)=1
trigger13= (playerID(ID-13),hitdefattr = SCA,AA,AT,AP || playerID(ID-13),movetype = A) && playerID(ID-13),teamside != root,teamside && playerID(ID-13),ishelper
trigger14= playerIDexist(ID-14)=1
trigger14= (playerID(ID-14),hitdefattr = SCA,AA,AT,AP || playerID(ID-14),movetype = A) && playerID(ID-14),teamside != root,teamside && playerID(ID-14),ishelper
trigger15= playerIDexist(ID-15)=1
trigger15= (playerID(ID-15),hitdefattr = SCA,AA,AT,AP || playerID(ID-15),movetype = A) && playerID(ID-15),teamside != root,teamside && playerID(ID-15),ishelper
trigger16= playerIDexist(ID-16)=1
trigger16= (playerID(ID-16),hitdefattr = SCA,AA,AT,AP || playerID(ID-16),movetype = A) && playerID(ID-16),teamside != root,teamside && playerID(ID-16),ishelper
trigger17= playerIDexist(ID-17)=1
trigger17= (playerID(ID-17),hitdefattr = SCA,AA,AT,AP || playerID(ID-17),movetype = A) && playerID(ID-17),teamside != root,teamside && playerID(ID-17),ishelper
trigger18= playerIDexist(ID-18)=1
trigger18= (playerID(ID-18),hitdefattr = SCA,AA,AT,AP || playerID(ID-18),movetype = A) && playerID(ID-18),teamside != root,teamside && playerID(ID-18),ishelper
trigger19= playerIDexist(ID-19)=1
trigger19= (playerID(ID-19),hitdefattr = SCA,AA,AT,AP || playerID(ID-19),movetype = A) && playerID(ID-19),teamside != root,teamside && playerID(ID-19),ishelper
trigger20= playerIDexist(ID-20)=1
trigger20= (playerID(ID-20),hitdefattr = SCA,AA,AT,AP || playerID(ID-20),movetype = A) && playerID(ID-20),teamside != root,teamside && playerID(ID-20),ishelper
var(47)=1

[State 40005];検出にかからなかったら消滅
type = destroyself
trigger1 = root,var(47)=0

;=============================================================



単に飛び道具を検出するだけの記述なので、
相手のヘルパーに攻撃判定があるかどうかぐらいしか参照してませんが、ちゃんとリダイレクト自体は出来ています。

[State 40005, 検出H]の最後のvar(47)=1 を
var(47)=ceil(playerID(ID-1),p2bodydist x)

あたりにすれば、相手のヘルパー式飛び道具と自分との距離が分かるので、
ちゃんとリダイレクトされてるっ!って感じると思いますw


ちなみにこの検出ヘルパーは相手の飛び道具がなくなったら一旦消えるので、
学習などは他のヘルパーにやらせないとvarを参照できないので注意。


と、ここまで書きましたが、
あまり練ってないので、「helper(40005)が出てる時に出たヘルパーは無視してしまう」というだいぶ大きな欠点が残ったままですw

まぁそこら辺も含め、この記述を使うときはそちらのほうで発展させていって頂くと言うことで
記事用にちょっと記述変えたからもしかしたらおかしいかも…

スポンサーサイト

AI講座的なもの    Comment(2)   TrackBack(0)   Top↑

Comment
Posted by 流れ者
えっ ループ式ヘルパーリダイレクトってよく見かけるの?
俺は一年ほど前にアリス用に開発したんだが、それより前からあったのかな
ヘルパーのリダイレクト技術ググってもベタにIDナンバー繰上げ検索してる記事しかなかったから必死に考えたんだけど
まさか俺の記事をそんなたくさんの人が読んでいるはずがない!まして使ってるなんて
・・・ええ、自意識過剰なのはわかってます

それはさておき、新規にヘルパー出してそのIDまでを検索する、というのは某氏のアイデアのみの記事がありましたな
ただ、1F以上前のヘルパーしか検索できないこと、コンパネ差が出るため若干情報鮮度が安定しないのが弱点ですかね?
マネージャヘルパーを常駐させてそいつが出せば、本体が出現させる分の探知については鮮度が保たれますが
もしくはプラス方向も検索するようにするか

個人的には非ループ式は追う数を増やす(=探知能力を向上させる)ほど行数が増える、というのが嫌なので、それでループ式を開発したんですが
行が多いと機能拡張するのも面倒になるので(検索数だけ拡張記述も増やすので能力が高いほど爆発的に記述が増える)
実際、アリスは結構面倒で長い記述を各検出済みヘルパーに対して処理してるのでベタ検索型だとやってられん
数字を間違えたりしたとき、ミスに気づきにくい、というのもそういった「長い」記述の一般的な弱点です
2010.03.20 Sat 23:43 URL [ Edit ]
Posted by 名無し/Nanashi
>>ループ式
当時あなたのの講座見たときは「よくわからないけどスゴそうだ!」って思ってましたよw
よく見るって書いたのは…自分が見たことあるヘルパーリダイレクトがループ式だけだったので。

厨忍氏が講座でやってるのがループ式ってのが大きいですかね


>>弱点
あそっか、プラス方向にも検索すれば後に出てきた奴もイケルのかw
情報鮮度は…どうだろう。相手がヘルパーを出す度に新しく射出し直してるから大丈夫…じゃないのかな(上の通りの欠点があるけど)

この記述を発展させる構想としては、
感知して出現させるヘルパーは、常駐ヘルパーにでも情報を送った後すぐ消えてしまえば、次のフレームでまた相手がヘルパーを出してきてもまた新しく射出されて、結果的に相手が毎フレ20ヘルパー出しても大丈夫!だと思うがどうなんだろう


>>非ループ式は行数が増えるし記述追加が面倒
ですよねーw
ミスに気づきにくってのもホントに…今まで使ってた記述のミスの数ひどかったですw

ループ使えばこういう長いのも短縮されて、弄りやすくなりますね。
実際今回「varaddを毎フレ2500回試行する記述でも意外と重くならんなーw」とか実験もして、ループ使ったヘルパーリダイレクトを講座内容に入れるつもりだったんですが、

技術が2つ絡むとわかりにくくなるかなーってんで非ループ式にしましたw
やっぱりできるだけシンプルな記述じゃないと仕組みがわかりづらいもんで

そのうちこの記事の発展版として上に書いた構想を含んだものと、ループを搭載したものを書きたいなと思ってたり

2010.03.21 Sun 00:52 URL [ Edit ]

管理者にだけ表示を許可する

Top↑

TrackBack
TrackBackURL
http://nanomugen644.blog54.fc2.com/tb.php/155-f177887c

Top↑

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。