bcdice 3.1.0 → 3.3.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 (160) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +78 -1
  3. data/README.md +1 -1
  4. data/i18n/MagicaLogia/zh_hans.yml +564 -0
  5. data/i18n/StellarKnights/ja_jp.yml +498 -0
  6. data/i18n/StellarKnights/ko_kr.yml +498 -0
  7. data/i18n/zh_hans.yml +7 -0
  8. data/lib/bcdice/command/parsed.rb +11 -3
  9. data/lib/bcdice/command/parser.rb +179 -100
  10. data/lib/bcdice/common_command/add_dice.rb +1 -1
  11. data/lib/bcdice/common_command/barabara_dice/node.rb +2 -2
  12. data/lib/bcdice/common_command/barabara_dice/result.rb +6 -0
  13. data/lib/bcdice/common_command/calc.rb +1 -1
  14. data/lib/bcdice/dice_table.rb +2 -0
  15. data/lib/bcdice/dice_table/d66_half_grid_table.rb +33 -0
  16. data/lib/bcdice/dice_table/d66_one_third_table.rb +34 -0
  17. data/lib/bcdice/dice_table/sai_fic_skill_table.rb +1 -1
  18. data/lib/bcdice/game_system.rb +6 -0
  19. data/lib/bcdice/game_system/AceKillerGene.rb +1 -1
  20. data/lib/bcdice/game_system/Ainecadette.rb +68 -0
  21. data/lib/bcdice/game_system/Airgetlamh.rb +1 -1
  22. data/lib/bcdice/game_system/Alsetto.rb +1 -1
  23. data/lib/bcdice/game_system/AlterRaise.rb +2 -2
  24. data/lib/bcdice/game_system/Amadeus.rb +110 -93
  25. data/lib/bcdice/game_system/AngelGear.rb +2 -2
  26. data/lib/bcdice/game_system/AnimaAnimus.rb +16 -9
  27. data/lib/bcdice/game_system/Arianrhod.rb +6 -8
  28. data/lib/bcdice/game_system/Avandner.rb +1 -1
  29. data/lib/bcdice/game_system/BarnaKronika.rb +1 -1
  30. data/lib/bcdice/game_system/BattleTech.rb +109 -28
  31. data/lib/bcdice/game_system/BeastBindTrinity.rb +28 -12
  32. data/lib/bcdice/game_system/BeginningIdol.rb +5 -5
  33. data/lib/bcdice/game_system/BeginningIdol_Korean.rb +5 -5
  34. data/lib/bcdice/game_system/BladeOfArcana.rb +1 -1
  35. data/lib/bcdice/game_system/BlindMythos.rb +39 -38
  36. data/lib/bcdice/game_system/BloodCrusade.rb +6 -7
  37. data/lib/bcdice/game_system/BloodMoon.rb +9 -8
  38. data/lib/bcdice/game_system/CardRanker.rb +8 -7
  39. data/lib/bcdice/game_system/ChaosFlare.rb +21 -15
  40. data/lib/bcdice/game_system/Chill.rb +10 -10
  41. data/lib/bcdice/game_system/Chill3.rb +9 -9
  42. data/lib/bcdice/game_system/CodeLayerd.rb +39 -39
  43. data/lib/bcdice/game_system/ColossalHunter.rb +34 -47
  44. data/lib/bcdice/game_system/CrashWorld.rb +1 -1
  45. data/lib/bcdice/game_system/Cthulhu.rb +1 -1
  46. data/lib/bcdice/game_system/Cthulhu7th.rb +48 -10
  47. data/lib/bcdice/game_system/Cthulhu7th_ChineseTraditional.rb +2 -2
  48. data/lib/bcdice/game_system/Cthulhu7th_Korean.rb +2 -2
  49. data/lib/bcdice/game_system/Cthulhu_ChineseTraditional.rb +1 -1
  50. data/lib/bcdice/game_system/Cthulhu_Korean.rb +1 -1
  51. data/lib/bcdice/game_system/DarkBlaze.rb +0 -11
  52. data/lib/bcdice/game_system/DarkDaysDrive.rb +8 -7
  53. data/lib/bcdice/game_system/DeadlineHeroes.rb +11 -10
  54. data/lib/bcdice/game_system/DemonParasite.rb +5 -13
  55. data/lib/bcdice/game_system/DesperateRun.rb +1 -1
  56. data/lib/bcdice/game_system/DoubleCross.rb +3 -1
  57. data/lib/bcdice/game_system/Dracurouge.rb +1 -1
  58. data/lib/bcdice/game_system/EclipsePhase.rb +14 -14
  59. data/lib/bcdice/game_system/Elric.rb +18 -14
  60. data/lib/bcdice/game_system/Elysion.rb +1 -1
  61. data/lib/bcdice/game_system/EmbryoMachine.rb +9 -8
  62. data/lib/bcdice/game_system/Emoklore.rb +25 -20
  63. data/lib/bcdice/game_system/Fiasco.rb +1 -1
  64. data/lib/bcdice/game_system/FilledWith.rb +205 -1272
  65. data/lib/bcdice/game_system/FutariSousa.rb +12 -10
  66. data/lib/bcdice/game_system/GURPS.rb +17 -28
  67. data/lib/bcdice/game_system/Garako.rb +1 -1
  68. data/lib/bcdice/game_system/GardenOrder.rb +12 -7
  69. data/lib/bcdice/game_system/GeishaGirlwithKatana.rb +1 -1
  70. data/lib/bcdice/game_system/GoblinSlayer.rb +1 -1
  71. data/lib/bcdice/game_system/Gorilla.rb +2 -8
  72. data/lib/bcdice/game_system/GranCrest.rb +18 -11
  73. data/lib/bcdice/game_system/Gundog.rb +9 -8
  74. data/lib/bcdice/game_system/GundogRevised.rb +10 -9
  75. data/lib/bcdice/game_system/GundogZero.rb +1 -1
  76. data/lib/bcdice/game_system/GurpsFW.rb +16 -16
  77. data/lib/bcdice/game_system/HarnMaster.rb +19 -26
  78. data/lib/bcdice/game_system/HatsuneMiku.rb +1 -1
  79. data/lib/bcdice/game_system/Hieizan.rb +12 -21
  80. data/lib/bcdice/game_system/HouraiGakuen.rb +1 -1
  81. data/lib/bcdice/game_system/HuntersMoon.rb +5 -10
  82. data/lib/bcdice/game_system/InfiniteFantasia.rb +19 -17
  83. data/lib/bcdice/game_system/Insane.rb +13 -20
  84. data/lib/bcdice/game_system/IthaWenUa.rb +8 -15
  85. data/lib/bcdice/game_system/JamesBond.rb +10 -10
  86. data/lib/bcdice/game_system/JekyllAndHyde.rb +1 -1
  87. data/lib/bcdice/game_system/Kamigakari.rb +1 -1
  88. data/lib/bcdice/game_system/KanColle.rb +4 -9
  89. data/lib/bcdice/game_system/KemonoNoMori.rb +26 -39
  90. data/lib/bcdice/game_system/KillDeathBusiness.rb +7 -15
  91. data/lib/bcdice/game_system/KurayamiCrying.rb +141 -2
  92. data/lib/bcdice/game_system/LiveraDoll.rb +254 -304
  93. data/lib/bcdice/game_system/LogHorizon.rb +13 -10
  94. data/lib/bcdice/game_system/MagicaLogia_SimplifiedChinese.rb +66 -0
  95. data/lib/bcdice/game_system/MeikyuDays.rb +10 -8
  96. data/lib/bcdice/game_system/MeikyuKingdom.rb +26 -26
  97. data/lib/bcdice/game_system/MeikyuKingdomBasic.rb +5 -4
  98. data/lib/bcdice/game_system/MetalHead.rb +12 -22
  99. data/lib/bcdice/game_system/MetalHeadExtream.rb +5 -5
  100. data/lib/bcdice/game_system/MonotoneMuseum.rb +8 -6
  101. data/lib/bcdice/game_system/Nechronica.rb +63 -90
  102. data/lib/bcdice/game_system/NinjaSlayer.rb +6 -7
  103. data/lib/bcdice/game_system/NjslyrBattle.rb +8 -11
  104. data/lib/bcdice/game_system/OneWayHeroics.rb +1 -1
  105. data/lib/bcdice/game_system/Paradiso.rb +3 -3
  106. data/lib/bcdice/game_system/ParasiteBlood.rb +1 -1
  107. data/lib/bcdice/game_system/Peekaboo.rb +4 -9
  108. data/lib/bcdice/game_system/Pendragon.rb +7 -7
  109. data/lib/bcdice/game_system/PhantasmAdventure.rb +8 -8
  110. data/lib/bcdice/game_system/Postman.rb +1 -1
  111. data/lib/bcdice/game_system/PulpCthulhu.rb +1 -1
  112. data/lib/bcdice/game_system/Raisondetre.rb +2 -2
  113. data/lib/bcdice/game_system/Revulture.rb +123 -0
  114. data/lib/bcdice/game_system/RuneQuest.rb +8 -8
  115. data/lib/bcdice/game_system/Ryutama.rb +1 -1
  116. data/lib/bcdice/game_system/SRS.rb +17 -16
  117. data/lib/bcdice/game_system/SamsaraBallad.rb +38 -11
  118. data/lib/bcdice/game_system/Satasupe.rb +32 -32
  119. data/lib/bcdice/game_system/ScreamHighSchool.rb +5 -5
  120. data/lib/bcdice/game_system/SharedFantasia.rb +19 -23
  121. data/lib/bcdice/game_system/ShinobiGami.rb +14 -6
  122. data/lib/bcdice/game_system/Skynauts.rb +103 -142
  123. data/lib/bcdice/game_system/SkynautsBouken.rb +228 -0
  124. data/lib/bcdice/game_system/StarryDolls.rb +318 -0
  125. data/lib/bcdice/game_system/SteamPunkers.rb +11 -6
  126. data/lib/bcdice/game_system/StellarKnights.rb +85 -706
  127. data/lib/bcdice/game_system/StellarKnights_Korean.rb +79 -0
  128. data/lib/bcdice/game_system/SterileLife.rb +2 -3
  129. data/lib/bcdice/game_system/StrangerOfSwordCity.rb +1 -1
  130. data/lib/bcdice/game_system/StratoShout.rb +8 -16
  131. data/lib/bcdice/game_system/Strave.rb +1 -1
  132. data/lib/bcdice/game_system/SwordWorld.rb +16 -7
  133. data/lib/bcdice/game_system/SwordWorld2_0.rb +2 -2
  134. data/lib/bcdice/game_system/SwordWorld2_5.rb +2 -2
  135. data/lib/bcdice/game_system/TherapieSein.rb +1 -1
  136. data/lib/bcdice/game_system/TokumeiTenkousei.rb +4 -3
  137. data/lib/bcdice/game_system/TokyoGhostResearch.rb +1 -1
  138. data/lib/bcdice/game_system/TrinitySeven.rb +279 -280
  139. data/lib/bcdice/game_system/TunnelsAndTrolls.rb +1 -1
  140. data/lib/bcdice/game_system/Utakaze.rb +53 -48
  141. data/lib/bcdice/game_system/Villaciel.rb +1 -1
  142. data/lib/bcdice/game_system/WARPS.rb +11 -9
  143. data/lib/bcdice/game_system/WaresBlade.rb +4 -9
  144. data/lib/bcdice/game_system/Warhammer.rb +15 -6
  145. data/lib/bcdice/game_system/Warhammer4.rb +15 -11
  146. data/lib/bcdice/game_system/WitchQuest.rb +1 -1
  147. data/lib/bcdice/game_system/YankeeYogSothoth.rb +4 -9
  148. data/lib/bcdice/game_system/Yggdrasill.rb +1 -1
  149. data/lib/bcdice/game_system/ZettaiReido.rb +20 -25
  150. data/lib/bcdice/game_system/filled_with/enemy_data_tables.rb +322 -0
  151. data/lib/bcdice/game_system/filled_with/event_tables.rb +392 -0
  152. data/lib/bcdice/game_system/filled_with/tresure_tables.rb +179 -0
  153. data/lib/bcdice/game_system/meikyu_kingdom_basic/kingdom_table.rb +1 -1
  154. data/lib/bcdice/game_system/sword_world/rating_parsed.rb +4 -4
  155. data/lib/bcdice/game_system/sword_world/rating_parser.rb +1 -1
  156. data/lib/bcdice/game_system/sword_world/transcendent_test.rb +26 -8
  157. data/lib/bcdice/repl.rb +1 -1
  158. data/lib/bcdice/result.rb +26 -0
  159. data/lib/bcdice/version.rb +1 -1
  160. metadata +18 -4
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'bcdice/base'
4
+
3
5
  module BCDice
