bcdice 3.3.0 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +158 -74
  3. data/README.md +2 -1
  4. data/i18n/BeginningIdol/ja_jp.yml +2806 -0
  5. data/i18n/BeginningIdol/ko_kr.yml +1400 -0
  6. data/i18n/Cthulhu/zh_hans.yml +11 -0
  7. data/i18n/FutariSousa/ja_jp.yml +705 -9
  8. data/i18n/KillDeathBusiness/ja_jp.yml +2 -2
  9. data/i18n/MagicaLogia/ja_jp.yml +1 -1
  10. data/i18n/MonotoneMuseum/ko_kr.yml +526 -53
  11. data/i18n/SwordWorld/ja_jp.yml +6 -0
  12. data/i18n/SwordWorld2_0/ja_jp.yml +37 -0
  13. data/i18n/SwordWorld2_5/ja_jp.yml +57 -0
  14. data/lib/bcdice/common_command/add_dice/node.rb +28 -4
  15. data/lib/bcdice/common_command/add_dice/parser.rb +149 -85
  16. data/lib/bcdice/common_command/choice.rb +82 -7
  17. data/lib/bcdice/common_command/tally_dice/node.rb +135 -0
  18. data/lib/bcdice/common_command/tally_dice/parser.rb +302 -0
  19. data/lib/bcdice/common_command/tally_dice.rb +19 -0
  20. data/lib/bcdice/common_command.rb +2 -0
  21. data/lib/bcdice/dice_table/d66_left_range_table.rb +29 -0
  22. data/lib/bcdice/dice_table/d66_parity_table.rb +8 -0
  23. data/lib/bcdice/dice_table/d66_table.rb +5 -1
  24. data/lib/bcdice/dice_table.rb +1 -0
  25. data/lib/bcdice/game_system/AngelGear.rb +9 -4
  26. data/lib/bcdice/game_system/Aoharubaan.rb +91 -0
  27. data/lib/bcdice/game_system/AssaultEngine.rb +91 -0
  28. data/lib/bcdice/game_system/Avandner.rb +1 -2
  29. data/lib/bcdice/game_system/Ayabito.rb +229 -0
  30. data/lib/bcdice/game_system/BadLife.rb +264 -289
  31. data/lib/bcdice/game_system/Bakenokawa.rb +244 -0
  32. data/lib/bcdice/game_system/BattleTech.rb +1 -1
  33. data/lib/bcdice/game_system/BeginningIdol.rb +116 -2390
  34. data/lib/bcdice/game_system/BeginningIdol_Korean.rb +10 -2312
  35. data/lib/bcdice/game_system/CastleInGray.rb +133 -0
  36. data/lib/bcdice/game_system/Cthulhu.rb +2 -2
  37. data/lib/bcdice/game_system/Cthulhu7th.rb +10 -10
  38. data/lib/bcdice/game_system/Cthulhu_SimplifiedChinese.rb +60 -0
  39. data/lib/bcdice/game_system/CyberpunkRed.rb +135 -0
  40. data/lib/bcdice/game_system/DarkDaysDrive.rb +76 -41
  41. data/lib/bcdice/game_system/DoubleCross.rb +5 -0
  42. data/lib/bcdice/game_system/Dracurouge.rb +2 -1
  43. data/lib/bcdice/game_system/Elysion.rb +36 -20
  44. data/lib/bcdice/game_system/Emoklore.rb +1 -1
  45. data/lib/bcdice/game_system/FateCoreSystem.rb +117 -0
  46. data/lib/bcdice/game_system/FutariSousa.rb +48 -4
  47. data/lib/bcdice/game_system/GranCrest.rb +171 -406
  48. data/lib/bcdice/game_system/Irisbane.rb +154 -0
  49. data/lib/bcdice/game_system/Karukami.rb +84 -0
  50. data/lib/bcdice/game_system/KemonoNoMori.rb +17 -17
  51. data/lib/bcdice/game_system/KurayamiCrying.rb +1 -1
  52. data/lib/bcdice/game_system/MonotoneMuseum_Korean.rb +4 -4
  53. data/lib/bcdice/game_system/NeverCloud.rb +19 -8
  54. data/lib/bcdice/game_system/PersonaO.rb +86 -0
  55. data/lib/bcdice/game_system/Revulture.rb +2 -2
  56. data/lib/bcdice/game_system/Shiranui.rb +145 -0
  57. data/lib/bcdice/game_system/ShuumatsuKikou.rb +298 -0
  58. data/lib/bcdice/game_system/StarryDolls.rb +318 -0
  59. data/lib/bcdice/game_system/SteamPunkers.rb +14 -1
  60. data/lib/bcdice/game_system/StellarKnights.rb +1 -1
  61. data/lib/bcdice/game_system/{SterileLife.rb → StellarLife.rb} +162 -226
  62. data/lib/bcdice/game_system/StrangerOfSwordCity.rb +18 -5
  63. data/lib/bcdice/game_system/SwordWorld.rb +11 -7
  64. data/lib/bcdice/game_system/SwordWorld2_0.rb +30 -38
  65. data/lib/bcdice/game_system/SwordWorld2_5.rb +9 -63
  66. data/lib/bcdice/game_system/TalesFromTheLoop.rb +83 -0
  67. data/lib/bcdice/game_system/TorgEternity.rb +2 -2
  68. data/lib/bcdice/game_system/ToshiakiHolyGrailWar.rb +92 -0
  69. data/lib/bcdice/game_system/VampireTheMasquerade5th.rb +29 -28
  70. data/lib/bcdice/game_system/YearZeroEngine.rb +40 -19
  71. data/lib/bcdice/game_system/beginning_idol/accessories_table.rb +31 -0
  72. data/lib/bcdice/game_system/beginning_idol/bad_status_table.rb +43 -0
  73. data/lib/bcdice/game_system/beginning_idol/chain_d66_table.rb +29 -0
  74. data/lib/bcdice/game_system/beginning_idol/chain_table.rb +37 -0
  75. data/lib/bcdice/game_system/beginning_idol/costume_table.rb +37 -0
  76. data/lib/bcdice/game_system/beginning_idol/d6_twice_table.rb +36 -0
  77. data/lib/bcdice/game_system/beginning_idol/item_table.rb +51 -0
  78. data/lib/bcdice/game_system/beginning_idol/my_skill_name_table.rb +44 -0
  79. data/lib/bcdice/game_system/beginning_idol/random_event_table.rb +31 -0
  80. data/lib/bcdice/game_system/beginning_idol/skill_table.rb +63 -0
  81. data/lib/bcdice/game_system/beginning_idol/table.rb +193 -0
  82. data/lib/bcdice/game_system/beginning_idol/with_abnormality.rb +74 -0
  83. data/lib/bcdice/game_system/beginning_idol/work_table.rb +57 -0
  84. data/lib/bcdice/game_system/cyberpunk_red/tables.rb +530 -0
  85. data/lib/bcdice/game_system/meikyu_kingdom/tables.rb +1 -1
  86. data/lib/bcdice/game_system/meikyu_kingdom_basic/table.rb +1 -1
  87. data/lib/bcdice/game_system/one_way_heroics/random_event_table.rb +4 -4
  88. data/lib/bcdice/game_system/satasupe/tables.rb +1 -1
  89. data/lib/bcdice/game_system/sword_world/rating_options.rb +47 -0
  90. data/lib/bcdice/game_system/sword_world/rating_parsed.rb +40 -45
  91. data/lib/bcdice/game_system/sword_world/rating_parser.rb +172 -141
  92. data/lib/bcdice/game_system/sword_world/transcendent_test.rb +14 -10
  93. data/lib/bcdice/game_system.rb +16 -1
  94. data/lib/bcdice/randomizer.rb +1 -1
  95. data/lib/bcdice/version.rb +1 -1
  96. metadata +45 -5
