bcdice 3.0.0 → 3.1.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 (99) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -1
  3. data/README.md +32 -0
  4. data/i18n/MonotoneMuseum/ja_jp.yml +3 -3
  5. data/lib/bcdice/game_system.rb +1 -0
  6. data/lib/bcdice/game_system/AlchemiaStruggle.rb +1 -1
  7. data/lib/bcdice/game_system/Alshard.rb +1 -1
  8. data/lib/bcdice/game_system/AngelGear.rb +123 -0
  9. data/lib/bcdice/game_system/ArsMagica.rb +1 -1
  10. data/lib/bcdice/game_system/BBN.rb +1 -1
  11. data/lib/bcdice/game_system/BadLife.rb +1 -1
  12. data/lib/bcdice/game_system/BarnaKronika.rb +1 -1
  13. data/lib/bcdice/game_system/BeastBindTrinity.rb +2 -2
  14. data/lib/bcdice/game_system/BlindMythos.rb +1 -1
  15. data/lib/bcdice/game_system/BloodCrusade.rb +42 -42
  16. data/lib/bcdice/game_system/BloodMoon.rb +41 -0
  17. data/lib/bcdice/game_system/CardRanker.rb +2 -2
  18. data/lib/bcdice/game_system/ChaosFlare.rb +1 -1
  19. data/lib/bcdice/game_system/Chill.rb +1 -1
  20. data/lib/bcdice/game_system/CodeLayerd.rb +1 -1
  21. data/lib/bcdice/game_system/Cthulhu.rb +8 -4
  22. data/lib/bcdice/game_system/Cthulhu7th.rb +40 -334
  23. data/lib/bcdice/game_system/Cthulhu7th_ChineseTraditional.rb +1 -1
  24. data/lib/bcdice/game_system/Cthulhu7th_Korean.rb +1 -1
  25. data/lib/bcdice/game_system/CthulhuTech.rb +1 -1
  26. data/lib/bcdice/game_system/DarkBlaze.rb +1 -1
  27. data/lib/bcdice/game_system/DiceOfTheDead.rb +1 -1
  28. data/lib/bcdice/game_system/DoubleCross.rb +1 -1
  29. data/lib/bcdice/game_system/EarthDawn.rb +1 -1
  30. data/lib/bcdice/game_system/EarthDawn3.rb +1 -1
  31. data/lib/bcdice/game_system/EarthDawn4.rb +1 -1
  32. data/lib/bcdice/game_system/Elysion.rb +2 -2
  33. data/lib/bcdice/game_system/EmbryoMachine.rb +1 -1
  34. data/lib/bcdice/game_system/EtrianOdysseySRS.rb +1 -1
  35. data/lib/bcdice/game_system/FullMetalPanic.rb +1 -1
  36. data/lib/bcdice/game_system/Garako.rb +12 -4
  37. data/lib/bcdice/game_system/GehennaAn.rb +1 -1
  38. data/lib/bcdice/game_system/GoblinSlayer.rb +1 -1
  39. data/lib/bcdice/game_system/Gorilla.rb +1 -1
  40. data/lib/bcdice/game_system/HarnMaster.rb +1 -1
  41. data/lib/bcdice/game_system/HatsuneMiku.rb +1 -1
  42. data/lib/bcdice/game_system/HouraiGakuen.rb +1 -1
  43. data/lib/bcdice/game_system/Illusio.rb +25 -34
  44. data/lib/bcdice/game_system/LostRoyal.rb +1 -1
  45. data/lib/bcdice/game_system/MeikyuDays.rb +1 -1
  46. data/lib/bcdice/game_system/MeikyuKingdom.rb +2 -2
  47. data/lib/bcdice/game_system/MeikyuKingdomBasic.rb +2 -2
  48. data/lib/bcdice/game_system/MetalHeadExtream.rb +1 -1
  49. data/lib/bcdice/game_system/MetallicGuardian.rb +1 -1
  50. data/lib/bcdice/game_system/MonotoneMuseum.rb +1 -1
  51. data/lib/bcdice/game_system/NeverCloud.rb +540 -5
  52. data/lib/bcdice/game_system/NightWizard.rb +1 -1
  53. data/lib/bcdice/game_system/NightWizard3rd.rb +1 -1
  54. data/lib/bcdice/game_system/NinjaSlayer.rb +4 -13
  55. data/lib/bcdice/game_system/OneWayHeroics.rb +1 -1
  56. data/lib/bcdice/game_system/OracleEngine.rb +1 -1
  57. data/lib/bcdice/game_system/OrgaRain.rb +17 -25
  58. data/lib/bcdice/game_system/Paradiso.rb +1 -1
  59. data/lib/bcdice/game_system/ParanoiaRebooted.rb +1 -1
  60. data/lib/bcdice/game_system/Postman.rb +1 -1
  61. data/lib/bcdice/game_system/PulpCthulhu.rb +1 -1
  62. data/lib/bcdice/game_system/RecordOfLodossWar.rb +1 -1
  63. data/lib/bcdice/game_system/RecordOfSteam.rb +1 -1
  64. data/lib/bcdice/game_system/RokumonSekai2.rb +1 -1
  65. data/lib/bcdice/game_system/Ryutama.rb +1 -1
  66. data/lib/bcdice/game_system/SRS.rb +1 -1
  67. data/lib/bcdice/game_system/SamsaraBallad.rb +1 -1
  68. data/lib/bcdice/game_system/Satasupe.rb +79 -860
  69. data/lib/bcdice/game_system/SevenFortressMobius.rb +1 -1
  70. data/lib/bcdice/game_system/SharedFantasia.rb +1 -1
  71. data/lib/bcdice/game_system/ShinkuuGakuen.rb +2 -2
  72. data/lib/bcdice/game_system/ShinobiGami.rb +3 -3
  73. data/lib/bcdice/game_system/Skynauts.rb +2 -2
  74. data/lib/bcdice/game_system/SteamPunkers.rb +1 -1
  75. data/lib/bcdice/game_system/StrangerOfSwordCity.rb +1 -1
  76. data/lib/bcdice/game_system/SwordWorld.rb +46 -182
  77. data/lib/bcdice/game_system/SwordWorld2_0.rb +21 -149
  78. data/lib/bcdice/game_system/SwordWorld2_5.rb +126 -40
  79. data/lib/bcdice/game_system/Torg.rb +1 -1
  80. data/lib/bcdice/game_system/TorgEternity.rb +2 -2
  81. data/lib/bcdice/game_system/TunnelsAndTrolls.rb +1 -1
  82. data/lib/bcdice/game_system/TwilightGunsmoke.rb +1 -1
  83. data/lib/bcdice/game_system/UnsungDuet.rb +1 -1
  84. data/lib/bcdice/game_system/Utakaze.rb +1 -1
  85. data/lib/bcdice/game_system/VampireTheMasquerade5th.rb +1 -1
  86. data/lib/bcdice/game_system/Warhammer.rb +1 -1
  87. data/lib/bcdice/game_system/Warhammer4.rb +1 -1
  88. data/lib/bcdice/game_system/WorldOfDarkness.rb +1 -1
  89. data/lib/bcdice/game_system/YearZeroEngine.rb +1 -1
  90. data/lib/bcdice/game_system/ZettaiReido.rb +1 -1
  91. data/lib/bcdice/game_system/cthulhu7th/full_auto.rb +294 -0
  92. data/lib/bcdice/game_system/cthulhu7th/rollable.rb +41 -0
  93. data/lib/bcdice/game_system/satasupe/tables.rb +723 -0
  94. data/lib/bcdice/game_system/sword_world/rating_lexer.rb +47 -0
  95. data/lib/bcdice/game_system/sword_world/rating_parsed.rb +99 -0
  96. data/lib/bcdice/game_system/sword_world/rating_parser.rb +457 -0
  97. data/lib/bcdice/game_system/sword_world/transcendent_test.rb +104 -0
  98. data/lib/bcdice/version.rb +1 -1
  99. metadata +10 -2
