トラック
/
Lean
Lean
/
演習
/
D&Dのキャラクター
D&Dのキャラクター

D&Dのキャラクター

中級

はじめに

何週間も待ち望んだ末、友達と集まって、初めての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回振った結果は、次のようになるかもしれません。

  • 5、3、1、6:1を捨て、5+3+6=14を合計し、これをstrengthに割り当てます。
  • 3、2、5、3:2を捨て、3+5+3=11を合計し、これをdexterityに割り当てます。
  • 1、1、1、1:1を捨て、1+1+1=3を合計し、これをconstitutionに割り当てます。
  • 2、1、6、6:1を捨て、2+6+6=14を合計し、これをintelligenceに割り当てます。
  • 3、5、3、4:3を捨て、5+3+4=12を合計し、これをwisdomに割り当てます。
  • 6、6、6、6:6を捨て、6+6+6=18を合計し、これをcharismaに割り当てます。

constitutionが3なので、constitutionの修正値は-4、hitpointsは6になります。

Note

ほとんどのプログラミング言語には(疑似)乱数生成器がありますが、サイコロを振るために設計されているプログラミング言語はほとんどありません。 そのひとつがTrollです。

Leanで疑似乱数を生成する

関数型言語では、ほとんどの関数は_純粋_です。 つまり、同じ引数の組に対してはいつも同じ出力を返し、それ以外のことは何もしません。 言い換えると、純粋な関数は決定的です。

しかし、乱数は定義上、予測できず、非決定的です。 乱数のように_見える_数列を返すこと、すなわち疑似乱数でさえ、純粋な文脈では簡単には実現できません。 なぜなら、疑似乱数生成器(PRNG)は、数列の次の数を返すために内部状態を追跡し続ける必要があるからです。

Leanには、この問題に対する2つの方法があります。

  1. PRNGの内部状態を変更できるモナドを使う方法です。 まさにそのための、すぐに使える関数IO.randがあります。

  2. ジェネレーターを引数に取り、生成された疑似乱数の値だけでなく、数列の次の数に向けて「準備された」更新済みのジェネレーターも返す、純粋な関数を使う方法です。

この演習では、2つ目の方法を使います。 疑似乱数の値を生成するすべての関数にはジェネレーターが渡され、その関数は値と更新済みのジェネレーターの両方を返すことが求められます。

あるジェネレーターは決定的である、つまり_いつも_同じ値を生成することに注意してください。 数列の中で次の疑似乱数の値を生成するには、更新済みのジェネレーターを使う必要があります。

乱数を検証する

この演習では、乱数はp < 0.0001という有意水準のカイ二乗検定で検証されます。

つまり、説明のとおりに能力値が生成されていれば、正しい実装が偶然によってテストに失敗する確率は0.01%未満です。

説明によると、能力値は_偏りのないd6(6面サイコロ)を4回振ったうち、大きいほうから3つの結果の合計_であることに注意してください。

GitHubで編集する リンクは新しいウィンドウまたはタブで開きます
Lean Exercism

D&Dのキャラクターを始める準備はできましたか?

Exercismに登録すれば、100個の演習、そして本物の人間によるメンタリングとともに、Leanを学んでマスターできます。すべて無料です。

D&Dのキャラクターを深く掘り下げよう!

(一見)ランダムなサイコロの出目をどうやって生成するのかを掘り下げます。シード、疑似乱数、よくある落とし穴について学びます。最後に、ランダムな値を返す関数のテストにプロパティベーステストがとても役立つことを見ていきます。