@@ -0,0 +1,154 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class Irisbane < Base
6
+ # ゲームシステムの識別子
7
+ ID = 'Irisbane'
8
+
9
+ # ゲームシステム名
10
+ NAME = '瞳逸らさぬイリスベイン'
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = 'ひとみそらさぬいりすへいん'
14
+
15
+ # ダイスボットの使い方
16
+ HELP_MESSAGE = <<~HELP
17
+ ■攻撃判定( ATTACKx@y<=z )
18
+ x: 攻撃力
19
+ y: 判定数
20
+ z: 目標値
21
+ (※ ATTACK は ATK または AT と簡略化可能)
22
+ 例) ATTACK2@3<=5
23
+ 例) ATK10@2<=4
24
+ 例) AT8@3<=2
25
+
26
+ 上記 x y z にはそれぞれ四則演算を指定可能。
27
+ 例) ATTACK2+7@3*2<=5-1
28
+
29
+ □攻撃判定のダメージ増減( ATTACKx@y<=z[+a] ATTACKx@y<=z[-a])
30
+ 末尾に [+a] または [-a] と指定すると、最終的なダメージを増減できる。
31
+ a: 増減量
32
+ 例) ATTACK2@3<=5[+10]
33
+ 例) ATK10@2<=4[-8]
34
+ 例) AT8@3<=2[-8+5]
35
+
36
+ ■シチュエーション(p115)
37
+ SceneSituation, SSi
38
+ HELP
39
+
40
+ ATTACK_ROLL_REG = %r{^AT(TACK|K)?([+\-*/()\d]+)@([+\-*/()\d]+)<=([+\-*/()\d]+)(\[([+\-])([+\-*/()\d]+)\])?}i.freeze
41
+ register_prefix('AT(TACK|K)?')
42
+
43
+ def initialize(command)
44
+ super(command)
45
+
46
+ @sort_barabara_dice = true
47
+ @round_type = RoundType::CEIL
48
+ end
49
+
50
+ def eval_game_system_specific_command(command)
51
+ command = ALIAS[command] || command
52
+
53
+ if (m = ATTACK_ROLL_REG.match(command))
54
+ roll_attack(m[2], m[3], m[4], m[6], m[7])
55
+ else
56
+ roll_tables(command, TABLES)
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def roll_attack(power_expression, dice_count_expression, border_expression, modification_operator, modification_expression)
63
+ power = Arithmetic.eval(power_expression, RoundType::CEIL)
64
+ dice_count = Arithmetic.eval(dice_count_expression, RoundType::CEIL)
65
+ border = Arithmetic.eval(border_expression, RoundType::CEIL)
66
+ modification_value = modification_expression.nil? ? nil : Arithmetic.eval(modification_expression, RoundType::CEIL)
67
+ return if power.nil? || dice_count.nil? || border.nil?
68
+ return if modification_operator && modification_value.nil?
69
+
70
+ power = 0 if power < 0
71
+ border = border.clamp(1, 6)
72
+
73
+ command = make_command_text(power, dice_count, border, modification_operator, modification_value)
74
+
75
+ if dice_count <= 0
76
+ return "#{command} > 判定数が 0 です"
77
+ end
78
+
79
+ dices = @randomizer.roll_barabara(dice_count, 6).sort
80
+
81
+ success_dice_count = dices.count { |dice| dice <= border }
82
+ damage = success_dice_count * power
83
+
84
+ message_elements = []
85
+ message_elements << command
86
+ message_elements << dices.join(',')
87
+ message_elements << "成功ダイス数 #{success_dice_count}"
88
+ message_elements << "× 攻撃力 #{power}" if success_dice_count > 0
89
+
90
+ if success_dice_count > 0
91
+ if modification_operator && modification_value
92
+ message_elements << "ダメージ #{damage}#{modification_operator}#{modification_value}"
93
+ damage = parse_operator(modification_operator).call(damage, modification_value)
94
+ damage = 0 if damage < 0
95
+ message_elements << damage.to_s
96
+ else
97
+ message_elements << "ダメージ #{damage}"
98
+ end
99
+ end
100
+
101
+ Result.new(message_elements.join(' > ')).tap do |r|
102
+ r.condition = success_dice_count > 0
103
+ end
104
+ end
105
+
106
+ def make_command_text(power, dice_count, border, modification_operator, modification_value)
107
+ text = "(ATTACK#{power}@#{dice_count}<=#{border}"
108
+ text += "[#{modification_operator}#{modification_value}]" if modification_operator
109
+ text += ")"
110
+ text
111
+ end
112
+
113
+ def parse_operator(operator)
114
+ case operator
115
+ when '+'
116
+ lambda { |x, y| x + y }
117
+ when '-'
118
+ lambda { |x, y| x - y }
119
+ end
120
+ end
121
+
122
+ TABLES = {
123
+ "SceneSituation" => DiceTable::D66LeftRangeTable.new(
124
+ "シチュエーション",
125
+ BCDice::D66SortType::NO_SORT,
126
+ [
127
+ [1..3, [
128
+ "【日常】何一つ変わることの無い日々の一幕。移ろい易い世界では、それはとても大切である。",
129
+ "【準備】何かを為すための用意をする一幕。情報収集、買物遠征、やるべきことは一杯だ。",
130
+ "【趣味】自分の時間を、有効活用している一幕。必要に追われていない分、心は軽く晴れやかだ。",
131
+ "【喫茶】一息入れ、嗜好品を嗜む時の一幕。穏やかな空気は、だが、往々にして変わりやすい。",
132
+ "【鍛錬】体を鍛え、心を養う修練の一幕。己さえ良ければ、その方法も何だって良い。",
133
+ "【職務】役割の元、仕事に精を出す時の一幕。目的が何であれ、為すべきことに変わりはない。",
134
+ ]],
135
+ [4..6, [
136
+ "【移動】何処かから何処かへと向かう一幕。進んでいるなら、手段も目的地も関係あるまい。",
137
+ "【墓前】故人が眠る場所へと赴く一幕。共に眠ることだけは無いように。",
138
+ "【操作】何かを操り、望みを果たしている一幕。運転にせよ何にせよ、脇見には注意が必要だ。",
139
+ "【食事】何かを糧とし、己の力を蓄える一幕。行動すれば消耗する。腹が減っては何とやらだ。",
140
+ "【休息】日々の合間の、憩いの一幕。“何もしない”というのも、立派な行いである。",
141
+ "【夢幻】現実に存在しない何かへと耽る一幕。時間帯に関わらず、何時かは必ず覚めるだろう。",
142
+ ]],
143
+ ]
144
+ ),
145
+ }.transform_keys(&:upcase).freeze
146
+
147
+ ALIAS = {
148
+ "SSi" => "SceneSituation",
149
+ }.transform_keys(&:upcase).transform_values(&:upcase).freeze
150
+
151
+ register_prefix(TABLES.keys, ALIAS.keys)
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class Karukami < Base
6
+ # ゲームシステムの識別子
7
+ ID = 'Karukami'
8
+
9
+ # ゲームシステム名
10
+ NAME = 'カルカミ'
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = 'かるかみ'
14
+
15
+ # ダイスボットの使い方
16
+ HELP_MESSAGE = <<~HELP_MESSAGE
17
+ ■ 行為判定、ダメージ算出 (xUB+y@c>=t)
18
+ 6面ダイスをx個ダイスロールし、クリティカル値以上の出目が出たら振り足して合計値を算出します。
19
+ x: ダイス数
20
+ y: 修正値(省略可)
21
+ c: クリティカル値(省略可)
22
+ t: 目標値値(省略可)
23
+ 例)2UB, 2UB>=7, 3UB+1@5, 3UB+1@5<10
24
+ HELP_MESSAGE
25
+
26
+ register_prefix('\d+UB')
27
+
28
+ def eval_game_system_specific_command(command)
29
+ roll_ub(command)
30
+ end
31
+
32
+ def roll_ub(command)
33
+ parser = Command::Parser.new("UB", round_type: @round_type)
34
+ .has_prefix_number
35
+ .enable_critical
36
+ parsed = parser.parse(command)
37
+ unless parsed
38
+ return nil
39
+ end
40
+
41
+ critical = parsed.critical || 6
42
+ if critical <= 1
43
+ return "(#{parsed}) > クリティカル値は2以上としてください"
44
+ end
45
+
46
+ list_list = []
47
+ criticals = 0
48
+ stack = parsed.prefix_number
49
+ while stack > 0
50
+ dice_list = @randomizer.roll_barabara(stack, 6)
51
+ list_list.push(dice_list)
52
+ stack = dice_list.count { |x| x >= critical }
53
+ criticals += stack
54
+ end
55
+
56
+ total = list_list.flatten.sum() + parsed.modify_number
57
+
58
+ result =
59
+ if list_list.first.all?(1)
60
+ total = 0
61
+ Result.fumble("ファンブル")
62
+ elsif parsed.cmp_op.nil?
63
+ Result.new()
64
+ elsif total.send(parsed.cmp_op, parsed.target_number)
65
+ Result.success("成功")
66
+ else
67
+ Result.failure("失敗")
68
+ end
69
+ result.critical = criticals > 0
70
+
71
+ sequence = [
72
+ "(#{parsed})",
73
+ *list_list.map { |list| "[#{list.join(',')}]" },
74
+ total,
75
+ ("#{criticals}クリティカル" if result.critical?),
76
+ result.text,
77
+ ].compact
78
+
79
+ result.text = sequence.join(" > ")
80
+ return result
81
+ end
82
+ end
83
+ end
84
+ end
@@ -17,27 +17,27 @@ module BCDice
17
17
 