@@ -23,7 +23,7 @@ module BCDice
23
23
   例)12SFM-5@7#2  1SFM  50SFM+5@7,10#2,5 50SFM-5+10@7,10#2,5+15+25
24
24
  INFO_MESSAGE_TEXT
25
25
 
26
- register_prefix('([-+]?\d+)?SFM.*', '2R6.*')
26
+ register_prefix('([-+]?\d+)?SFM', '2R6')
27
27
 
28
28
  def initialize(command)
29
29
  super(command)
@@ -21,7 +21,7 @@ module BCDice
21
21
  例) SF+4>=9 : 2D6して4を足した値が9以上なら成功
22
22
  MESSAGETEXT
23
23
 
24
- register_prefix('SF.*', 'ST.*')
24
+ register_prefix('SF', 'ST')
25
25
 
26
26
  def change_text(string)
27
27
  string.gsub(/SF/i, "2D6").gsub(/ST/i, "2D6")
@@ -34,8 +34,8 @@ module BCDice
34
34
  MESSAGETEXT
35
35
 
36
36
  register_prefix(
37
- 'CRL.*', 'CSW.*', 'CLS.*', 'CSS.*', 'CSP.*', 'CAX.*', 'CCL.*', 'CMA.*', 'CBX.*', 'CPR.*', 'CST.*',
38
- 'RL.*', 'SW.*', 'LS.*', 'SS.*', 'SP.*', 'AX.*', 'CL.*', 'BW.*', 'MA.*', 'BX.*', 'PR.*', 'ST.*'
37
+ 'CRL', 'CSW', 'CLS', 'CSS', 'CSP', 'CAX', 'CCL', 'CMA', 'CBX', 'CPR', 'CST',
38
+ 'RL', 'SW', 'LS', 'SS', 'SP', 'AX', 'CL', 'BW', 'MA', 'BX', 'PR', 'ST'
39
39
  )
