再現可能な乱数発生器その2

再現可能な乱数発生器 - 永字八法に引き続き、NScripter(のみ)で可能な乱数発生器(ルーチン)をもう一つ。
まだやってたのかよ!と言うツッコミはなしの方向でお願いします。
しつこく探していたらhttp://ayusya.hp.infoseek.co.jp/AlgorithmRandom.htmlなんてページをみつけたので、ここに書いてあるJavaのソースをNScripterに移植してみることにしたのです。見ればわかりますが、やたらめったらxorとかビットシフトとか使ってます。ビット演算 - 永字八法はこのための布石だったのです!

使い方

  • %ays_seedにあらかじめ種になる数値を仕込んでから使ってください。
  • もし仕込まなかったら、0が乱数の種になります。
  • ays_rndを実行すれば、±2147483647の範囲(多分)で擬似乱数を取得できます。
  • 得られた数値を適当に加工して必要な形にして使ってください。
  • 気が向いたら、rndとrnd2でさらにラッピングしたバージョンをアップします。
  • 使ってみましたが、saveoffした状態でやんないと時間かかり過ぎてイラつきます。

define節game以上

mov %0,100 ; お好みで
numalias num2bit_bit,%0:inc %0
numalias num2bit_num,%0:inc %0
numalias num2bit_loop,%0:inc %0
numalias num2bit_sgn,%0:inc %0
numalias num2bit_letter,%0:inc %0

numalias bit_result,%0:inc %0
numalias bit_a,%0:inc %0
numalias bit_b,%0:inc %0
numalias bit_lettera,%0:inc %0
numalias bit_letterb,%0:inc %0
numalias bit_letter,%0:inc %0
numalias bit_loop,%0:inc %0

numalias bit_aa,%0:inc %0
numalias bit_bb,%0:inc %0
numalias bit_cc,%0:inc %0

defsub num2bit
defsub bit2num
defsub bit_and
defsub bit_nand
defsub bit_or
defsub bit_nor
defsub bit_xor
defsub bit_xnor
defsub bit_not
defsub bit_lshift
defsub bit_rshift
defsub bit_rshift_logical
defsub and
defsub nand
defsub or
defsub nor
defsub xor
defsub xnor
defsub not
defsub lshift
defsub rshift
defsub rshift_logical

numalias ays_rnd_seed,%0:inc %0
numalias ays_rnd_result,%0:inc %0
numalias ays_rnd_and,%0:inc %0
numalias ays_rnd_base,%0:inc %0
numalias ays_rnd_temp1,%0:inc %0
numalias ays_rnd_temp2,%0:inc %0
numalias ays_rnd_temp3,%0:inc %0
numalias ays_rnd_temp4,%0:inc %0
numalias ays_rnd_temp5,%0:inc %0
defsub ays_rnd

game以下start節以上

;==================
; ays_rnd
;==================
; あるアルゴリズムに基づいた擬似乱数発生装置。
; 第一引数:乱数を受け取る数値変数
; http://ayusya.hp.infoseek.co.jp/AlgorithmRandom.html 参照のこと
*ays_rnd
getparam i%ays_rnd_result
;if $ays_rnd_seed="" gettimer %ays_rnd_seed:num2bit $ays_rnd_seed,%ays_rnd_seed
and %ays_rnd_and,%ays_rnd_seed,3
bit_rshift $ays_rnd_base,"01100101101011001001001101100101",%ays_rnd_and
if $ays_rnd_base="" mov $ays_rnd_base,"01100101101011001001001101100101"
bit_xor $ays_rnd_seed,$ays_rnd_seed,$ays_rnd_base
bit_rshift $ays_rnd_temp1,$ays_rnd_seed,4
bit_rshift $ays_rnd_temp2,$ays_rnd_seed,3
bit_lshift $ays_rnd_temp3,$ays_rnd_seed,3
bit_lshift $ays_rnd_temp4,$ays_rnd_seed,4
bit_xor $ays_rnd_temp1,$ays_rnd_temp1,$ays_rnd_temp2
bit_xor $ays_rnd_temp1,$ays_rnd_temp1,$ays_rnd_temp3
bit_xor $ays_rnd_temp1,$ays_rnd_temp1,$ays_rnd_temp4
bit_xor $ays_rnd_seed,$ays_rnd_temp1,$ays_rnd_seed
bit2num %ays_rnd_seed,$ays_rnd_seed
mov %%ays_rnd_result,%ays_rnd_seed
return

