keimei main -> キハポスト@VRM -> VRM4スクリプト -> ランダム編

VRM4スクリプト(13)〜ランダム編

この文章を書いた時点でのVRM4のバージョンは「4.0.1.1」です。これ以前のバージョンでは間違いなく動作しません。また、今後のバージョンアップによって仕様が変更される可能性もあります。

● 遊び方 ●

まずは、レイアウトで遊んでみてください。[s]キーを押すと3本の列車が走り出します。カメラの切り替えは自由ですが、運転台カメラでは面白くないので上空カメラ辺りがいいでしょう(デフォでそうなっています)。また、[1]-[3]キーで視点となる列車の切り替えができます。

注:列車の走行中に「SetActiveTrain」命令を用いると、その列車がストップしてしまう、という現象がうちでは発生しました。止まらない場合もあり、原因が不明です。もし、[1]-[3]キーを用いた時、列車が止まるようなことがあれば、[s]キーで運転開始する前か、駅で停車中に切り替えてください。

注:車輌が201系なのは趣味です。お持ちでない場合は、他のものにすげ替えてください。その場合、車輌配置はそのままで、編成エディタで車輌単位で入換てください。編成エディタのスクリプトを消してしまわないようにご注意ください。

さて、遊んでいて何か気付きましたか?3本の列車が抜きつ抜かれつしますが、その抜きつ抜かれつの部分がループを周回する度に違っているでしょう。また、ある時は別のルートを走る時もあります。さらに、ビューアーを起動し直す度に違った運転パターンになると思います。そう、これは作者もどうなるか分からない、ランダムな走行を行うレイアウトなのです。

● はじめに ●

Tatsuoさんがお作りになった数々の作品には私も影響を受け、いつも参考にさせて頂いているのですが、その画期的なアイデアと計算しつくされた動作には定評があります。自動で列車が運転され、それを眺めるという作品が多いのですが、例えば、駅や踏切で必ず列車同士がすれ違うなどのツボをついた演出には脱帽ものです。そして、VRM4ではスクリプトを用いたさらに驚異的な作品もお目に掛かれるようになりました。

だがしかし、ここで敢えて冷静な目で見てみましょう。コンピュータが一番得意とする物は何でしょう? それは、正確に同じことを繰り返し実行することにあります。つまり、「1+1」はいつどのパソコンで計算しても、答えは「2」になります。時速60kmで走る列車を 1km後方から時速120kmの列車で追い掛けると必ず1分後に追いつき、それが1分1秒になったり59秒になったりすることはありません。Tatsuoさんがどういった方法で自動運転レイアウトを設計されているか分かりませんが、試行錯誤を繰り返しているとしても、ある程度計算はでき、すれ違いシーンなど、一度タイミングが見つかってしまえば、二度目からはそれを全く正確に再現できるということです。

さて、ここで逆転の発想です。すれ違いシーンなどいつも決まったパターンで自動運転するのではなく、実行する度にランダムで状況が変化するようなレイアウトは作れないのか? というのが、今回のテーマです。

● 乱数を発生させるには? ●

話を簡単にするために上図のようなポイントを考えます。右からやってきた列車をセンサによって目的の方向:AかBへ分岐させることが出来ますね。これをランダムに分岐させる、Aへ行くのかBへ行くのか列車を走らせてみないと分からない、というようなことが可能なのでしょうか?

BASICやC言語など最近の言語には、乱数を発生させる関数や命令があります。MS ExcelにもRND関数があったりします。一般的にランダムな状況を作りたい場合、これを利用します。例えば、0から1までの乱数を発生させ、0.5未満なら A方向、0.5以上なら B方向に分岐させる、といったプログラムを組めばランダムな状況が作り出せます。7:3で A方向に分岐する確率が高い、というのであれば、0.7未満なら A方向、0.7以上なら B方向とすればよろしい。

だがしかし、VRM4スクリプトにはランダム関数なんてものは存在しません。昔、マイコン時代のBASIC言語もやはりランダム関数を持たないものがほとんどでした。その場合、どうしたかというと……時計を利用します。パソコンは内部に時計を持っていますから、その時刻を呼び出して制御を行います。例えば、センサを通過した時刻が、3時12分54秒なら A方向へ、 6時43分25秒なら B方向に分岐させます……わかりますか? つまり、秒の単位が奇数か偶数かで振り分けを行うわけです。センサを通過する時刻は列車を運転する度に違ってくる筈ですから、これで疑似的にランダムな状況が作り出せます。

だがしかし、VRMには現在時刻を読み出す命令すらありません。しかし、諦めるのはまだ早いです。我々の手には、「SetEventTimer」命令があります。フィードバック制御のところで述べた通り、これでビューアーが起動されてからの時間を計ることが出来ます。しかし、それだけでは、ランダムになりません。ビューアーが起動されてからの相対的な時間では毎回同じ結果になってしまうからです。となると、最後の手段として……人の手を介入させる方法を用いるしかありません。人間ほどランダムな物はありませんしね。

● ランダムの秘密 ●

秘密は「s」キーで運転を開始するという点にあります。つまり、ビューアーが起動してから、「s」キーが押されるまでの時間は人によって、また、実行する度に違ってくる筈です。これでなんとかランダムな状況は作り出せます。もっとも、ストップウォッチと驚異的に反応する指先によって毎回同じタイミングで[s]キーを押せば、同じパターンで運転することが出来るということなんですが。ちなみに、「SetEventTimer」で計っているのは0.3秒単位です。あとは、ポイントや速度制御を行うのに、センサを通過した時間を用いればよろしい。具体的には経過時間(clock)を適当な数で割って、その余り(mod)で制御を行っています( 3で割り切れたらAへ、そうでなければBへって具合)。

だがしかし、これはあくまで擬似的な乱数です。なぜならば、「s」キーを押した時点で世界の運命が決まってしまう:その後は人間には予測は付かないがコンピュータとしては決まったパターンで運転を行うだけですから。つまり、何十か何百かあるパターンの1つを選んでそれを実行するだけなのです。VRMでランダムな状況を作り出すとしたら、まあ、この辺が限界でしょう。