40
40
 
41
41
  def eval_game_system_specific_command(command)
@@ -109,10 +109,10 @@ module BCDice
109
109
  total = dice_total + cmd.modify_number
110
110
 
111
111
  result =
112
- if dice_total >= cmd.critical
113
- Result.critical(SPECIAL)
114
- elsif dice_total <= cmd.fumble
112
+ if dice_total <= cmd.fumble
115
113
  Result.fumble("ファンブル")
114
+ elsif dice_total >= cmd.critical
115
+ Result.critical(SPECIAL)
116
116
  elsif cmd.cmp_op.nil?
117
117
  Result.new
118
118
  elsif total >= cmd.target_number
@@ -25,14 +25,14 @@ module BCDice
25
25
  ◆砲撃判定+ダメージチェック (BOMn/Dx/y@m) n:目標値(省略時:7)
26
26
   x:ダメージ左側の値、y:ダメージ右側の値
27
27
   m:《弾道学》(省略可)上:8、下:2、左:4、右:6
28
-  例) BOM/D/4 BOM9/D19@4
28
+  例) BOM/D/4 BOM9/D19/2@4
29
29
  ◆《回避運動》 (AVOn@mXX) n:目標値(省略時:7)
30
30
   m:回避方向。上:8、下:2、左:4、右:6、XX:ダメージチェック結果
31
31
   例)
32
32
   AVO9@8[縦1,横4],[縦2,横6],[縦3,横8] AVO@2[縦6,横4],[縦2,横6]
33
33
  MESSAGETEXT
34
34
 
35
- register_prefix('D.*', '2[Dd]6<=.*', 'SN.*', 'NV.*', 'AVO.*', 'BOM.*')
35
+ register_prefix('D', '2D6<=', 'SN', 'NV', 'AVO', 'BOM')
36
36
 
37
37
  def initialize(command)
38
38
  super(command)
@@ -481,7 +481,7 @@ module BCDice
481
481
  )
482
482
  }.freeze
483
483
 
484
- register_prefix('SP.*', TABLES.keys)
484
+ register_prefix('SP', TABLES.keys)
485
485
  end
486
486
  end
487
487
  end
@@ -21,7 +21,7 @@ module BCDice
21
21
  ・D66ダイスあり
22
22
  INFO_MESSAGE_TEXT
23
23
 
24
- register_prefix('\d+SR.*')
24
+ register_prefix('\d+SR')
25
25
 
26
26
  def initialize(command)
27
27
  super(command)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "bcdice/game_system/sword_world/rating_parser"
4
+
3
5
  module BCDice
4
6
  module GameSystem
5
7
  class SwordWorld < Base
@@ -15,35 +17,13 @@ module BCDice
15
17
  # ダイスボットの使い方
16
18
  HELP_MESSAGE = "・SW レーティング表 (Kx[c]+m$f) (x:キー, c:クリティカル値, m:ボーナス, f:出目修正)\n"