;==================
; num2bit
;==================
; 数値を、2進数の文字列に変換する。
; 第一引数:結果を受け取る文字列変数
; 第二引数:変換したい数値
*num2bit
getparam s%num2bit_bit,%num2bit_num
if %num2bit_num=0 mov %num2bit_sgn,0:jumpf
if %num2bit_num<0 mov %num2bit_sgn,-1:jumpf
if %num2bit_num>0 mov %num2bit_sgn,1
~
mul %num2bit_num,%num2bit_sgn
mov $%num2bit_bit,""
for %num2bit_loop=1 to 31
	if %num2bit_num=0 mov $num2bit_letter,"0":jumpf
	mov %num2bit_letter,%num2bit_num mod 2
	div %num2bit_num,2
	itoa $num2bit_letter,%num2bit_letter
~
	mov $%num2bit_bit,$num2bit_letter+$%num2bit_bit
next
mov $%num2bit_bit,"0"+$%num2bit_bit
if %num2bit_sgn=-1 bit_not $%num2bit_bit,$%num2bit_bit
return

;==================
; bit2num
;==================
; 数値を、2進数の文字列に変換する。
; 第一引数:結果を受け取る数値変数
; 第二引数:変換したい文字列
*bit2num
getparam i%num2bit_num,$num2bit_bit
mid $num2bit_sgn,$num2bit_bit,0,1
if $num2bit_sgn="1" bit_not $num2bit_bit,$num2bit_bit
mov %%num2bit_num,0
for %num2bit_loop=1 to 31
	mul %%num2bit_num,2
	mid $num2bit_letter,$num2bit_bit,%num2bit_loop,1
	if $num2bit_letter="1" inc %%num2bit_num
next
if $num2bit_sgn="1" mul %%num2bit_num,-1
return

;==================
; bit_and
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_and
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"0"
	if $bit_lettera="1" && $bit_letterb="1" mov $bit_letter,"1"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_nand
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_nand
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"1"
	if $bit_lettera="1" && $bit_letterb="1" mov $bit_letter,"0"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_or
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_or
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"1"
	if $bit_lettera="0" && $bit_letterb="0" mov $bit_letter,"0"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_nor
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_nor
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"0"
	if $bit_lettera="0" && $bit_letterb="0" mov $bit_letter,"1"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_xor
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_xor
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"1"
	if $bit_lettera=$bit_letterb mov $bit_letter,"0"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_xnor
;==================
; 二つの2進数(32桁限定)をビット比較で論理積する。
; 第一引数:結果を受け取る文字列変数
; 第二引数・第三引数:二つの2進数文字列
*bit_xnor
getparam s%bit_result,$bit_a,$bit_b
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	mid $bit_letterb,$bit_b,%bit_loop,1
	mov $bit_letter,"0"
	if $bit_lettera=$bit_letterb mov $bit_letter,"1"
	add $%bit_result,$bit_letter
next
return

;==================
; bit_not
;==================
; 2進数(32桁限定)のビットを反転させる。
; 第一引数:結果を受け取る文字列変数
; 第二引数:反転させたい文字列変数
*bit_not
getparam s%bit_result,$bit_a
mov $%bit_result,""
for %bit_loop=0 to 31
	mid $bit_lettera,$bit_a,%bit_loop,1
	if $bit_lettera="0" add $%bit_result,"1"
	if $bit_lettera="1" add $%bit_result,"0"
next
return

