bcdice 3.0.0.pre.alpha.2 → 3.0.0.pre.rc.1

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 (151) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/README.md +1 -0
  4. data/i18n/KillDeathBusiness/ja_jp.yml +4 -4
  5. data/i18n/KillDeathBusiness/ko_kr.yml +5 -4
  6. data/i18n/MagicaLogia/ko_kr.yml +564 -0
  7. data/i18n/MonotoneMuseum/ja_jp.yml +37 -1
  8. data/i18n/StratoShout/ja_jp.yml +4 -4
  9. data/i18n/StratoShout/ko_kr.yml +4 -4
  10. data/lib/bcdice.rb +2 -1
  11. data/lib/bcdice/arithmetic.rb +22 -0
  12. data/lib/bcdice/arithmetic/node.rb +112 -43
  13. data/lib/bcdice/arithmetic/parser.rb +240 -0
  14. data/lib/bcdice/arithmetic_evaluator.rb +5 -156
  15. data/lib/bcdice/base.rb +8 -1
  16. data/lib/bcdice/command/lexer.rb +57 -0
  17. data/lib/bcdice/command/parsed.rb +65 -0
  18. data/lib/bcdice/command/parser.rb +489 -0
  19. data/lib/bcdice/common_command/add_dice.rb +1 -1
  20. data/lib/bcdice/common_command/add_dice/node.rb +142 -69
  21. data/lib/bcdice/common_command/add_dice/parser.rb +100 -83
  22. data/lib/bcdice/common_command/barabara_dice/node.rb +7 -1
  23. data/lib/bcdice/common_command/barabara_dice/result.rb +22 -0
  24. data/lib/bcdice/common_command/calc/node.rb +10 -1
  25. data/lib/bcdice/common_command/calc/parser.rb +1 -1
  26. data/lib/bcdice/common_command/d66_dice.rb +3 -1
  27. data/lib/bcdice/common_command/lexer.rb +2 -1
  28. data/lib/bcdice/common_command/upper_dice/parser.rb +118 -97
  29. data/lib/bcdice/common_command/version.rb +1 -1
  30. data/lib/bcdice/deprecated/checker.rb +6 -6
  31. data/lib/bcdice/dice_table.rb +1 -0
  32. data/lib/bcdice/dice_table/d66_parity_table.rb +34 -0
  33. data/lib/bcdice/game_system.rb +3 -0
  34. data/lib/bcdice/game_system/AceKillerGene.rb +1 -1
  35. data/lib/bcdice/game_system/AlchemiaStruggle.rb +312 -0
  36. data/lib/bcdice/game_system/Alshard.rb +0 -1
  37. data/lib/bcdice/game_system/Amadeus.rb +1 -1
  38. data/lib/bcdice/game_system/AnimaAnimus.rb +1 -5
  39. data/lib/bcdice/game_system/BadLife.rb +1 -1
  40. data/lib/bcdice/game_system/BeastBindTrinity.rb +1 -10
  41. data/lib/bcdice/game_system/BeginningIdol.rb +4 -4
  42. data/lib/bcdice/game_system/BeginningIdol_Korean.rb +4 -4
  43. data/lib/bcdice/game_system/BladeOfArcana.rb +4 -4
  44. data/lib/bcdice/game_system/BlindMythos.rb +12 -9
  45. data/lib/bcdice/game_system/BloodCrusade.rb +12 -38
  46. data/lib/bcdice/game_system/BloodMoon.rb +2 -2
  47. data/lib/bcdice/game_system/CardRanker.rb +23 -63
  48. data/lib/bcdice/game_system/ChaosFlare.rb +3 -3
  49. data/lib/bcdice/game_system/CodeLayerd.rb +1 -1
  50. data/lib/bcdice/game_system/ColossalHunter.rb +2 -2
  51. data/lib/bcdice/game_system/Cthulhu7th.rb +2 -2
  52. data/lib/bcdice/game_system/CthulhuTech.rb +0 -1
  53. data/lib/bcdice/game_system/DarkBlaze.rb +4 -4
  54. data/lib/bcdice/game_system/DeadlineHeroes.rb +1 -1
  55. data/lib/bcdice/game_system/DoubleCross.rb +60 -93
  56. data/lib/bcdice/game_system/EmbryoMachine.rb +5 -5
  57. data/lib/bcdice/game_system/EtrianOdysseySRS.rb +0 -1
  58. data/lib/bcdice/game_system/FilledWith.rb +3 -3
  59. data/lib/bcdice/game_system/FullMetalPanic.rb +0 -1
  60. data/lib/bcdice/game_system/GURPS.rb +1 -1
  61. data/lib/bcdice/game_system/Garako.rb +3 -2
  62. data/lib/bcdice/game_system/GardenOrder.rb +1 -1
  63. data/lib/bcdice/game_system/GehennaAn.rb +3 -3
  64. data/lib/bcdice/game_system/Gundog.rb +1 -1
  65. data/lib/bcdice/game_system/GundogRevised.rb +3 -3
  66. data/lib/bcdice/game_system/GundogZero.rb +2 -2
  67. data/lib/bcdice/game_system/GurpsFW.rb +2 -5
  68. data/lib/bcdice/game_system/HatsuneMiku.rb +1 -1
  69. data/lib/bcdice/game_system/HuntersMoon.rb +17 -110
  70. data/lib/bcdice/game_system/JuinKansen.rb +251 -0
  71. data/lib/bcdice/game_system/KanColle.rb +17 -166
  72. data/lib/bcdice/game_system/KillDeathBusiness.rb +35 -44
  73. data/lib/bcdice/game_system/KillDeathBusiness_Korean.rb +2 -1
  74. data/lib/bcdice/game_system/LogHorizon.rb +8 -8
  75. data/lib/bcdice/game_system/LostRoyal.rb +1 -3
  76. data/lib/bcdice/game_system/MagicaLogia.rb +3 -3
  77. data/lib/bcdice/game_system/MagicaLogia_Korean.rb +66 -0
  78. data/lib/bcdice/game_system/MeikyuDays.rb +1 -1
  79. data/lib/bcdice/game_system/MeikyuKingdom.rb +1 -1
  80. data/lib/bcdice/game_system/MeikyuKingdomBasic.rb +1 -1
  81. data/lib/bcdice/game_system/MetalHeadExtream.rb +4 -4
  82. data/lib/bcdice/game_system/MetallicGuardian.rb +0 -1
  83. data/lib/bcdice/game_system/MonotoneMuseum.rb +3 -2
  84. data/lib/bcdice/game_system/MonotoneMuseum_Korean.rb +1 -1
  85. data/lib/bcdice/game_system/NSSQ.rb +2 -2
  86. data/lib/bcdice/game_system/Nechronica.rb +3 -3
  87. data/lib/bcdice/game_system/NightWizard.rb +1 -1
  88. data/lib/bcdice/game_system/NightmareHunterDeep.rb +3 -4
  89. data/lib/bcdice/game_system/NinjaSlayer.rb +26 -28
  90. data/lib/bcdice/game_system/OracleEngine.rb +13 -17
  91. data/lib/bcdice/game_system/Paradiso.rb +2 -2
  92. data/lib/bcdice/game_system/PhantasmAdventure.rb +0 -4
  93. data/lib/bcdice/game_system/Raisondetre.rb +1 -1
  94. data/lib/bcdice/game_system/RecordOfLodossWar.rb +2 -3
  95. data/lib/bcdice/game_system/RokumonSekai2.rb +2 -2
  96. data/lib/bcdice/game_system/RuinBreakers.rb +1 -1
  97. data/lib/bcdice/game_system/Ryutama.rb +1 -1
  98. data/lib/bcdice/game_system/SRS.rb +0 -5
  99. data/lib/bcdice/game_system/SamsaraBallad.rb +4 -3
  100. data/lib/bcdice/game_system/Satasupe.rb +22 -14
  101. data/lib/bcdice/game_system/ScreamHighSchool.rb +2 -2
  102. data/lib/bcdice/game_system/ShinkuuGakuen.rb +1 -1
  103. data/lib/bcdice/game_system/ShinobiGami.rb +75 -39
  104. data/lib/bcdice/game_system/StellarKnights.rb +1 -3
  105. data/lib/bcdice/game_system/SterileLife.rb +1 -1
  106. data/lib/bcdice/game_system/StrangerOfSwordCity.rb +1 -1
  107. data/lib/bcdice/game_system/StratoShout.rb +10 -36
  108. data/lib/bcdice/game_system/StratoShout_Korean.rb +2 -1
  109. data/lib/bcdice/game_system/SwordWorld.rb +5 -5
  110. data/lib/bcdice/game_system/SwordWorld2_5.rb +1 -1
  111. data/lib/bcdice/game_system/TherapieSein.rb +2 -2
  112. data/lib/bcdice/game_system/TokumeiTenkousei.rb +2 -2
  113. data/lib/bcdice/game_system/Torg.rb +1 -1
  114. data/lib/bcdice/game_system/TorgEternity.rb +4 -7
  115. data/lib/bcdice/game_system/TrinitySeven.rb +2 -2
  116. data/lib/bcdice/game_system/TunnelsAndTrolls.rb +6 -6
  117. data/lib/bcdice/game_system/TwilightGunsmoke.rb +1 -1
  118. data/lib/bcdice/game_system/Utakaze.rb +1 -1
  119. data/lib/bcdice/game_system/Warhammer.rb +6 -6
  120. data/lib/bcdice/game_system/Warhammer4.rb +9 -12
  121. data/lib/bcdice/game_system/ZettaiReido.rb +1 -1
  122. data/lib/bcdice/normalize.rb +1 -1
  123. data/lib/bcdice/preprocessor.rb +12 -8
  124. data/lib/bcdice/randomizer.rb +12 -0
  125. data/lib/bcdice/repl.rb +1 -1
  126. data/lib/bcdice/result.rb +2 -0
  127. data/lib/bcdice/user_defined_dice_table.rb +26 -15
  128. data/lib/bcdice/version.rb +1 -1
  129. metadata +14 -25
  130. data/.editorconfig +0 -21
  131. data/.github/.codecov.yaml +0 -10
  132. data/.github/workflows/coverage.yaml +0 -21
  133. data/.github/workflows/lint.yaml +0 -13
  134. data/.github/workflows/test.yml +0 -20
  135. data/.gitignore +0 -14
  136. data/.rubocop.yml +0 -108
  137. data/.rubocop_todo.yml +0 -114
  138. data/Gemfile +0 -14
  139. data/ROADMAP.md +0 -30
  140. data/Rakefile +0 -152
  141. data/bcdice.gemspec +0 -29
  142. data/bin/repl.rb +0 -21
  143. data/docs/README.txt +0 -2028
  144. data/docs/dicebot_sort_key.md +0 -72
  145. data/docs/how_to_make_dicebot.md +0 -453
  146. data/lib/bcdice/command_parser.rb +0 -242
  147. data/lib/bcdice/common_command/add_dice/parser.y +0 -153
  148. data/lib/bcdice/common_command/barabara_dice/parser.y +0 -107
  149. data/lib/bcdice/common_command/calc/parser.y +0 -79
  150. data/lib/bcdice/common_command/reroll_dice/parser.y +0 -158
  151. data/lib/bcdice/common_command/upper_dice/parser.y +0 -143