17
19
 
18
- register_prefix('H?K\d+.*')
20
+ register_prefix('H?K\d+')
19
21
 
20
22
  def initialize(command)
21
23
  super(command)
22
24
  @rating_table = 0
23
25
  end
24
26
 
25
- # change_textで使うレーティング表コマンドの正規表現
26
- #
27
- # SW 2.5のダイスボットでも必要なため、共通化のために定数として定義する
28
- RATING_TABLE_RE_FOR_CHANGE_TEXT = /\AS?H?K\d+/i.freeze
29
-
30
- # コマンド実行前にメッセージを置換する
31
- # @param [String] string 受信したメッセージ
32
- # @return [String]
33
- def replace_text(string)
34
- return string unless RATING_TABLE_RE_FOR_CHANGE_TEXT.match?(string)
35
-
36
- string
37
- .gsub(/\[(\d+)\]/) { "c[#{Regexp.last_match(1)}]" }
38
- .gsub(/@(\d+)/) { "c[#{Regexp.last_match(1)}]" }
39
- .gsub(/\$([-+]?\d+)/) { "m[#{Regexp.last_match(1)}]" }
40
- .gsub(/r([-+]?\d+)/i) { "r[#{Regexp.last_match(1)}]" }
41
- end
42
-
43
- def getRatingCommandStrings
44
- "cmCM"
45
- end
46
-
47
27
  def result_2d6(total, dice_total, _dice_list, cmp_op, target)
48
28
  if dice_total >= 12
49
29
  Result.critical("自動的成功")
@@ -64,60 +44,32 @@ module BCDice
64
44
 
65
45
  private
66
46
 
47
+ def rating_parser
48
+ return RatingParser.new
49
+ end
50
+
67
51
  #################### SWレーティング表 ########################
68
52
  def rating(string) # レーティング表
69
- string = replace_text(string)
70
53
  debug("rating string", string)
54
+ command = rating_parser.parse(string)
71
55
 
