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

Sign up to get free protection for your applications and to get access to all the features.
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)