@@ -154,8 +154,8 @@ module BCDice
154
154
  return "1D100 > #{dice}"
155
155
  end
156
156
 
157
- unless BONUS_DICE_RANGE.include?(bonus_dice)
158
- return "エラー。ボーナス・ペナルティダイスの値は#{BONUS_DICE_RANGE.min}~#{BONUS_DICE_RANGE.max}です。"
157
+ if bonus_dice.abs > 100
158
+ return "ボーナス・ペナルティダイスの値は-100以上、100以下としてください"
159
159
  end
160
160
 
161
161
  total, total_list = roll_with_bonus(bonus_dice)
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'bcdice/arithmetic_evaluator'
4
4
 
5
- # クトゥルフテックのダイスボット
6
5
  module BCDice
7
6
  module GameSystem
8
7
  class CthulhuTech < Base
@@ -35,9 +35,9 @@ module BCDice
35
35
  return string unless string =~ /DB/i
36
36
 
37
37
  string = string.gsub(/DB(\d),(\d)/) { "DB#{Regexp.last_match(1)}#{Regexp.last_match(2)}" }
38
- string = string.gsub(/DB\@(\d)\@(\d)/) { "DB#{Regexp.last_match(1)}#{Regexp.last_match(2)}" }
39
- string = string.gsub(/DB(\d)(\d)(#([\d][\+\-\d]*))/) { "3R6+#{Regexp.last_match(4)}[#{Regexp.last_match(1)},#{Regexp.last_match(2)}]" }
40
- string = string.gsub(/DB(\d)(\d)(#([\+\-\d]*))/) { "3R6#{Regexp.last_match(4)}[#{Regexp.last_match(1)},#{Regexp.last_match(2)}]" }
38
+ string = string.gsub(/DB@(\d)@(\d)/) { "DB#{Regexp.last_match(1)}#{Regexp.last_match(2)}" }
39
+ string = string.gsub(/DB(\d)(\d)(#(\d[+\-\d]*))/) { "3R6+#{Regexp.last_match(4)}[#{Regexp.last_match(1)},#{Regexp.last_match(2)}]" }
40
+ string = string.gsub(/DB(\d)(\d)(#([+\-\d]*))/) { "3R6#{Regexp.last_match(4)}[#{Regexp.last_match(1)},#{Regexp.last_match(2)}]" }
41
41
  string = string.gsub(/DB(\d)(\d)/) { "3R6[#{Regexp.last_match(1)},#{Regexp.last_match(2)}]" }
42
42
 
43
43
  return string
@@ -56,7 +56,7 @@ module BCDice
56
56
 
57
57
  def check_roll(string)
58
58
  string = replace_text(string)
59
- return nil unless (m = /(^|\s)S?(3[rR]6([\+\-\d]+)?(\[(\d+),(\d+)\])(([>=]+)(\d+))?)(\s|$)/i.match(string))
59
+ return nil unless (m = /(^|\s)S?(3[rR]6([+\-\d]+)?(\[(\d+),(\d+)\])(([>=]+)(\d+))?)(\s|$)/i.match(string))
60
60
 
61
61
  string = m[2]
62
62
  mod = 0
@@ -55,7 +55,7 @@ module BCDice
55
55
  private
56
56
 
57
57
  def resolute_action(command)
58
- m = /^DLH(\d+([\+\-]\d+)*)$/.match(command)
58
+ m = /^DLH(\d+([+\-]\d+)*)$/.match(command)
59
59
  unless m
60
60
  return nil
61
61
  end
@@ -55,14 +55,14 @@ module BCDice
55
55
 
56
56
  # 成功判定を行う
57
57
  # @param randomizer [Randomizer]
58
- # @return [String] 判定結果
58
+ # @return [Result] 判定結果
59
59
  def execute(randomizer)
60
60
  if @critical_value < 2
61
- return "(#{@expression}) > #{translate('DoubleCross.DX.invalid_critical')}"
61
+ return Result.new("(#{@expression}) > #{translate('DoubleCross.DX.invalid_critical')}")
62
62
  end
63
63
 
64
64
  if @num < 1
65
- return "(#{@expression}) > #{translate('DoubleCross.DX.auto_failure')}"
65
+ return Result.failure("(#{@expression}) > #{translate('DoubleCross.DX.auto_failure')}")
66
66
  end
67
67
 
68
68
  # 出目のグループの配列
@@ -85,7 +85,7 @@ module BCDice
85
85
  loop_count += 1
86
86
  end
87
87
 
88
- return result_str(value_groups)
88
+ return result(value_groups)
89
89
  end
90
90
 
91
91
  private
@@ -98,46 +98,51 @@ module BCDice
98
98
  return @target_value ? "#{lhs}>=#{@target_value}" : lhs
99
99
  end
100
100
 
101
- # 判定結果の文字列を返す
101
+ # 判定結果を返す
102
102
  # @param [Array<ValueGroup>] value_groups 出目のグループの配列
103
- # @return [String]
104
- def result_str(value_groups)
105
- fumble = value_groups[0].values.all? { |value| value == 1 }
103
+ # @return [Result]
104
+ def result(value_groups)
105
+ r = Result.new
106
+
107
+ r.fumble = value_groups[0].values.all?(1)
108
+
106
109
  sum = value_groups.map(&:max).sum
107
- achieved_value = fumble ? 0 : (sum + @modifier)
110
+ achieved_value = r.fumble? ? 0 : (sum + @modifier)
111
+
112
+ # ファンブルかどうかを含む達成値の表記
113
+ achieved_value_with_if_fumble =
114
+ if r.fumble?
115
+ "#{achieved_value} (#{translate('fumble')})"
116
+ else
117
+ achieved_value.to_s
118
+ end
108
119
 
109
120
  parts = [
110
121
  "(#{@expression})",
111
122
  "#{value_groups.join('+')}#{@modifier_str}",
112
- achieved_value_with_if_fumble(achieved_value, fumble),
113
- compare_result(achieved_value, fumble)
123
+ achieved_value_with_if_fumble
114
124
  ]
115
125
 
116
- return parts.compact.join(' > ')
117
- end
118
-
119
- # ファンブルかどうかを含む達成値の表記を返す
120
- # @param [Integer] achieved_value 達成値
121
- # @param [Boolean] fumble ファンブルしたか
122
- # @return [String]
123
- def achieved_value_with_if_fumble(achieved_value, fumble)
124
- fumble ? "#{achieved_value} (#{translate('fumble')})" : achieved_value.to_s
125
- end
126
-
127
- # 達成値と目標値を比較した結果を返す
128
- # @param [Integer] achieved_value 達成値
129
- # @param [Boolean] fumble ファンブルしたか
130
- # @return [String, nil]
131
- def compare_result(achieved_value, fumble)
132
- return nil unless @target_value
126
+ if @target_value
127
+ # 行為判定成功か?
128
+ #
129
+ # ファンブル時は自動失敗、達成値が目標値以上ならば行為判定成功
130
+ # [3rd ルールブック1 pp. 186-187]
131
+ success = !r.fumble? && (achieved_value >= @target_value)
132
+
133
+ if success
134
+ r.success = true
135
+ else
136
+ r.failure = true
137
+ end
138
+
139
+ compare_result_text = translate(success ? 'success' : 'failure')
140
+ parts.push(compare_result_text)
141
+ end
133
142
 
134
- # ファンブル時は自動失敗
135
- # [3rd ルールブック1 pp. 186-187]
136
- return translate("failure") if fumble
143
+ r.text = parts.join(' > ')
137
144
 
138
- # 達成値が目標値以上ならば行為判定成功
139
- # [3rd ルールブック1 p. 187]
140
- return achieved_value >= @target_value ? translate("success") : translate("failure")
145
+ return r
141
146
  end
142
147
  end
143
148
 
@@ -192,22 +197,6 @@ module BCDice
192
197
  end
193
198
  end
194
199
 
195
- def check_nD10(total, _dice_total, dice_list, cmp_op, target)
196
- return '' if target == '?'
197
- return '' unless cmp_op == :>=
198
-
199
- result =
200
- if dice_list.count(1) == dice_list.size
201
- translate("fumble")
202
- elsif total >= target
203
- translate("success")
204
- else
205
- translate("failure")
206
- end
207
-
208
- return " > #{result}"
209
- end
210
-
211
200
  # ダイスボット固有コマンドの処理を行う
212
201
  # @param [String] command コマンド
213
202
  # @return [String] ダイスボット固有コマンドの結果
@@ -226,71 +215,49 @@ module BCDice
226
215
 
227
216
  private
228
217
 
229
- # OD Tool式の成功判定コマンドの正規表現
230
- #
231
- # キャプチャ内容は以下のとおり:
232
- #
233
- # 1. ダイス数
234
- # 2. 修正値
235
- # 3. クリティカル値
236
- # 4. 達成値
237
- DX_OD_TOOL_RE = /\A(\d+)DX([-+]\d+(?:[-+*]\d+)*)?@(\d+)(?:>=(\d+))?\z/io.freeze
238
-
239
- # 疾風怒濤式の成功判定コマンドの正規表現
240
- #
241
- # キャプチャ内容は以下のとおり:
242
- #
243
- # 1. ダイス数
244
- # 2. クリティカル値
245
- # 3. 修正値
246
- # 4. 達成値
247
- DX_SHIPPU_DOTO_RE = /\A(\d+)DX(\d+)?([-+]\d+(?:[-+*]\d+)*)?(?:>=(\d+))?\z/io.freeze
248
-
249
218
  # 成功判定コマンドの構文解析を行う
250
219
  # @param [String] command コマンド文字列
251
220
  # @return [DX, nil]
252
221
  def parse_dx(command)
253
- case command
254
- when DX_OD_TOOL_RE
255
- return parse_dx_od(Regexp.last_match)
256
- when DX_SHIPPU_DOTO_RE
257
- return parse_dx_shippu_doto(Regexp.last_match)
258
- end
259
-
260
- return nil
222
+ parse_dx_od(command) || parse_dx_shippu_doto(command)
261
223
  end
262
224
 
263
225
  # OD Tool式の成功判定コマンドの正規表現マッチ情報からノードを作る
264
- # @param [MatchData] m 正規表現のマッチ情報
226
+ # @param command [String]
265
227
  # @return [DX]
266
- def parse_dx_od(m)
267
- num = m[1].to_i
268
- modifier = m[2] ? ArithmeticEvaluator.eval(m[2]) : 0
269
- critical_value = m[3] ? m[3].to_i : 10
228
+ def parse_dx_od(command)
229
+ parser = Command::Parser.new(/\d+DX/, round_type: round_type)
230
+ .enable_critical
231
+ .restrict_cmp_op_to(nil, :>=)
232
+ parsed = parser.parse(command)
233
+ return nil unless parsed
270
234
 
271
- target_value = m[4]&.to_i
235
+ num = parsed.command.to_i
236
+ critical_value = parsed.critical || 10
272
237
 
273
- return self.class::DX.new(num, critical_value, modifier, target_value)
238
+ self.class::DX.new(num, critical_value, parsed.modify_number, parsed.target_number)
274
239
  end
275
240
 
276
241
  # 疾風怒濤式の成功判定コマンドの正規表現マッチ情報からノードを作る
277
242
  # @param [MatchData] m 正規表現のマッチ情報
278
243
  # @return [DX]
279
- def parse_dx_shippu_doto(m)
280
- num = m[1].to_i
281
- critical_value = m[2] ? m[2].to_i : 10
282
- modifier = m[3] ? ArithmeticEvaluator.eval(m[3]) : 0
244
+ def parse_dx_shippu_doto(command)
245
+ parser = Command::Parser.new(/\d+DX\d*/, round_type: round_type)
246
+ .restrict_cmp_op_to(nil, :>=)
247
+ parsed = parser.parse(command)
248
+ return nil unless parsed
283
249
 
284
- target_value = m[4]&.to_i
250
+ num, critical_value = parsed.command.split("DX", 2).map { |x| x&.to_i }
251
+ critical_value ||= 10
285
252
 
286
- return self.class::DX.new(num, critical_value, modifier, target_value)
253
+ self.class::DX.new(num, critical_value, parsed.modify_number, parsed.target_number)
287
254
  end
288
255
 
289
256
  # 感情表を振る
290
257
  #
291
258
  # ポジティブとネガティブの両方を振って、表になっている側に○を付ける。
292
259
  #
293
- # @return [String]
260
+ # @return [Result]
294
261
  def roll_emotion_table
295
262
  pos_result = self.class::POSITIVE_EMOTION_TABLE.roll(@randomizer)
296
263
  neg_result = self.class::NEGATIVE_EMOTION_TABLE.roll(@randomizer)
@@ -309,7 +276,7 @@ module BCDice
309
276
  pos_neg_text.join(' - ')
310
277
  ]
311
278
 
312
- return output_parts.join(' > ')
279
+ return Result.new(output_parts.join(' > '))
313
280
  end
314
281
 
315
282
  class << self
@@ -34,10 +34,10 @@ module BCDice
34
34
 
35
35
  def replace_text(string)
36
36
  string
37
- .gsub(/EM(\d+)([\+\-][\+\-\d]+)(@(\d+))(\#(\d+))/i) { "2R10#{Regexp.last_match(2)}>=#{Regexp.last_match(1)}[#{Regexp.last_match(4)},#{Regexp.last_match(6)}]" }
38
- .gsub(/EM(\d+)([\+\-][\+\-\d]+)(\#(\d+))/i) { "2R10#{Regexp.last_match(2)}>=#{Regexp.last_match(1)}[20,#{Regexp.last_match(4)}]" }
39
- .gsub(/EM(\d+)([\+\-][\+\-\d]+)(@(\d+))/i) { "2R10#{Regexp.last_match(2)}>=#{Regexp.last_match(1)}[#{Regexp.last_match(4)},2]" }
40
- .gsub(/EM(\d+)([\+\-][\+\-\d]+)/i) { "2R10#{Regexp.last_match(2)}>=#{Regexp.last_match(1)}[20,2]" }
37
+ .gsub(/EM(\d+)([+\-][+\-\d]+)(@(\d+))(\#(\d+))/i) { "2R10#{Regexp.last_match(2)}>=#{Regexp.last_match(1)}[#{Regexp.last_match(4)},#{Regexp.last_match(6)}]" }
38
+ .gsub(/EM(\d+)([+\-][+\-\d]+)(\#(\d+))/i) { "2R10#{Regexp.last_match(2)}>=#{Regexp.last_match(1)}[20,#{Regexp.last_match(4)}]" }
39
+ .gsub(/EM(\d+)([+\-][+\-\d]+)(@(\d+))/i) { "2R10#{Regexp.last_match(2)}>=#{Regexp.last_match(1)}[#{Regexp.last_match(4)},2]" }
40
+ .gsub(/EM(\d+)([+\-][+\-\d]+)/i) { "2R10#{Regexp.last_match(2)}>=#{Regexp.last_match(1)}[20,2]" }
41
41
  .gsub(/EM(\d+)(@(\d+))(\#(\d+))/i) { "2R10>=#{Regexp.last_match(1)}[#{Regexp.last_match(3)},#{Regexp.last_match(5)}]" }
42
42
  .gsub(/EM(\d+)(\#(\d+))/i) { "2R10>=#{Regexp.last_match(1)}[20,#{Regexp.last_match(3)}]" }
43
43
  .gsub(/EM(\d+)(@(\d+))/i) { "2R10>=#{Regexp.last_match(1)}[#{Regexp.last_match(3)},2]" }
@@ -63,7 +63,7 @@ module BCDice
63
63
  def checkRoll(string)
64
64
  string = replace_text(string)
65
65
 
66
- return nil unless /(^|\s)S?(2[rR]10([\+\-\d]+)?([>=]+(\d+))(\[(\d+),(\d+)\]))(\s|$)/i =~ string
66
+ return nil unless /(^|\s)S?(2[rR]10([+\-\d]+)?([>=]+(\d+))(\[(\d+),(\d+)\]))(\s|$)/i =~ string
67
67
 
68
68
  string = Regexp.last_match(2)
69
69
  diff = 0
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'bcdice/game_system/SRS'
4
4
 
5
- # 世界樹の迷宮SRSのダイスボット
6
5
  module BCDice
7
6
  module GameSystem
8
7
  class EtrianOdysseySRS < SRS
@@ -140,12 +140,12 @@ module BCDice
140
140
  crt = 4
141
141
  fmb = 17
142
142
 
143
- if command =~ /(\d[\+\-\d]*)-(\d+)FW(\@(\d+))?(\#(\d+))?/i
143
+ if command =~ /(\d[+\-\d]*)-(\d+)FW(@(\d+))?(\#(\d+))?/i
144
144
  difficultyText = Regexp.last_match(1)
145
145
  diceCount = Regexp.last_match(2).to_i
146
146
  crt = Regexp.last_match(4).to_i unless Regexp.last_match(3).nil?
147
147
  fmb = Regexp.last_match(6).to_i unless Regexp.last_match(5).nil?
148
- elsif command =~ /(\d+)FW(\@(\d+))?(\#(\d+))?(<=([\+\-\d]*))?/i
148
+ elsif command =~ /(\d+)FW(@(\d+))?(\#(\d+))?(<=([+\-\d]*))?/i
149
149
  diceCount = Regexp.last_match(1).to_i
150
150
  crt = Regexp.last_match(3).to_i unless Regexp.last_match(2).nil?
151
151
  fmb = Regexp.last_match(5).to_i unless Regexp.last_match(4).nil?
@@ -222,7 +222,7 @@ module BCDice
222
222
 
223
223
  # 夢幻の迷宮財宝表
224
224
  def getTresureResult(command)
225
- return nil unless command =~ /TRS(\d+)([\+\-]\d)?/
225
+ return nil unless command =~ /TRS(\d+)([+\-]\d)?/
226
226
 
227
227
  rank = Regexp.last_match(1).to_i
228
228
  modify = Regexp.last_match(2).to_i
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'bcdice/game_system/SRS'
4
4
 
5
- # フルメタル・パニック!のダイスボット
6
5
  module BCDice
7
6
  module GameSystem
8
7
  class FullMetalPanic < SRS
@@ -78,7 +78,7 @@ module BCDice
78
78
  end
79
79
 
80
80
  def roll_3d6(command)
81
- m = /^([\d\+\-]+)\-3D6?([\d\+\-]*)$/.match(command)
81
+ m = /^([\d+\-]+)-3D6?([\d+\-]*)$/.match(command)
82
82
  return nil unless m
83
83
 
84
84
  target_number = ArithmeticEvaluator.eval(m[1])
@@ -53,10 +53,11 @@ module BCDice
53
53
  # @param command [String]
54
54
  # @return [String, nil]
55
55
  def roll_gr(command)
56
- parser = CommandParser.new("GR")
56
+ parser = Command::Parser.new("GR", round_type: round_type)
57
+ .enable_fumble
58
+ .restrict_cmp_op_to(:>=)
57
59
  cmd = parser.parse(command)
58
60
  return nil unless cmd
59
- return nil if cmd.critical
60
61
 
61
62
  modify_number = cmd.modify_number || 0
62
63
  auto_failure_number = cmd.fumble || 1
@@ -32,7 +32,7 @@ module BCDice
32
32
 
33
33
  def eval_game_system_specific_command(command)
34
34
  case command
35
- when %r{GO(\-?\d+)(/(\d+))?(@(\d+))?}i
35
+ when %r{GO(-?\d+)(/(\d+))?(@(\d+))?}i
36
36
  success_rate = Regexp.last_match(1).to_i
37
37
  repeat_count = (Regexp.last_match(3) || 1).to_i
38
38
  critical_border_text = Regexp.last_match(5)
@@ -35,9 +35,9 @@ module BCDice
35
35
 
36
36
  def replace_text(string)
37
37
  string
38
- .gsub(/(\d+)GA(\d+)([\+\-][\+\-\d]+)/) { "#{Regexp.last_match(1)}R6#{Regexp.last_match(3)}>=#{Regexp.last_match(2)}[1]" }
38
+ .gsub(/(\d+)GA(\d+)([+\-][+\-\d]+)/) { "#{Regexp.last_match(1)}R6#{Regexp.last_match(3)}>=#{Regexp.last_match(2)}[1]" }
39
39
  .gsub(/(\d+)GA(\d+)/) { "#{Regexp.last_match(1)}R6>=#{Regexp.last_match(2)}[1]" }
40
- .gsub(/(\d+)G(\d+)([\+\-][\+\-\d]+)/) { "#{Regexp.last_match(1)}R6#{Regexp.last_match(3)}>=#{Regexp.last_match(2)}[0]" }
40
+ .gsub(/(\d+)G(\d+)([+\-][+\-\d]+)/) { "#{Regexp.last_match(1)}R6#{Regexp.last_match(3)}>=#{Regexp.last_match(2)}[0]" }
41
41
  .gsub(/(\d+)G(\d+)/) { "#{Regexp.last_match(1)}R6>=#{Regexp.last_match(2)}[0]" }
42
42
  end
43
43
 
@@ -46,7 +46,7 @@ module BCDice
46
46
  def eval_game_system_specific_command(string)
47
47
  string = replace_text(string)
48
48
 
49
- unless /(^|\s)S?((\d+)[rR]6([\+\-\d]+)?([>=]+(\d+))(\[(\d)\]))(\s|$)/i =~ string
49
+ unless /(^|\s)S?((\d+)[rR]6([+\-\d]+)?([>=]+(\d+))(\[(\d)\]))(\s|$)/i =~ string
50
50
  return nil
51
51
  end
52
52
 
@@ -41,7 +41,7 @@ module BCDice
41
41
  if dig1 <= 0
42
42
  " > クリティカル(達成値20+SL)"
43
43
  else
44
- " > 成功(達成値#{(dig10 + dig1)}+SL)"
44
+ " > 成功(達成値#{dig10 + dig1}+SL)"
45
45
  end
46
46
  else
47
47
  " > 失敗"
@@ -52,7 +52,7 @@ module BCDice
52
52
  if dig1 <= 0
53
53
  " > クリティカル(達成値20+SL)"
54
54
  else
55
- " > 成功(達成値#{(dig10 + dig1)}+SL)"
55
+ " > 成功(達成値#{dig10 + dig1}+SL)"
56
56
  end
57
57
  else
58
58
  " > 失敗"
@@ -68,7 +68,7 @@ module BCDice
68
68
  mod = 0
69
69
 
70
70
  # ダメージペナルティ表
71
- if /(\w)DPT([\+\-\d]*)/i =~ string
71
+ if /(\w)DPT([+\-\d]*)/i =~ string
72
72
  ttype = 'ダメージペナルティー'
73
73
  head = Regexp.last_match(1)
74
74
  mod = ArithmeticEvaluator.eval(Regexp.last_match(2)) if Regexp.last_match(2)
@@ -77,7 +77,7 @@ module BCDice
77
77
  end
78
78
 
79
79
  # ファンブル表
80
- if /(\w)FT([\+\-\d]*)/i =~ string
80
+ if /(\w)FT([+\-\d]*)/i =~ string
81
81
  ttype = 'ファンブル'
82
82
  head = Regexp.last_match(1)
83
83
  mod = ArithmeticEvaluator.eval(Regexp.last_match(2)) if Regexp.last_match(2)
@@ -37,7 +37,7 @@ module BCDice
37
37
  mod = 0
38
38
 
39
39
  # ダメージペナルティ表
40
- if /(\w)DPT([\+\-\d]*)/i =~ string
40
+ if /(\w)DPT([+\-\d]*)/i =~ string
41
41
  ttype = 'ダメージペナルティー'
42
42
  head = Regexp.last_match(1)
43
43
  mod = ArithmeticEvaluator.eval(Regexp.last_match(2)) if Regexp.last_match(2)
@@ -46,7 +46,7 @@ module BCDice
46
46
  end
47
47
 
48
48
  # ファンブル表
49
- if /(\w)FT([\+\-\d]*)/i =~ string
49
+ if /(\w)FT([+\-\d]*)/i =~ string
50
50
  ttype = 'ファンブル'
51
51
  head = Regexp.last_match(1)
52
52
  mod = ArithmeticEvaluator.eval(Regexp.last_match(2)) if Regexp.last_match(2)