diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cac38ce8..65665a7b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - 「コード:レイヤード」で達成値修正とクリティカル値変更に対応。くずもちさんありがとうっ! (#149) - 「SwordWorld/2.0/2.5」 レーティング表で半減ができるように。銀色のかぼちゃさん提案ありがとうっ! (#151) - ダイスボットに「迷宮キングダム 基本ルールブック」を追加。TakaYamsさんありがとうっ! (#152) +- ダイスボットに「BBNTRPG」を追加。neuzさん、エレリーナさんありがとうっ! (#166) ### Ver2.04.00 2020/03/26 - ダイスボットに「獸ノ森」を追加。ゆいこさんありがとうっ! (#124) diff --git a/src/diceBot/BBN.rb b/src/diceBot/BBN.rb new file mode 100644 index 000000000..c4b3de070 --- /dev/null +++ b/src/diceBot/BBN.rb @@ -0,0 +1,138 @@ +# -*- coding: utf-8 -*- + +class BBN < DiceBot + # ダイスボットで使用するコマンドを配列で列挙する + setPrefixes(['\d+BN.*']) + + ID = 'BBN'.freeze + + NAME = 'BBNTRPG'.freeze + + SORT_KEY = 'ひいひいえぬTRPG'.freeze + + HELP_MESSAGE = <=z[c,f]) + xD6の判定。クリティカル、ファンブルの自動判定を行います。 + 1Dのクリティカル値とファンブル値は1。2Dのクリティカル値とファンブル値は2。 + nDのクリティカル値とファンブル値は n/2 の切り上げ。 + クリティカルとファンブルが同時に発生した場合、クリティカルを優先。 + x:xに振るダイス数を入力。 + y:yに修正値を入力。省略可能。 + z:zに目標値を入力。省略可能。 + c:クリティカルに必要なダイス目「6」の数の増減。省略可能。 + f:ファンブルに必要なダイス目「1」の数の増減。省略可能。 + 例) 3BN+4 3BN>=8 3BN+1>=10[-1] 3BN+1>=10[,1] 3BN+1>=10[1,1] +MESSAGETEXT + + def rollDiceCommand(command) + unless parse(command) + return nil + end + + # ダイスロール + dice, dice_str = roll(@roll_times, 6) + dice_list = dice_str.split(',').map(&:to_i).sort + + total = dice + @modify + + # 出力文の生成 + sequence = [ + "(#{command})", + "#{dice}[#{dice_str}]#{@modify_str}", + total + ] + + # クリティカルとファンブルが同時に発生した時にはクリティカルが優先 + if critical?(dice_list) + sequence.push("クリティカル!", *additional_roll(dice_list.count(6), total)) + elsif fumble?(dice_list) + sequence.push("ファンブル!") + elsif @difficulty + sequence.push(total >= @difficulty ? "成功" : "失敗") + end + + return sequence.join(" > ") + end + + private + + # コマンド文字列をパースする + # + # @param command [String] コマンド + # @return [Boolean] パースに成功したか + def parse(command) + m = /^(\d+)BN([+-]\d+)?(>=(([+-]?\d+)))?(\[([+-]?\d+)?(,([+-]?\d+))?\])?/.match(command) + unless m + return false + end + + @roll_times = m[1].to_i + @modify_str = m[2] || '' + @modify = m[2].to_i + @difficulty = m[4] ? m[4].to_i : nil + + base = critical_base(@roll_times) + @critical = base + m[7].to_i + @fumble = base + m[9].to_i + + return true + end + + # 振るダイスの数からクリティカルとファンブルの基本値を算出する + # + # @param roll_times [Integer] 振るダイスの数 + # @return [Integer] クリティカルの値 + def critical_base(roll_times) + case roll_times + when 1, 2 + roll_times + else + (roll_times.to_f / 2).ceil + end + end + + # @return [Boolean] クリティカルか + def critical?(dice_list) + dice_list.count(6) >= @critical + end + + # @return [Boolean] ファンブルか + def fumble?(dice_list) + dice_list.count(1) >= @fumble + end + + # クリティカルの追加ロールをする + # 追加ロールで6が出た場合、さらに追加ロールが行われる + # + # @param additional_dice [Integer] クリティカルによる追加のダイス数 + # @param total [Integer] 現在の合計値 + # @return [Array] + def additional_roll(additional_dice, total) + sequence = [] + reroll_count = 0 + + # 追加クリティカルは無限ループしうるので、10回に制限 + while additional_dice > 0 && reroll_count < 10 + reroll_count += 1 + + dice_total, dice_str = roll(additional_dice, 6) + additional_dice = dice_str.split(',').map(&:to_i).count(6) + + sequence.push("#{total}+#{dice_total}[#{dice_str}]") + sequence.push("追加クリティカル!") if additional_dice > 0 + + total += dice_total + end + + if additional_dice > 0 + sequence.push("無限ループ防止のため中断") + end + + sequence.push total + if @difficulty + sequence.push(total >= @difficulty ? "成功" : "失敗") + end + + return sequence + end +end diff --git a/src/test/data/BBN.txt b/src/test/data/BBN.txt new file mode 100644 index 000000000..b95620a18 --- /dev/null +++ b/src/test/data/BBN.txt @@ -0,0 +1,174 @@ +input: +1BN クリティカル +output: +BBN : (1BN) > 6[6] > 6 > クリティカル! > 6+4[4] > 10 +rand:6/6,4/6 +============================ +input: +1BN ファンブル +output: +BBN : (1BN) > 1[1] > 1 > ファンブル! +rand:1/6 +============================ +input: +1BN +output: +BBN : (1BN) > 5[5] > 5 +rand:5/6 +============================ +input: +2BN クリティカル +output: +BBN : (2BN) > 12[6,6] > 12 > クリティカル! > 12+2[1,1] > 14 +rand:6/6,6/6,1/6,1/6 +============================ +input: +2BN 2Dの時は6ゾロのみクリティカル +output: +BBN : (2BN) > 8[6,2] > 8 +rand:6/6,2/6 +============================ +input: +2BN ファンブル +output: +BBN : (2BN) > 2[1,1] > 2 > ファンブル! +rand:1/6,1/6 +============================ +input: +2BN 2Dの時はピンゾロのみクリティカル +output: +BBN : (2BN) > 3[1,2] > 3 +rand:1/6,2/6 +============================ +input: +3BN クリティカル +output: +BBN : (3BN) > 13[6,6,1] > 13 > クリティカル! > 13+2[1,1] > 15 +rand:6/6,6/6,1/6,1/6,1/6 +============================ +input: +3BN ファンブル +output: +BBN : (3BN) > 8[6,1,1] > 8 > ファンブル! +rand:6/6,1/6,1/6 +============================ +input: +3BN クリティカルでもファンブルでもない +output: +BBN : (3BN) > 10[6,1,3] > 10 +rand:6/6,1/6,3/6 +============================ +input: +4BN クリティカル +output: +BBN : (4BN) > 21[6,6,4,5] > 21 > クリティカル! > 21+5[2,3] > 26 +rand:6/6,6/6,4/6,5/6,2/6,3/6 +============================ +input: +4BN ファンブル +output: +BBN : (4BN) > 11[1,1,4,5] > 11 > ファンブル! +rand:1/6,1/6,4/6,5/6 +============================ +input: +4BN クリティカルでもファンブルでもない +output: +BBN : (4BN) > 16[1,6,4,5] > 16 +rand:1/6,6/6,4/6,5/6 +============================ +input: +4BN クリティカルとファンブルはクリティカルが優先 +output: +BBN : (4BN) > 14[6,6,1,1] > 14 > クリティカル! > 14+6[2,4] > 20 +rand:6/6,6/6,1/6,1/6,2/6,4/6 +============================ +input: +2BN 追加クリティカル1回 +output: +BBN : (2BN) > 12[6,6] > 12 > クリティカル! > 12+7[6,1] > 追加クリティカル! > 19+1[1] > 20 +rand:6/6,6/6,6/6,1/6,1/6 +============================ +input: +2BN 追加クリティカル1回 +output: +BBN : (2BN) > 12[6,6] > 12 > クリティカル! > 12+12[6,6] > 追加クリティカル! > 24+2[1,1] > 26 +rand:6/6,6/6,6/6,6/6,1/6,1/6 +============================ +input: +2BN 追加クリティカル3回 +output: +BBN : (2BN) > 12[6,6] > 12 > クリティカル! > 12+7[6,1] > 追加クリティカル! > 19+6[6] > 追加クリティカル! > 25+6[6] > 追加クリティカル! > 31+1[1] > 32 +rand:6/6,6/6,6/6,1/6,6/6,6/6,1/6 +============================ +input: +2BN[-1] +output: +BBN : (2BN[-1]) > 8[6,2] > 8 > クリティカル! > 8+2[2] > 10 +rand:6/6,2/6,2/6 +============================ +input: +2BN[1,-1] +output: +BBN : (2BN[1,-1]) > 6[5,1] > 6 > ファンブル! +rand:5/6,1/6 +============================ +input: +2BN[,-1] +output: +BBN : (2BN[,-1]) > 6[5,1] > 6 > ファンブル! +rand:5/6,1/6 +============================ +input: +4BN[1,1] クリティカルとファンブル引き上げ +output: +BBN : (4BN[1,1]) > 14[6,6,1,1] > 14 +rand:6/6,6/6,1/6,1/6 +============================ +input: +4BN[1,1] クリティカル +output: +BBN : (4BN[1,1]) > 19[6,6,6,1] > 19 > クリティカル! > 19+6[4,1,1] > 25 +rand:6/6,6/6,6/6,1/6,4/6,1/6,1/6 +============================ +input: +4BN[1,2] ファンブル +output: +BBN : (4BN[1,2]) > 4[1,1,1,1] > 4 > ファンブル! +rand:1/6,1/6,1/6,1/6 +============================ +input: +1BN 無限ループ防止のため追加クリティカルは10回まで +output: +BBN : (1BN) > 6[6] > 6 > クリティカル! > 6+6[6] > 追加クリティカル! > 12+6[6] > 追加クリティカル! > 18+6[6] > 追加クリティカル! > 24+6[6] > 追加クリティカル! > 30+6[6] > 追加クリティカル! > 36+6[6] > 追加クリティカル! > 42+6[6] > 追加クリティカル! > 48+6[6] > 追加クリティカル! > 54+6[6] > 追加クリティカル! > 60+6[6] > 追加クリティカル! > 無限ループ防止のため中断 > 66 +rand:6/6,6/6,6/6,6/6,6/6,6/6,6/6,6/6,6/6,6/6,6/6 +============================ +input: +3BN+3>=10[-1,-1] +output: +BBN : (3BN+3>=10[-1,-1]) > 7[2,3,2]+3 > 10 > 成功 +rand:2/6,3/6,2/6 +============================ +input: +3BN+3>=10[-1,-1] +output: +BBN : (3BN+3>=10[-1,-1]) > 6[2,2,2]+3 > 9 > 失敗 +rand:2/6,2/6,2/6 +============================ +input: +3BN-2>=10[-1,-1] クリティカルによって成功 +output: +BBN : (3BN-2>=10[-1,-1]) > 8[6,1,1]-2 > 6 > クリティカル! > 6+5[5] > 11 > 成功 +rand:6/6,1/6,1/6,5/6 +============================ +input: +3BN-2>=10[-1,-1] クリティカルしたけど失敗 +output: +BBN : (3BN-2>=10[-1,-1]) > 8[6,1,1]-2 > 6 > クリティカル! > 6+2[2] > 8 > 失敗 +rand:6/6,1/6,1/6,2/6 +============================ +input: +3BN+3>=10[-1,-1] 目標値は超えてるけどファンブル +output: +BBN : (3BN+3>=10[-1,-1]) > 11[1,5,5]+3 > 14 > ファンブル! +rand:1/6,5/6,5/6 +============================