72
- commands = getRatingCommandStrings
73
-
74
- m = /^S?(H?K[\d+\-]+([#{commands}]\[([\d+\-]+)\])*([\d+\-]*)([CMR]\[([\d+\-]+)\]|GF|H)*)/i.match(string)
75
- unless m
56
+ unless command
76
57
  debug("not matched")
77
58
  return '1'
78
59
  end
79
60
 
80
- string = m[1]
81
- half = string.include?("H")
82
-
83
- rateUp, string = getRateUpFromString(string)
84
- crit, string = getCriticalFromString(string, half)
85
- firstDiceChanteTo, firstDiceChangeModify, string = getDiceChangesFromString(string)
86
-
87
- key, addValue = getKeyAndAddValueFromString(string)
88
-
89
- return '1' unless key =~ /(\d+)/
90
-
91
- key = Regexp.last_match(1).to_i
92
-
93
61
  # 2.0対応
94
62
  rate_sw2_0 = getSW2_0_RatingTable
95
63
 
96
64
  keyMax = rate_sw2_0.length - 1
97
65
  debug("keyMax", keyMax)
98
- if key > keyMax
66
+ if command.rate > keyMax
99
67
  return "キーナンバーは#{keyMax}までです"
100
68
  end
101
69
 
102
70
  newRates = getNewRates(rate_sw2_0)
103
71
 
104
- output = "KeyNo.#{key}"
105
-
106
- output += "c[#{crit}]" if crit < 13
107
- output += "m[#{firstDiceChangeModify}]" if firstDiceChangeModify != 0
108
- output += "m[#{firstDiceChanteTo}]" if firstDiceChanteTo != 0
109
- output += "r[#{rateUp}]" if rateUp != 0
110
-
111
- output, values = getAdditionalString(string, output)
112
-
113
- debug('output', output)
114
-
115
- if addValue != 0
116
- output += "+#{addValue}" if addValue > 0
117
- output += addValue.to_s if addValue < 0
118
- end
119
-
120
- output += " > "
72
+ output = "#{command}"
121
73
 
122
74
  diceResultTotals = []
123
75
  diceResults = []
@@ -126,17 +78,19 @@ module BCDice
126
78
  diceOnlyTotal = 0
127
79
  totalValue = 0
128
80
  round = 0
81
+ first_to = command.first_to
82
+ first_modify = command.first_modify
129
83
 
130
84
  loop do
131
- dice_raw, diceText = rollDice(values)
85
+ dice_raw, diceText = rollDice(command)
132
86
  dice = dice_raw
133
87
 
134
- if firstDiceChanteTo != 0
135
- dice = dice_raw = firstDiceChanteTo
136
- firstDiceChanteTo = 0
137
- elsif firstDiceChangeModify != 0
138
- dice += firstDiceChangeModify.to_i
139
- firstDiceChangeModify = 0
88
+ if first_to != 0
89
+ dice = dice_raw = first_to
90
+ first_to = 0
91
+ elsif first_modify != 0
92
+ dice += first_modify
93
+ first_modify = 0
140
94
  end
141
95
 
142
96
  # 出目がピンゾロの時にはそこで終了
@@ -149,12 +103,12 @@ module BCDice
149
103
  break
150
104
  end
151
105
 
152
- dice += getAdditionalDiceValue(dice, values)
106
+ dice += command.kept_modify if (command.kept_modify != 0) && (dice != 2)
153
107
 
154
108
  dice = 2 if dice < 2
155
109
  dice = 12 if dice > 12
156
110
 
157
- currentKey = [key + round * rateUp, keyMax].min
111
+ currentKey = [command.rate + round * command.rateup, keyMax].min
158
112
  debug("currentKey", currentKey)
159
113
  rateValue = newRates[dice][currentKey]
160
114
  debug("rateValue", rateValue)
@@ -168,79 +122,15 @@ module BCDice
168
122
 
169
123
  round += 1
170
124
 
171
- break unless dice >= crit
125
+ break unless dice >= command.critical
172
126
  end
173
127
 
174
- output += getResultText(totalValue, addValue, diceResults, diceResultTotals,
175
- rateResults, diceOnlyTotal, round, half)
128
+ output += getResultText(totalValue, command, diceResults, diceResultTotals,
129
+ rateResults, diceOnlyTotal, round)
176
130
 
177
131
  return output
178
132
  end
179
133
 
180
- def getAdditionalString(_string, output)
181
- values = {}
182
- return output, values
183
- end
184
-
185
- def getAdditionalDiceValue(_dice, _values)
186
- 0
187
- end
188
-
189
- def getCriticalFromString(string, half)
190
- crit = half ? 13 : 10
191
-
192
- regexp = /c\[(\d+)\]/i
193
-
194
- if regexp =~ string
195
- crit = Regexp.last_match(1).to_i
196
- crit = 3 if crit < 3 # エラートラップ(クリティカル値が3未満なら3とする)
197
- string = string.gsub(regexp, '')
198
- end
199
-
200
- return crit, string
201
- end
202
-
203
- def getDiceChangesFromString(string)
204
- firstDiceChanteTo = 0
205
- firstDiceChangeModify = 0
206
-
207
- regexp = /m\[([\d+\-]+)\]/i
208
-
209
- if regexp =~ string
210
- firstDiceChangeModify = Regexp.last_match(1)
211
-
212
- unless /[+\-]/ =~ firstDiceChangeModify
213
- firstDiceChanteTo = firstDiceChangeModify.to_i
214
- firstDiceChangeModify = 0
215
- end
216
-
217
- string = string.gsub(regexp, '')
218
- end
219
-
220
- return firstDiceChanteTo, firstDiceChangeModify, string
221
- end
222
-
223
- def getRateUpFromString(string)
224
- rateUp = 0
225
- return rateUp, string
226
- end
227
-
228
- def getKeyAndAddValueFromString(string)
229
- key = nil
230
- addValue = 0
231
-
232
- if /K(\d+)([\d+\-]*)/i =~ string # ボーナスの抽出
233
- key = Regexp.last_match(1)
234
- if Regexp.last_match(2)
235
- addValue = ArithmeticEvaluator.eval(Regexp.last_match(2))
236
- end
237
- else
238
- key = string
239
- end
240
-
241
- return key, addValue
242
- end
243
-
244
134
  def getSW2_0_RatingTable
245
135
  rate_sw2_0 = [
246
136
  # 0
@@ -397,7 +287,7 @@ module BCDice
397
287
  return newRates
398
288
  end
399
289
 
400
- def rollDice(_values)
290
+ def rollDice(_command)
401
291
  dice_list = @randomizer.roll_barabara(2, 6)
402
292
  total = dice_list.sum()
403
293
  dice_str = dice_list.join(",")
@@ -405,15 +295,14 @@ module BCDice
405
295
  end
406
296
 
407
297
  # @param rating_total [Integer]
408
- # @param modifier [Integer]
298
+ # @param command [SwordWorld::RatingParsed]
409
299
  # @param diceResults [Array<String>]
410
300
  # @param diceResultTotals [Array<String>]
411
301
  # @param rateResults [Array<String>]
412
302
  # @param dice_total [Integer]
413
303
  # @param round [Integer]
414
- # @param half [Boolean]
415
- def getResultText(rating_total, modifier, diceResults, diceResultTotals,
416
- rateResults, dice_total, round, half)
304
+ def getResultText(rating_total, command, diceResults, diceResultTotals,
305
+ rateResults, dice_total, round)
417
306
  sequence = []
418
307
 
419
308
  sequence.push("2D:[#{diceResults.join(' ')}]=#{diceResultTotals.join(',')}")
@@ -425,14 +314,21 @@ module BCDice
425
314
  end
426
315
 
427
316
  # rate回数が1回で、修正値がない時には途中式と最終結果が一致するので、途中式を省略する
428
- if rateResults.size > 1 || modifier != 0
429
- text = rateResults.join(',') + Format.modifier(modifier)
430
- if half
317
+ if rateResults.size > 1 || command.modifier != 0
318
+ text = rateResults.join(',') + Format.modifier(command.modifier)
319
+ if command.half
431
320
  text = "(#{text})/2"
321
+ if command.modifier_after_half != 0
322
+ text += Format.modifier(command.modifier_after_half)
323
+ end
324
+ end
325
+ sequence.push(text)
326
+ elsif command.half
327
+ text = "#{rateResults.first}/2"
328
+ if command.modifier_after_half != 0
329
+ text += Format.modifier(command.modifier_after_half)
432
330
  end
433
331
  sequence.push(text)
434
- elsif half
435
- sequence.push("#{rateResults.first}/2")
436
332
  end
437
333
 
438
334
  if round > 1
@@ -440,9 +336,12 @@ module BCDice
440
336
  sequence.push(round_text)
441
337
  end
442
338
 
443
- total = rating_total + modifier
444
- if half
339
+ total = rating_total + command.modifier
340
+ if command.half
445
341
  total = (total / 2.0).ceil
342
+ if command.modifier_after_half != 0
343
+ total += command.modifier_after_half
344
+ end
446
345
  end
447
346
 
448
347
  total_text = total.to_s
@@ -450,41 +349,6 @@ module BCDice
450
349
 
451
350
  return sequence.join(" > ")
452
351
  end
453
-
454
- def setRatingTable(tnick)
455
- mode_str = ""
456
- pre_mode = @rating_table
457
-
458
- if /(\d+)/ =~ tnick
459
- @rating_table = Regexp.last_match(1).to_i
460
- if @rating_table > 1
461
- mode_str = "2.0-mode"
462
- @rating_table = 2
463
- elsif @rating_table > 0
464
- mode_str = "new-mode"
465
- @rating_table = 1
466
- else
467
- mode_str = "old-mode"
468
- @rating_table = 0
469
- end
470
- else
471
- case tnick
472
- when /old/i
473
- @rating_table = 0
474
- mode_str = "old-mode"
475
- when /new/i
476
- @rating_table = 1
477
- mode_str = "new-mode"
478
- when /2\.0/i
479
- @rating_table = 2
480
- mode_str = "2.0-mode"
481
- end
482
- end
483
-
484
- return '1' if @rating_table == pre_mode
485
-
486
- return "RatingTableを#{mode_str}に変更しました"
487
- end
488
352
  end
489
353
  end
490
354
  end
@@ -3,6 +3,7 @@
3
3
  require 'bcdice/arithmetic_evaluator'
4
4
 
5
5
  require 'bcdice/game_system/SwordWorld'
6
+ require 'bcdice/game_system/sword_world/transcendent_test'
6
7
 
7
8
  module BCDice
8
9
  module GameSystem
@@ -34,10 +35,12 @@ module BCDice
34
35
   またタイプの軽減化のために末尾に「@クリティカル値」でも処理するようにしました。
35
36
   例)K20[10]   K10+5[9]   k30[10]   k10[9]+10   k10-5@9
36
37
 
37
- ・レーティング表の半減 (HKx)
38
+ ・レーティング表の半減 (HKx, KxH+N)
38
39
   レーティング表の先頭または末尾に"H"をつけると、レーティング表を振って最終結果を半減させます。
40
+  末尾につけた場合、直後に修正ををつけることで、半減後の加減算を行うことができます。
41
+  この際、複数の項による修正にはカッコで囲うことが必要です(カッコがないとパースに失敗します)
39
42
   クリティカル値を指定しない場合、クリティカルなしと扱われます。
40
-  例)HK20  K20h  HK10-5@9  K10-5@9H  K20gfH
43
+  例)HK20  K20h  HK10-5@9  K10-5@9H  K20gfH  K20+8H+2  K20+8H(1+1)
41
44
 
42
45
  ・ダイス目の修正(運命変転やクリティカルレイ用)
43
46
   末尾に「$修正値」でダイス目に修正がかかります。
@@ -65,115 +68,13 @@ module BCDice
65
68
   絡み効果表を出すことができます。
66
69
  INFO_MESSAGE_TEXT
67
70
 
68
- register_prefix('H?K\d+.*', 'Gr(\d+)?', '2D6?@\d+.*', 'FT', 'TT')
69
-
70
- # 超越判定のノード
71
- class TranscendentTest
72
- # @param [Integer] critical_value クリティカル値
73
- # @param [Integer] modifier 修正値
74
- # @param [String, nil] cmp_op 比較演算子(> または >=)
75
- # @param [Integer, nil] target 目標値
76
- def initialize(critical_value, modifier, cmp_op, target)
77
- @critical_value = critical_value
78
- @modifier = modifier
79
- @cmp_op = cmp_op
80
- @target = target
81
-
82
- @modifier_str = Format.modifier(@modifier)
83
- @expression = node_expression()
84
- end
85
-
86
- # 超越判定を行う
87
- # @param randomizer [Randomizer]
88
- # @return [String]
89
- def execute(randomizer)
90
- if @critical_value < 3
91
- return "(#{@expression}) > クリティカル値が小さすぎます。3以上を指定してください。"
92
- end
93
-
94
- first_value_group = randomizer.roll_barabara(2, 6)
95
- value_groups = [first_value_group]
96
-
97
- fumble = first_value_group == [1, 1]
98
- critical = first_value_group == [6, 6]
99
-
100
- if !fumble && !critical
101
- while sum_of_dice(value_groups.last) >= @critical_value
102
- value_groups.push(randomizer.roll_barabara(2, 6))
103
- end
104
- end
105
-
106
- sum = sum_of_dice(value_groups)
107
- total_sum = sum + @modifier
108
-
109
- parts = [
110
- "(#{@expression})",
111
- "#{dice_str(value_groups, sum)}#{@modifier_str}",
112
- total_sum,
113
- @target && result_str(total_sum, value_groups.length, fumble, critical)
114
- ].compact
115
-
116
- return parts.join(' > ')
117
- end
118
-
119
- private
120
-
121
- # 数式表記を返す
122
- # @return [String]
123
- def node_expression
124
- lhs = "2D6@#{@critical_value}#{@modifier_str}"
125
-
126
- return @target ? "#{lhs}#{@cmp_op}#{@target}" : lhs
127
- end
128
-
129
- # 出目の合計を返す
130
- # @param [(Integer, Integer), Array<(Integer, Integer)>] value_groups
131
- # 出目のグループまたはその配列
132
- # @return [Integer]
133
- def sum_of_dice(value_groups)
134
- value_groups.flatten.sum
135
- end
136
-
137
- # ダイス部分の文字列を返す
138
- # @param [Array<(Integer, Integer)>] value_groups 出目のグループの配列
139
- # @param [Integer] sum 出目の合計
140
- # @return [String]
141
- def dice_str(value_groups, sum)
142
- value_groups_str =
143
- value_groups
144
- .map { |values| "[#{values.join(',')}]" }
145
- .join
146
-
147
- return "#{sum}#{value_groups_str}"
148
- end
149
-
150
- # 判定結果の文字列を返す
151
- # @param [Integer] total_sum 合計値
152
- # @param [Integer] n_value_groups 出目のグループの数
153
- # @param [Boolean] fumble ファンブルかどうか
154
- # @param [Boolean] critical クリティカルかどうか
155
- # @return [String]
156
- def result_str(total_sum, n_value_groups, fumble, critical)
157
- return '自動的失敗' if fumble
158
- return '自動的成功' if critical
159
-
160
- if total_sum.send(@cmp_op, @target)
161
- # 振り足しが行われ、合計値が41以上ならば「超成功」
162
- n_value_groups >= 2 && total_sum >= 41 ? '超成功' : '成功'
163
- else
164
- '失敗'
165
- end
166
- end
167
- end
71
+ register_prefix('H?K\d+', 'Gr(\d+)?', '2D6?@\d+', 'FT', 'TT')
168
72
 
169
73
  def initialize(command)
170
74
  super(command)
171
75
  @rating_table = 2
172
76
  end
173
77
 
174
- # 超越判定のパターン
175
- TRANSCENDENT_TEST_RE = /\A2D6?@(\d+)([-+\d]+)?(?:(>=?)(\d+))?/.freeze
176
-
177
78
  def eval_game_system_specific_command(command)
178
79
  case command
179
80
  when /^Gr(\d+)?/i
@@ -182,15 +83,17 @@ module BCDice
182
83
  else
183
84
  growth
184
85
  end
185
- when TRANSCENDENT_TEST_RE
186
- m = Regexp.last_match
187
-
188
- critical_value = m[1].to_i
189
- modifier = m[2] ? ArithmeticEvaluator.eval(m[2]) : 0
190
- cmp_op = m[3]
191
- target = m[3] && m[4].to_i
86
+ when /^2D6?@\d+/i
87
+ transcendent_parser = Command::Parser.new(/2D6?/i, round_type: BCDice::RoundType::CEIL)
88
+ .enable_critical
89
+ .restrict_cmp_op_to(nil, :>=, :>)
90
+ cmd = transcendent_parser.parse(command)
91
+
92
+ unless cmd
93
+ return nil
94
+ end
192
95
 
193
- node = TranscendentTest.new(critical_value, modifier, cmp_op, target)
96
+ node = TranscendentTest.new(cmd.critical, cmd.modify_number, cmd.cmp_op, cmd.target_number)
194
97
  node.execute(@randomizer)
195
98
  when 'FT'
196
99
  get_fumble_table
@@ -201,32 +104,13 @@ module BCDice
201
104
  end
202
105
  end
203
106
 
204
- def getRateUpFromString(string)
205
- rateUp = 0
206
-
207
- regexp = /r\[(\d+)\]/i
208
- if (m = regexp.match(string))
209
- rateUp = m[1].to_i
210
- string = string.gsub(regexp, '')
211
- end
212
-
213
- return rateUp, string
214
- end
215
-
216
- def getAdditionalString(string, output)
217
- output, values = super(string, output)
218
-
219
- isGratestFortune, = getGratestFortuneFromString(string)
220
-
221
- values['isGratestFortune'] = isGratestFortune
222
- output += "gf" if isGratestFortune
223
-
224
- return output, values
107
+ def rating_parser
108
+ return RatingParser.new(version: :v2_0)
225
109
  end
226
110
 
227
- def rollDice(values)
228
- unless values['isGratestFortune']
229
- return super(values)
111
+ def rollDice(command)
112
+ unless command.greatest_fortune
113
+ return super(command)
230
114
  end
231
115
 
232
116
  dice = @randomizer.roll_once(6)
@@ -234,18 +118,6 @@ module BCDice
234
118
  return dice * 2, "#{dice},#{dice}"
235
119
  end
236
120
 
237
- def getGratestFortuneFromString(string)
238
- isGratestFortune = false
239
-
240
- regexp = /gf/i
241
- if regexp.match?(string)
242
- isGratestFortune = true
243
- string = string.gsub(regexp, '')
244
- end
245
-
246
- return isGratestFortune, string
247
- end
248
-
249
121
  def growth(count = 1)
250
122
  ((1..count).map { growth_step }).join " | "
251
123
  end