数日前に、巷の一部で話題になった『乱数にコクを出す方法について』に対しての走り書きになりますが、番外編ということでご勘弁を!
話題の件のまとめがこちらです。
乱数とは?
乱数と言えばゲームを作る上でも重要で、乱数によって動作や結果をコントロールすると同時に、その取り扱いによってプレイ感が大きく左右されるものだと思います。レトロゲーにおけるストレス要因はほとんど乱数絡まりのような気が。一歩エンカウントとかね。
自分で作ると、ここら辺は痛感します。ちょうどよいランダム感を出すにはどうすればいいか?今回の件は、そこらへんの大きなヒントになりそうです。
その乱数とは、規則性の無い、ランダムな数字であり、プログラミング上では、Random関数を使い不規則に数字を生成します。しかし単純に作られる本当に不規則な乱数と人間が自然に感じるランダム感は違うんだ、とのことです。“1/fの揺らぎ”もここら辺に通ずると思います。ろうそくの火とか焚き火の火って飽きないですよね。
人間の体感上のランダムさ
理屈はともかくとして、
ゲームやってる人にとっては、体感的には理解できることだと思います。
不規則だけれどもある程度の値のまとまり、あるいは多少の偏りがあった方がゲームなどの場合では良い場合があります。
例えばRPGであれば、与えるダメージ、受けるダメージも乱数の幅が広いと、場合によっては緊張感を生み出しますが、ストレスにもなり得ると思います。
ドラクエで言えば、バギ系の呪文はダメージ幅が大きいし、効かないモンスターも多いので使いづらい魔法になりますが、それが特徴になるわけです。バギクロスは強いんですけど、雑魚戦のグループ対策が主な活躍の場になりますね。逆にメラ系はダメージ幅が安定しているから使いやすい、みたいな。
( Random() + Random() + Rrandom() + Random() + Random() ) / 5.0f;
乱数いえどもある程度のまとまり、柔らかい規則性が欲しい時に、このコクのある乱数の出し方が役に立つのかなと。
ワタクシは実証主義なんで、このアルゴリズムを使うと実際どうなるのかを確認するために簡単なコードを組んでみました。Visual Studioのコンソールアプリで作ってみました。RandomクラスのNextメソッドを利用して1から10までの生成をランダムに発生させる、という内容です。
コクのある乱数製造プログラム
while(true){}の無限ループを利用して、
エンターキーをずっと押してると延々と乱数が生成されるように作りました。
↑'C'キーを押さない限り二枚目の画像の上半分のコードが延々と繰り返されます
実行すると、
Tキー押すと、コクが出るモードです。
Enterキーなどを押しっぱなしにしてると、こんな感じにドンドン出てきます。
生成した乱数の集計も同時にしており、ちょうどいい具合になったら(30秒ちょい)Countの頭文字であるCキーを押すと、それまでに乱数の1から10までがそれぞれをどれくらい出てきたのかを一覧表示するようにしました。とりあえず千回くらいで集計しています。
まずはコクのある乱数たち。確かに4を頂点に山なりの分布になってる!おもしれー。
次は通常の乱数。確かに全体に均等になっていますね。
(この集計結果部分のコードに関しては、初めてラムダ式を実際にうまく使えたのでやってみて良かったなと思います。)
確かにコクがある!
実際に結果を見比べてみると、確かに正規分布的に中央に集まって、平均値を中心に山なりに収束するのが見てとれます。逆に普通のランダム関数は全体的にほとんど差が無いようにばらついてます。どちらとも10が出てなかったのでもしかしたら、コードの組み立てに問題があるかもしれませんが、一応はその傾向というのが確認できたので、ひとまずよしとします。(逃げ。)
(後日追記)はい。未熟でした。
10は出るはずないです。出すためにはrnd.Next(0, 11);としなければ
なりませんからね。不覚。
でもこのまま失敗は失敗として自戒のために残しておきます。
プログラミングによる動き、アニメーション等に関しては
こちらの方がより自然に感じるみたいなので、Unityでいえば自然物の動き、
敵キャラの動きなどに応用できるのかなと思います。
もう少し調べてUnityにいかしたいですぜ!勉強になりました!
※12月29日追記
今回の記事の後日談というかプログラムを改良、拡張し再度検証してみました!
各乱数(0~9)が、それぞれどのくらいの間隔で発生するか、という部分を新たに集計してみるという内容になります!