何週間も待ち望んだ末、友達と集まって、初めてのDungeons & Dragons(D&D)のゲームを遊ぶことになりました。 これがゲームの最初のセッションなので、プレイヤーはそれぞれ、遊ぶためのキャラクターを作らなければなりません。 キャラクターの能力は6面ダイスを振って決まりますが、そのダイスは_どこに_あるのでしょうか? はっと気づくと、友達はダイスを用意してくれるのを待っています。何しろ、D&Dで遊ぼうと言い出したのは自分なのですから! 慌てて、ダイスを持ってくるのを忘れたことに気づきます。それではD&Dのゲームができません。 幸い少しはプログラミングの基礎を身につけていたので、すぐに解決策を思いつきます。ダイスを振る動きをシミュレートするプログラムを書くのです。
Dungeons & Dragonsのゲームでは、まずプレイヤーそれぞれが、遊ぶためのキャラクターを生成するところから始めます。 このキャラクターには、ほかにもいろいろな要素がありますが、なかでも6つの能力があります。strength、dexterity、constitution、intelligence、wisdom、charismaです。 これら6つの能力には、それぞれランダムに決まるスコアがあります。 スコアは、6面のサイコロを4つ振り、大きいほうから3つの出目の合計を記録して求めます。 これを6回、能力ごとに1回ずつ行います。
キャラクターの初期hitpointsは、10にconstitutionの修正値を足した値です。 constitutionの修正値は、constitutionから10を引き、その結果を2で割って切り下げると求められます。
上記のルールに従って、ランダムにキャラクターを生成するプログラムを書いてください。
たとえば、4つのサイコロを6回振った結果は、次のようになるかもしれません。
constitutionが3なので、constitutionの修正値は-4、hitpointsは6になります。
ほとんどのプログラミング言語には(疑似)乱数生成器がありますが、サイコロを振るために設計されているプログラミング言語はほとんどありません。 そのひとつがTrollです。
Zigの標準ライブラリは隠れたグローバル状態を避ける設計になっているため、自分で乱数生成器を保持するのではなく、関数は値を得るためのstd.Randomインターフェースを受け取ります。
テストは、std.testing.random_seedでシードされた乱数生成器を渡し、同じシードを持つ乱数生成器が同じキャラクターを生成することを確認します。
能力値の分布は、p < 0.0001という有意水準でカイ二乗検定によって検証されます。
abilityが返すスコアは、期待される分布と比較されます。正しい実装が各テストに失敗する確率は、0.01%未満です。
能力値とは何かについては、上の説明を参照してください。