ワンポイントテクニック No.032(投稿:ミッピュ)

移植にも気配りを!…『擬似乱数計算式を使う』

今時(平成元年当時)のポケコンにRND関数の備わっていないものなんてほぼ存在しないでしょう!
それなのに何故わざわざ擬似乱数の計算式なんかが必要なのでしょう?!
…と思われるかもしれません。
しかし、必要になるケースがあるのです。
それは他機種への移植やデータの共有です。
乱数の順列に依存したプログラムを組んだ場合にはソフト的に移植がまず不可能です。
特に研究用途に作成したソフトではポケコンだけではなくパソコンでもデータの共有をする必要があるかもしれません。
つまり『どのような環境でも同じ値が再現出来るようにするぞぉ!』と言うのが今回のテーマで、そのテクニックとして『再現させる為には自作の擬似乱数計算式を使おう!』っていう流れに至っています。

移植を想定したプログラミングをするのならばBASICでもマシン語でも簡単に計算が出来る様な式や値が望ましいと思うのですね!
ですから、扱う数値は8ビット(0〜255)にしました。(8ビットを越えた場合、越えた上位の部分は切り捨てられます。)
それがこの式で、0〜255の正の整数がもれなく256回で一巡します。

x'=(ax+b) and FFh
※{a=4l+1,b=2m+1 ; l,mは整数}

このa,bの値がミソで、テキト〜な値を入れるとすぐに一巡してしまって乱数として使いにくいものになってしまいます。
そういう意味ではこの度このa,bの条件を導く事に成功した事はとてもラッキーな出来事でした(^o^)! (…もしかすると定番なのかも知れませんが。。。)

でもよくよく見てみると奇数偶数の繰り返しになっていますので、何らかの加工を(例えば、端っこのビットは使わないで中央付近のビットだけを使ったり、時折A,B,Xの値を書き換えたり)して使うのが望ましいでしょう!


この式をBASICで表すと、、、
X=(A*X+B) AND &HFF
です。

この時A,Bの値を、255を超える正数の整数や負の数にしても意味を成しません(8ビットを超えてもループするだけですから計算に影響を与えません。)ので、A,Bは8ビット内にしておくのが良いでしょう。

例として8192パターン(A,Bの組み合わせ)中ひとつパターンを紹介します。
a=5,b=15でx(初期値)=0の時
{15,90,209,36,195,222,101,8,55,34,185,172,107,38,205,16,95,234,161,52,19,110,53,24,135,178,137,188,187,182,157,32,175,122,113,68,99,254,5,40,215,66,89,204,11,70,109,48,255,10,65,84,179,142,213,56,39,210,41,220,91,214,61,64,79,154,17,100,3,30,165,72,119,98,249,236,171,102,13,80,159,42,225,116,83,174,117,88,199,242,201,252,251,246,221,96,239,186,177,132,163,62,69,104,23,130,153,12,75,134,173,112,63,74,129,148,243,206,21,120,103,18,105,28,155,22,125,128,143,218,81,164,67,94,229,136,183,162,57,44,235,166,77,144,223,106,33,180,147,238,181,152,7,50,9,60,59,54,29,160,47,250,241,196,227,126,133,168,87,194,217,76,139,198,237,176,127,138,193,212,51,14,85,184,167,82,169,92,219,86,189,192,207,26,145,228,131,158,37,200,247,226,121,108,43,230,141,208,31,170,97,244,211,46,245,216,71,114,73,124,123,118,93,224,111,58,49,4,35,190,197,232,151,2,25,140,203,6,45,240,191,202,1,20,115,78,149,248,231,146,233,156,27,150,253,0}
《はぁぁぁ、、、やっと書き終わったぁ(^ω^)》

次にこの擬似乱数計算式を使用した例を紹介します。
・サイコロの場合
10 CLS :WAIT
20 A=5,B=15,X=0
30 X=(A*X+B) AND &HFF
40 PRINT INT (6*X/&HFF+1)
50 GOTO 30

・ジャンケンポンの場合、
10 CLS :WAIT
20 A=5,B=15,X=0
30 X=(A*X+B) AND &HFF
40 PRINT MID$ ("グーチョキパー",3*INT (3*X/&HFF)+1,3)
GOTO 30


ちなみに、、、a=1,b=1にすると…
{1,2,3,…,253,254,255,0}の繰り返しで全然乱数とは言えない順列に仕上がってしまいます。。。
A,Bをいろいろと変えて試してみてくださいね!


(解説:おちゃめ)
 BASICに搭載されている乱数RNDは疑似乱数ですが、ほぼ全ての機種に線形合同法が用いられていると思われます。しかし、その計算式はブラックボックス化されているため乱数を使ったゲームを作った場合は他の機種で同じように動かすことは非常に難解です。
 今回のこの方法は線形合同法を用いながらポケコンで手軽に使えるようにアレンジがしてあるため短くて組み込みやすいでしょう。


RETURN

inserted by FC2 system