いぬいver.2

以前ちょろっとご披露した、「Rダイスで1回以上クリティカルする確率を返す」スクリプト『いぬい』。Rダイスのサブファンクションが出来上がった記念に(?)バージョンアップしました。
……正確には8割がた出来たかな?記念ですが。まあそれはともかく。
今度のいぬいは、600回振った時の達成値の平均値と最大値も答えます。

スクリプト

/* すくりぷと:いぬい ver.2  */

/*
nRmダイスにおいて、
1)クリティカルする確率、
2)規定回数nRD10ダイスを振った時の平均の達成値
3) 2)の達成値の最大値(最小値は0で決まってるようなもんだから)
を出力するスクリプト
*/

function event::onChannelText(prefix, channel, text)
{
    /* 変数の定義 */
    //試行回数
    var sampleNumber = 600;     
    //結果格納オブジェクト定義
    var rolledResult = new Object;
    //結果返却用オブジェクト内達成値
    rolledResult.sum = 0;       //積算値
    rolledResult.max = 0;       //最大値
    rolledResult.average = 0;   //平均値

    /* 特定の入力文字列に反応する */
    if (text.match(/!\d+R\d+/i)){
        
        //該当文字列を配列matchedTextに格納
        var matchedText = text.match(/!(\d+)R(\d+)/i);
        
        /* 1回以上のクリティカル率をを計算 */
        //クリティカル率計算
        var rateCritical = Math.round((1 - ( Math.pow((matchedText[2]-1)/10, matchedText[1])) ) * 100);

        /* sampleNumber回振った時の平均の達成値を計算 */

        /* 規定回数Rダイスを振る */
        for (i=0; i < sampleNumber; i++){
            var achieve = renegadeDice(matchedText[1],matchedText[2]);
            rolledResult.sum += achieve.value;
                        
            //最大値の比較
            if (achieve.value > rolledResult.max){
                rolledResult.max = achieve.value;
            }

/*
            //途中経過を出力
            for (j=0; j < achieve.array.length; j++){
                send(channel, prefix.nick + ':' + achieve.array[j] );
            }
*/

        }
        
        /* 平均値を出す */
        rolledResult.average = Math.round(rolledResult.sum / sampleNumber);
    
        /* 結果をチャンネルに出力 */
        send(channel, 'いぬい「ダイス' + 
            matchedText[1] + '個、クリティカル値' + matchedText[2] +
            'で、1度以上クリティカルする確率は' + rateCritical + '%」');
        send(channel, 'いぬい「' + 
            sampleNumber + '回振った時の達成値の平均は' + rolledResult.average + 
            '、最大値は' + rolledResult.max + '」');
    
    }
}

/* Rダイス */
function renegadeDice(diceNumber, critNumber)
{
    /* 前のエントリーの繰り返しなので省略 */
}

最初は最小値も出力させようと思ったのですが、よく考えてみたら600回も振れば1回はどっかでファンブルするだろうし、そうすると最小値は0固定なので省略しました。

実行結果

23:32 (ten-you) !1r9
23:32 (ten-you) いぬい「ダイス1個、クリティカル値9で、1度以上クリティカルする確率は20%」
23:32 (ten-you) いぬい「600回振った時の達成値の平均は6、最大値は38」
23:32 (ten-you) !2r9
23:32 (ten-you) いぬい「ダイス2個、クリティカル値9で、1度以上クリティカルする確率は36%」
23:32 (ten-you) いぬい「600回振った時の達成値の平均は9、最大値は43」
23:32 (ten-you) !3r10
23:32 (ten-you) いぬい「ダイス3個、クリティカル値10で、1度以上クリティカルする確率は27%」
23:32 (ten-you) いぬい「600回振った時の達成値の平均は10、最大値は29」
23:32 (ten-you) !3r7
23:32 (ten-you) いぬい「ダイス3個、クリティカル値7で、1度以上クリティカルする確率は78%」
23:32 (ten-you) いぬい「600回振った時の達成値の平均は19、最大値は72」

ちなみにスクリプトの途中にある「途中経過を出力」のコメントアウト。これを機能させると途中経過も出力してくれます。

23:33 (ten-you) !1r9
23:33 (ten-you) ten-you:1R9=[2]=2
23:33 (ten-you) ten-you:1R9=[10]=10 Critical!!
23:33 (ten-you) ten-you:1R9=[9]=20 Critical!!
23:33 (ten-you) ten-you:1R9=[6]=26
23:33 (ten-you) ten-you:1R9=[3]=3
23:33 (ten-you) ten-you:1R9=[1]=0 Fumble!!
23:33 (ten-you) ten-you:1R9=[3]=3
23:33 (ten-you) ten-you:1R9=[2]=2
23:33 (ten-you) ten-you:1R9=[4]=4
23:33 (ten-you) ten-you:1R9=[9]=10 Critical!!
23:33 (ten-you) ten-you:1R9=[6]=16
23:33 (ten-you) ten-you:1R9=[2]=2
23:33 (ten-you) ten-you:1R9=[5]=5
23:33 (ten-you) いぬい「ダイス1個、クリティカル値9で、1度以上クリティカルする確率は20%」
23:33 (ten-you) いぬい「10回振った時の達成値の平均は6、最大値は26」

……ただし、途中経過を出力する場合は

        //試行回数
        var sampleNumber = 600;     

を10回以下に減らしてください。大変なことになると思います(やってませんが)。

振ってみて気付いたこと。

600回も振(らせ)ると、それなりに出目が平均化されますね。
最大値のふり幅は大きいですが(特にクリティカル値が下がると)、平均値はいつもだいたい同じ結果が出ました。

改善点

現状のコメントアウトじゃなくて、IRCへの発言文から途中経過を出力するかどうかをコントロールできるほうが便利だなー。
ちょっと変えてみます。……また正規表現と格闘かー。