ベータ分布乱数
ベータ分布乱数とは、一様乱数を「ベータ分布」と呼ばれる確率分布に変換する手法です。
ベータ分布のパラメータを調整すると「当たるときは極端に連続して当たり、ハマるときはトコトンハマる」という波(偏り)を1発の乱数だけで表現できます。
仕組み 編集
- 通常の一様乱数(0〜1)を2つ以上取得する。
- 数式(累積分布関数の近似など)を用いて、両極端(0の近辺と1の近辺)に値が集中する波を作る。
演出 編集
乱数値が0の近辺なら「超高確率(即連)」、1の近辺なら「大ハマリ」となり、通常の1/319のようなフラットな抽選ではあり得ない「連チャンの塊」が自然に生まれます。
実装例: Z80 編集
ベータ分布を愚直に浮動小数点数で計算(対数や分数など)しようとすると、Z80の計算能力では破綻します。しかし当時は「ルックアップテーブル(LUT)」を使って解決していました。
大当たり値を「0」と「255」に設定しておきます。テーブル(グラフ)の形状が両端でガクッと落ち込んでいるため、元の乱数が多少ズレても、変換後は「0」や「255」に吸い込まれるように着地します。
;---------------------------------------------------
; テーブル参照による偏り乱数の取得
; 入力: Aレジスタ = 元の一様乱数 (0〜255)
; ※元の一様乱数は、Z80のRレジスタ(リフレッシュカウンタ)などを利用
; 出力: Aレジスタ = 偏り補正された乱数
;---------------------------------------------------
GET_BIASED_RAND:
LD H, HIGH(BIASED_TABLE) ; テーブルの上位アドレスをセット
LD L, A ; 一様乱数を下位アドレスにセット
LD A, (HL) ; ROMテーブルから偏った値を読み出す
RET
;---------------------------------------------------
; ROMデータ配置 (メモリ上の256バイトのエリア)
; 両端(0付近と255付近)に値が超高確率で集中するベータ分布を模したデータ例
;---------------------------------------------------
ORG 0x2000 ; テーブルの配置アドレス(例)
BIASED_TABLE:
; 入力が 0〜63 のときは、出力が「0」付近に集中(超高確率ゾーン)
DB 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 5, 8, ...
; 入力が 64〜191 のときは、出力がなだらかに変化(通常・ハマリゾーン)
DB 15, 20, 30, 45, 60, 80, 100, 120, 150, 180, ...
; 入力が 192〜255 のときは、出力が「255」付近に集中(即連戻りゾーン)
DB 240, 250, 252, 254, 255, 255, 255, 255, ...
実装例: C# 編集
using System;
public class RomTableRandom
{
private readonly Random _sourceRand = new Random();
private readonly byte[] _biasedTable = new byte[256];
public RomTableRandom()
{
GenerateBiasedTable();
}
/// <summary>
/// 両端(0付近と255付近)に値が集中するベータ分布(U型)のテーブルを擬似生成
/// </summary>
private void GenerateBiasedTable()
{
for (int i = 0; i < 256; i++)
{
double t = i / 255.0;
// 独自の数式でU字型のカーブを作り、0〜255にマッピング
// 0近辺と255近辺の面積が非常に広くなるように補正
double biasedT = Math.Sin((t - 0.5) * Math.PI) * 0.5 + 0.5;
biasedT = Math.Pow(biasedT, 3); // 3乗してさらに歪み(偏り)を強化
_biasedTable[i] = (byte)(biasedT * 255);
}
}
/// <summary>
/// テーブルを参照して偏った乱数を返す
/// </summary>
public byte NextBiased()
{
// 0〜255の一様乱数をベースにする
int index = _sourceRand.Next(0, 256);
// テーブル(ROM)から偏った値を取得
return _biasedTable[index];
}
}