4
6
  module GameSystem
5
7
  class SamsaraBallad < Base
@@ -59,38 +61,63 @@ module BCDice
59
61
  total = 100 if total == 0
60
62
  end
61
63
 
62
- cmp_result = compare(total, cmd)
64
+ result = compare(total, cmd)
65
+
66
+ result_str =
67
+ if result.failure?
68
+ "失敗"
69
+ elsif result.success?
70
+ "成功"
71
+ end
72
+
73
+ additional_str =
74
+ if result.fumble?
75
+ "ファンブル"
76
+ elsif result.critical?
77
+ "クリティカル"
78
+ end
63
79
 
64
80
  sequence = [
65
81
  "(D100#{cmd.cmp_op}#{cmd.target_number})",
66
82
  places_text,
67
83
  total.to_s,
68
- cmp_result,
84
+ result_str,
85
+ additional_str,
69
86
  ].compact
70
87
 
71
- return sequence.join(" > ")
88
+ result.text = sequence.join(" > ")
89
+
90
+ return result
72
91
  end
73
92
 
74
93
  private
75
94
 
76
- # @return [String]
77
- # @return [nil]
95
+ # @return [Result]
78
96
  def compare(total, cmd)
79
97
  if [:<=, :<].include?(cmd.cmp_op)
80
98
  if !total.send(cmd.cmp_op, cmd.target_number)
