bcdice 3.1.0 → 3.3.0

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