18
18
  # ダイスボットの使い方
19
19
  HELP_MESSAGE = <<~MESSAGETEXT
20
- ・行為判定(成功度自動算出): KAx[±y]
20
+ ・行為判定(成功度自動算出)(P119): KAx[±y]
21
21
  ・継続判定(成功度+1固定): KCx[±y]
22
22
  x=目標値
23
23
  y=目標値への修正(任意) x+y-z のように複数指定可能
24
24
  例1)KA7+3 → 目標値7にプラス3の修正を加えた行為判定
25
25
  例2)KC6 → 目標値6の継続判定
26
- ・罠動作判定: CTR
27
- 罠ごとに1D12を振る。12が出た場合は罠が動作し、獲物がその効果を受ける
26
+ ・罠動作チェック+獲物表(P163): CTR
27
+ 罠ごとに1D12を振り、12が出た場合には生き物が罠を動作させ、その影響を受けている。
28
28
  ・各種表
29
- ・大失敗表: FT
30
- ・能力値ランダム決定表: RST
31
- ・ランダム所要時間表: RTT
32
- ・ランダム消耗表: RET
33
- ・ランダム天気表: RWT
34
- ・ランダム天気持続表: RWDT
35
- ・ランダム遮蔽物表(屋外): ROMT
36
- ・ランダム遮蔽物表(屋内): RIMT
37
- ・逃走体験表: EET
38
- ・食材採集表: GFT
39
- ・水採集表: GWT
40
- ・白の魔石効果表: WST
29
+ ・大失敗表(P120): FT
30
+ ・能力値ランダム決定表(P121): RST
31
+ ・ランダム所要時間表(P122): RTT
32
+ ・ランダム消耗表(P122): RET
33
+ ・ランダム天気表(P128): RWT
34
+ ・ランダム天気持続表(P128): RWDT
35
+ ・ランダム遮蔽物表(屋外)(P140): ROMT
36
+ ・ランダム遮蔽物表(屋内)(P140): RIMT
37
+ ・逃走体験表(P144): EET
38
+ ・食材採集表(P157): GFT
39
+ ・水採集表(P157): GWT
40
+ ・白の魔石効果表(P186): WST
41
41
  MESSAGETEXT
