地図法1.5のスプレッドシートではAT値を計算する処理を工夫しましたので、その解説をします。
数学が嫌いな方には、ちょっときついかもしれませんが・・・。
まず、p1=1103515245, p2=12345 とすると seed=seed*p1+p2 がATで使われるSEED値更新の計算式です。
関数 seed(<地図SEED値>,<回数>) は<地図SEED値>を初期値とし、<回数>だけ更新した時のSEED値と定義します。
seed(n,m+1)=seed(n,m)*p1+p2 となり seed(n,0)=n です。(更新なしなので地図SEED値そのまま)
ここで、seed(n,1)〜seed(n,3) を展開してみます。
seed(n,1)=seed(n,0)*p1+p2=n*p1+p2
seed(n,2)=seed(n,1)*p1+p2=(n*p1+p2)*p1+p2=n*p1^2+p1*p2+p2
seed(n,3)=seed(n,2)*p1+p2=(n*p1^2+p1*p2+p2)*p1+p2=n*p1^3+p1^2*p2+p1*p2+p2
今度は、地図SEED値=0 だった時を考えてみます。
seed(0,1)=seed(0,0)*p1+p2=0*p1+p2=p2
seed(0,2)=seed(0,1)*p1+p2=p1*p2+p2
seed(0,3)=seed(0,2)*p1+p2=(p1*p2+p2)*p1+p2=p1^2*p2+p1*p2+p2
この2つを比較すると、次のようになることが判ります。
seed(n,1)=n*p1+seed(0,1)
seed(n,2)=n*p1^2+seed(0,2)
seed(n,3)=n*p1^3+seed(0,3)
ということで、次のように纏めることができます。
seed(n,m)=n*p1^m+seed(0,m)
ここで、p1^m と seed(0,m) は地図SEED値に左右されない定数となります。
つまり、この2つの定数が判れば、どんな地図SEED値の何回目でも1回の計算で出せるわけです。
では、今度はこの2つの定数について考えてみます。
関数 tmlt(m)=p1^m と定義します。
tmlt(m+1)=p1^(m+1)=p1^m*p1=tmlt(m)*p1
ということで、1つ前の値が判れば、それに p1 を掛ければ次の値は計算できます。
関数 tadd(m)=seed(0,m) と定義します。
tadd(m+1)=seed(0,m+1)=seed(0,m)*p1+p2
ということで、1つ前の値が判れば、SEEDと同様に、それに p1 を掛けて p2 を足せば次の値は計算できます。
さて、地図開閉即接続の場合に参照されるのは、154回更新したSEED値です。
seed(n,154)=n*tmlt(154)+tadd(154) で普通に計算すると tmlt(154)=4094391497, tadd(154)=2268227462 です。
その時のAT値は seed(n,154) >> 16 & 0x7fff=(n*tmlt(154)+tadd(154)) >> 16 & 0x7fff で求まります。
そして、155回目の定数は tmlt(155)=tmlt(154)*p1, tadd(155)=tadd(154)*p1+p2 で計算できますし、その次も同様です。
もしくは、seed(n,154) をこの方法で求め、連続する次以降は seed(n,m+1)=seed(n,m)*p1+p2 で求めてもいいわけです。
なお、ここまで桁あふれのことは無視しましたが、加算でも乗算でもあふれた分は下位に影響しないので問題ありません。