81
- "失敗"
99
+ Result.failure(nil)
82
100
  elsif fumble_?(total, cmd.fumble)
83
- "ファンブル"
101
+ Result.new.tap do |r|
102
+ r.success = true
103
+ r.fumble = true
104
+ end
84
105
  elsif critical_?(total, cmd.critical)
85
- "クリティカル"
106
+ Result.critical(nil)
86
107
  else
87
- "成功"
108
+ Result.success(nil)
88
109
  end
89
110
  elsif fumble_?(total, cmd.fumble)
90
111
  # ファンブル優先
91
- "ファンブル"
112
+ Result.new.tap do |r|
113
+ r.fumble = true
114
+ end
92
115
  elsif critical_?(total, cmd.critical)
93
- "クリティカル"
116
+ Result.new.tap do |r|
117
+ r.critical = true
118
+ end
119
+ else
120
+ Result.new
94
121
  end
95
122
  end
96
123
 
@@ -49,7 +49,7 @@ module BCDice
49
49
  ・D66ダイスあり
50
50
  INFO_MESSAGE_TEXT
51
51
 
52
- register_prefix('\d+R', 'SR\d+', 'TAGT', 'GETSST', 'NPCT', TABLES.keys, ALIASES.keys)
52
+ register_prefix('\d+R', 'SR', 'TAGT', 'GETSST', 'NPCT', TABLES.keys, ALIASES.keys)
53
53
 
54
54
  CREATE_ARMS_STRUCT = Struct.new(:base_parts, :accessory_parts, :parts_effect, :hit, :damage, :life, :kutibeni, :kiba, :abilities)
55
55
 
@@ -64,7 +64,7 @@ module BCDice
64
64
  debug("eval_game_system_specific_command begin string", command)
65
65
 
66
66
  result = checkRoll(command)
67
- return result unless result.empty?
67
+ return result unless result.nil?
68
68
 
69
69
  debug("判定ロールではなかった")
70
70
 
@@ -81,13 +81,13 @@ module BCDice
81
81
  debug("checkRoll begin string", string)
82
82
 
83
83
  m = /^(\d+)R>=(\d+)(\[(\d+)?(,|,\d+)?(,\d+(S)?)?\])?$/i.match(string)
84
- return '' unless m
84
+ return nil unless m
85
85
 
86
86
  roll_times = m[1].to_i
87
87
  target = m[2].to_i
88
88
  params = m[3]
89
89
 