42
42
 
43
43
  def eval_game_system_specific_command(command)
@@ -106,9 +106,9 @@ module BCDice
106
106
  [1..3, '【余裕】が3点減少する(最低0まで)'],
107
107
  [4..5, 'ランダムな荷物1個が落ちて行方不明になる(大失敗したエリアのアイテム調査で見つけることが可能)'],
108
108
  [6..7, 'ランダムな荷物1個が破壊される'],
109
- [8..9, 'ランダム天気表を使用し、結果をターンの終了まで適用する'],
109
+ [8..9, 'ランダム天気表(RWT)を使用し、結果をターンの終了まで適用する'],
110
110
  [10, 'ランダムな準備している小道具1個が破壊される'],
111
- [11, '着想している防具が破壊される'],
111
+ [11, '着装している防具が破壊される'],
112
112
  [12, '準備している武器が破壊される'],
113
113
  ]
114
114
  ),
@@ -47,7 +47,7 @@ module BCDice
47
47
  "さっきからずっと、不気味な視線を感じる……どうやら、良くない存在に目をつけられてしまったようだ。「怪異」があなたに一方的な「ツナガリ」を獲得する。すでに「怪異」から「ツナガリ」を獲得されている場合、ダイスを振り直し、再度「アクシデント表」に当てはめる。",