;==================
; bit_lshift
;==================
; ビットを左に動かす。空いたビットには"0"が埋められる。
; 第一引数:結果を受け取る文字列変数
; 第二引数:変えたい文字列変数
; 第三引数:動かす桁数
*bit_lshift
getparam s%bit_result,$bit_a,%bit_a
mov $%bit_result,""
if %bit_a<1 return
mid $%bit_result,$bit_a,%bit_a-1,32-%bit_a
for %bit_loop=1 to %bit_a
	add $%bit_result,"0"
next
return

;==================
; bit_rshift
;==================
; ビットを右に動かす。空いたビットには"0"が埋められる。
; 第一引数:結果を受け取る文字列変数
; 第二引数:変えたい文字列変数
; 第三引数:動かす桁数
*bit_rshift
getparam s%bit_result,$bit_a,%bit_a
mov $%bit_result,""
if %bit_a<1 return
mid $bit_letter,$bit_a,0,1
for %bit_loop=1 to %bit_a+1
	add $%bit_result,$bit_letter
next
mid $bit_lettera,$bit_a,1,31-%bit_a
add $%bit_result,$bit_lettera
return

;==================
; bit_rshift_logical
;==================
; ビットを右に動かす。空いたビットには"0"が埋められる。
; 第一引数:結果を受け取る文字列変数
; 第二引数:変えたい文字列変数
; 第三引数:動かす桁数
*bit_rshift_logical
getparam s%bit_result,$bit_a,%bit_a
mov $%bit_result,""
if %bit_a<1 return
for %bit_loop=1 to %bit_a
	add $%bit_result,"0"
next
mid $bit_lettera,$bit_a,0,32-%bit_a
add $%bit_result,$bit_lettera
return

;==================
; and
;==================
; 数値変数をビット演算する。and
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*and
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_and $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; nand
;==================
; 数値変数をビット演算する。nand
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*nand
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_nand $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; or
;==================
; 数値変数をビット演算する。or
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*or
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_or $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; nor
;==================
; 数値変数をビット演算する。nor
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*nor
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_nor $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; xor
;==================
; 数値変数をビット演算する。xor
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*xor
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_xor $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; xnor
;==================
; 数値変数をビット演算する。xnor
; 第一引数:結果を受け取る引数
; 第二引数と第三引数:比較される二つの数値
*xnor
getparam i%bit_cc,%bit_aa,%bit_bb
num2bit $bit_aa,%bit_aa
num2bit $bit_bb,%bit_bb
bit_xnor $bit_cc,$bit_aa,$bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; not
;==================
; 数値変数をビット演算する。not
; 第一引数:結果を受け取る引数
; 第二引数:反転させる数値
*not
getparam i%bit_cc,%bit_aa
num2bit $bit_aa,%bit_aa
not $bit_cc,$bit_aa
bit_bit2num %%bit_cc,$bit_cc
return

;==================
; lshift
;==================
; 数値変数をビット演算する。lshift
; 第一引数:結果を受け取る引数
; 第二引数:対象の数値
; 第三引数:ずらす数値
*lshift
getparam i%bit_cc,%bit_aa,%bit_bb
mov %%bit_cc,0
if %bit_bb<1 return
num2bit $bit_aa,%bit_aa
bit_lshift $bit_cc,$bit_aa,%bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; rshift
;==================
; 数値変数をビット演算する。rshift
; 第一引数:結果を受け取る引数
; 第二引数:対象の数値
; 第三引数:ずらす数値
*rshift
getparam i%bit_cc,%bit_aa,%bit_bb
mov %%bit_cc,0
if %bit_bb<1 return
num2bit $bit_aa,%bit_aa
bit_rshift $bit_cc,$bit_aa,%bit_bb
bit2num %%bit_cc,$bit_cc
return

;==================
; rshift_logical
;==================
; 数値変数をビット演算する。rshift_logical
; 第一引数:結果を受け取る引数
; 第二引数:対象の数値
; 第三引数:ずらす数値
*rshift_logical
getparam i%bit_cc,%bit_aa,%bit_bb
mov %%bit_cc,0
if %bit_bb<1 return
num2bit $bit_aa,%bit_aa
bit_rshift_logical $bit_cc,$bit_aa,%bit_bb
bit2num %%bit_cc,$bit_cc
return