90
- min_suc, fumble, critical, isCriticalStop = getRollParams(params)
90
+ min_suc, fumble, critical, is_critical_stop = get_roll_params(params)
91
91
 
92
92
  result = ""
93
93
 
@@ -104,8 +104,8 @@ module BCDice
104
104
  end
105
105
 
106
106
  if fumble >= 6
107
- result += "#{getJudgeInfo(target, fumble, critical)} > ファンブル率が6を超えたため自動失敗!"
108
- return result
107
+ result += "#{get_judge_info(target, fumble, critical)} > ファンブル率が6を超えたため自動失敗!"
108
+ return Result.failure(result)
109
109
  end
110
110
 
111
111
  if target < 5
@@ -113,23 +113,30 @@ module BCDice
113
113
  target = 5
114
114
  end
115
115
 
116
- dice_str, total_suc, isCritical, isFumble = checkRollLoop(roll_times, min_suc, target, critical, fumble, isCriticalStop)
116
+ dice_str, total_suc, is_critical, is_fumble = check_roll_loop(roll_times, min_suc, target, critical, fumble, is_critical_stop)
117
117
 
118
- result += "#{getJudgeInfo(target, fumble, critical)} > #{dice_str} > 成功度#{total_suc}"
118
+ result += "#{get_judge_info(target, fumble, critical)} > #{dice_str} > 成功度#{total_suc}"
119
119
 
120
- if isFumble
120
+ if is_fumble
121
121
  result += " > ファンブル"
122
122
  end
123
123
 
124
- if isCritical && (total_suc > 0)
124
+ if is_critical && (total_suc > 0)
125
125
  result += " > 必殺発動可能!"
126
126
  end
127
127
 
128
128
  debug('checkRoll result result', result)
129
- return result
129
+
130
+ return Result.new.tap do |r|
131
+ r.text = result
132
+ r.success = !is_fumble && min_suc > 0 && total_suc >= min_suc
133
+ r.failure = is_fumble
134
+ r.critical = is_critical
135
+ r.fumble = is_fumble
136
+ end
130
137
  end
131
138
 
132
- def getRollParams(params)
139
+ def get_roll_params(params)
133
140
  min_suc = 0
134
141
  fumble = 1
135
142
  critical = 13
@@ -154,19 +161,14 @@ module BCDice
154
161
  return min_suc, fumble, critical, isCriticalStop
155
162
  end
156
163
 
157
- def getJudgeInfo(target, fumble, critical)
158
- "【難易度#{target}、ファンブル率#{fumble}#{getcriticalString(critical)}】"
164
+ def get_judge_info(target, fumble, critical)
165
+ return "【難易度#{target}、ファンブル率#{fumble}、必殺#{critical == 13 ? 'なし' : critical.to_s}】"
159
166
  end
160
167
 
161
- def getcriticalString(critical)
162
- criticalString = (critical == 13 ? "なし" : critical.to_s)
163
- return "、必殺#{criticalString}"
164
- end
165
-
166
- def checkRollLoop(roll_times, min_suc, target, critical, fumble, isCriticalStop)
168
+ def check_roll_loop(roll_times, min_suc, target, critical, fumble, is_critical_stop)
167
169
  dice_str = ''
168
- isFumble = false
169
- isCritical = false
170
+ is_fumble = false
171
+ is_critical = false
170
172
  total_suc = 0
171
173
 
172
174
  roll_times.times do |_i|
@@ -193,38 +195,36 @@ module BCDice
193
195
  total_suc += dice_suc
194
196
 
195
197
  if critical <= d1 + d2
196
- isCritical = true
198
+ is_critical = true
197
199
  dice_str += "『必殺!』"
198
200
  end
199
201
 
200
202
  if (d1 == d2) && (d1 <= fumble) # ファンブルの確認
201
- isFumble = true
202
- isCritical = false
203
+ is_fumble = true
204
+ is_critical = false
203
205
  break
204
206
  end
205
207
 
206
- if isCritical && isCriticalStop # 必殺止めの確認
208
+ if is_critical && is_critical_stop # 必殺止めの確認
207
209
  break
208
210
  end
209
211
  end
210
212
 
211
- return dice_str, total_suc, isCritical, isFumble
213
+ return dice_str, total_suc, is_critical, is_fumble
212
214
  end
213
215
 
214
216
  def check_seigou(string)
215
217
  debug("check_seigou begin string", string)
216
218
 
217
- m = /^SR(\d+).*$/i.match(string)
218
- return '' unless m
219
-
220
- target = m[1].to_i
221
- sr_parser = Command::Parser.new(/SR\d+/i, round_type: round_type)
219
+ sr_parser = Command::Parser.new("SR", round_type: round_type)
220
+ .has_suffix_number
222
221
  .restrict_cmp_op_to(nil)
223
222
  cmd = sr_parser.parse(string)
224
223
  return '' unless cmd
225
224
 
226
225
  dice = @randomizer.roll_sum(2, 6)
227
226
  diceTotal = dice + cmd.modify_number
227
+ target = cmd.suffix_number
228
228
 
229
229
  seigou = if target < diceTotal
230
230
  "「激」"
@@ -37,8 +37,8 @@ module BCDice
37
37
  INFO_MESSAGE_TEXT
38
38
 
39
39
  register_prefix(
40
- '(SH|SHS)(\-?\d+)(\/\d+)?(@\d+)?',
41
- '(EM|TR|FE)(\-?\d+)(@\d+)?',
40
+ '(SH|SHS)',
41
+ '(EM|TR|FE)',
42
42
  'DC(SL|BL|IM|BR|RF|EL).+'
43
43
  )
44
44
 
