ググったけど無かったので(英語圏のサイト除く)公開してみる。
擬似乱数とは、予測可能な、パターンが決まった乱数のこと。パターンは与えるシード(種になる数)によって変えることができる。
なんで予測可能な乱数が必要かというと、シミュレーション上適当な数字が欲しいけど、結果が再現できないと困る場合に重宝するわけだ。これはゲームでも同じ。シミュレーションゲーム、RPG、シューティング等様々なゲームで揺らぎを表現するために乱数が使用されている。
極端な話、予測不能な乱数がゲームの展開を大きく支配している場合はプレイヤーはゲームを学習することができない(俺は学習できないゲームはキライだ)。まったく同じ操作をmsec単位で行うなら同じ結果が返ってきて欲しい。以上が俺が擬似乱数を使いたい理由。
ちなみにコンピューターは予測不能な乱数は生み出すことができないよ。一見デタラメに見えても、シードにUnixtimeを入れてたりする。
擬似乱数ではxor演算とシフトを使ったxorshiftってアルゴリズムが高速でゲーム向きと聞いたのだけど、ライセンスがGPLらしい。
他には十分に長い周期で優れたアルゴリズムといわれるSFMTがある。こちらは修正BSDライセンス。ってことでだれかActionScript版ライブラリ公開してるよねと思ってググったんだけど無いみたい?
上でアップしたAS版SFMTは簡易版で周期が短いらしいのだけれど、ゲームなどに使うのであれば十分かと。注意点としてはVector配列を使ってるのでFlashPlayer10以上じゃないと動きませぬ。まあ、短いソースなので、すぐ修正できるよ。
用途がゲームで処理速度で問題が出そうなら、割り切って、乱数を入れた配列を更新せずに加工するとか、決められたタイミングでシードを変え、一括で取得とかすればいいだろう。リプレイなど、再現が欲しいならリプレイデータにシードを保存すればいいし。ちなみに加工する場合はビット演算(>>とか)がActionScriptの場合でも速いらしいよ。
シードはどうやって決めるのか。色々あるけどそれは開発者が決めればいいのかもね。変な値にすれば変な特徴がでておもしろいかも。重要なのはシードが同じなら同じ周期を返し、偏りが無いことだ。
追記なんだけど、Math.randomとSFMTを比べてみた。
実験は0以上320未満の2つの乱数でベクトルとして、320ピクセル角内にピクセルを打つ。
重複した場合は該当ピクセルを明るくしていく。実行環境はFlashPlayer10.0 r12。
まずMathクラスのrandom()メソッド。0から1未満の擬似乱数を返す。
アルゴリズムは非公開。シードを与えられないので予測不能。

1千万回ほどのループ。以外に偏りが無くいいカンジ。
ピクセルや表示処理なども入ってるのであてにならないが、処理時間は65秒ほど。
各ピクセルの値はリアルタイムの処理で値の保存などしてないんだけど、なぜか500万を越えたあたりから急激なパフォーマンスの低下がある。プロセス自体かなり重くなりPCに影響あり。ランタイム内部で更新でもしてんだろーか?
続いてSFMTクラス。

同様に1千万回(少しrandom版を超えちゃったけど)ほど。妙に明るいところや暗いところもないので十分。しかも処理時間が20秒ほどと、なぜかビルトインのMath.random()よりも3倍高速な結果に。計算式がCPUにやさしいので占有率も低い。
もちろん、同じシードを与えれば同じ画像が得られるよ。
結果、ビルトインのMath.random()が存在を問われることに。
ActionScriptで研究なんてやらんだろーし、こんなに大量な乱数を必要とするアプリもないだろうけど、SFMTはActionScriptでも優れていることが証明されたかな。
こっからは独り言。
しかし、擬似乱数アルゴリズムで特許出願が多いのは辟易する...。特許庁はちゃんとオープンソースなアルゴリズムとかちゃんと見てるよねー?既にあるオープンソースなアルゴリズムが出願中(登録済)に無いことを祈る。
乱数発生アルゴリズムはその生まれた経歴から暗号化にも使われたりするけど、アルゴリズムを公開しなければならない特許登録とのジレンマを感じるよ。効率的で秘密な乱数発生なんて今後生まれたりするんだろーか...


