bcdice 3.1.2 → 3.4.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 (161) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +154 -75
  3. data/README.md +3 -2
  4. data/i18n/Cthulhu/zh_hans.yml +11 -0
  5. data/i18n/MagicaLogia/zh_hans.yml +564 -0
  6. data/i18n/StellarKnights/ja_jp.yml +498 -0
  7. data/i18n/StellarKnights/ko_kr.yml +498 -0
  8. data/i18n/zh_hans.yml +7 -0
  9. data/lib/bcdice/command/parsed.rb +11 -3
  10. data/lib/bcdice/command/parser.rb +179 -100
  11. data/lib/bcdice/common_command/add_dice.rb +1 -1
  12. data/lib/bcdice/common_command/barabara_dice/node.rb +2 -2
  13. data/lib/bcdice/common_command/barabara_dice/result.rb +6 -0
  14. data/lib/bcdice/common_command/calc.rb +1 -1
  15. data/lib/bcdice/common_command/choice.rb +78 -7
  16. data/lib/bcdice/dice_table.rb +3 -0
  17. data/lib/bcdice/dice_table/d66_half_grid_table.rb +33 -0
  18. data/lib/bcdice/dice_table/d66_left_range_table.rb +29 -0
  19. data/lib/bcdice/dice_table/d66_one_third_table.rb +34 -0
  20. data/lib/bcdice/game_system.rb +10 -0
  21. data/lib/bcdice/game_system/AceKillerGene.rb +1 -1
  22. data/lib/bcdice/game_system/Ainecadette.rb +68 -0
  23. data/lib/bcdice/game_system/Airgetlamh.rb +1 -1
  24. data/lib/bcdice/game_system/Alsetto.rb +1 -1
  25. data/lib/bcdice/game_system/AlterRaise.rb +2 -2
  26. data/lib/bcdice/game_system/Amadeus.rb +110 -93
  27. data/lib/bcdice/game_system/AngelGear.rb +10 -5
  28. data/lib/bcdice/game_system/AnimaAnimus.rb +16 -9
  29. data/lib/bcdice/game_system/Arianrhod.rb +6 -8
  30. data/lib/bcdice/game_system/Avandner.rb +1 -1
  31. data/lib/bcdice/game_system/BarnaKronika.rb +1 -1
  32. data/lib/bcdice/game_system/BattleTech.rb +109 -28
  33. data/lib/bcdice/game_system/BeastBindTrinity.rb +28 -12
  34. data/lib/bcdice/game_system/BeginningIdol.rb +5 -5
  35. data/lib/bcdice/game_system/BeginningIdol_Korean.rb +5 -5
  36. data/lib/bcdice/game_system/BladeOfArcana.rb +1 -1
  37. data/lib/bcdice/game_system/BlindMythos.rb +39 -38
  38. data/lib/bcdice/game_system/BloodCrusade.rb +6 -7
  39. data/lib/bcdice/game_system/BloodMoon.rb +9 -8
  40. data/lib/bcdice/game_system/CardRanker.rb +8 -7
  41. data/lib/bcdice/game_system/ChaosFlare.rb +21 -15
  42. data/lib/bcdice/game_system/Chill.rb +10 -10
  43. data/lib/bcdice/game_system/Chill3.rb +9 -9
  44. data/lib/bcdice/game_system/CodeLayerd.rb +39 -39
  45. data/lib/bcdice/game_system/ColossalHunter.rb +34 -47
  46. data/lib/bcdice/game_system/CrashWorld.rb +1 -1
  47. data/lib/bcdice/game_system/Cthulhu.rb +1 -1
  48. data/lib/bcdice/game_system/Cthulhu7th.rb +50 -12
  49. data/lib/bcdice/game_system/Cthulhu7th_ChineseTraditional.rb +1 -1
  50. data/lib/bcdice/game_system/Cthulhu7th_Korean.rb +1 -1
  51. data/lib/bcdice/game_system/Cthulhu_SimplifiedChinese.rb +60 -0
  52. data/lib/bcdice/game_system/DarkBlaze.rb +0 -11
  53. data/lib/bcdice/game_system/DarkDaysDrive.rb +8 -7
  54. data/lib/bcdice/game_system/DeadlineHeroes.rb +11 -10
  55. data/lib/bcdice/game_system/DemonParasite.rb +5 -13
  56. data/lib/bcdice/game_system/DesperateRun.rb +1 -1
  57. data/lib/bcdice/game_system/DoubleCross.rb +3 -1
  58. data/lib/bcdice/game_system/Dracurouge.rb +3 -2
  59. data/lib/bcdice/game_system/EclipsePhase.rb +14 -14
  60. data/lib/bcdice/game_system/Elric.rb +18 -14
  61. data/lib/bcdice/game_system/Elysion.rb +1 -1
  62. data/lib/bcdice/game_system/EmbryoMachine.rb +9 -8
  63. data/lib/bcdice/game_system/Emoklore.rb +25 -20
  64. data/lib/bcdice/game_system/Fiasco.rb +1 -1
  65. data/lib/bcdice/game_system/FilledWith.rb +4 -0
  66. data/lib/bcdice/game_system/FutariSousa.rb +12 -10
  67. data/lib/bcdice/game_system/GURPS.rb +17 -28
  68. data/lib/bcdice/game_system/Garako.rb +1 -1
  69. data/lib/bcdice/game_system/GardenOrder.rb +12 -7
  70. data/lib/bcdice/game_system/GeishaGirlwithKatana.rb +1 -1
  71. data/lib/bcdice/game_system/GoblinSlayer.rb +1 -1
  72. data/lib/bcdice/game_system/Gorilla.rb +2 -8
  73. data/lib/bcdice/game_system/GranCrest.rb +189 -417
  74. data/lib/bcdice/game_system/Gundog.rb +9 -8
  75. data/lib/bcdice/game_system/GundogRevised.rb +10 -9
  76. data/lib/bcdice/game_system/GundogZero.rb +1 -1
  77. data/lib/bcdice/game_system/GurpsFW.rb +16 -16
  78. data/lib/bcdice/game_system/HarnMaster.rb +19 -26
  79. data/lib/bcdice/game_system/HatsuneMiku.rb +1 -1
  80. data/lib/bcdice/game_system/Hieizan.rb +12 -21
  81. data/lib/bcdice/game_system/HouraiGakuen.rb +1 -1
  82. data/lib/bcdice/game_system/HuntersMoon.rb +5 -10
  83. data/lib/bcdice/game_system/InfiniteFantasia.rb +19 -17
  84. data/lib/bcdice/game_system/Insane.rb +13 -20
  85. data/lib/bcdice/game_system/Irisbane.rb +154 -0
  86. data/lib/bcdice/game_system/IthaWenUa.rb +8 -15
  87. data/lib/bcdice/game_system/JamesBond.rb +10 -10
  88. data/lib/bcdice/game_system/JekyllAndHyde.rb +1 -1
  89. data/lib/bcdice/game_system/Kamigakari.rb +1 -1
  90. data/lib/bcdice/game_system/KanColle.rb +4 -9
  91. data/lib/bcdice/game_system/KemonoNoMori.rb +26 -39
  92. data/lib/bcdice/game_system/KillDeathBusiness.rb +7 -15
  93. data/lib/bcdice/game_system/KurayamiCrying.rb +141 -2
  94. data/lib/bcdice/game_system/LiveraDoll.rb +254 -304
  95. data/lib/bcdice/game_system/LogHorizon.rb +13 -10
  96. data/lib/bcdice/game_system/MagicaLogia_SimplifiedChinese.rb +66 -0
  97. data/lib/bcdice/game_system/MeikyuDays.rb +10 -8
  98. data/lib/bcdice/game_system/MeikyuKingdom.rb +26 -26
  99. data/lib/bcdice/game_system/MeikyuKingdomBasic.rb +4 -3
  100. data/lib/bcdice/game_system/MetalHead.rb +12 -22
  101. data/lib/bcdice/game_system/MetalHeadExtream.rb +5 -5
  102. data/lib/bcdice/game_system/MonotoneMuseum.rb +8 -6
  103. data/lib/bcdice/game_system/Nechronica.rb +63 -90
  104. data/lib/bcdice/game_system/NinjaSlayer.rb +6 -7
  105. data/lib/bcdice/game_system/NjslyrBattle.rb +8 -11
  106. data/lib/bcdice/game_system/OneWayHeroics.rb +1 -1
  107. data/lib/bcdice/game_system/Paradiso.rb +3 -3
  108. data/lib/bcdice/game_system/ParasiteBlood.rb +1 -1
  109. data/lib/bcdice/game_system/Peekaboo.rb +4 -9
  110. data/lib/bcdice/game_system/Pendragon.rb +7 -7
  111. data/lib/bcdice/game_system/PersonaO.rb +86 -0
  112. data/lib/bcdice/game_system/PhantasmAdventure.rb +8 -8
  113. data/lib/bcdice/game_system/Postman.rb +1 -1
  114. data/lib/bcdice/game_system/PulpCthulhu.rb +1 -1
  115. data/lib/bcdice/game_system/Raisondetre.rb +2 -2
  116. data/lib/bcdice/game_system/Revulture.rb +123 -0
  117. data/lib/bcdice/game_system/RuneQuest.rb +8 -8
  118. data/lib/bcdice/game_system/Ryutama.rb +1 -1
  119. data/lib/bcdice/game_system/SRS.rb +17 -16
  120. data/lib/bcdice/game_system/SamsaraBallad.rb +38 -11
  121. data/lib/bcdice/game_system/Satasupe.rb +32 -32
  122. data/lib/bcdice/game_system/ScreamHighSchool.rb +5 -5
  123. data/lib/bcdice/game_system/SharedFantasia.rb +19 -23
  124. data/lib/bcdice/game_system/ShinobiGami.rb +14 -6
  125. data/lib/bcdice/game_system/Skynauts.rb +103 -142
  126. data/lib/bcdice/game_system/SkynautsBouken.rb +228 -0
  127. data/lib/bcdice/game_system/StarryDolls.rb +318 -0
  128. data/lib/bcdice/game_system/SteamPunkers.rb +25 -7
  129. data/lib/bcdice/game_system/StellarKnights.rb +85 -706
  130. data/lib/bcdice/game_system/StellarKnights_Korean.rb +79 -0
  131. data/lib/bcdice/game_system/SterileLife.rb +2 -3
  132. data/lib/bcdice/game_system/StratoShout.rb +8 -16
  133. data/lib/bcdice/game_system/Strave.rb +1 -1
  134. data/lib/bcdice/game_system/SwordWorld.rb +16 -7
  135. data/lib/bcdice/game_system/SwordWorld2_0.rb +2 -2
  136. data/lib/bcdice/game_system/SwordWorld2_5.rb +2 -2
  137. data/lib/bcdice/game_system/TherapieSein.rb +1 -1
  138. data/lib/bcdice/game_system/TokumeiTenkousei.rb +4 -3
  139. data/lib/bcdice/game_system/TokyoGhostResearch.rb +1 -1
  140. data/lib/bcdice/game_system/TorgEternity.rb +2 -2
  141. data/lib/bcdice/game_system/ToshiakiHolyGrailWar.rb +92 -0
  142. data/lib/bcdice/game_system/TrinitySeven.rb +279 -280
  143. data/lib/bcdice/game_system/TunnelsAndTrolls.rb +1 -1
  144. data/lib/bcdice/game_system/Utakaze.rb +53 -48
  145. data/lib/bcdice/game_system/Villaciel.rb +1 -1
  146. data/lib/bcdice/game_system/WARPS.rb +11 -9
  147. data/lib/bcdice/game_system/WaresBlade.rb +4 -9
  148. data/lib/bcdice/game_system/Warhammer.rb +15 -6
  149. data/lib/bcdice/game_system/Warhammer4.rb +15 -11
  150. data/lib/bcdice/game_system/WitchQuest.rb +1 -1
  151. data/lib/bcdice/game_system/YankeeYogSothoth.rb +4 -9
  152. data/lib/bcdice/game_system/Yggdrasill.rb +1 -1
  153. data/lib/bcdice/game_system/ZettaiReido.rb +20 -25
  154. data/lib/bcdice/game_system/meikyu_kingdom_basic/kingdom_table.rb +1 -1
  155. data/lib/bcdice/game_system/sword_world/rating_parsed.rb +4 -4
  156. data/lib/bcdice/game_system/sword_world/rating_parser.rb +1 -1
  157. data/lib/bcdice/game_system/sword_world/transcendent_test.rb +26 -8
  158. data/lib/bcdice/repl.rb +1 -1
  159. data/lib/bcdice/result.rb +26 -0
  160. data/lib/bcdice/version.rb +1 -1
  161. metadata +22 -5
