2007/10/8

SearchPoint命令の話  VRMスクリプト禅問答
オフィシャルもスーパーバイザーも回答するつもりがないようなので。
NULL文字がありませんが
 書込:tetta さん DATE:2007/10/04(Thu) 05:35 メッセージNo.584

スクリプトマニュアルの SearchPoint で
>探索を開始する前にpointobj変数は、NULLで初期化してください。
とありますが、NULL文字が見当たりません。
Set pointobj変数, ""
でいいのでしょうかね???

スクリプト会議室 メッセージNo.584 より
まず結論から。

ローカル変数=SearchPoint命令が実行されるのと同じメソッド内でVarPoint命令を使って宣言した変数、を使う限りにおいて、製品付属マニュアルの「事前にNULLで初期化しておきます」の記述は無視していいです。なぜなら、宣言直後のオブジェクト変数はNULLだから。

<NULLとは?>

VRMスクリプトにおける“NULL”は、どこにも定義が書かれていないため観測される動作から類推するしかありませんが、ボクが見るところ、(1)宣言済みのオブジェクト変数に、(2)何も代入されていない状態、と考えて差し支えないようです。ちなみに、一般変数は未代入時は“0”扱いとなり、NULL状態は存在しないようです。

で、このNULL状態のオブジェクト変数には“オブジェクト参照で使用した場合、その命令が(結果的に)無効化される”という特権的な位置づけがあるようです。つまり、ユーザーはcall命令等でメソッド実行先を指定するオブジェクト変数に、具体的な中身が指定されているかを検証することなく、call命令を実行しても問題ない・・・と言うか、オブジェクト変数が値取得済であるかを直接判定する命令がないので、そもそも検証ができない(間接的になら可能)という話です。

なお、tetta氏の直接の質問内容である“任意の宣言・代入済みオブジェクト変数をNULLにする方法は?”の答えは、ボクの知る限りは存在しません。



*     *     *

以下、製品付属マニュアルの「事前にNULLで初期化しておきます」の記述が、何を意図して書かれたのか、推理していきます。結論から言うと、どうやら、開発者はSearchPoint命令の信用性に自信がないようです。

僕がVRM4.0.7.2で簡単な検証をおこなった結果によると、SearchPoint命令のポイント取得用オブジェクト変数がローカル変数であろうとグローバル変数(メソッドの外で宣言された変数)であろうと、SearchPoint命令が実行された時点で指定距離内にポイントがないと、ポイント取得変数にはNULLが返ってきているように見えました。

なぜそう言えるのか、というと、
<編成スクリプト>
Var EventTimer
SetEventTimer this MtdTest EventTimer 1000
// VarPoint ObjPoint

BeginFunc MtdTest
  VarPoint ObjPoint
  DrawMessage "SearchPointを実行"
  SearchPoint 30 ObjPoint
  call ObjPoint MtdWhoAmI
EndFunc

<ポイントスクリプト>
VarPoint Me
get Me this

BeginFunc MtdWhoAmI
  DrawVar Me
EndFunc
経路上に2つ以上のポイントを設け、編成を1つ配置して上掲スクリプトを組み込んだレイアウトで実験をしたからです。

ボクが最初に疑ったのは“探索範囲内にポイントがない場合、ポイント取得変数の値が変化しないのではないか?”ということでした。上掲スクリプトのように、VarPoint命令がメソッド内にある(=ローカル変数である)場合、SearchPoint命令が実行される時点で、変数の値は常にNULLです。なので、SearchPoint命令が変数の値を書き換えなかった場合、続くcall命令は空振りします。

が、もし、上掲スクリプトの太字部分のコメント位置を入れ替えて、これをグローバル変数にした場合、ボクの疑いが正しければ結果が変わるはずです。つまり、SearchPoint命令が実行される時点で、変数の値は前回SearchPoint命令が実行されたときの結果になっているはずです。もし、ポイントが見つからない場合に変数の内容がNULLに上書きされないとすれば、前回の探査でポイントが存在し、今回の探査では(編成の位置が変わって)ポイントが存在しない場合、既に後方に通り過ぎているポイント名が変数に残ってしまうことになります。これを回避するには、マニュアルにあるように「事前にNULLで初期化しておきます」が必要になります。

ところが、実際にテストしてみると、上掲スクリプトのVarPoint命令をどちらで有効化しても結果は変わりませんでした。これが意味するのは、SearchPoint命令は実行時点で探査範囲内にポイントがみつからない場合、ポイント取得変数の値をNULLで上書きする、ということです。

あれ・・・じゃぁ「事前にNULLで初期化しておきます」なんて必要ないじゃん、と。いや、もう1つ、この記述を書かざるを得ないケースがあります。それは、この文言を書いた書き手が、SearchPoint命令の動作結果に自信を持っていない場合です。

単純に考えれば、編成の進路上の直近ポイントは、いかなる場合も1つであるはずです。が、その経路はユーザーが好き勝手にレールを敷いて作るワケですから、ひょっとすると、何かうまくいかないケースがあるかも知れません。何せ組み合わせは事実上無限にありますし、そのすべてを事前にテストすることなんて出来ませんから。

SearchPoint命令が正しくポイント取得変数を上書しないケースがあり得ることが、そのロジック上(たとえば、探索が無限ループしないように一定時間経過して答えが見つからない場合は強制的に処理を終了して次下の命令へ進む=いわゆるタイムアウト)わかっているとしましょう。そうだとすれば、この副作用で意図せぬ“直前の探索でグローバル変数に収められたポイントに対するcall”を回避するために「事前にNULLで初期化しておきます」と書きたくなるだろう、と。非常にレアなケースだとは思いますけど、そういうの。

*     *     *

まぁ、以上はあくまでもボクの推理でしかありませんが、これが的を射ているにせよいないにせよ、

未定義語使って対告衆・意図共に不明な言い訳をして、いったい誰のために何がしたいの?

な気分ではあります。スクリプトに限っても、ちゃんと説明せにゃならん極々基本的なことが他に山ほどあるだろう、と。

まぁ、それを言い出したら、I.MAGiCの言動の大半は常に意図不明ですが。わからないこっちがバカなのか、それとも向こうがバカなのか、判断は賢明な読者諸兄銘々に委ねましょう。まぁ、それ以前に、本稿の意味意図がわからない読者が多いような気もしますけど。それは間違いなくボクがバカなんでしょう。
0

2007/10/8  3:33

投稿者:tetta
こんばんは。今のバタバタが終結したら実験してみようと思っていた矢先に、この技術検証レポート。
最近はビジネスレベルでも、ここまで書いてくれる方は少ないような気がします。感謝です。

>スクリプトに限っても、ちゃんと説明せにゃならん極々基本的なこと
同感です。会議室への書き込みもNULLに関して多くの方に周知されればと。

結果は予想に反して?検索できない時はクリアすることが意識されていたようですね。
PC能力が低い場合、まさか内部でSet命令落ち(Nullクリアが保障されない)・・・。いやそれはあり得ないかな(笑)。
個人的にはSearch系の命令が増えると幅が広がりそうな気がしているのですが。

コメントを書く

この記事にはコメントを投稿できません




teacup.ブログ “AutoPage”
AutoPage最新お知らせ