From 741ac00d6f3a30f34fa9e2760a7d424c0f9d9bcb Mon Sep 17 00:00:00 2001 From: Faceless192x Date: Thu, 19 Jan 2023 18:46:12 +0900 Subject: [PATCH 1/6] =?UTF-8?q?D&D5th=E3=81=AE=E6=88=A6=E9=97=98=E3=83=AD?= =?UTF-8?q?=E3=83=BC=E3=83=AB=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/bcdice/game_system/DungeonsAndDragons5.rb | 87 ++++++++++++++++++ test/data/DungeonsAndDragons5.toml | 89 +++++++++++++++++++ 2 files changed, 176 insertions(+) create mode 100644 lib/bcdice/game_system/DungeonsAndDragons5.rb create mode 100644 test/data/DungeonsAndDragons5.toml diff --git a/lib/bcdice/game_system/DungeonsAndDragons5.rb b/lib/bcdice/game_system/DungeonsAndDragons5.rb new file mode 100644 index 000000000..3456375c9 --- /dev/null +++ b/lib/bcdice/game_system/DungeonsAndDragons5.rb @@ -0,0 +1,87 @@ +# frozen_string_literal: true + +module BCDice + module GameSystem + class DungeonsAndDragons5 < Base + # ゲームシステムの識別子 + ID = 'DungeonsAndDragons5' + + # ゲームシステム名 + NAME = 'ダンジョンズ&ドラゴンズ第5版' + + # ゲームシステム名の読みがな + SORT_KEY = 'たんしよんすあんととらこんす5' + + # ダイスボットの使い方 + HELP_MESSAGE = <<~INFO_MESSAGE_TEXT + ・命中判定 [x]AC(敵AC) +  x:有利(+)・不利(-)。省略可。 +  ファンブル/失敗/成功/クリティカル を自動判定。 +  例)AC10 +AC18 -AC16 + INFO_MESSAGE_TEXT + + register_prefix('[+-]?AC\d+') + + def initialize(command) + super(command) + + @sort_barabara_dice = false # バラバラロール(Bコマンド)でソート有 + end + + def eval_game_system_specific_command(command) + attack_roll(command) + end + + def attack_roll(command) + m = /^([-+]?)AC(\d+)(\s|$)/.match(command) + unless m + return nil + end + + advantage = m[1] + difficulty = m[2]&.to_i + + usedie = 0 + output = ["(#{advantage}AC#{difficulty})"] + + if advantage.empty? + usedie = @randomizer.roll_once(20) + else + dices = @randomizer.roll_barabara(2, 20) + output.push(dices.join(",")) + if advantage == "+" + usedie = dices.max + else + usedie = dices.min + end + end + output.push(usedie) + + result = Result.new + if usedie == 20 + result.critical = true + result.success = true + output.push("クリティカル") + elsif usedie == 1 + result.fumble = true + output.push("ファンブル") + elsif usedie >= difficulty + result.success = true + output.push("成功") + else + output.push("失敗") + end + + Result.new.tap do |r| + r.text = output.join(" > ") + if result + r.condition = result.success? + r.critical = result.critical? + r.fumble = result.fumble? + end + end + end + + end + end +end diff --git a/test/data/DungeonsAndDragons5.toml b/test/data/DungeonsAndDragons5.toml new file mode 100644 index 000000000..014a8b3ef --- /dev/null +++ b/test/data/DungeonsAndDragons5.toml @@ -0,0 +1,89 @@ +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "AC10 失敗の表示確認" +output = "(AC10) > 3 > 失敗" +failure = true +rands = [ + { sides = 20, value = 3 }, +] + +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "AC10 成功(同値)の表示確認" +output = "(AC10) > 10 > 成功" +success = true +rands = [ + { sides = 20, value = 10 }, +] + +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "AC10 成功の表示確認" +output = "(AC10) > 19 > 成功" +success = true +rands = [ + { sides = 20, value = 19 }, +] + +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "AC10 クリティカルの表示確認" +output = "(AC10) > 20 > クリティカル" +success = true +critical = true +rands = [ + { sides = 20, value = 20 }, +] + +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "AC10 ファンブルの表示確認" +output = "(AC10) > 1 > ファンブル" +failure = true +fumble = true +rands = [ + { sides = 20, value = 1 }, +] + + +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "+AC18 有利の表示確認" +output = "(+AC18) > 1,3 > 3 > 失敗" +failure = true +rands = [ + { sides = 20, value = 1 }, + { sides = 20, value = 3 }, +] + +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "+AC18" +output = "(+AC18) > 18,3 > 18 > 成功" +success = true +rands = [ + { sides = 20, value = 18 }, + { sides = 20, value = 3 }, +] + + +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "-AC16 不利の表示確認" +output = "(-AC16) > 3,6 > 3 > 失敗" +failure = true +rands = [ + { sides = 20, value = 3 }, + { sides = 20, value = 6 }, +] + +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "-AC16 不利の表示確認" +output = "(-AC16) > 18,3 > 3 > 失敗" +failure = true +rands = [ + { sides = 20, value = 18 }, + { sides = 20, value = 3 }, +] + From 155a9c37e11f77b9fd6ef85f52e7dba49bfba839 Mon Sep 17 00:00:00 2001 From: Faceless192x Date: Mon, 20 Mar 2023 13:49:41 +0900 Subject: [PATCH 2/6] =?UTF-8?q?=E6=AD=A6=E5=99=A8=E3=81=AE=E4=B8=A1?= =?UTF-8?q?=E6=89=8B=E6=8C=81=E3=81=A1=E3=83=80=E3=83=A1=E3=83=BC=E3=82=B8?= =?UTF-8?q?=E3=81=AB=E5=AF=BE=E5=BF=9C=E3=81=99=E3=82=8B=E3=82=B3=E3=83=9E?= =?UTF-8?q?=E3=83=B3=E3=83=89=E3=81=AE=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/bcdice/game_system/DungeonsAndDragons5.rb | 51 ++++++++++++++- test/data/DungeonsAndDragons5.toml | 65 +++++++++++++++++++ 2 files changed, 114 insertions(+), 2 deletions(-) diff --git a/lib/bcdice/game_system/DungeonsAndDragons5.rb b/lib/bcdice/game_system/DungeonsAndDragons5.rb index 683eab5b5..ab064beb9 100644 --- a/lib/bcdice/game_system/DungeonsAndDragons5.rb +++ b/lib/bcdice/game_system/DungeonsAndDragons5.rb @@ -23,9 +23,14 @@ class DungeonsAndDragons5 < Base ・能力値判定 AR[x][>=t][y]  攻撃ロールと同様。失敗/成功を自動判定。  例)AR AR>=10 AR+5>=18 AR-3>=16 ARA AR>=10A AR+3>=18A AR-3>=16 ARD AR>=10D AR+5>=18D AR-5>=16D + ・両手持ちのダメージ 2HnDx[m] +  n:ダイスの個数 +  x:ダイスの面数 +  m:+-修正。省略可。 +  パラディンとファイターの武器の両手持ちによるダメージダイスの1,2の出目の振り直しを行います。 INFO_MESSAGE_TEXT - register_prefix('AT([+-]\d+)?(>=\d+)?[AD]?', 'AR([+-]\d+)?(>=\d+)?[AD]?') + register_prefix('AT([+-]\d+)?(>=\d+)?[AD]?', 'AR([+-]\d+)?(>=\d+)?[AD]?', '2H(\d+)D(\d+)([+-]\d+)?') def initialize(command) super(command) @@ -34,7 +39,7 @@ def initialize(command) end def eval_game_system_specific_command(command) - attack_roll(command) || ability_roll(command) + attack_roll(command) || ability_roll(command) || twohands_damage_roll(command) end def number_with_sign_from_int(number) @@ -47,6 +52,7 @@ def number_with_sign_from_int(number) end end + # 攻撃ロール def attack_roll(command) m = /^AT([-+]\d+)?(>=(\d+))?([AD]?)/.match(command) unless m @@ -122,6 +128,7 @@ def attack_roll(command) end end + # 能力値ロール def ability_roll(command) m = /^AR([-+]\d+)?(>=(\d+))?([AD]?)/.match(command) unless m @@ -189,6 +196,46 @@ def ability_roll(command) end end end + + # 武器の両手持ちダメージ + def twohands_damage_roll(command) + m = /^2H(\d+)D(\d+)([+-]\d+)?/.match(command) + unless m + return nil + end + + dice_count = m[1].to_i + dice_number = m[2].to_i + modify = m[3].to_i + mod_str = number_with_sign_from_int(modify) + output = ["(2H#{dice_count}D#{dice_number}#{mod_str})"] + + dice = @randomizer.roll_barabara(dice_count, dice_number) + roll_dice = "[" + dice.join(",") + "]" + output.push("#{roll_dice}#{mod_str}") + + ex_dice = [] + new_dice = [] + sum_dice = 0 + dice.each do |num| + if num.to_i > 2 + sum_dice += num.to_i + ex_dice.push(num) + else + one_die = @randomizer.roll_once(dice_number) + sum_dice += one_die.to_i + new_dice.push(one_die) + end + end + if new_dice.!empty? + output.push("[" + ex_dice.join(",") + "][" + new_dice.join(",") + "]#{mod_str}") + end + output.push((sum_dice + modify).to_s) + + Result.new.tap do |r| + r.text = output.join(" > ") + end + end end end end diff --git a/test/data/DungeonsAndDragons5.toml b/test/data/DungeonsAndDragons5.toml index fb67b7a3f..c01f83e35 100644 --- a/test/data/DungeonsAndDragons5.toml +++ b/test/data/DungeonsAndDragons5.toml @@ -405,3 +405,68 @@ rands = [ { sides = 20, value = 18 }, { sides = 20, value = 3 }, ] + + +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "2H3D6 両手持ちダメージ、振り直しなし、修正なし" +output = "(2H3D6) > [5,4,3] > 12" +rands = [ + { sides = 6, value = 5 }, + { sides = 6, value = 4 }, + { sides = 6, value = 3 }, +] + +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "2H3D6+3 振り直しなし、+修正" +output = "(2H3D6+3) > [3,4,5]+3 > 15" +rands = [ + { sides = 6, value = 3 }, + { sides = 6, value = 4 }, + { sides = 6, value = 5 }, +] + +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "2H3D6-5 振り直しなし、-修正" +output = "(2H3D6-5) > [5,4,3]-5 > 7" +rands = [ + { sides = 6, value = 5 }, + { sides = 6, value = 4 }, + { sides = 6, value = 3 }, +] + +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "2H3D6 振り直しあり、修正なし" +output = "(2H3D6) > [5,4,2] > [5,4][4] > 13" +rands = [ + { sides = 6, value = 5 }, + { sides = 6, value = 4 }, + { sides = 6, value = 2 }, + { sides = 6, value = 4 }, +] + +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "2H3D6+5 振り直しあり、+修正" +output = "(2H3D6+5) > [5,2,4]+5 > [5,4][4]+5 > 18" +rands = [ + { sides = 6, value = 5 }, + { sides = 6, value = 2 }, + { sides = 6, value = 4 }, + { sides = 6, value = 4 }, +] + +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "2H3D6-3 振り直しあり、-修正" +output = "(2H3D6-3) > [5,4,2]-3 > [5,4][6]-3 > 12" +rands = [ + { sides = 6, value = 5 }, + { sides = 6, value = 4 }, + { sides = 6, value = 2 }, + { sides = 6, value = 6 }, +] + From 1c7981e4d4bd9b66002301575f6dd7fac3f27f31 Mon Sep 17 00:00:00 2001 From: Faceless192x Date: Mon, 20 Mar 2023 14:00:39 +0900 Subject: [PATCH 3/6] =?UTF-8?q?HELP=E3=81=AE=E6=9B=B8=E3=81=8D=E6=BC=8F?= =?UTF-8?q?=E3=82=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/bcdice/game_system/DungeonsAndDragons5.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/bcdice/game_system/DungeonsAndDragons5.rb b/lib/bcdice/game_system/DungeonsAndDragons5.rb index ab064beb9..da4e338fc 100644 --- a/lib/bcdice/game_system/DungeonsAndDragons5.rb +++ b/lib/bcdice/game_system/DungeonsAndDragons5.rb @@ -28,6 +28,7 @@ class DungeonsAndDragons5 < Base  x:ダイスの面数  m:+-修正。省略可。  パラディンとファイターの武器の両手持ちによるダメージダイスの1,2の出目の振り直しを行います。 +  例)2H3D6 2H1D10+3 2H2D8-1 INFO_MESSAGE_TEXT register_prefix('AT([+-]\d+)?(>=\d+)?[AD]?', 'AR([+-]\d+)?(>=\d+)?[AD]?', '2H(\d+)D(\d+)([+-]\d+)?') From cfde88aaaa466b4d445815c2c6cfa6b09c02c563 Mon Sep 17 00:00:00 2001 From: Faceless192x Date: Wed, 22 Mar 2023 12:08:13 +0900 Subject: [PATCH 4/6] =?UTF-8?q?=E6=9D=A1=E4=BB=B6=E6=96=87=E3=81=8C?= =?UTF-8?q?=E3=82=84=E3=82=84=E3=81=A3=E3=81=93=E3=81=97=E3=81=8B=E3=81=A3?= =?UTF-8?q?=E3=81=9F=E3=81=AE=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/bcdice/game_system/DungeonsAndDragons5.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bcdice/game_system/DungeonsAndDragons5.rb b/lib/bcdice/game_system/DungeonsAndDragons5.rb index da4e338fc..eb24b8898 100644 --- a/lib/bcdice/game_system/DungeonsAndDragons5.rb +++ b/lib/bcdice/game_system/DungeonsAndDragons5.rb @@ -228,7 +228,7 @@ def twohands_damage_roll(command) new_dice.push(one_die) end end - if new_dice.!empty? + unless new_dice.empty? output.push("[" + ex_dice.join(",") + "][" + new_dice.join(",") + "]#{mod_str}") end output.push((sum_dice + modify).to_s) From f1300a75754cf3c3ab86d2da03c0aa693e9f6c2e Mon Sep 17 00:00:00 2001 From: Faceless192x Date: Thu, 23 Mar 2023 09:05:24 +0900 Subject: [PATCH 5/6] =?UTF-8?q?=E6=94=BB=E6=92=83=E3=83=AD=E3=83=BC?= =?UTF-8?q?=E3=83=AB=E6=99=82=E3=81=AB=E3=82=AF=E3=83=AA=E3=83=86=E3=82=A3?= =?UTF-8?q?=E3=82=AB=E3=83=AB=E5=80=A4=E3=82=92=E6=8C=87=E5=AE=9A=E3=81=A7?= =?UTF-8?q?=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/bcdice/game_system/DungeonsAndDragons5.rb | 16 +++-- test/data/DungeonsAndDragons5.toml | 60 +++++++++++++++++++ 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/lib/bcdice/game_system/DungeonsAndDragons5.rb b/lib/bcdice/game_system/DungeonsAndDragons5.rb index eb24b8898..ed8ce831f 100644 --- a/lib/bcdice/game_system/DungeonsAndDragons5.rb +++ b/lib/bcdice/game_system/DungeonsAndDragons5.rb @@ -31,7 +31,7 @@ class DungeonsAndDragons5 < Base  例)2H3D6 2H1D10+3 2H2D8-1 INFO_MESSAGE_TEXT - register_prefix('AT([+-]\d+)?(>=\d+)?[AD]?', 'AR([+-]\d+)?(>=\d+)?[AD]?', '2H(\d+)D(\d+)([+-]\d+)?') + register_prefix('AT([+-]\d+)?(@\d+)?(>=\d+)?[AD]?', 'AR([+-]\d+)?(>=\d+)?[AD]?', '2H(\d+)D(\d+)([+-]\d+)?') def initialize(command) super(command) @@ -55,19 +55,25 @@ def number_with_sign_from_int(number) # 攻撃ロール def attack_roll(command) - m = /^AT([-+]\d+)?(>=(\d+))?([AD]?)/.match(command) + m = /^AT([-+]\d+)?(@(\d+))?(>=(\d+))?([AD]?)/.match(command) unless m return nil end modify = m[1].to_i - difficulty = m[3].to_i - advantage = m[4] + critical_no = m[3].to_i + difficulty = m[5].to_i + advantage = m[6] usedie = 0 roll_die = "" dice_command = "AT#{number_with_sign_from_int(modify)}" + if critical_no > 0 + dice_command += "@#{critical_no}" + else + critical_no = 20 + end if difficulty > 0 dice_command += ">=#{difficulty}" end @@ -101,7 +107,7 @@ def attack_roll(command) end result = Result.new - if usedie == 20 + if usedie >= critical_no result.critical = true result.success = true output.push("クリティカル") diff --git a/test/data/DungeonsAndDragons5.toml b/test/data/DungeonsAndDragons5.toml index c01f83e35..faf766bc3 100644 --- a/test/data/DungeonsAndDragons5.toml +++ b/test/data/DungeonsAndDragons5.toml @@ -16,6 +16,36 @@ rands = [ { sides = 20, value = 20 }, ] +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "AT@19 クリティカル" +output = "(AT@19) > 19 > クリティカル" +critical = true +success = true +rands = [ + { sides = 20, value = 19 }, +] + +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "AT@18 クリティカル" +output = "(AT@18) > 18 > クリティカル" +critical = true +success = true +rands = [ + { sides = 20, value = 18 }, +] + +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "AT@18 クリティカル" +output = "(AT@18) > 19 > クリティカル" +critical = true +success = true +rands = [ + { sides = 20, value = 19 }, +] + [[ test ]] game_system = "DungeonsAndDragons5" input = "AT ファンブル" @@ -64,6 +94,16 @@ rands = [ { sides = 20, value = 20 }, ] +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "AT@18>=10 クリティカルの表示確認" +output = "(AT@18>=10) > 18 > クリティカル" +success = true +critical = true +rands = [ + { sides = 20, value = 18 }, +] + [[ test ]] game_system = "DungeonsAndDragons5" input = "AT>=10 ファンブルの表示確認" @@ -145,6 +185,16 @@ rands = [ { sides = 20, value = 20 }, ] +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "AT+3@18>=10 クリティカルの表示確認" +output = "(AT+3@18>=10) > 18+3 > 21 > クリティカル" +success = true +critical = true +rands = [ + { sides = 20, value = 18 }, +] + [[ test ]] game_system = "DungeonsAndDragons5" input = "AT-3>=10 クリティカルの表示確認" @@ -155,6 +205,16 @@ rands = [ { sides = 20, value = 20 }, ] +[[ test ]] +game_system = "DungeonsAndDragons5" +input = "AT-3@18>=10 クリティカルの表示確認" +output = "(AT-3@18>=10) > 18-3 > 15 > クリティカル" +success = true +critical = true +rands = [ + { sides = 20, value = 18 }, +] + [[ test ]] game_system = "DungeonsAndDragons5" input = "AT+3>=10 ファンブルの表示確認" From 232e67dd0fc619a6f628e45d36bfca199fa28954 Mon Sep 17 00:00:00 2001 From: Faceless192x Date: Thu, 23 Mar 2023 09:09:07 +0900 Subject: [PATCH 6/6] =?UTF-8?q?HELP=E3=81=AE=E8=BF=BD=E5=8A=A0=E5=BF=98?= =?UTF-8?q?=E3=82=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/bcdice/game_system/DungeonsAndDragons5.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/bcdice/game_system/DungeonsAndDragons5.rb b/lib/bcdice/game_system/DungeonsAndDragons5.rb index ed8ce831f..b40990352 100644 --- a/lib/bcdice/game_system/DungeonsAndDragons5.rb +++ b/lib/bcdice/game_system/DungeonsAndDragons5.rb @@ -14,12 +14,14 @@ class DungeonsAndDragons5 < Base # ダイスボットの使い方 HELP_MESSAGE = <<~INFO_MESSAGE_TEXT - ・攻撃ロール AT[x][>=t][y] + ・攻撃ロール AT[x][@c][>=t][y]  x:+-修正。省略可。 -  y:有利(A), 不利(D)。省略可。 +  c:クリティカル値。省略可。  t:敵のアーマークラス。>=を含めて省略可。 +  y:有利(A), 不利(D)。省略可。  ファンブル/失敗/成功/クリティカル を自動判定。  例)AT AT>=10 AT+5>=18 AT-3>=16 ATA AT>=10A AT+3>=18A AT-3>=16 ATD AT>=10D AT+5>=18D AT-5>=16D +   AT@19 AT+5@18 AT-2@19>=15 ・能力値判定 AR[x][>=t][y]  攻撃ロールと同様。失敗/成功を自動判定。  例)AR AR>=10 AR+5>=18 AR-3>=16 ARA AR>=10A AR+3>=18A AR-3>=16 ARD AR>=10D AR+5>=18D AR-5>=16D