48
48
  "ぶつんと頭の中で音がする。あれっ?誰かのことを考えていたような……なんだか記憶が霞んで、思い出せない。あなたが獲得している「ツナガリ」をランダムに1つ失う(「継続的なツナガリ」である場合、セッション終了後に再度獲得する)。「ツナガリ」が1つもない場合、ダイスを振り直し、再度「アクシデント表」に当てはめる。",
49
49
  "ぞわりと背中に懇寒が走る。自分を取り巻く「流れ」──運命に似た何かが歪んでしまったような、おぞましい予感が胸を走る。「確保」しているダイスの目が「10」になる。ダイスを「確保」していない場合、新たに「10」を「確保」する。すでに「10」の目を「確保」している場合、ダイスを振り直し、再度「アクシデント表」に当てはめる。",
50
- "違う……違う、違う。これは自分のせいじゃない。いや、きっと何かの間違いだ。そう、あいつのせいに決まってる!進行役があなた以外の主人公をランダムに1人選ぷ(誰を選んだか参加者に教えてはならない) 。選ばれた主人公が次に判定を行った際、進行役は、最も低い数字を示しているダイスの目を「10」に変更する。",
50
+ "違う……違う、違う。これは自分のせいじゃない。いや、きっと何かの間違いだ。そう、あいつのせいに決まってる!進行役があなた以外の主人公をランダムに1人選ぶ(誰を選んだか参加者に教えてはならない) 。選ばれた主人公が次に判定を行った際、進行役は、最も低い数字を示しているダイスの目を「10」に変更する。",
51
51
  "あぁ……見つからない。アレがないとダメなのに。一体どうしたら──!「アイテム」をランダムに1つ失う(「継続品」である場合、センョン終了後に再度獲得する)。「アイテム」を1つも所持していない場合、「アイテム」を所持する主人公をランダムに1人選び、2点のダメージを与え、「アイテム」を1つ奪い取る。主人公が誰も「アイテム」を所持していない場合、「理性」を2点失う。",
52
52
  "まるで自分を支える何かが失われたように、あなたはその場に立ち尽くす。諦めと絶望が心を支配する。ああ、そうか。これが、「心が折れる」ということか……。あなたは「理性」を4点失う。"
53
53
  ]
@@ -23,10 +23,10 @@ module BCDice
23
23
    자동성공, 자동실패, 성공, 실패를 자동표기합니다.
24
24
  ・각종표
25
25
   ・감정표 ET/감정표 2.0 ET2
26
-  ・징조표 OT/兆候表ver2.0 OT2/兆候表ver3.0 OT3
27
-  ・일그러짐표 DT/일그러짐표ver2.0 DT2/歪み表(野外) DTO/歪み表() DTS/歪み表(館・城) DTM
28
-  ・세계왜곡표  WDT/世界歪曲表2.0 WDT2
29
-  ・永劫消失表 EDT
26
+  ・징조표 OT/징조표ver2.0 OT2/징조표ver3.0 OT3
27
+  ・일그러짐표 DT/일그러짐표ver2.0 DT2/일그러짐표(야외) DTO/일그러짐표(바다) DTS/일그러짐표(저택・성) DTM
28
+  ・세계왜곡표  WDT/세계왜곡표2.0 WDT2
29
+  ・영구소실표 EDT
30
30
  ・D66다이스 있음
31
31
  INFO_MESSAGE_TEXT
32
32
 
@@ -19,6 +19,8 @@ module BCDice
19
19
 
20
20
  # ダイスボットの使い方
21
21
  HELP_MESSAGE = <<~MESSAGETEXT
22
+ ・LIST のコマンドを入力して、ルールの解説・2D6表、一覧の表示
23
+
22
24
  ・判定(xNC±y>=z)
23
25
   xD6の判定を行います。ファンブル、クリティカルの場合、その旨を出力します。
24
26
   x:振るダイスの数。
@@ -27,7 +29,6 @@ module BCDice
27
29
   ダイスの出目ふたつが6ならクリティカル(自動成功)
28
30
   ダイスの出目すべてが1ならファンブル(自動失敗)
29
31
   例) 2NC+2>=5 1NC
30
- ・ルール詳細、表の一覧(LIST)
31
32
  MESSAGETEXT
32
33
 
33
34
  def eval_game_system_specific_command(command)
@@ -37,6 +38,8 @@ module BCDice
37
38
  return TEXTS[command].chomp
38
39
  elsif TABLES.key?(command)
39
40
  return roll_tables(command, TABLES)
