偶然を扱う
カイヨワが遊びの要素に挙げたように、偶然はゲームにおいても重要な役割を持っている。
偶然性のないゲームでは完全に実力勝負になる。競技性の高いゲームでは偶然の要素を無くす、あるいは低く抑えるのが一般的である。
逆にカジュアルなゲームでは偶然の要素を多めに入れると、初心者でも勝つことができたり、運悪く負けたという言い訳もできたりして、盛り上がりやすくできる。
偶然の要素が大きすぎると、俗に「運ゲー」と呼ばれるように、プレイヤーがいくら頑張っても結局は運次第と感じてしまうとつまらなくなってしまうかもしれない。
色々なゲームでどのような偶然性があるか、どのようなゲームが偶然性が高い/低いか、考えてみよう。
乱数
コンピュータで偶然を扱うには、一般には疑似乱数を使用する。疑似乱数は、ある値から特定の計算式で次の値を計算することで、乱数のように見える数列を得る方法である。確定的な計算であり真の乱数ではないが、実用的には十分なことも多い。
プログラミング言語には乱数を発生する機能がほぼ必ず用意されている。Pythonではrandomモジュールがある。
import random print(random.random()) #0以上1未満の一様分布の乱数を生成する print(random.randint(1, 6)) #1〜6の整数の乱数を生成する
5%の確率でSSR(スペシャルスーパーレア)、15%の確率でSR(スーパーレア)、80%の確率でR(レア)が出るガチャがある。乱数を10回発生させて抽選結果を表示するプログラム gacha.py を書いてみよう。
一様分布とそれ以外の分布
random.random()が返す乱数は一様分布、つまり0以上1未満の範囲で均等な確率で乱数が生成される。
一方で、一様分布以外の確率分布を使いたい場合もある。想定している値に近いほど出現確率が高く、大きく異なる値は滅多に出ないようにした場合などである。
ゲームにおいては、TRPG(Table-talk Role Playing Game)では4面体、6面体、8面体、12面体、20面体のサイコロを使うことが多い。例えば「2d6」という表記は6面体のサイコロを2個振ることを表している。その名残で、ビデオゲームでもこうした乱数を使うこともある。
3d8の乱数を生成するプログラム dice.py を書いてみよう。
Pythonのrandomモジュールには色々な分布の乱数を生成するメソッドが用意されている。
偶然性の感じ方
確率論を知っていても、偶然性の感じ方は往々にして不合理となる。次のような例がある。
- 5%で外れる攻撃は結構外れる。
- 10%で当たるくじを10回引けば1回くらいは必ず当たる。
- サイコロを10回振ったけど1の目は1回も出なかった。イカサマサイコロに違いない。
- 1%で当たるガチャを100回引いても来なかったが、もうすぐ来るだろう。
- 1/8192(≒0.012%)の確率なんて何回試しても当たらない。
確率に関する有名な問題に、モンティ・ホール問題がある。
プレーヤーの前に閉じた3つのドアがあって、1つのドアの後ろには景品の新車が、2つのドアの後ろには、はずれを意味するヤギがいる。プレーヤーは新車のドアを当てると新車がもらえる。プレーヤーが1つのドアを選択した後、司会のモンティが残りのドアのうちヤギがいるドアを開けてヤギを見せる。ここでプレーヤーは、最初に選んだドアを、残っている開けられていないドアに変更してもよいと言われる。ここでプレーヤーはドアを変更すべきだろうか?(Wikipediaより)
この問題を検証するプログラム montyhall.py を書いてみよう。ドアを変更しない場合とする場合で、それぞれ1000回ずつ試行して、当たる確率を求めよう。
このように、プレイヤーが確率を正しく理解することは難しい。これまでの経験、思い込み、主観確率など、さまざまな要因で確率は直感を裏切る。