@@ -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
@@ -0,0 +1,228 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class SkynautsBouken < Base
6
+ # ゲームシステムの識別子
7
+ ID = 'SkynautsBouken'
8
+
9
+ # ゲームシステム名
10
+ NAME = '歯車の塔の探空士(冒険企画局)'
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = 'はくるまのとうのすかいのおつ2'
14
+
15
+ # ダイスボットの使い方
16
+ HELP_MESSAGE = <<~MESSAGETEXT
17
+ ・行為判定(nSNt#f) n:ダイス数(省略時2)、t:目標値(省略時7)、f:ファンブル値(省略時1)
18
+ 例)SN6#2 3SN
19
+ ・ダメージチェック (Dx/y@m) x:ダメージ範囲、y:攻撃回数
20
+   m:《弾道学》(省略可)上:8、下:2、左:4、右:6
21
+   例) D/4 D19/2 D/3@8 D[大揺れ]/2
22
+ ・回避(AVO@mダメージ)
23
+   m:回避方向(上:8、下:2、左:4、右:6)、ダメージ:ダメージチェック結果
24
+   例)AVO@8[1,4],[2,6],[3,8] AVO@2[6,4],[2,6]
25
+ ・FT ファンブル表(p76)
26
+ ・NV 航行表
27
+
28
+ ■ 判定セット
29
+ ・《回避運動》判定+回避(nSNt#f/AVO@ダメージ)
30
+   nSNt#f → 成功なら AVO@m
31
+   例)SN/AVO@8[1,4],[2,6],[3,8] 3SN#2/AVO@2[6,4],[2,6]
32
+ ・砲撃判定+ダメージチェック (nSNt#f/Dx/y@m)
33
+   行為判定の出目変更タイミングを逃すので要GMの許可
34
+   nSNt#f → 成功なら Dx/y@m
35
+   例)SN/D/4 3SN#2/D[大揺れ]/2
36
+ MESSAGETEXT
37
+
38
+ TABLES = {
39
+ 'FT' => DiceTable::Table.new(
40
+ 'ファンブル表',
41
+ '1D6', [
42
+ "なんとか大事にはいたらなかった。通常の失敗と同様の処理を行うこと。",
43
+ "転んでしまった。キミは[転倒](p107)する。",
44
+ "失敗にイライラしてしまった。キミは獲得している【キズナ】1つの「支援チェック」にチェックを入れる。",
45
+ "自身のいるマスを[破損](p104)させる。この[破損]によって、キミの【生命点】は減少しない。",
46
+ "頭をぶつけてしまった。キミの【生命点】を「1d6点」減少する。",
47
+ "奇跡的な結果。 この行為判定は成功となる。",
48
+ ]
49
+ ),
50
+ 'NV' => DiceTable::Table.new(
51
+ '航海表',
52
+ '1d6',
53
+ [
54
+ 'スポット1つ分進む',
55
+ 'スポット1つ分進む',
56
+ 'スポット1つ分進む',
57
+ 'スポット2つ分進む',
58
+ 'スポット2つ分進む',
59
+ 'スポット3つ分進む',
60
+ ]
61
+ )
62
+ }.freeze
63
+
64
+ register_prefix('D', '\d?SN', 'NV', 'FT', 'AVO')
65
+
66
+ def initialize(command)
67
+ super(command)
68
+ @round_type = RoundType::FLOOR # 端数切り捨て
69
+ end
70
+
71
+ def eval_game_system_specific_command(command)
72
+ command_sn(command) || command_d(command) || command_avo(command) || command_snavo(command) ||
73
+ command_snd(command) || roll_tables(command, TABLES)
74
+ end
75
+
76
+ private
77
+
78
+ DIRECTION_INFOS = {
79
+ 0 => {name: "", position_diff: [0, 0]},
80
+ 1 => {name: "左下", position_diff: [-1, +1]},
81
+ 2 => {name: "下", position_diff: [0, +1]},
82
+ 3 => {name: "右下", position_diff: [+1, +1]},
83
+ 4 => {name: "左", position_diff: [-1, 0]},
84
+ 5 => {name: "", position_diff: [0, 0]},
85
+ 6 => {name: "右", position_diff: [+1, 0]},
86
+ 7 => {name: "左上", position_diff: [-1, -1]},
87
+ 8 => {name: "上", position_diff: [0, -1]},
88
+ 9 => {name: "右上", position_diff: [+1, -1]},
89
+ }.freeze
90
+
91
+ D_REGEXP = %r{^D([1-46-9]{0,8})(\[.+\]|S|F|SF|FS)?/(\d{1,2})(@([2468]))?$}.freeze
92
+
93
+ def command_sn(command)
94
+ debug("SN", command)
95
+ cmd = Command::Parser.new(/[1-9]?SN(\d{0,2})/, round_type: round_type)
96
+ .restrict_cmp_op_to(nil)
97
+ .enable_fumble.parse(command)
98
+ return nil unless cmd
99
+
100
+ # [dice_count]SN[target]
101
+ dice_count, target = cmd.command.split("SN", 2).map(&:to_i)
102
+ dice_count = 2 if dice_count == 0
103
+ target = 7 if target == 0
104
+ fumble = cmd.fumble.nil? ? 1 : cmd.fumble
105
+
106
+ debug("SN Parsed", dice_count, target, fumble)
107
+
108
+ dice_list = @randomizer.roll_barabara(dice_count, 6)
109
+ dice_top_two = dice_list.sort[-2..-1]
110
+ res = if dice_top_two == [6, 6]
111
+ Result.critical("スペシャル(【生命点】1d6回復)")
112
+ elsif dice_list.max <= fumble
113
+ Result.fumble("ファンブル(ファンブル表FT)")
114
+ elsif dice_top_two.sum >= target
115
+ Result.success("成功")
116
+ else
117
+ Result.failure("失敗")
118
+ end
119
+
120
+ if dice_count == 2
121
+ res.text = ["(#{dice_count}SN#{target}##{fumble})", "#{dice_top_two.sum}[#{dice_list.join(',')}]", res.text]
122
+ .compact.join(" > ")
123
+ else
124
+ res.text = ["(#{dice_count}SN#{target}##{fumble})", "[" + dice_list.join(",") + "]", "#{dice_top_two.sum}[#{dice_top_two.join(',')}]", res.text]
125
+ .compact.join(" > ")
126
+ end
127
+ res
128
+ end
129
+
130
+ def command_d(command)
131
+ m = D_REGEXP.match(command)
132
+ return nil unless m
133
+
134
+ fire_count = m[3].to_i # 砲撃回数
135
+ fire_range = m[1].to_s # 砲撃範囲
136
+ ballistics = m[5].to_i # 《弾道学》
137
+
138
+ points = get_fire_points(fire_count, fire_range)
139
+ command = command.sub("SF/", "[大揺れ,火災]/").sub("FS/", "[火災,大揺れ]/").sub("F/", "[火災]/").sub("S/", "[大揺れ]/")
140
+ result = ["(#{command})", get_points_text(points, 0, 0)]
141
+ if ballistics != 0
142
+ dir = DIRECTION_INFOS[ballistics]
143
+ diff_x, diff_y = dir[:position_diff]
144
+ result[-1] += "\n"
145
+ result << "《弾道学》#{dir[:name]}"
146
+ result << get_points_text(points, diff_x, diff_y)
147
+ end
148
+
149
+ result.compact.join(" > ")
150
+ end
151
+
152
+ def command_avo(command)
153
+ debug("AVO", command)
154
+ dmg = command.match(/^AVO@([2468])(.*?)$/)
155
+ return nil unless dmg
156
+
157
+ dir = DIRECTION_INFOS[dmg[1].to_i]
158
+ diff_x, diff_y = dir[:position_diff]
159
+ "《回避運動》#{dir[:name]} > " + dmg[2].gsub(/\(?\[(\d),(\d{1,2})\]\)?/) do
160
+ y = Regexp.last_match(1).to_i + diff_y
161
+ x = Regexp.last_match(2).to_i + diff_x
162
+ get_xy_text(x, y)
163
+ end
164
+ end
165
+
166
+ def command_snavo(command)
167
+ sn, avo = command.split(%r{/?AVO}, 2)
168
+ debug("SNAVO", sn, avo)
169
+ am = /^@([2468])(.*?)$/.match(avo)
170
+ return nil unless am
171
+
172
+ res = command_sn(sn)
173
+ return nil unless res
174
+
175
+ if res.success?
176
+ res.text += "\n > " + command_avo("AVO" + avo)
177
+ end
178
+ res
179
+ end
180
+
181
+ def command_snd(command)
182
+ sn, d = command.split(%r{/?D}, 2)
183
+ debug("SND", sn, d)
184
+ m = D_REGEXP.match("D#{d}")
185
+ return nil unless m
186
+
187
+ res = command_sn(sn)
188
+ return nil unless res
189
+
190
+ if res.success?
191
+ res.text += "\n > #{command_d('D' + d)}"
192
+ end
193
+ res
194
+ end
195
+
196
+ def get_points_text(points, diff_x, diff_y)
197
+ "[縦,横]=" + points.map do |list|
198
+ list.map do |x, y|
199
+ get_xy_text(x + diff_x, y + diff_y)
200
+ end.join()
201
+ end.join(",")
202
+ end
203
+
204
+ # 範囲内なら[y,x]、範囲外なら([y,x])と表示
205
+ def get_xy_text(x, y)
206
+ if (2..12).include?(x) && (1..6).include?(y)
207
+ "[#{y},#{x}]"
208
+ else
209
+ "([#{y},#{x}])"
210
+ end
211
+ end
212
+
213
+ # 命中場所と範囲から、ダメージ位置を割り出す
214
+ def get_fire_points(fire_count, fire_range)
215
+ range = fire_range.chars.map(&:to_i)
216
+ fire_count.times.map do
217
+ y = @randomizer.roll_once(6) # 縦
218
+ x = @randomizer.roll_sum(2, 6) # 横
219
+
220
+ [[x, y]] + range.map do |r|
221
+ xdiff, ydiff = DIRECTION_INFOS[r][:position_diff]
222
+ [x + xdiff, y + ydiff]
223
+ end
224
+ end
225
+ end
226
+ end
227
+ end
228
+ end