41
+ elsif ALIAS_TEXTS.key?(command)
42
+ return TEXTS[ALIAS_TEXTS[command]].chomp
40
43
  else
41
44
  return nil
42
45
  end
@@ -88,23 +91,27 @@ module BCDice
88
91
  ・キャラ作成アプリ:https://nctrpg.com/bloomi
89
92
 
90
93
  ・判定(xD6±y>=z)
94
+
95
+ ()内のコマンドを入力して詳細を表示。
96
+
91
97
  2D6(CHAR1) ・所属表(2D6またはRoC。基本ルール書籍版P33)
92
- 2D6(CHRA2) ・趣味表(2D6またはRoC。基本ルール書籍版P38)
98
+ 2D6(CHAR2) ・趣味表(2D6またはRoC。基本ルール書籍版P38)
93
99
  2D6(CHAR3) ・リビド武装形状表(2D6またはRoC。基本ルール書籍版P39)
94
100
  2D6(NAYA1) 悩みの詳細表・愛/Love:得意方向(正面)(2D6またはRoC。基本ルール書籍版P49)
95
101
  2D6(NAYA2) 悩みの詳細表・体/Figure:得意方向(正面)(2D6またはRoC。基本ルール書籍版P49)
96
102
  2D6(NAYA3) 悩みの詳細表・才/Talent:得意方向(背面)(2D6またはRoC。基本ルール書籍版P49)
97
103
  2D6(NAYA4) 悩みの詳細表・絆/Bonds:得意方向(側面)(2D6またはRoC。基本ルール書籍版P49)
98
104
  2D6(NAYA5) 悩みの詳細表・住/Home:得意方向(側面)(2D6またはRoC。基本ルール書籍版P49)
99
- 各種RoC表はコマンドの最後にアルファベットのLを付けることにより一覧表示が可能
100
105
 
101
- (LIKE) LIKE(基本ルール書籍版P60)
106
+ 各種2D6:RoC表はコマンドの最後にアルファベットのLを付けて一覧表示が可能(例:NAYA5→NAYA5L)
107
+
108
+ (LIKE1) LIKE(基本ルール書籍版P60)
102
109
  (RESE1) リサーチカード(基本ルール書籍版P63)
103
110
  (RESE2) インタビュー(基本ルール書籍版P62)
104
111
  (RESE3) パイルドライヴ(基本ルール書籍版P64)
105
112
  (RESE4) [決意]と[使命](基本ルール書籍版P61)
106
113
 
107
- (ARTS) リビドアーツのデータ項目(基本ルール書籍版P40)
114
+ (ARTS1) リビドアーツのデータ項目(基本ルール書籍版P40)
108
115
  (STAT1) SSリスト(基本ルール書籍版P41)
109
116
  (STAT2) LSリスト(基本ルール書籍版P411)
110
117
  (ACTI1) タイミング:サブアクション(基本ルール書籍版P422)
@@ -132,7 +139,7 @@ module BCDice
132
139
  (MINI5) ねばくらミニでのスペシャルアーツ(ねばくらミニ書籍版P13)
133
140
  (MINI6) ねばくらミニでのポータルとサーヴァント(ねばくらミニ書籍版P14)
134
141
  TEXT
135
- 'LIKE' => <<~TEXT,
142
+ 'LIKE1' => <<~TEXT,
136
143
  LIKE(基本ルール書籍版P60)
137
144
  ・全ての参加者(PLやGMや見学者)はセッション中にPCやGMのロールプレイや行動に、
138
145
   共感や称賛や琴線に触れた時[LIKE:~]と言ってその内容と共に記述して蓄積して行く。
@@ -167,7 +174,7 @@ module BCDice
167
174
  ・これとは別にGMは[LIKE]の合計点を5で割った値を[使命]言う単位(最大5点)とする。
168
175
   [決意]と[使命]は[Pコトノハ][Sコトノハ][ワード]の単語ごとに割り振られ、これらの単語を使用したロールプレイを推奨する。
169
176
  TEXT
170
- 'ARTS' => <<~TEXT,
177
+ 'ARTS1' => <<~TEXT,
171
178
  リビドアーツのデータ項目(基本ルール書籍版P40)
172
179
  ・射程:起点から『ぴったり』に、何Sq離れたキャラクターを対象に取れるかを示す。射程0は自身のみのことである。
173
180
  ・威力:そのアーツを使用した結果に対象に及ぼす数値を示す。ダイスロールを含む場合「威力ロール」と呼ぶ。
@@ -602,8 +609,12 @@ module BCDice
602
609
  ),
603
610
  }.freeze
604
611
 
612
+ ALIAS_TEXTS = {
613
+ "ARTS" => "ARTS1",
614
+ }.freeze
615
+
605
616
  # ダイスボットで使用するコマンドを配列で列挙する
606
- register_prefix('\d+NC', '\d+D6?([\+\-\d]*)>=\d+', TEXTS.keys, TABLES.keys)
617
+ register_prefix('\d+NC', '\d+D6?([\+\-\d]*)>=\d+', TEXTS.keys, TABLES.keys, ALIAS_TEXTS.keys)
607
618
  end