@@ -73,13 +73,13 @@ module BCDice
73
73
 
74
74
  dice_value = @randomizer.roll_once(100)
75
75
  result = get_check_result(dice_value, success_rate, critical_border, fumble_border)
76
- title, supplementary = get_supplementary(command_type, result)
76
+ title, supplementary = get_supplementary(command_type, result.text)
77
77
  unless supplementary.empty?
78
78
  supplementary = "(#{supplementary})"
79
79
  end
80
80
 
81
- text = "#{title}判定 D100<=#{success_rate}@#{critical_border} > #{dice_value} > #{result}#{supplementary}"
82
- return text
81
+ result.text = "#{title}判定 D100<=#{success_rate}@#{critical_border} > #{dice_value} > #{result.text}#{supplementary}"
82
+ return result
83
83
  end
84
84
 
85
85
  def get_supplementary(command_type, result)
@@ -24,11 +24,12 @@ module BCDice
24
24
  register_prefix('SF', 'ST')
25
25
 
26
26
  def change_text(string)
27
- string.gsub(/SF/i, "2D6").gsub(/ST/i, "2D6")
27
+ string.gsub(/S[FT]/i, "2D6")
28
28
  end
29
29
 
30
- def check_2D6(total, dice_total, _dice_list, cmp_op, target)
31
- return '' if target == '?'
30
+ def result_2d6(total, dice_total, _dice_list, cmp_op, target)
31
+ return Result.nothing if target == '?'
32
+ return nil unless [:>=, :>].include?(cmp_op)
32
33
 
33
34
  critical = false
34
35
  fumble = false
@@ -39,28 +40,23 @@ module BCDice
39
40
  fumble = true
40
41
  end
41
42
 
42
- totalValueBonus = 0
43
- if cmp_op == :>=
44
- totalValueBonus = 1
45
- end
43
+ totalValueBonus = (cmp_op == :>= ? 1 : 0)
46
44
 
47
- if [:>=, :>].include?(cmp_op)
48
- if (total + totalValueBonus) > target
49
- if critical
50
- return " > 自動成功(劇的成功)"
51
- elsif fumble
52
- return " > 自動失敗"
53
- else
54
- return " > 成功"
55
- end
45
+ if (total + totalValueBonus) > target
46
+ if critical
47
+ Result.critical("自動成功(劇的成功)")
48
+ elsif fumble
49
+ Result.failure("自動失敗")
50
+ else
51
+ Result.success("成功")
52
+ end
53
+ else
54
+ if critical
55
+ Result.success("自動成功")
56
+ elsif fumble
57
+ Result.fumble("自動失敗(致命的失敗)")
56
58
  else
57
- if critical
58
- return " > 自動成功"
59
- elsif fumble
60
- return " > 自動失敗(致命的失敗)"
61
- else
62
- return " > 失敗"
63
- end
59
+ Result.failure("失敗")
64
60
  end
65
61
  end
66
62
  end
@@ -16,12 +16,13 @@ module BCDice
16
16
 
17
17
  # ダイスボットの使い方
18
18
  HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
19
- ・行為判定 SG@s#f>=x
20
-  2D6の行為判定を行う
19
+ ・行為判定 nSG@s#f>=x
20
+  2D6の行為判定を行う。ダイス数が指定された場合、大きい出目2個を採用する。
21
+  n: ダイス数 (省略時 2)
21
22
   s: スペシャル値 (省略時 12)
22
23
   f: ファンブル値 (省略時 2)
23
24
   x: 目標値 (省略可)
24
-  例)SG, SG@11, SG@11#3, SG#3>=7
25
+  例)SG, SG@11, SG@11#3, SG#3>=7, 3SG>=7
25
26
  ・各種表
26
27
   ・(無印)シーン表 ST/ファンブル表 FT/感情表 ET
27
28
     /変調表 WT/戦場表 BT/異形表 MT
@@ -68,7 +69,7 @@ module BCDice
68
69
  end
69
70
  end
70
71
 
71
- register_prefix("SG")
72
+ register_prefix('\d*SG')
72
73
 
73
74
  def eval_game_system_specific_command(command)
74
75
  result = action_roll(command) || roll_tables(command, TABLES) || RTT.roll_command(@randomizer, command)
@@ -94,17 +95,23 @@ module BCDice
94
95
  private
95
96
 
96
97
  def action_roll(command)
97
- parser = Command::Parser.new("SG", round_type: round_type)
98
+ parser = Command::Parser.new(/\d*SG/, round_type: round_type)
98
99
  .restrict_cmp_op_to(:>=, nil)
99
100
  .enable_critical
100
101
  .enable_fumble
101
102
  cmd = parser.parse(command)
102
103
  return nil unless cmd
103
104
 
105
+ times = cmd.command.start_with?(/\d/) ? cmd.command.to_i : 2
106
+ return nil if times <= 1
107
+
104
108
  cmd.critical ||= 12
105
109
  cmd.fumble ||= 2
106
110
 
107
- dice_list = @randomizer.roll_barabara(2, 6).sort
111
+ dice_list_full = @randomizer.roll_barabara(times, 6).sort
112
+ dice_list_full_str = "[#{dice_list_full.join(',')}]" if times > 2
113
+
114
+ dice_list = dice_list_full[-2, 2]
108
115
  dice_total = dice_list.sum()
109
116
  total = dice_total + cmd.modify_number
110
117
 
@@ -123,6 +130,7 @@ module BCDice
123
130
 
