//****************************************************************************** // ActionScript2.0 Game Framework // Copyright(C) 2005 BeInteractive!, all rights reserved. // // $Id: Rand.as 6 2007-03-26 03:54:35Z yossy $ //****************************************************************************** /** Math.Rand Mersenne Twister法による乱数発生ルーチンです。 Original code by yaneurao (from yaneSDK4D) */ class ASGF.Math.Rand { private var Mt:Array; private var Mti:Number; /** 生成時にseedを設定すると、それを乱数の種として使用し、 それに基づいた乱数を生成します。 (内部的にsetSeedを呼び出します) 前回と同じ乱数系列を再現したい場合などにコレを使います。 @param seed Number 乱数の種 */ public function Rand (seed:Number) { if(seed != undefined) { setSeed(seed); } else { Mti = 624 + 1; // means Mt is not initialized. } } /** 乱数の種を設定します。 設定された種に基づいて乱数は生成されていきます。 必ず1度は呼び出す必要があります。 もし呼び出さないときは4352が種として与えられます。 @param seed Number 乱数の種 @return void */ public function setSeed (seed:Number) : Void { var Mt_:Array = Mt = new Array(624); for(var i:Number=0; i<624; ++i) { Mt_[i] = seed & 0xffff0000; seed = (69069 * seed + 1) & 0xffffffff; Mt_[i] |= (seed & 0xffff0000) >>> 16; seed = (69069 * seed + 1) & 0xffffffff; } Mti = 624; } /** 乱数の種として現在時刻を与えます。 @param void @return void */ public function randomize () : Void { setSeed((new Date).getTime()); } /** 0〜n-1までの乱数を取得します。但し、n>0。 @param n Number 取得する乱数の範囲 @return Number 0〜n-1までの乱数 */ public function getTo (n:Number) : Number { if(n==0) throw new Error(); return get32() % n; } /** 32bit精度の乱数を取得します。 @param void @return Number 32bit精度の乱数 */ public function get32 () : Number { var r:Number; if(Mti >= 624) { var mag01:Array = [0x0, 0x9908b0df]; var kk:Number; if(Mti == (624+1)) { setSeed(4357); } var m_:Array = Mt; for(kk=0; kk<(624-397); ++kk) { r = (m_[kk]&0x80000000)|(m_[kk+1]&0x7fffffff); m_[kk] = m_[kk+397] ^ (r >>> 1) ^ mag01[r & 0x1]; } for(; kk<(624-1); ++kk) { r = (m_[kk]&0x80000000)|(m_[kk+1]&0x7fffffff); m_[kk] = m_[kk+(397-624)] ^ (r >>> 1) ^ mag01[r & 0x1]; } r = (m_[624-1]&0x80000000)|(m_[0]&0x7fffffff); m_[624-1] = m_[397-1] ^ (r >>> 1) ^ mag01[r & 0x1]; Mti = 0; } r = Mt[Mti++]; r ^= (r >>> 11); r ^= (r << 7) & 0x9d2c5680; r ^= (r << 15) & 0xefc60000; r ^= (r >>> 18); // 苦し紛れ・・・ // (こうしないと最上位ビットが1の場合マイナス値になってしまう) var res:Number = 0; for(var i:Number=0; i<32; ++i) { if((r>>>i)&1) res += Math.pow(2, i); } return res; } /** [0, 1]範囲の乱数を取得(0, 1を含む) @param void @return Number [0, 1]範囲の乱数 */ public function get1 () : Number { return get32() * (1.0/4294967295.0); /* divided by 2^32-1 */ } /** [0, 1)範囲の乱数を取得(0は含む、1は含まない) @param void @return Number [0, 1)範囲の乱数 */ public function get2 () : Number { return get32() * (1.0/4294967296.0) /* divided by 2^32 */ } /** (0, 1]範囲の乱数を取得(1は含む、0は含まない) @param void @return Number (0, 1]範囲の乱数 */ public function get3 () : Number { return (get32()+1) * (1.0/4294967296.0); /* divided by 2^32 */ } /** (0, 1)範囲の乱数を取得(0, 1を含まない) @param void @return Number (0, 1)範囲の乱数 */ public function get4 () : Number { return (get32()+0.5) * (1.0/4294967296.0); /* divided by 2^32 */ } }