608
619
  end
609
620
  end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class PersonaO < Base
6
+ # ゲームシステムのの識別子
7
+ ID = 'PersonaO'
8
+
9
+ # ゲームシステム名
10
+ NAME = 'ペルソナTRPG-O'
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = 'へるそなTRPGO'
14
+
15
+ # ダイスボットの使い方
16
+ HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
17
+ ・基本判定
18
+  PTx@y x:目標値、y:クリティカル値(省略時は5)
19
+  例)PT60 PT90@10
20
+
21
+ ・ダメージ計算
22
+  nPD+(x+y*2)%(z-a)-b n:ダイス個数、x:スキル固定値、y:ボーナス、z:バフ倍率、a:耐性、b:敵防御力
23
+  nPD+(x+y*2)までがスキルによる素のダメージ、zおよびaは計算式を入れてよい。
24
+  
25
+  例)ソニックパンチ、力B2点、
26
+    タルカジャがかかっており、打撃耐性あり、
27
+    目標の物理防御力は2点
28
+    
29
+    2PD+(20+2*2)%(100+50-50)-2
30
+ INFO_MESSAGE_TEXT
31
+
32
+ register_prefix(
33
+ 'PT',
34
+ '\d+PD'
35
+ )
36
+
37
+ def eval_game_system_specific_command(command)
38
+ roll_attack(command) || roll_damage(command)
39
+ end
40
+
41
+ private
42
+
43
+ def roll_attack(command)
44
+ m = /^PT(-?\d+)?(@(-?\d+))?$/i.match(command)
45
+ unless m
46
+ return nil
47
+ end
48
+
49
+ success_rate = m[1].to_i
50
+ critical_border = m[3]&.to_i || 5
51
+
52
+ dice_value = @randomizer.roll_once(100)
53
+ result =
54
+ if dice_value <= critical_border
55
+ Result.critical("クリティカル")
56
+ elsif dice_value <= success_rate
57
+ Result.success("成功")
58
+ else
59
+ Result.failure("失敗")
60
+ end
61
+
62
+ result.text = "D100<=#{success_rate}@#{critical_border} > #{dice_value} > #{result.text}"
63
+ return result
64
+ end
65
+
66
+ def roll_damage(command)
67
+ m = /^(\d+)PD\+(-?\d+)%(-?\d+)-(\d+)$/i.match(command)
68
+ unless m
69
+ return nil
70
+ end
71
+
72
+ dice = m[1].to_i
73
+ kotei = m[2].to_i
74
+ hosei = m[3].to_i
75
+ bougyo = m[4].to_i
76
+
77
+ dice_list = @randomizer.roll_barabara(dice, 10)
78
+ dice_sum = dice_list.sum
79
+
80
+ dmg = dice_sum + (hosei * kotei / 100.0).to_i - bougyo
81
+
82
+ return "#{dice}D10+#{kotei}*#{hosei}%-#{bougyo} > [#{dice_list.join(',')}]+#{kotei}*#{hosei}%-#{bougyo} > #{dmg} ダメージ!"
83
+ end
84
+ end
85
+ end
86
+ end
@@ -50,8 +50,8 @@ module BCDice
50
50
  private
51
51
 
52
52
  def roll_attack(dice_count_expression, border_expression, additional_damage_rules)
53
- dice_count = Arithmetic.eval(dice_count_expression, round_type: RoundType::FLOOR)
54
- border = Arithmetic.eval(border_expression, round_type: RoundType::FLOOR).clamp(1, 6) if border_expression
53
+ dice_count = Arithmetic.eval(dice_count_expression, RoundType::FLOOR)
54
+ border = Arithmetic.eval(border_expression, RoundType::FLOOR).clamp(1, 6) if border_expression
55
55
 
56
56
  command = make_command_text(dice_count, border, additional_damage_rules)