124
131
  sequence = [
125
132
  "(#{cmd.to_s(:after_modify_number)})",
133
+ dice_list_full_str,
126
134
  "#{dice_total}[#{dice_list.join(',')}]#{Format.modifier(cmd.modify_number)}",
127
135
  total,
128
136
  result.text
@@ -7,10 +7,10 @@ module BCDice
7
7
  ID = 'Skynauts'
8
8
 
9
9
  # ゲームシステム名
10
- NAME = '歯車の塔の探空士'
10
+ NAME = '歯車の塔の探空士(六畳間幻想空間)'
11
11
 
12
12
  # ゲームシステム名の読みがな
13
- SORT_KEY = 'すかいのおつ'
13
+ SORT_KEY = 'はくるまのとうのすかいのおつ'
14
14
 
15
15
  # ダイスボットの使い方
16
16
  HELP_MESSAGE = <<~MESSAGETEXT
@@ -43,72 +43,46 @@ module BCDice
43
43
  debug("\n=======================================\n")
44
44
  debug("eval_game_system_specific_command command", command)
45
45
 
46
- # 通常判定
47
- result = getJudgeResult(command)
48
- return result unless result.nil?
49
-
50
- # 航行チェック
51
- result = navigationResult(command)
52
- return result unless result.nil?
53
-
54
- # ダメージチェック
55
- result = getFireResult(command)
56
- return result unless result.nil?
57
-
58
- # 砲撃判定+ダメージチェック
59
- result = getBomberResult(command)
60
- return result unless result.nil?
61
-
62
- # 回避運動(操舵判定含む)
63
- result = getAvoidResult(command)
64
- return result unless result.nil?
65
-
66
- debug("rollCommand result")
67
- return nil
46
+ return get_judge_result(command) || navigation_result(command) || get_fire_result(command) ||
47
+ get_bomb_result(command) || get_avoid_result(command)
68
48
  end
69
49
 
70
- def getJudgeResult(command)
50
+ private
51
+
52
+ def get_judge_result(command)
71
53
  return nil unless (m = (/^2D6<=(\d)$/i.match(command) || /^SN(\d*)$/i.match(command)))
72
54
 
73
- debug("====getJudgeResult====")
55
+ debug("====get_judge_result====")
74
56
 
75
57
  target = m[1].empty? ? 7 : m[1].to_i # 目標値。省略時は7
76
58
  debug("目標値", target)
77
59
 
78
60
  dice_list = @randomizer.roll_barabara(2, 6)
79
61
  total = dice_list.sum()
80
- diceText = dice_list.join(",")
81
-
62
+ text = "(2D6<=#{target}) > #{total}[#{dice_list.join(',')}] > #{total}"
82
63
  if total <= 2
83
- result = "ファンブル"
64
+ Result.fumble(text + "ファンブル")
84
65
  elsif total <= target
85
- result = "成功"
66
+ Result.success(text + "成功")
86
67
  else
87
- result = "失敗"
68
+ Result.failure(text + "失敗")
88
69
  end
89
-
90
- text = "(2D6<=#{target}) > #{total}[#{diceText}] > #{total} > #{result}"
91
-
92
- return text
93
70
  end
94
71
 
95
- def navigationResult(command)
72
+ def navigation_result(command)
96
73
  return nil unless (m = /^NV(\+(\d+))?$/.match(command))
97
74
 
98
- debug("====navigationResult====")
75
+ debug("====navigation_result====")
99
76
 
100
77
  bonus = m[2].to_i # 〈操舵室〉の修正。GMの任意修正にも対応できるように(マイナスは無視)
101
78
  debug("移動修正", bonus)
102
79
 
103
80
  total = @randomizer.roll_once(6)
104
- movePointBase = (total / 2) <= 0 ? 1 : (total / 2)
105
- movePoint = movePointBase + bonus
81
+ move_point_base = (total / 2) <= 0 ? 1 : (total / 2)
82
+ movePoint = move_point_base + bonus
106
83
  debug("移動エリア数", movePoint)
107
84
 
108
- text = "航行チェック(最低1) (1D6/2+#{bonus}) > #{total} /2+#{bonus} > "
109
- text += "#{movePointBase}+#{bonus} > #{movePoint}エリア進む"
110
-
111
- return text
85
+ Result.new("航行チェック(最低1) (1D6/2+#{bonus}) > #{total} /2+#{bonus} > #{move_point_base}+#{bonus} > #{movePoint}エリア進む")
112
86
  end
113
87
 
114
88
  DIRECTION_INFOS = {
@@ -123,201 +97,188 @@ module BCDice
123
97
  9 => {name: "右上", position_diff: {x: +1, y: -1}},
124
98
  }.freeze
125
99
 
126
- def getDirectionInfo(direction, key, defaultValue = nil)
100
+ def get_direction_info(direction, key, default_value = nil)
127
101
  info = DIRECTION_INFOS[direction.to_i]
128
- return defaultValue if info.nil?
102
+ return default_value if info.nil?
129
103
 
130
104
  return info[key]
131
105
  end
132
106
 
133
- def getFireResult(command)
134
- return nil unless (m = %r{^D([12346789]*)(\[.+\])*/(\d+)(@([2468]))?$}.match(command))
107
+ def get_fire_result(command)
108
+ return nil unless (m = %r{^D([12346789]*)(\[.+\])*/(\d{1,2})(@([2468]))?$}.match(command))
135
109
 
136
- debug("====getFireResult====")
110
+ debug("====get_fire_result====")
137
111
 
138
- fireCount = m[3].to_i # 砲撃回数
139
- fireRange = m[1].to_s # 砲撃範囲
112
+ fire_count = m[3].to_i # 砲撃回数
113
+ fire_range = m[1].to_s # 砲撃範囲
140
114
  ballistics = m[5].to_i # 《弾道学》
141
- debug("fireCount", fireCount)
142
- debug("fireRange", fireRange)
115
+ debug("fire_count", fire_count)
116
+ debug("fire_range", fire_range)
143
117
  debug("ballistics", ballistics)
144
118
 
145
- fireCountMax = 25
146
- fireCount = [fireCount, fireCountMax].min
147
-
148
- firePoint = getFirePoint(fireRange, fireCount) # 着弾座標取得(3次元配列)
149
- fireText = getFirePointText(firePoint, fireCount) # 表示用文字列作成
119
+ fire_point = get_fire_point(fire_range, fire_count) # 着弾座標取得(3次元配列)
120
+ result = [command, get_fire_point_text(fire_point, fire_count).text] # 表示用文字列作成
150
121
 
151
122
  if ballistics != 0 # 《弾道学》有
152
- fireText += " 《弾道学》:"
153
- fireText += getDirectionInfo(ballistics, :name, "")
154
- fireText += "\n > "
155
- fireText += getFirePointText(firePoint, fireCount, ballistics)
123
+ result << "《弾道学》:#{get_direction_info(ballistics, :name, '')}\n"
124
+ result << get_fire_point_text(fire_point, fire_count, ballistics).text
156
125
  end
157
-
158
- text = "#{command} > #{fireText}"
159
-
160
- return text
126
+ Result.new(result.join(" > "))
161
127
  end
162
128
 
163
- def getFirePoint(fireRange, fireCount)
164
- debug("====getFirePoint====")
129
+ def get_fire_point(fire_range, fire_count)
130
+ debug("====get_fire_point====")
165
131
 
166
- firePoint = []
132
+ fire_point = []
167
133
 
168
- fireCount.times do |count|
134
+ fire_count.times do |count|
169
135
  debug("\n砲撃回数", count + 1)
170
136
 
171
- firePoint << []
137
+ fire_point << []
172
138
 
173
- yPos = @randomizer.roll_once(6) # 縦
174
- xPos = @randomizer.roll_sum(2, 6) # 横
175
- position = [xPos, yPos]
139
+ y_pos = @randomizer.roll_once(6) # 縦
140
+ x_pos = @randomizer.roll_sum(2, 6) # 横
141
+ position = [x_pos, y_pos]
176
142
 
177
- firePoint[-1] << position
143
+ fire_point[-1] << position
178
144
 
179
- debug("着弾点", firePoint)
145
+ debug("着弾点", fire_point)
180
146
 
181
- fireRange.split(//).each do |rangeText|
182
- debug("範囲", rangeText)
147
+ fire_range.chars do |range_text|
148
+ debug("範囲", range_text)
183
149
 
184
- position_diff = getDirectionInfo(rangeText, :position_diff, {})
185
- position = [xPos + position_diff[:x].to_i, yPos + position_diff[:y].to_i]
150
+ position_diff = get_direction_info(range_text, :position_diff, {})
151
+ position = [x_pos + position_diff[:x].to_i, y_pos + position_diff[:y].to_i]
186
152
 
187
- firePoint[-1] << position
188
- debug("着弾点:範囲", firePoint)
153
+ fire_point[-1] << position
154
+ debug("着弾点:範囲", fire_point)
189
155
  end
190
156
  end
191
157
 
192
- debug("\n最終着弾点", firePoint)
158
+ debug("\n最終着弾点", fire_point)
193
159
 
194
- return firePoint
160
+ return fire_point
195
161
  end
196
162
 
197
- def getFirePointText(firePoint, _fireCount, direction = 0)
198
- debug("====getFirePointText====")
163
+ def get_fire_point_text(fire_point, _fire_count, direction = 0)
164
+ debug("====get_fire_point_text====")
199
165
 
200
- fireTextList = []
201
- firePoint.each do |point|
166
+ fire_text_list = []
167
+ fire_point.each do |point|
202
168
  text = ""
203
169
  point.each do |x, y|
204
170
  # 《弾道学》《回避運動》などによる座標移動
205
- x, y = getMovePoint(x, y, direction)
171
+ x, y = get_move_point(x, y, direction)
206
172
 
207
173
  # マップ外の座標は括弧を付ける
208
- text += (isInMapPosition(x, y) ? "[縦#{y},横#{x}]" : "([縦#{y},横#{x}])")
174
+ text += in_map_position?(x, y) ? "[縦#{y},横#{x}]" : "([縦#{y},横#{x}])"
209
175
  debug("着弾点テキスト", text)
210
176
  end
211
177
 
212
- fireTextList << text
178
+ fire_text_list << text
213
179
  end
214
180
 
215
- fireText = fireTextList.join(",")
216
-
217
- debug("\n最終着弾点テキスト", fireText)
218
- return fireText
181
+ Result.new(fire_text_list.join(","))
219
182
  end
220
183
 
221
- def isInMapPosition(x, y)
184
+ def in_map_position?(x, y)
222
185
  ((1 <= y) && (y <= 6)) && ((2 <= x) && (x <= 12))
223
186
  end
224
187
 
225
- def getMovePoint(x, y, direction)
226
- debug("====getMovePoint====")
188
+ def get_move_point(x, y, direction)
189
+ debug("====get_move_point====")
227
190
  debug("方向", direction)
228
- debug("座標移動前x", x)
229
- debug("座標移動前y", y)
191
+ debug("座標移動前(x,y)", x, y)
230
192
 
231
- position_diff = getDirectionInfo(direction, :position_diff, {})
193
+ position_diff = get_direction_info(direction, :position_diff, {})
232
194
  x += position_diff[:x].to_i
233
195
  y += position_diff[:y].to_i
234
196
 
235
- debug("\n座標移動後x", x)
236
- debug("座標移動後y", y)
197
+ debug("\n座標移動後(x,y)", x, y)
237
198
  return x, y
238
199
  end
239
200
 
240
- def getBomberResult(command)
201
+ def get_bomb_result(command)
241
202
  return nil unless (m = %r{^BOM(\d*)?/D([12346789]*)(\[.+\])*/(\d+)(@([2468]))?$}i.match(command))
242
203
 
243
- debug("====getBomberResult====", command)
204
+ debug("====get_bomb_result====", command)
244
205
 
245
206
  target = m[1].to_s
246
207
  direction = m[6].to_i
247
208
  debug("弾道学方向", direction)
248
209
 
249
- text = "#{command} > "
250
- text += getJudgeResult("SN" + target) # 砲撃判定
210
+ sn = get_judge_result("SN" + target) # 砲撃判定
251
211
 
252
- return text unless text =~ /成功/
212
+ if sn.failure?
213
+ sn.text = "#{command} > #{sn.text}"
214
+ return sn
215
+ end
253
216
 
254
217
  # ダメージチェック部分
255
- fireCommand = command.slice(%r{D([12346789]*)(\[.+\])*/(\d+)(@([2468]))?})
256
-
257
- text += "\n > #{getFireResult(fireCommand)}"
258
-
259
- return text
218
+ fire_command = command.slice(%r{D([12346789]*)(\[.+\])*/(\d+)(@([2468]))?})
219
+ sn.text = "#{command} > #{sn.text}\n > #{get_fire_result(fire_command).text}"
220
+ sn
260
221
  end
261
222
 
262
- def getAvoidResult(command)
223
+ def get_avoid_result(command)
263
224
  return nil unless (m = /^AVO(\d*)?(@([2468]))(\(?\[縦\d+,横\d+\]\)?,?)+$/.match(command))
264
225
 
265
- debug("====getAvoidResult====", command)
226
+ debug("====get_avoid_result====", command)
266
227
 
267
228
  direction = m[3].to_i
268
229
  debug("回避方向", direction)
269
230
 
270
- judgeCommand = command.slice(/^AVO(\d*)?(@([2468]))/) # 判定部分
271
- text = "#{judgeCommand} 《回避運動》"
272
- text += getJudgeResult("SN" + Regexp.last_match(1).to_s) # 操舵判定
231
+ judge_command = command.slice(/^AVO(\d*)?(@([2468]))/) # 判定部分
232
+ sn = get_judge_result("SN" + Regexp.last_match(1).to_s)
273
233
 
274
- return text unless text =~ /成功/
275
-
276
- pointCommand = command.slice(/(\(?\[縦\d+,横\d+\]\)?,?)+/) # 砲撃座標
277
-
278
- firePoint = scanFirePoints(pointCommand)
279
- fireCount = firePoint.size
280
-
281
- text += "\n > #{pointCommand}"
282
- text += " > 《回避運動》:"
283
- text += getDirectionInfo(direction, :name, "")
284
- text += "\n"
285
- text += getFirePointText(firePoint, fireCount, direction)
286
-
287
- return text
234
+ if sn.failure?
235
+ sn.text = "#{judge_command} > 《回避運動》#{sn.text}"
236
+ return sn
237
+ end
238
+ point_command = command.slice(/(\(?\[縦\d+,横\d+\]\)?,?)+/) # 砲撃座標
239
+
240
+ fire_point = scan_fire_point(point_command)
241
+ fire_count = fire_point.size
242
+ Result.success([
243
+ judge_command,
244
+ "《回避運動》#{sn.text}\n",
245
+ point_command,
246
+ "《回避運動》:" + get_direction_info(direction, :name, "") + "\n",
247
+ get_fire_point_text(fire_point, fire_count, direction).text
248
+ ].compact.join(" > "))
288
249
  end
289
250
 
290
- def scanFirePoints(command)
291
- debug("====scanFirePoints====", command)
251
+ def scan_fire_point(command)
252
+ debug("====scan_fire_point====", command)
292
253
 
293
254
  command = command.gsub(/\(|\)/, "") # 正規表現が大変なので最初に括弧を外しておく
294
255
 
295
- firePoint = []
256
+ fire_point = []
296
257
 
297
258
  # 一組ずつに分ける("[縦y,横xの単位)
298
- command.split(/\],/).each do |pointText|
299
- debug("pointText", pointText)
259
+ command.split(/\],/).each do |point_text|
260
+ debug("point_text", point_text)
300
261
 
301
- firePoint << []
262
+ fire_point << []
302
263
 
303
264
  # D以外の砲撃範囲がある時に必要
304
- pointText.split(/\]/).each do |point|
265
+ point_text.split(/\]/).each do |point|
305
266
  debug("point", point)
306
267
 
307
- firePoint[-1] << []
268
+ fire_point[-1] << []
308
269
 
309
270
  next unless point =~ /[^\d]*(\d+),[^\d]*(\d+)/
310
271
 
311
272
  y = Regexp.last_match(1).to_i
312
273
  x = Regexp.last_match(2).to_i
313
274
 
314
- firePoint[-1][-1] = [x, y]
275
+ fire_point[-1][-1] = [x, y]
315
276
 
316
- debug("着弾点", firePoint)
277
+ debug("着弾点", fire_point)
317
278
  end
318
279
  end
319
280
 
320
- return firePoint
281
+ return fire_point
321
282
  end
322
283
  end
323
284
  end