2007/10/2

and命令って何の役に立つの?  VRMスクリプト禅問答
【怎麼生】

and命令などの論理演算命令は、VRMには不必要のように思えます。何か使い道があるのでしょうか。

【説破】 4.0.7.2

馬鹿と鋏は使いよう、と申しますが、ないよりはあった方がいいでしょう。

・・・では答えにならないので、1つ、具体的な活用例を紹介します。なお、以下のお話は二進数の概念を理解していないと、おそらくワケがわかりませんので「え、二進数って何?」という方は、ここらへんでお勉強を済ませてから先へ進んでください。

*     *     *

二進数は、すべての桁が0または1で出来ている数です。これをON/OFF切替ができるスイッチが並んでいる、と考えるといろいろなことが出来ます(というか、それがコンピュータの本質ですが、ここでは捨て置きます)。

レイアウト上に8コの二叉ポイントがあるとします。それぞれのポイントについて、ある列車がどのように通過するかは、正位へ進むか反位へ進むか、の二通りしかありません。つまり、これはON/OFFのスイッチです。したがって、このレイアウト上の列車がどのポイントをどちらへ通るか、は、ポイントの数だけ、つまり、8つのON/OFFスイッチがあれば表現することが出来ます。たとえば・・・


クリックすると元のサイズで表示します

のような感じで。このルールで表現すると、このレイアウト上の経路は(上り下りを区別しなければ) 28 = 256 通りですから、十進数で0〜255の1つの数で表すことができることになります。

andやorといった論理演算命令は、このような二進数の世界で有用な命令です。以前にも少し触れましたが、and命令は二進数の任意の桁のみをフィルターして取り出すのに便利な命令です。話を単純化するために、レイアウト上のポイントを3つに減らして考えましょう。前述のルールでこのレイアウト上の経路を表現すると

クリックすると元のサイズで表示します

の8通りになります。レイアウト上の編成は、0〜7のいずれかの数字をプロパティ(グローバル変数)として持ってさえいれば、どのポイントをどちらへ向かうか表現出来ることになります。が、もちろん表現するだけでは意味がなくて、センサー+ポイントスクリプトを使って、この0〜7の数字に秘められた意味を取り出さなくてはなりません。
<編成スクリプト>

Var VarPointSwitch
set VarPointSwitch { 0 〜 7 の数字 }

<センサースクリプト>

Var EventID
Var VarPointNo
set VarPointNo { 1 / 2 / 4 のいずれか }
VarPoint ObjPoint
get ObjPoint {このセンサーが担当するポイント名}
SetEventSensor MtdSenseTrain EventID

BeginFunc MtdSenseTrain
  Var Tmp
  VarTrain ObjTrain
  GetSenseTrain ObjTrain
  mov Tmp ObjTrain.VarPointSwitch // プロパティの取り出し
  and Tmp VarPointNo // 二進数のフィルター処理
  ifzero Tmp
    call ObjPoint MtdStraight
  else
    call ObjPoint MtdTurnout
  endif
EndFunc

<ポイントスクリプト>

BeginFunc MtdStraight
  SetPointBranch 0
EndFunc

BeginFunc MtdTurnout
  SetPointBranch 1
EndFunc
ミニマムには上掲サンプルスクリプトのように書くことが出来ます。大雑把に言えば、これはセンサーが編成を検知すると、その編成のプロパティVarPointSwitchを調べて、ポイントを正/反位へ切り替えるスクリプトです。味噌は、センサースクリプトのand命令です。

仮に変数VarPointNoに2がsetされているとしましょう。つまり、これはこのセンサーが2番目のポイントを担当していることを意味します。and命令は、常に and Tmp 2 として実行されます。この命令によってローカル変数Tmpに得られる値は0か2のどちらかです。Tmpの元の値(=編成から取って来たVarPointSwitch)を二進数で表現したときに、右から二番目の桁が0であれば、and命令の結果は0に、1であれば2になります。表にしてみましょう。

クリックすると元のサイズで表示します

となります。and命令に続くif命令で“Tmpが0ならばMtdStraightをcall(正位切替)し、そうでなければMtdTurnoutをcall(反位切替)”していますから、編成スクリプトのVarPointSwitchの値の二進数の二桁目が、ポイントの正/反位と一対一対応していることになります。

ここまでで、既にVRM3のポイント自動制御機能+αを実現出来ています。さらに、ビュワー起動後に編成のVarPointSwitchの値を書き換えれば、レイアウト上の経路を動的に変更することも可能です。これはVRM3では不可能だったことです。たとえば、エンドレスループを一周する毎にVarPointSwitchにirnd命令で乱数を代入し、周回毎に経路が変化する(しかも、どこを通るか予め知ることが出来る)レイアウトを作ることが出来ます。

*     *     *

こんなややこしいことをして何の意味があるのだ!?と憤る方もおいででしょう。無理もありません。二進数に馴れない方にとっては、この仕組みはあまりに非直感的で扱い辛く感じることでしょう。

一方で、この方法ならではの利点もあって、レイアウト上のポイントの数がいくら増えても(厳密にはVRM4が扱える二進数の桁の数に制約を受けますが、実害はないでしょう)スクリプトのロジックには一切手を加える必要がありません。VarPointSwitch、VaPointNo、そしてObjPointの3つの変数に適切な値を与えれば、すべての編成がどのポイントをどちらへ通るか、完全に制御することが出来ます。これは、特にこの仕組みをスクロール化する際に利点となります。

他にも、二進数の桁を各種の車両ギミックに対応させる等、いろいろな応用があり得ます。面白いアイデアが浮かんだら教えてください、スクロール化してみますので。まぁ、実用に供するにはスクリプトウィザードに桁数指定でビット入力できるようなI/F拡張が欲しいところですけども。
0

コメントを書く

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




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