57
57
 
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class Shiranui < Base
6
+ # ゲームシステムの識別子
7
+ ID = 'Shiranui'
8
+
9
+ # ゲームシステム名
10
+ NAME = '不知火'
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = 'しらぬい'
14
+
15
+ # ダイスボットの使い方
16
+ HELP_MESSAGE = <<~HELP
17
+ ■∞D66ダイスロール
18
+ 「 ∞D66 」または「 ID66 」
19
+ ( ID は Infinite D の略です)
20
+
21
+ □行動力や攻撃力の指定
22
+ 「 x+∞D66 」または「 x+ID66 」
23
+ ( x は行動力や攻撃力)
24
+
25
+ □鬼火の使用について
26
+ 鬼火を使用する∞D66は、ダイスボットでサポートしていません。
27
+
28
+ ■おみくじを引く
29
+ OMKJ
30
+ HELP
31
+
32
+ INFINITE_D66_ROLL_REG = /^((\d+)\+)?(∞|I)D66$/i.freeze
33
+ register_prefix('(\d+\+)?(∞|I)D66')
34
+
35
+ def initialize(command)
36
+ super(command)
37
+
38
+ @sort_barabara_dice = true
39
+ end
40
+
41
+ def eval_game_system_specific_command(command)
42
+ if (m = INFINITE_D66_ROLL_REG.match(command))
43
+ fixed_score = m[1]&.to_i
44
+ roll_infinite_d66(fixed_score)
45
+ else
46
+ roll_tables(command, TABLES)
47
+ end
48
+ end
49
+
50
+ def roll_infinite_d66(fixed_score)
51
+ steps = []
52
+
53
+ while steps.empty? || steps.last.to_continue_diceroll?
54
+ # 個別の出目をあつかうので、 roll_d66 ではなく roll_barabara を使う
55
+ dices = @randomizer.roll_barabara(2, 6).sort
56
+
57
+ steps << InifiniteD66Step.new(dices)
58
+ end
59
+
60
+ is_failure = steps.first.score.zero? # 「しくじり」か?
61
+ total = is_failure ? 0 : steps.sum(&:score) + fixed_score.to_i
62
+
63
+ result_text = "(#{self.class.make_command_text(fixed_score)})"
64
+ result_text += " > " + steps.map(&:to_s).join(' > ')
65
+ if is_failure
66
+ result_text += " > しくじり"
67
+ else
68
+ result_text += " > " + self.class.score_expression_text(steps, fixed_score) if steps.size > 1 || !fixed_score.nil?
69
+ result_text += " > " + total.to_s
70
+ end
71
+
72
+ Result.new(result_text).tap do |r|
73
+ r.critical = steps.size > 1
74
+ r.failure = is_failure
75
+ r.fumble = is_failure
76
+ end
77
+ end
78
+
79
+ def self.make_command_text(fixed_score)
80
+ fixed_score.nil? ? "∞D66" : "#{fixed_score}+∞D66"
81
+ end
82
+
83
+ def self.score_expression_text(steps, fixed_score)
84
+ text = steps.map(&:score).join('+')
85
+ text = "#{fixed_score}+(#{text})" unless fixed_score.nil?
86
+ text
87
+ end
88
+
89
+ class InifiniteD66Step
90
+ def initialize(dices)
91
+ @dices = dices.dup.freeze
92
+ end
93
+
94
+ def score
95
+ if repdigit?
96
+ # ゾロ目の場合
97
+
98
+ digit = @dices.first
99
+
100
+ if digit == 1
101
+ # 1 のゾロ目なら 0 となる
102
+ 0
103
+ else
104
+ # 1 以外のゾロ目なら、数字の 10 倍となる
105
+ digit * 10
106
+ end
107
+ else
108
+ # ゾロ目でない場合は、 D66 様式で値を算出する
109
+ @dices[0] * 10 + @dices[1]
110
+ end
111
+ end
112
+
113
+ def repdigit?
114
+ @dices[0] == @dices[1]
115
+ end
116
+
117
+ # ダイスロールを継続する必要があるか?
118
+ def to_continue_diceroll?
119
+ repdigit? && @dices[0] != 1
120
+ end
121
+
122
+ def to_s
123
+ "[#{@dices[0]},#{@dices[1]}]"
124
+ end
125
+ end
126
+
127
+ TABLES = {
128
+ "OMKJ" => DiceTable::Table.new(
129
+ "おみくじ",
130
+ "1D6",
131
+ [
132
+ "大凶[御利益1]――このみくじにあたる人は、凶運から逃れることができぬ者なり。まさに凶運にその身をゆだねてこそ、浮かぶ瀬もあれ。……これより上演中に演者が振る[∞D66]で初めて⚀⚀が出たら、御利益を使っても振り直しができない。",
133
+ "凶[御利益2]――このみくじにあたる人は、吉兆を逃す定めにある。まさに、天の与うるを取らざれば反ってその咎めを受く。……これより上演中に演者が振る[∞D66]で初めて⚅⚅が出たら、強制的に1回の振り直しをする。",
134
+ "小吉[御利益3]――このみくじにあたる人は、神使の機嫌を損ねている。神使が何に怒り、何に苛立っているのかは、まさに神のみぞ知る。……神使の機嫌が突然、悪くなる。これより上演中に神使は何かと理由をつけてはシラヌイの前から立ち去ろうとする。",
135
+ "中吉[御利益4]――このみくじにあたる人は、神使の機嫌を良くすることを行った者なり。神使が何に喜び、なぜ機嫌が良いのか、まさに神のみぞ知る。……神使の機嫌がすこぶる良くなる。これより上演中に神使は上機嫌となり、シラヌイに何かにつけて話しかけてくれる。",
136
+ "吉[御利益5]――このみくじにあたる人は、悪運を幸運へと変える道を進む者なり。まさに禍福は糾える縄の如し。……これより上演中に演者が振る[∞D66]で初めて⚀⚀が出たら、御利益を消費することなく、1回の振り直しをする。",
137
+ "大吉[御利益6]――このみくじにあたる人は、思いもよらぬ幸運に巡り合う者なり。まさに、暗き道より出て、気づけば月の光あり。……これより上演中に演者が振る[∞D66]で1回だけ、サイコロの出目を⚅⚅に変えてよい。",
138
+ ]
139
+ ),
140
+ }.freeze
141
+
142
+ register_prefix(TABLES.keys)
143
+ end
144
+ end
145
+ end