bcdice 3.0.0.pre.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (258) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +21 -0
  3. data/.github/.codecov.yaml +10 -0
  4. data/.github/workflows/coverage.yaml +21 -0
  5. data/.github/workflows/lint.yaml +13 -0
  6. data/.github/workflows/test.yml +20 -0
  7. data/.gitignore +14 -0
  8. data/.rubocop.yml +96 -0
  9. data/.rubocop_todo.yml +113 -0
  10. data/CHANGELOG.md +868 -0
  11. data/Gemfile +11 -0
  12. data/LICENSE +29 -0
  13. data/README.md +38 -0
  14. data/ROADMAP.md +30 -0
  15. data/Rakefile +118 -0
  16. data/bcdice.gemspec +27 -0
  17. data/bin/repl.rb +21 -0
  18. data/docs/README.txt +2028 -0
  19. data/docs/dicebot_sort_key.md +72 -0
  20. data/docs/how_to_make_dicebot.md +453 -0
  21. data/lib/bcdice.rb +8 -0
  22. data/lib/bcdice/arithmetic_evaluator.rb +167 -0
  23. data/lib/bcdice/base.rb +423 -0
  24. data/lib/bcdice/command_parser.rb +242 -0
  25. data/lib/bcdice/common_command.rb +23 -0
  26. data/lib/bcdice/common_command/add_dice.rb +54 -0
  27. data/lib/bcdice/common_command/add_dice/node.rb +488 -0
  28. data/lib/bcdice/common_command/add_dice/parser.rb +282 -0
  29. data/lib/bcdice/common_command/add_dice/randomizer.rb +48 -0
  30. data/lib/bcdice/common_command/barabara_dice.rb +57 -0
  31. data/lib/bcdice/common_command/calc.rb +39 -0
  32. data/lib/bcdice/common_command/choice.rb +35 -0
  33. data/lib/bcdice/common_command/d66_dice.rb +63 -0
  34. data/lib/bcdice/common_command/reroll_dice.rb +190 -0
  35. data/lib/bcdice/common_command/upper_dice.rb +165 -0
  36. data/lib/bcdice/common_command/version.rb +26 -0
  37. data/lib/bcdice/dice_table.rb +8 -0
  38. data/lib/bcdice/dice_table/chain_table.rb +33 -0
  39. data/lib/bcdice/dice_table/d66_grid_table.rb +26 -0
  40. data/lib/bcdice/dice_table/d66_range_table.rb +26 -0
  41. data/lib/bcdice/dice_table/d66_table.rb +34 -0
  42. data/lib/bcdice/dice_table/range_table.rb +267 -0
  43. data/lib/bcdice/dice_table/roll_result.rb +43 -0
  44. data/lib/bcdice/dice_table/sai_fic_skill_table.rb +32 -0
  45. data/lib/bcdice/dice_table/table.rb +35 -0
  46. data/lib/bcdice/enum.rb +15 -0
  47. data/lib/bcdice/format.rb +36 -0
  48. data/lib/bcdice/game_system.rb +187 -0
  49. data/lib/bcdice/game_system/AFF2e.rb +141 -0
  50. data/lib/bcdice/game_system/AceKillerGene.rb +55 -0
  51. data/lib/bcdice/game_system/Airgetlamh.rb +117 -0
  52. data/lib/bcdice/game_system/Alsetto.rb +124 -0
  53. data/lib/bcdice/game_system/Alshard.rb +27 -0
  54. data/lib/bcdice/game_system/AlterRaise.rb +282 -0
  55. data/lib/bcdice/game_system/Amadeus.rb +622 -0
  56. data/lib/bcdice/game_system/Amadeus_Korean.rb +501 -0
  57. data/lib/bcdice/game_system/AnimaAnimus.rb +96 -0
  58. data/lib/bcdice/game_system/Arianrhod.rb +50 -0
  59. data/lib/bcdice/game_system/ArsMagica.rb +149 -0
  60. data/lib/bcdice/game_system/Avandner.rb +101 -0
  61. data/lib/bcdice/game_system/BBN.rb +143 -0
  62. data/lib/bcdice/game_system/BadLife.rb +435 -0
  63. data/lib/bcdice/game_system/BarnaKronika.rb +188 -0
  64. data/lib/bcdice/game_system/BattleTech.rb +530 -0
  65. data/lib/bcdice/game_system/BeastBindTrinity.rb +348 -0
  66. data/lib/bcdice/game_system/BeginningIdol.rb +2527 -0
  67. data/lib/bcdice/game_system/BeginningIdol_Korean.rb +2378 -0
  68. data/lib/bcdice/game_system/BladeOfArcana.rb +252 -0
  69. data/lib/bcdice/game_system/BlindMythos.rb +460 -0
  70. data/lib/bcdice/game_system/BloodCrusade.rb +423 -0
  71. data/lib/bcdice/game_system/BloodMoon.rb +213 -0
  72. data/lib/bcdice/game_system/CardRanker.rb +249 -0
  73. data/lib/bcdice/game_system/ChaosFlare.rb +181 -0
  74. data/lib/bcdice/game_system/Chill.rb +163 -0
  75. data/lib/bcdice/game_system/Chill3.rb +52 -0
  76. data/lib/bcdice/game_system/CodeLayerd.rb +132 -0
  77. data/lib/bcdice/game_system/ColossalHunter.rb +569 -0
  78. data/lib/bcdice/game_system/CrashWorld.rb +81 -0
  79. data/lib/bcdice/game_system/Cthulhu.rb +252 -0
  80. data/lib/bcdice/game_system/Cthulhu7th.rb +767 -0
  81. data/lib/bcdice/game_system/Cthulhu7th_ChineseTraditional.rb +386 -0
  82. data/lib/bcdice/game_system/Cthulhu7th_Korean.rb +383 -0
  83. data/lib/bcdice/game_system/CthulhuTech.rb +263 -0
  84. data/lib/bcdice/game_system/Cthulhu_ChineseTraditional.rb +243 -0
  85. data/lib/bcdice/game_system/Cthulhu_Korean.rb +240 -0
  86. data/lib/bcdice/game_system/DarkBlaze.rb +207 -0
  87. data/lib/bcdice/game_system/DarkDaysDrive.rb +425 -0
  88. data/lib/bcdice/game_system/DarkSouls.rb +91 -0
  89. data/lib/bcdice/game_system/DeadlineHeroes.rb +583 -0
  90. data/lib/bcdice/game_system/DemonParasite.rb +524 -0
  91. data/lib/bcdice/game_system/DetatokoSaga.rb +310 -0
  92. data/lib/bcdice/game_system/DetatokoSaga_Korean.rb +310 -0
  93. data/lib/bcdice/game_system/DiceBot.rb +17 -0
  94. data/lib/bcdice/game_system/DiceOfTheDead.rb +111 -0
  95. data/lib/bcdice/game_system/DoubleCross.rb +373 -0
  96. data/lib/bcdice/game_system/DoubleCross_Korean.rb +371 -0
  97. data/lib/bcdice/game_system/Dracurouge.rb +1856 -0
  98. data/lib/bcdice/game_system/Dracurouge_Korean.rb +310 -0
  99. data/lib/bcdice/game_system/DungeonsAndDragons.rb +19 -0
  100. data/lib/bcdice/game_system/EarthDawn.rb +225 -0
  101. data/lib/bcdice/game_system/EarthDawn3.rb +275 -0
  102. data/lib/bcdice/game_system/EarthDawn4.rb +272 -0
  103. data/lib/bcdice/game_system/EclipsePhase.rb +51 -0
  104. data/lib/bcdice/game_system/Elric.rb +36 -0
  105. data/lib/bcdice/game_system/Elysion.rb +1213 -0
  106. data/lib/bcdice/game_system/EmbryoMachine.rb +227 -0
  107. data/lib/bcdice/game_system/EndBreaker.rb +132 -0
  108. data/lib/bcdice/game_system/EtrianOdysseySRS.rb +27 -0
  109. data/lib/bcdice/game_system/Fiasco.rb +123 -0
  110. data/lib/bcdice/game_system/Fiasco_Korean.rb +122 -0
  111. data/lib/bcdice/game_system/FilledWith.rb +1543 -0
  112. data/lib/bcdice/game_system/FullMetalPanic.rb +27 -0
  113. data/lib/bcdice/game_system/FutariSousa.rb +994 -0
  114. data/lib/bcdice/game_system/FutariSousa_Korean.rb +994 -0
  115. data/lib/bcdice/game_system/Garako.rb +559 -0
  116. data/lib/bcdice/game_system/GardenOrder.rb +451 -0
  117. data/lib/bcdice/game_system/GehennaAn.rb +136 -0
  118. data/lib/bcdice/game_system/GeishaGirlwithKatana.rb +120 -0
  119. data/lib/bcdice/game_system/GoblinSlayer.rb +168 -0
  120. data/lib/bcdice/game_system/GoldenSkyStories.rb +77 -0
  121. data/lib/bcdice/game_system/Gorilla.rb +44 -0
  122. data/lib/bcdice/game_system/GranCrest.rb +518 -0
  123. data/lib/bcdice/game_system/Gundog.rb +52 -0
  124. data/lib/bcdice/game_system/GundogRevised.rb +294 -0
  125. data/lib/bcdice/game_system/GundogZero.rb +261 -0
  126. data/lib/bcdice/game_system/Gurps.rb +403 -0
  127. data/lib/bcdice/game_system/GurpsFW.rb +2330 -0
  128. data/lib/bcdice/game_system/HarnMaster.rb +208 -0
  129. data/lib/bcdice/game_system/HatsuneMiku.rb +706 -0
  130. data/lib/bcdice/game_system/Hieizan.rb +48 -0
  131. data/lib/bcdice/game_system/HouraiGakuen.rb +270 -0
  132. data/lib/bcdice/game_system/HuntersMoon.rb +503 -0
  133. data/lib/bcdice/game_system/Illusio.rb +89 -0
  134. data/lib/bcdice/game_system/InfiniteFantasia.rb +51 -0
  135. data/lib/bcdice/game_system/Insane.rb +822 -0
  136. data/lib/bcdice/game_system/Insane_Korean.rb +773 -0
  137. data/lib/bcdice/game_system/IthaWenUa.rb +38 -0
  138. data/lib/bcdice/game_system/JamesBond.rb +45 -0
  139. data/lib/bcdice/game_system/Kamigakari.rb +394 -0
  140. data/lib/bcdice/game_system/Kamigakari_Korean.rb +428 -0
  141. data/lib/bcdice/game_system/KanColle.rb +938 -0
  142. data/lib/bcdice/game_system/KemonoNoMori.rb +258 -0
  143. data/lib/bcdice/game_system/KillDeathBusiness.rb +1420 -0
  144. data/lib/bcdice/game_system/KillDeathBusiness_Korean.rb +1510 -0
  145. data/lib/bcdice/game_system/KurayamiCrying.rb +49 -0
  146. data/lib/bcdice/game_system/LiveraDoll.rb +375 -0
  147. data/lib/bcdice/game_system/LogHorizon.rb +3567 -0
  148. data/lib/bcdice/game_system/LogHorizon_Korean.rb +1407 -0
  149. data/lib/bcdice/game_system/LostRecord.rb +30 -0
  150. data/lib/bcdice/game_system/LostRoyal.rb +242 -0
  151. data/lib/bcdice/game_system/MagicaLogia.rb +1148 -0
  152. data/lib/bcdice/game_system/MeikyuDays.rb +415 -0
  153. data/lib/bcdice/game_system/MeikyuKingdom.rb +466 -0
  154. data/lib/bcdice/game_system/MeikyuKingdomBasic.rb +269 -0
  155. data/lib/bcdice/game_system/MetalHead.rb +249 -0
  156. data/lib/bcdice/game_system/MetalHeadExtream.rb +917 -0
  157. data/lib/bcdice/game_system/MetallicGuardian.rb +31 -0
  158. data/lib/bcdice/game_system/MonotoneMuseum.rb +354 -0
  159. data/lib/bcdice/game_system/MonotoneMuseum_Korean.rb +304 -0
  160. data/lib/bcdice/game_system/Nechronica.rb +211 -0
  161. data/lib/bcdice/game_system/Nechronica_Korean.rb +160 -0
  162. data/lib/bcdice/game_system/NeverCloud.rb +74 -0
  163. data/lib/bcdice/game_system/NightWizard.rb +231 -0
  164. data/lib/bcdice/game_system/NightWizard3rd.rb +24 -0
  165. data/lib/bcdice/game_system/NightmareHunterDeep.rb +117 -0
  166. data/lib/bcdice/game_system/NinjaSlayer.rb +274 -0
  167. data/lib/bcdice/game_system/NjslyrBattle.rb +54 -0
  168. data/lib/bcdice/game_system/Nuekagami.rb +293 -0
  169. data/lib/bcdice/game_system/OneWayHeroics.rb +134 -0
  170. data/lib/bcdice/game_system/OracleEngine.rb +265 -0
  171. data/lib/bcdice/game_system/OrgaRain.rb +77 -0
  172. data/lib/bcdice/game_system/Oukahoushin3rd.rb +162 -0
  173. data/lib/bcdice/game_system/Paradiso.rb +323 -0
  174. data/lib/bcdice/game_system/Paranoia.rb +64 -0
  175. data/lib/bcdice/game_system/ParanoiaRebooted.rb +109 -0
  176. data/lib/bcdice/game_system/ParasiteBlood.rb +231 -0
  177. data/lib/bcdice/game_system/Pathfinder.rb +21 -0
  178. data/lib/bcdice/game_system/Peekaboo.rb +324 -0
  179. data/lib/bcdice/game_system/Pendragon.rb +39 -0
  180. data/lib/bcdice/game_system/PhantasmAdventure.rb +73 -0
  181. data/lib/bcdice/game_system/Postman.rb +185 -0
  182. data/lib/bcdice/game_system/PulpCthulhu.rb +184 -0
  183. data/lib/bcdice/game_system/Raisondetre.rb +171 -0
  184. data/lib/bcdice/game_system/RecordOfLodossWar.rb +58 -0
  185. data/lib/bcdice/game_system/RecordOfSteam.rb +149 -0
  186. data/lib/bcdice/game_system/RokumonSekai2.rb +110 -0
  187. data/lib/bcdice/game_system/RoleMaster.rb +24 -0
  188. data/lib/bcdice/game_system/RuneQuest.rb +47 -0
  189. data/lib/bcdice/game_system/RyuTuber.rb +266 -0
  190. data/lib/bcdice/game_system/Ryutama.rb +199 -0
  191. data/lib/bcdice/game_system/SRS.rb +348 -0
  192. data/lib/bcdice/game_system/SamsaraBallad.rb +111 -0
  193. data/lib/bcdice/game_system/Satasupe.rb +1173 -0
  194. data/lib/bcdice/game_system/ScreamHighSchool.rb +128 -0
  195. data/lib/bcdice/game_system/SevenFortressMobius.rb +34 -0
  196. data/lib/bcdice/game_system/ShadowRun.rb +26 -0
  197. data/lib/bcdice/game_system/ShadowRun4.rb +49 -0
  198. data/lib/bcdice/game_system/ShadowRun5.rb +80 -0
  199. data/lib/bcdice/game_system/SharedFantasia.rb +69 -0
  200. data/lib/bcdice/game_system/ShinMegamiTenseiKakuseihen.rb +85 -0
  201. data/lib/bcdice/game_system/ShinkuuGakuen.rb +506 -0
  202. data/lib/bcdice/game_system/ShinobiGami.rb +680 -0
  203. data/lib/bcdice/game_system/ShoujoTenrankai.rb +677 -0
  204. data/lib/bcdice/game_system/Skynauts.rb +324 -0
  205. data/lib/bcdice/game_system/SteamPunkers.rb +485 -0
  206. data/lib/bcdice/game_system/StellarKnights.rb +856 -0
  207. data/lib/bcdice/game_system/SterileLife.rb +452 -0
  208. data/lib/bcdice/game_system/StrangerOfSwordCity.rb +103 -0
  209. data/lib/bcdice/game_system/StratoShout.rb +316 -0
  210. data/lib/bcdice/game_system/StratoShout_Korean.rb +314 -0
  211. data/lib/bcdice/game_system/Strave.rb +223 -0
  212. data/lib/bcdice/game_system/SwordWorld.rb +491 -0
  213. data/lib/bcdice/game_system/SwordWorld2_0.rb +295 -0
  214. data/lib/bcdice/game_system/SwordWorld2_5.rb +121 -0
  215. data/lib/bcdice/game_system/TherapieSein.rb +93 -0
  216. data/lib/bcdice/game_system/TokumeiTenkousei.rb +96 -0
  217. data/lib/bcdice/game_system/TokyoGhostResearch.rb +122 -0
  218. data/lib/bcdice/game_system/TokyoNova.rb +19 -0
  219. data/lib/bcdice/game_system/Torg.rb +364 -0
  220. data/lib/bcdice/game_system/Torg1_5.rb +139 -0
  221. data/lib/bcdice/game_system/TorgEternity.rb +414 -0
  222. data/lib/bcdice/game_system/TrinitySeven.rb +364 -0
  223. data/lib/bcdice/game_system/TunnelsAndTrolls.rb +287 -0
  224. data/lib/bcdice/game_system/TwilightGunsmoke.rb +527 -0
  225. data/lib/bcdice/game_system/Utakaze.rb +153 -0
  226. data/lib/bcdice/game_system/VampireTheMasquerade5th.rb +132 -0
  227. data/lib/bcdice/game_system/Villaciel.rb +555 -0
  228. data/lib/bcdice/game_system/WARPS.rb +33 -0
  229. data/lib/bcdice/game_system/WaresBlade.rb +34 -0
  230. data/lib/bcdice/game_system/Warhammer.rb +336 -0
  231. data/lib/bcdice/game_system/WitchQuest.rb +275 -0
  232. data/lib/bcdice/game_system/WorldOfDarkness.rb +135 -0
  233. data/lib/bcdice/game_system/YankeeYogSothoth.rb +440 -0
  234. data/lib/bcdice/game_system/YearZeroEngine.rb +134 -0
  235. data/lib/bcdice/game_system/ZettaiReido.rb +142 -0
  236. data/lib/bcdice/game_system/meikyu_kingdom/item_table.rb +383 -0
  237. data/lib/bcdice/game_system/meikyu_kingdom/kingdom_name_table.rb +89 -0
  238. data/lib/bcdice/game_system/meikyu_kingdom/landscape_table.rb +196 -0
  239. data/lib/bcdice/game_system/meikyu_kingdom/name_tables.rb +223 -0
  240. data/lib/bcdice/game_system/meikyu_kingdom/placename_table.rb +214 -0
  241. data/lib/bcdice/game_system/meikyu_kingdom/tables.rb +610 -0
  242. data/lib/bcdice/game_system/meikyu_kingdom/word_table.rb +117 -0
  243. data/lib/bcdice/game_system/meikyu_kingdom_basic/item_table.rb +380 -0
  244. data/lib/bcdice/game_system/meikyu_kingdom_basic/kingdom_table.rb +184 -0
  245. data/lib/bcdice/game_system/meikyu_kingdom_basic/name_table.rb +417 -0
  246. data/lib/bcdice/game_system/meikyu_kingdom_basic/table.rb +912 -0
  247. data/lib/bcdice/game_system/meikyu_kingdom_basic/word_table.rb +121 -0
  248. data/lib/bcdice/game_system/one_way_heroics/dungeon_table.rb +67 -0
  249. data/lib/bcdice/game_system/one_way_heroics/random_event_table.rb +166 -0
  250. data/lib/bcdice/game_system/one_way_heroics/tables.rb +668 -0
  251. data/lib/bcdice/loader.rb +37 -0
  252. data/lib/bcdice/normalize.rb +38 -0
  253. data/lib/bcdice/preprocessor.rb +87 -0
  254. data/lib/bcdice/randomizer.rb +137 -0
  255. data/lib/bcdice/repl.rb +155 -0
  256. data/lib/bcdice/user_defined_dice_table.rb +153 -0
  257. data/lib/bcdice/version.rb +3 -0
  258. metadata +304 -0
@@ -0,0 +1,324 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class Skynauts < Base
6
+ # ゲームシステムの識別子
7
+ ID = 'Skynauts'
8
+
9
+ # ゲームシステム名
10
+ NAME = '歯車の塔の探空士'
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = 'すかいのおつ'
14
+
15
+ # ダイスボットの使い方
16
+ HELP_MESSAGE = <<~MESSAGETEXT
17
+ ◆判定 (SNn)、(2D6<=n) n:目標値(省略時:7)
18
+  例)SN5 SN5 SN(3+2)
19
+ ◆航行チェック (NV+n) n:修正値(省略時:0)
20
+  例)NV NV+1
21
+ ◆ダメージチェック (Dx/y@m) x:ダメージ左側の値、y:ダメージ右側の値
22
+  m:《弾道学》(省略可)上:8、下:2、左:4、右:6
23
+  飛空艇シート外の座標は()が付きます。
24
+  例) D/4 D19/2 D/3@8 D[大揺れ]/2
25
+ ◆砲撃判定+ダメージチェック (BOMn/Dx/y@m) n:目標値(省略時:7)
26
+  x:ダメージ左側の値、y:ダメージ右側の値
27
+  m:《弾道学》(省略可)上:8、下:2、左:4、右:6
28
+  例) BOM/D/4 BOM9/D19@4
29
+ ◆《回避運動》 (AVOn@mXX) n:目標値(省略時:7)
30
+  m:回避方向。上:8、下:2、左:4、右:6、XX:ダメージチェック結果
31
+  例)
32
+  AVO9@8[縦1,横4],[縦2,横6],[縦3,横8] AVO@2[縦6,横4],[縦2,横6]
33
+ MESSAGETEXT
34
+
35
+ register_prefix(['D.*', '2[Dd]6<=.*', 'SN.*', 'NV.*', 'AVO.*', 'BOM.*'])
36
+
37
+ def initialize(command)
38
+ super(command)
39
+ @round_type = RoundType::FLOOR # 端数切り捨て
40
+ end
41
+
42
+ def eval_game_system_specific_command(command)
43
+ debug("\n=======================================\n")
44
+ debug("eval_game_system_specific_command command", command)
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
68
+ end
69
+
70
+ def getJudgeResult(command)
71
+ return nil unless (m = (/^2D6<=(\d)$/i.match(command) || /^SN(\d*)$/i.match(command)))
72
+
73
+ debug("====getJudgeResult====")
74
+
75
+ target = m[1].empty? ? 7 : m[1].to_i # 目標値。省略時は7
76
+ debug("目標値", target)
77
+
78
+ dice_list = @randomizer.roll_barabara(2, 6)
79
+ total = dice_list.sum()
80
+ diceText = dice_list.join(",")
81
+
82
+ if total <= 2
83
+ result = "ファンブル"
84
+ elsif total <= target
85
+ result = "成功"
86
+ else
87
+ result = "失敗"
88
+ end
89
+
90
+ text = "(2D6<=#{target}) > #{total}[#{diceText}] > #{total} > #{result}"
91
+
92
+ return text
93
+ end
94
+
95
+ def navigationResult(command)
96
+ return nil unless (m = /^NV(\+(\d+))?$/.match(command))
97
+
98
+ debug("====navigationResult====")
99
+
100
+ bonus = m[2].to_i # 〈操舵室〉の修正。GMの任意修正にも対応できるように(マイナスは無視)
101
+ debug("移動修正", bonus)
102
+
103
+ total = @randomizer.roll_once(6)
104
+ movePointBase = (total / 2) <= 0 ? 1 : (total / 2)
105
+ movePoint = movePointBase + bonus
106
+ debug("移動エリア数", movePoint)
107
+
108
+ text = "航行チェック(最低1) (1D6/2+#{bonus}) > #{total} /2+#{bonus} > "
109
+ text += "#{movePointBase}+#{bonus} > #{movePoint}エリア進む"
110
+
111
+ return text
112
+ end
113
+
114
+ DIRECTION_INFOS = {
115
+ 1 => {name: "左下", position_diff: {x: -1, y: +1}},
116
+ 2 => {name: "下", position_diff: {x: 0, y: +1}},
117
+ 3 => {name: "右下", position_diff: {x: +1, y: +1}},
118
+ 4 => {name: "左", position_diff: {x: -1, y: 0}},
119
+ # 5 は中央。算出する意味がないので対象外
120
+ 6 => {name: "右", position_diff: {x: +1, y: 0}},
121
+ 7 => {name: "左上", position_diff: {x: -1, y: -1}},
122
+ 8 => {name: "上", position_diff: {x: 0, y: -1}},
123
+ 9 => {name: "右上", position_diff: {x: +1, y: -1}},
124
+ }.freeze
125
+
126
+ def getDirectionInfo(direction, key, defaultValue = nil)
127
+ info = DIRECTION_INFOS[direction.to_i]
128
+ return defaultValue if info.nil?
129
+
130
+ return info[key]
131
+ end
132
+
133
+ def getFireResult(command)
134
+ return nil unless (m = %r{^D([12346789]*)(\[.+\])*/(\d+)(@([2468]))?$}.match(command))
135
+
136
+ debug("====getFireResult====")
137
+
138
+ fireCount = m[3].to_i # 砲撃回数
139
+ fireRange = m[1].to_s # 砲撃範囲
140
+ ballistics = m[5].to_i # 《弾道学》
141
+ debug("fireCount", fireCount)
142
+ debug("fireRange", fireRange)
143
+ debug("ballistics", ballistics)
144
+
145
+ fireCountMax = 25
146
+ fireCount = [fireCount, fireCountMax].min
147
+
148
+ firePoint = getFirePoint(fireRange, fireCount) # 着弾座標取得(3次元配列)
149
+ fireText = getFirePointText(firePoint, fireCount) # 表示用文字列作成
150
+
151
+ if ballistics != 0 # 《弾道学》有
152
+ fireText += " > 《弾道学》:"
153
+ fireText += getDirectionInfo(ballistics, :name, "")
154
+ fireText += "\n > "
155
+ fireText += getFirePointText(firePoint, fireCount, ballistics)
156
+ end
157
+
158
+ text = "#{command} > #{fireText}"
159
+
160
+ return text
161
+ end
162
+
163
+ def getFirePoint(fireRange, fireCount)
164
+ debug("====getFirePoint====")
165
+
166
+ firePoint = []
167
+
168
+ fireCount.times do |count|
169
+ debug("\n砲撃回数", count + 1)
170
+
171
+ firePoint << []
172
+
173
+ yPos = @randomizer.roll_once(6) # 縦
174
+ xPos = @randomizer.roll_sum(2, 6) # 横
175
+ position = [xPos, yPos]
176
+
177
+ firePoint[-1] << position
178
+
179
+ debug("着弾点", firePoint)
180
+
181
+ fireRange.split(//).each do |rangeText|
182
+ debug("範囲", rangeText)
183
+
184
+ position_diff = getDirectionInfo(rangeText, :position_diff, {})
185
+ position = [xPos + position_diff[:x].to_i, yPos + position_diff[:y].to_i]
186
+
187
+ firePoint[-1] << position
188
+ debug("着弾点:範囲", firePoint)
189
+ end
190
+ end
191
+
192
+ debug("\n最終着弾点", firePoint)
193
+
194
+ return firePoint
195
+ end
196
+
197
+ def getFirePointText(firePoint, _fireCount, direction = 0)
198
+ debug("====getFirePointText====")
199
+
200
+ fireTextList = []
201
+ firePoint.each do |point|
202
+ text = ""
203
+ point.each do |x, y|
204
+ # 《弾道学》《回避運動》などによる座標移動
205
+ x, y = getMovePoint(x, y, direction)
206
+
207
+ # マップ外の座標は括弧を付ける
208
+ text += (isInMapPosition(x, y) ? "[縦#{y},横#{x}]" : "([縦#{y},横#{x}])")
209
+ debug("着弾点テキスト", text)
210
+ end
211
+
212
+ fireTextList << text
213
+ end
214
+
215
+ fireText = fireTextList.join(",")
216
+
217
+ debug("\n最終着弾点テキスト", fireText)
218
+ return fireText
219
+ end
220
+
221
+ def isInMapPosition(x, y)
222
+ ((1 <= y) && (y <= 6)) && ((2 <= x) && (x <= 12))
223
+ end
224
+
225
+ def getMovePoint(x, y, direction)
226
+ debug("====getMovePoint====")
227
+ debug("方向", direction)
228
+ debug("座標移動前x", x)
229
+ debug("座標移動前y", y)
230
+
231
+ position_diff = getDirectionInfo(direction, :position_diff, {})
232
+ x += position_diff[:x].to_i
233
+ y += position_diff[:y].to_i
234
+
235
+ debug("\n座標移動後x", x)
236
+ debug("座標移動後y", y)
237
+ return x, y
238
+ end
239
+
240
+ def getBomberResult(command)
241
+ return nil unless (m = %r{^BOM(\d*)?/D([12346789]*)(\[.+\])*/(\d+)(@([2468]))?$}i.match(command))
242
+
243
+ debug("====getBomberResult====", command)
244
+
245
+ target = m[1].to_s
246
+ direction = m[6].to_i
247
+ debug("弾道学方向", direction)
248
+
249
+ text = "#{command} > "
250
+ text += getJudgeResult("SN" + target) # 砲撃判定
251
+
252
+ return text unless text =~ /成功/
253
+
254
+ # ダメージチェック部分
255
+ fireCommand = command.slice(%r{D([12346789]*)(\[.+\])*/(\d+)(@([2468]))?})
256
+
257
+ text += "\n > #{getFireResult(fireCommand)}"
258
+
259
+ return text
260
+ end
261
+
262
+ def getAvoidResult(command)
263
+ return nil unless (m = /^AVO(\d*)?(@([2468]))(\(?\[縦\d+,横\d+\]\)?,?)+$/.match(command))
264
+
265
+ debug("====getAvoidResult====", command)
266
+
267
+ direction = m[3].to_i
268
+ debug("回避方向", direction)
269
+
270
+ judgeCommand = command.slice(/^AVO(\d*)?(@([2468]))/) # 判定部分
271
+ text = "#{judgeCommand} > 《回避運動》"
272
+ text += getJudgeResult("SN" + Regexp.last_match(1).to_s) # 操舵判定
273
+
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
288
+ end
289
+
290
+ def scanFirePoints(command)
291
+ debug("====scanFirePoints====", command)
292
+
293
+ command = command.gsub(/\(|\)/, "") # 正規表現が大変なので最初に括弧を外しておく
294
+
295
+ firePoint = []
296
+
297
+ # 一組ずつに分ける("[縦y,横xの単位)
298
+ command.split(/\],/).each do |pointText|
299
+ debug("pointText", pointText)
300
+
301
+ firePoint << []
302
+
303
+ # D以外の砲撃範囲がある時に必要
304
+ pointText.split(/\]/).each do |point|
305
+ debug("point", point)
306
+
307
+ firePoint[-1] << []
308
+
309
+ next unless point =~ /[^\d]*(\d+),[^\d]*(\d+)/
310
+
311
+ y = Regexp.last_match(1).to_i
312
+ x = Regexp.last_match(2).to_i
313
+
314
+ firePoint[-1][-1] = [x, y]
315
+
316
+ debug("着弾点", firePoint)
317
+ end
318
+ end
319
+
320
+ return firePoint
321
+ end
322
+ end
323
+ end
324
+ end
@@ -0,0 +1,485 @@
1
+ require 'bcdice/dice_table/d66_range_table'
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class SteamPunkers < Base
6
+ ID = 'SteamPunkers'.freeze
7
+ NAME = 'スチームパンカーズ'.freeze
8
+ SORT_KEY = 'すちいむはんかあす'.freeze
9
+
10
+ HELP_MESSAGE = <<~MESSAGETEXT.freeze
11
+ ・判定コマンド (SPn)
12
+ SP(判定ダイス数)>=(目標値)
13
+ SP4>=3のように入力し、5が出たらヒット数1,6が出たらヒット数2として成功数を数えます。
14
+ ≪スチームパンク!≫による振り直しのため、出力には失敗ダイス数を表示します。
15
+ 目標値は省略可能です。
16
+ 例:(SP4>=3) > [3,4,1,6] > 成功数:2, 失敗数:3 > 失敗
17
+ 例:(SP4) > [3,4,1,6] > 成功数:2, 失敗数:3
18
+ ・表
19
+ ・プロフ(Profile):年齢表 PAT, 性別表 PST, 国籍表 PCT
20
+ ・名前表(Name):イギリス NIT, アメリカ NAT, フランス NFT, ドイツ NGT, ソビエト NST, 日本表 NJT
21
+ ・過去表(Past):トゥルース PTT, ガーディアン PGT, ノーブル PNT, デヴォート PDT, エセティック PET, チャレンジ PCT
22
+ ・経緯表(Background):ギガントアームズ BGT, アーマードリム BAT, エッジモービル BET, クロノウェポン BCT, スパイテック BST, スチームウェア BWT
23
+ ・特徴表(Feature):特徴表S FST, 特徴表P FPT
24
+ ・関係性表(Relationship):関係性表S RST, 関係性表P RPT
25
+ ・感情表(Emotion):感情表S EST, 感情表P EPT
26
+ ・その他(Other);災厄表 ODT, 場面表 OST, 交流表 OIT, 激憤表 OFT
27
+ MESSAGETEXT
28
+
29
+ def eval_game_system_specific_command(command)
30
+ result = roll_tables(command, TABLES)
31
+ return result if result
32
+
33
+ return roll_sp(command)
34
+ end
35
+
36
+ def roll_sp(command)
37
+ m = /^SP(\d+)(?:>=(\d+))?$/i.match(command)
38
+ unless m
39
+ return nil
40
+ end
41
+
42
+ dice_count = m[1].to_i
43
+ target_number = m[2]&.to_i
44
+
45
+ dice_list = @randomizer.roll_barabara(dice_count, 6)
46
+ dice_list_text = dice_list.join(',')
47
+
48
+ successes = dice_list.count(6) * 2 + dice_list.count(5)
49
+ failures = dice_list.count { |x| x <= 4 }
50
+
51
+ result =
52
+ if dice_list.all? { |x| x == 1 }
53
+ "ファンブル"
54
+ elsif target_number
55
+ successes >= target_number ? "成功" : "失敗"
56
+ end
57
+
58
+ sequence = [
59
+ "(#{command})",
60
+ "[#{dice_list_text}]",
61
+ "成功数:#{successes}, 失敗数:#{failures}",
62
+ result
63
+ ].compact
64
+
65
+ return sequence.join(" > ")
66
+ end
67
+
68
+ # スチームパンカーズ用のテーブル
69
+ class SPTable < DiceTable::D66RangeTable
70
+ # @param name [String]
71
+ # @param items [Array<String>]
72
+ def initialize(name, items)
73
+ if items.size != RANGE.size
74
+ raise UnexpectedTableSize.new(name, items.size)
75
+ end
76
+
77
+ items_with_range = RANGE.zip(items)
78
+
79
+ super(name, items_with_range)
80
+ end
81
+
82
+ # 23..32 と 61..66 が6パターン分
83
+ # その他が4パターン分
84
+ RANGE = [11..14, 15..22, 23..32, 33..36, 41..44, 45..52, 53..56, 61..66].freeze
85
+ end
86
+
87
+ class UnexpectedTableSize < StandardError; end
88
+
89
+ TABLES = {
90
+ "PAT" => SPTable.new(
91
+ "年齢表",
92
+ [
93
+ "【14~15歳】 まだまだ、子ども扱い。また、過去の内容は父か母のことを指している。",
94
+ "【16~17歳】 そろそろ成人として扱われる。また、過去の内容は父か母のことを指している。",
95
+ "【18~19歳】 職場では修行期間中である。また、過去の内容は両親のことか、あなた自身のことだ。",
96
+ "【20~21歳】 ようやく一人前の年齢である。また、過去の内容は両親のことか、あなた自身のことだ",
97
+ "【22~23歳】 働き盛りである。また、過去の内容はあなた自身のことだ。",
98
+ "【24~25歳】 働き盛りである。また、過去の内容はあなた自身のことだ。",
99
+ "【26~27歳】 かつて、従軍した可能性がある。また、過去の内容はあなた自身のことだ。",
100
+ "【28~30歳】 蒸気大戦末期をよく知っている。また、過去の内容はあなた自身のことだ。"
101
+ ]
102
+ ),
103
+ "PST" => SPTable.new(
104
+ "性別表",
105
+ [
106
+ "【男性】 背が高く、がっしりしている。",
107
+ "【女性】 蠱惑的な身体をしている。",
108
+ "【男性】 平均的な中肉中背である。",
109
+ "【女性】 女性らしい体形をしている。",
110
+ "【男性】 近世の取れた肉体をしている。",
111
+ "【女性】 彫刻のように美しい体形である。",
112
+ "【男性】 一見すると細身に見える。",
113
+ "【女性】 スリムな体形をしている。"
114
+ ]
115
+ ),
116
+ "PCT" => SPTable.new(
117
+ "国籍表",
118
+ [
119
+ "【日本皇国】 あなたは日本人である。",
120
+ "【フランス共和国】 あなたはフランス人である。",
121
+ "【アメリカ合衆国】 あなたはアメリカ人である。",
122
+ "【イギリス王国】 あなたはイギリス人である。",
123
+ "【イギリス王国】 あなたはイギリス人である。",
124
+ "【イギリス王国】 あなたはイギリス人である。",
125
+ "【ドイツ帝国】 あなたはドイツ人である。",
126
+ "【ソビエト連邦】 あなたはソビエト人である。"
127
+ ]
128
+ ),
129
+ "NIT" => SPTable.new(
130
+ "名前表・イギリス(男性名/女性名/名字)",
131
+ [
132
+ "アーロン/アビゲイル/アダム",
133
+ "カラム/オーレリア/バーナード",
134
+ "クライヴ/ブレンダ/ビーチャム",
135
+ "カーティス/キャロライン/ビリンガム",
136
+ "ダンカン/クリス/ボイド",
137
+ "アイオン/イーニッド/クロムウェル",
138
+ "ネイサン/グレイス/エアハート",
139
+ "ウィリアム/ローレンシア/ハックワース"
140
+ ]
141
+ ),
142
+ "NAT" => SPTable.new(
143
+ "名前表・アメリカ(男性名/女性名/名字)",
144
+ [
145
+ "ジェラルド/デイジー/キャンベル",
146
+ "クラーク/ベアトリス/ベックフォード",
147
+ "ヴィクター/ケイト/ガードナー",
148
+ "ザック/ルシール/キンケイド",
149
+ "ヘクター/エレイン/コールリッジ",
150
+ "アーサー/アンジェリカ/アレクサンダー",
151
+ "アドニス/アルダ/オースティン",
152
+ "ランバート/イヴ/デビットソン"
153
+ ]
154
+ ),
155
+ "NFT" => SPTable.new(
156
+ "名前表・フランス(男性名/女性名/名字)",
157
+ [
158
+ "ベルナール/ベアトリス/バシュラール",
159
+ "セドリック/セシリア/ベルモンド",
160
+ "エルネスト/コレット/ボニツェール",
161
+ "フレデリック/エルザ/ボワイエ",
162
+ "ロランド/リュクレース/ディノワール",
163
+ "イアサント/アンリエット/シャルトー",
164
+ "バスティアン/ブリジット/オードラン",
165
+ "ルイ/リリアーヌ/ドラクランジュ"
166
+ ]
167
+ ),
168
+ "NGT" => SPTable.new(
169
+ "名前表・ドイツ(男性名/女性名/名字)",
170
+ [
171
+ "アルベルト/アデーレ/アッカーマン",
172
+ "バシリウス/アルマ/バルツァー",
173
+ "ブルーノ/クリステル/ビットナー",
174
+ "エトムント/エルネスタ/コルネリウス",
175
+ "ゴッツ/クラリッサ/アイヒマン",
176
+ "ヨハン/モニカ/フリードリヒ",
177
+ "レオンハルト/オクタヴィア/ハイセルタ",
178
+ "ブルクハルト/クロジンデ/ビンデバルト"
179
+ ]
180
+ ),
181
+ "NST" => SPTable.new(
182
+ "名前表・ソビエト(男性名/女性名/名字)",
183
+ [
184
+ "イリイチ/バルバラ/バビチェフ",
185
+ "ミハイル/ジナイーダ/ボブロフ",
186
+ "セルゲイ/クラーラ/ヴォルコフ",
187
+ "イヴァン/レイラ/ガボエフ",
188
+ "アラン/オルガ/ジェミチェフ",
189
+ "ボリス/ナタリヤ/ドミトリエフ",
190
+ "ウラジミル/ソフィア/エルマコフ",
191
+ "アレクセイ/マルタ/ダンチェンコ"
192
+ ]
193
+ ),
194
+ "NJT" => SPTable.new(
195
+ "名前表・日本(男性名/女性名/名字)",
196
+ [
197
+ "タキジ/タキ/トウドウ",
198
+ "シンヤ/アヤ/マツモト",
199
+ "レイジ/カオルコ/サガラ",
200
+ "コウタロウ/セン/オオシマ",
201
+ "ヒロシ/チサ/クジョウ",
202
+ "ジロウ/カナ/ヤマガタ",
203
+ "マサヒト/マイ/イトウ",
204
+ "ショウジ/アヤメ/シンドウ"
205
+ ]
206
+ ),
207
+ "PTT" => SPTable.new(
208
+ "過去表『トゥルース』",
209
+ [
210
+ "【決着】 あなたは怨敵である蒸気事件の犯人を追っている。いつの日か、そいつとは決着をつけるつもりだ。",
211
+ "【陰謀】 とある陰謀により、あなたは故郷、あるいはかつての地位を失ってしまった。",
212
+ "【後悔】 ある蒸気事件を解決できなかった。結果、あなたは大切な人を失ってしまった。",
213
+ "【失踪】 かつて、あなたが愛した人は不自然な失踪を遂げてしまった。あの人はいったいどこへ……?",
214
+ "【冤罪】 ある陰謀により、あなたは冤罪をかけられ、かつての地位を追われてしまった。",
215
+ "【裏切り】 とある蒸気事件の際に無二の親友があなたを裏切り、理由も告げぬまま消え去った。",
216
+ "【誓い】 とある陰謀により、あなたは大切な何かを失った。いつか陰謀を暴く……それがあなたの誓いだ。",
217
+ "【喪失】 とある蒸気事件の際、あなたの家族は何者かの手により惨殺された。犯人は今も見つかっていない。"
218
+ ]
219
+ ),
220
+ "PGT" => SPTable.new(
221
+ "過去表『ガーディアン』",
222
+ [
223
+ "【後悔】 ある蒸気事件を解決できなかった。結果、あなたは大切な人を失ってしまった。",
224
+ "【贖罪】 あなたは過去に罪なき人々の虐殺を強制させられた。だから、贖罪のために人々を護っている。",
225
+ "【無力】 かつて、あなたは無力だった。そして、無力ゆえに大切な人を護ることができなかった。",
226
+ "【憧れ】 あなたの憧れた人は、いつだって弱者の味方だった。そして、あなたはあの人の背中を追い続けている。",
227
+ "【使命】 弱き者たちの盾となる。それが生まれたときから、あなたに課せられ唯一の使命だった。",
228
+ "【見殺し】 あなたはやむを得ない事情により、仲間を見殺しにしてしまった。だから、次は絶対見殺しにしない。",
229
+ "【死別】 とある事件の際、あなたは家族を護りきれず失ってしまった。だから……今度こそ護ってみせる。",
230
+ "【庇護】 現在、あなたには護るべき人、護るべき場所がある。それらの日常を護るべく、あなたは戦ったいる。"
231
+ ]
232
+ ),
233
+ "PNT" => SPTable.new(
234
+ "過去表『ノーブル』",
235
+ [
236
+ "【復讐】 あなたの家族は蒸気事件の犠牲となった。ゆえに、あなたは家族の仇を討つべく犯人を捜している。",
237
+ "【理不尽】 あなたは幼少期に、心優しかった使用人が理不尽な虐待の末に殺害される場面を目撃してしまった。",
238
+ "【反発】 あなたの親は悪徳を重ねる権力者だった。そんな親が嫌いで、あなたは常に反発していた。",
239
+ "【高貴】 あなたは生来から高貴な信念の持ち主だ。それゆえ弱者を救い、導くことに疑問はない。",
240
+ "【偽物】 あなたは貴族の影武者を務める元平民だ。しかし、演じるうちに、あなたは真の高貴を身に着けた。",
241
+ "【悲恋】 あなたは、下層市民と身分違いの恋をした。だが、愛する人は蒸気事件の犠牲者となった。",
242
+ "【権謀】 あなたの両親は、とある権力闘争に巻き込まれた際、不自然な蒸気事件に遭遇して命を落とした。",
243
+ "【慈愛】 あなたは、真の貴族であった両親から他者を慈しむことは当然だと教育された。"
244
+ ]
245
+ ),
246
+ "PDT" => SPTable.new(
247
+ "過去表『デヴォート』",
248
+ [
249
+ "【忠義】 あなたは、忠義の大切さを教えられて育ってきた。それゆえ、あなたは主に忠誠をささげるのだ。",
250
+ "【忠臣】 あなたは国や組織に仕える忠臣だった。だが、権力闘争によって追われ、今は市井に身を潜めている。",
251
+ "【恩義】 あなたは現在の主たる人物、または組織に救われた。いつの日か、この恩に報いなければ。",
252
+ "【無心】 あなたは生来より、主や組織に仕える教育を受けてきた。ゆえに、忠義を尽くすことに疑問はない。",
253
+ "【心酔】 あなたは現在の主や組織に心酔している。だから、主や組織のために蒸気事件に立ち向かう",
254
+ "【復習】 あなたの主は邪悪な蒸気事件の犠牲となった。以後、あなたは主の仇を討つべく犯人を捜している。",
255
+ "【約束】 あなたの主は蒸気事件の犠牲者だ。主を看取る際、あなたは世界から蒸気事件を一掃すると約束した。",
256
+ "【犠牲】 あなたには尊敬に値する主がいた。だが、その主はあなたを庇って、邪悪な陰謀の犠牲となった。"
257
+ ]
258
+ ),
259
+ "PET" => SPTable.new(
260
+ "過去表『エセティック』",
261
+ [
262
+ "【研究】 あなたは蒸気犯罪で用いられるスチームギアを撲滅するために、常に研究を続けている。",
263
+ "【悪用】 あなたは過去に自らが製造した、あるいは所有するスチームギアが悪用され、憤慨したことがある。",
264
+ "【仁義】 あなた、仁義の大切さを教えられて育ってきた。それゆえ、あなたは虐げられる物たちを救うのだ。",
265
+ "【美意識】 あなたは、スチームギアが犯罪に用いられる場面を目撃した際、吐き気がするほど醜いと感じた。",
266
+ "【正義】 あなたは蒸気事件の元犠牲者だ。あなたは、自らの正義を成すために今も蒸気事件に挑み続けている。",
267
+ "【正論】 あなたは昔から、スチームギアが正しい方法で利用されないことが我慢ならない。",
268
+ "【天誅】 あなたは蒸気事件によって、全てを失ってしまった。だから、蒸気事件を起こす黒幕が許せない。",
269
+ "【報復】 あなたの恩師は過去に蒸気事件で犠牲となっている。あなたはいつか、その犯人に報復するつもりだ。"
270
+ ]
271
+ ),
272
+ "BGT" => SPTable.new(
273
+ "経緯表『ギガントアームズ』",
274
+ [
275
+ "【元近衛兵】 あなたは上層部の警護を任されていた元近衛兵で、スチームギアは大戦時に入手したものである。",
276
+ "【反逆者の子】 スチームギアは、スチームパンカーだったあなたの亡父が使っていた形見である。",
277
+ "【元殺し屋】 あなたは、かつて殺し屋だった。このスチームギアは以前の仕事の報酬として受け取ったものだ。",
278
+ "【元傭兵】 あなたは蒸気大戦で荒稼ぎしていた元傭兵で、このスチームギアは大戦時に入手したものだ。",
279
+ "【元英雄】 あなたは蒸気大戦の英雄だ。あなたは戦線に赴く際、上層部から新世代スチームギアを支給されたのだ。",
280
+ "【元軍人】 あなたは蒸気大戦にも従軍した元軍人で、大戦時にスチームギアを入手した。",
281
+ "【元特殊部隊】 あなたは蒸気大戦で活躍した元特殊部隊員で、大戦時にスチームギアを入手した。",
282
+ "【戦場帰り】 あなたは蒸気大戦に従軍した経験を持つ戦場帰りで、大戦時にスチームギアを入手した。"
283
+ ]
284
+ ),
285
+ "BAT" => SPTable.new(
286
+ "経緯表『アーマードリム』",
287
+ [
288
+ "【試験操縦士】 あなたは軍や企業で試験操縦士を務めており、その折に、スチームギアを密かに入手した。",
289
+ "【闇取引】 あなたは闇取引のコネクションがあり、そのコネを利用してスチームギアを入手した。",
290
+ "【貴族出身】 あなたは貴族、あるいは元貴族だ。スチームギアは、屋敷の倉にあった品を改造したものである。",
291
+ "【元研究者】 あなたはスチームギアの元研究者で、自らの肉体を防護するためにスチームギアを開発した。",
292
+ "【戦場帰り】 あなたは蒸気大戦に従軍した経験を持つ戦場帰りで、大戦時にスチームギアを入手した。",
293
+ "【謎の協力者】 あなたが蒸気事件に立ち向かおうとした際、謎の協力者が現れ、スチームギアを与えてくれた。",
294
+ "【元修理屋】 あなたは元修理屋だ。スチームギアはジャンク置き場で偶然見かけたものをレストアしたものだ。",
295
+ "【簒奪者】 あなたは蒸気事件に巻き込まれた際、偶然と幸運が重なり、相手のスチームギアを奪取できた。"
296
+ ]
297
+ ),
298
+ "BET" => SPTable.new(
299
+ "経緯表『エッジモービル』",
300
+ [
301
+ "【車泥棒】 あなたは元車泥棒だ。このスチームギアは出所不明のものをちょろまかしたものだ。",
302
+ "【元機関工】 あなたは優れた技術を持つ元機関工で、出所不明のスチームギアを偶然にも入手した。",
303
+ "【元エース】 あなたは蒸気大戦時に英雄と呼ばれた元操縦士で、大戦時にスチームギアを入手した。",
304
+ "【元輸送兵】 あなたは蒸気大戦に従軍した経験を持つ元輸送兵で、大戦時にスチームギアを入手した。",
305
+ "【蒸気工の子】 あなたは蒸気工、あるいは蒸気技術者の子供だった。スチームギアは、両親が所有していたものである。",
306
+ "【元レーサー】 あなたは蒸気車両のレースに出場していたレーサーで、スチームギアは偶然にも入手したものだ。",
307
+ "【違法改造屋】 あなたはかつて、違法で改造を施すモグリの機関工だった。スチームギアは、その際に入手したものだ。",
308
+ "【逃亡兵】 あなたは、戦場から逃げ出した逃亡兵だ。スチームギアは戦場に赴く際に支給された試作機である。"
309
+ ]
310
+ ),
311
+ "BCT" => SPTable.new(
312
+ "経緯表『クロノウェポン』",
313
+ [
314
+ "【元武器商人】 あなたは蒸気大戦時にスチームギアを販売していた元武器商人、あるいはその護衛だ。",
315
+ "【元製造者】 あなたは蒸気大戦時にスチームギアを製造していた。そして、身を護るために自身の手で製造したのだ。",
316
+ "【反逆者の子】 スチームギアは、スチームパンカーだったあなたの亡父が使っていた形見である。",
317
+ "【元近衛兵】 あなたは上層部の警護を任されていた元近衛兵で、スチームギアは大戦時に入手したものである。",
318
+ "【元特殊部隊】 あなたは蒸気大戦で活躍した元特殊部隊員で、大戦時にスチームギアを入手した。",
319
+ "【元傭兵】 あなたは蒸気大戦で荒稼ぎしていた元傭兵で、このスチームギアは大戦時に入手したものだ。",
320
+ "【裏稼業】 あなたはかつて裏稼業に手を染めていた荒事屋で、スチームギアは、かつての仕事の報酬である。",
321
+ "【元英雄】 あなたは蒸気大戦の英雄だ。あなたは戦線に赴く際、上層部から新世代スチームギアを支給されたのだ。"
322
+ ]
323
+ ),
324
+ "BST" => SPTable.new(
325
+ "経緯表『スパイテック』",
326
+ [
327
+ "【元刑事】 あなたは、蒸気事件ばかりを追っていた元刑事だ。スチームギアは犯罪者から奪い取ったものである。",
328
+ "【元結社の一員】 あなたは邪悪な秘密結社に所属していた元工作員だ。スチームギアはその頃に支給されたものである。",
329
+ "【研究者の肉親】 あなたの肉親が軍の研究者で、彼らが試作機として制作したものを偶然入手した。",
330
+ "【元工作員】 あなたは、蒸気大戦の裏側で活躍した元工作員で、大戦終結と同時に、そのスチームギアを入手した。",
331
+ "【元諜報員】 あなたは蒸気大戦の際に活躍した元スパイで、当時支給されたスチームギアを私物化している。",
332
+ "【後援者】 あなたが行なう蒸気事件の調査を援助する者がいる。彼は、このスチームギアを制作した人物である。",
333
+ "【元暗殺部隊】 あなたは、蒸気大戦時に暗躍した元暗殺部隊員で、スチームギアはその頃に入手したものだ。",
334
+ "【元盗人】 あなたは盗品として流れてきたスチームギアを偶然発見して、入手した。"
335
+ ]
336
+ ),
337
+ "BWT" => SPTable.new(
338
+ "経緯表『スチームウェア』",
339
+ [
340
+ "【独自ルート】 あなたは人間の限界を超えるために、独自のルートを使って、自らの意志で肉体を機械化した。",
341
+ "【相棒の技師】 あなたが蒸気事件で肉体を欠損した際、機械技師をしている相棒が欠損部位を機械化してくれた。",
342
+ "【元実験体】 あなたは蒸気事件で重傷を負った際、実験体となる代わりに特殊な機械化手術を施された。",
343
+ "【元機械化兵】 あなたは大戦時に機械化手術で蘇った元蒸気兵だ。終戦後、スチームギアをわざと取り換えなかった。",
344
+ "【帰還兵】 あなたは蒸気大戦から帰還した帰還兵だ。だが戦時中に肉体が欠損し、軍部が機械化してくれた。",
345
+ "【元機械闘士】 あなたは機械化格闘に出場した元格闘士だ。機械化した部位は、その頃に違法改造したものだ。",
346
+ "【元闇医者】 あなたは、元モグリの機械医師だった。機械化したその部位は、その頃に自身で改造したものだ。",
347
+ "【元英雄】 あなたは蒸気大戦の英雄だ。あなたは戦線に赴く際、上層部から新世代スチームギアを支給されたのだ。"
348
+ ]
349
+ ),
350
+ "FST" => SPTable.new(
351
+ "特徴表S",
352
+ [
353
+ "【蒸気帽】 あなたは、なんらかの蒸気機械を仕込んだ帽子を愛用している。",
354
+ "【装飾品】 あなたは、蒸気仕掛けが施された特殊なアクセサリーやペンダントを愛用している。",
355
+ "【蒸気杖/傘】 あなたは、特殊機能を備えた蒸気機械式の傘を、あるいはステッキを愛用している。",
356
+ "【ゴーグル】 あなたは、特殊機能を備えたゴーグルを愛用している。",
357
+ "【特殊眼鏡】 あなたは、拡大機能などを備えた眼鏡や単眼鏡を愛用している。",
358
+ "【蒸気ライター】 あなたは、小さなマグナイトが仕込まれた蒸気式ライターを隠し持っている。",
359
+ "【機関手袋】 あなたは、特殊機能を備えた頑丈な革手袋を愛用している。",
360
+ "【偽造カード】 あなたは、偽造した戸籍情報を点刻したパンチカードを隠し持っている。"
361
+ ]
362
+ ),
363
+ "FPT" => SPTable.new(
364
+ "特徴表P",
365
+ [
366
+ "【傷】 顔、あるいは体のどこかに傷がある。",
367
+ "【美声】 一度聞くと忘れられないほど、美しい声だ。",
368
+ "【筋肉質】 鍛え抜かれた肉体をしている。",
369
+ "【美形】 生きている宝石のように美しい容貌をしている。",
370
+ "【童顔】 年齢に関係なく、非常に若く見える。",
371
+ "【髪】 不思議な髪の色、あるいはパンクな髪型をしている。",
372
+ "【刺青】 体のどこかに特徴的なタトゥーがある。",
373
+ "【瞳】 不思議な瞳の色、あるいは特徴的な眼差しをしている。"
374
+ ]
375
+ ),
376
+ "RST" => SPTable.new(
377
+ "関係性表S",
378
+ [
379
+ "【元敵同士】 相手とは、元敵同士の間柄だ。どのように敵対していたかは、プレイヤーと相談して決定せよ。",
380
+ "【愛憎】 相手とは、愛憎渦巻く仲だ。愛しあっていた、憎みあっていたのかはプレイヤーと相談して決定せよ。",
381
+ "【元相棒】 相手とは、元相棒の間柄だ。なぜ相棒でなくなったかについてはプレイヤーと相談して決定せよ。",
382
+ "【犬猿】 相手とは、犬猿の仲だ。なぜ、いがみあっているかについてはプレイヤーと相談して決定せよ。",
383
+ "【共依存】 相手とは、共依存の関係だ。どのように依存しあっているかはプレイヤーと相談して決定せよ。",
384
+ "【仇同士】 相手とは、仇同士の間柄だ。どのような因縁であるかはプレイヤーと相談して決定せよ。",
385
+ "【主従】 相手とは、主従の間柄だ。どちらが主で、どちらが従者かはプレイヤーと相談して決定せよ。",
386
+ "【裏切り】 相手とは、裏切りあった間柄だ。どちらが裏切ったかについてはプレイヤーと相談して決定せよ。"
387
+ ]
388
+ ),
389
+ "RPT" => SPTable.new(
390
+ "関係性表P",
391
+ [
392
+ "【血縁】 相手とは、血縁がある。どの程度の間柄であるかについてはプレイヤーと相談して決定せよ。",
393
+ "【同志】 相手は、同じ志を持っている。どんな志を共にしているかはプレイヤーと相談して決定せよ。",
394
+ "【好敵手】 相手とは、良きライバルだ。どのような形での好敵手かは、プレイヤーと相談して決定せよ。",
395
+ "【親友】 相手とは、親友の間柄だ。どのくらい仲が良いかについては、プレイヤーと相談して決定せよ。",
396
+ "【相棒】 相手は、無二の相棒だ。どのくらいの年月を共にしてきたかについてはプレイヤーと相談して決定せよ。",
397
+ "【腐れ縁】 相手とは幼い頃からの腐れ縁だ。どのくらいの年齢からであるかはプレイヤーと相談して決定せよ。",
398
+ "【戦友】 相手とは戦友の間柄だ。どこで、なにと戦ったかについてはプレイヤーと相談して決定せよ。",
399
+ "【師弟】 相手は師、あるいは弟子だ。どちらが師で、どちらが弟子かはプレイヤーと相談して決定せよ。"
400
+ ]
401
+ ),
402
+ "EST" => SPTable.new(
403
+ "感情表S",
404
+ [
405
+ "【殺意】 相手に殺意を覚えている。どういった経緯で殺意を抱いているかについては自身で決定せよ。",
406
+ "【優越感】 相手に優越感がある。どういった経緯で優越感を抱いているかについては自身で決定せよ。",
407
+ "【嫉妬】 相手に嫉妬している。どういった経緯で嫉妬しているかについては自身で決定せよ。",
408
+ "【劣等感】 相手に劣等感がある。どういった経緯で劣等感を抱いているかについては自身で決定せよ。",
409
+ "【罪悪感】 相手に罪悪感がある。どういった経緯で罪悪感を持っているかについては自身で決定せよ。",
410
+ "【不安】 相手のことが不安だ。どういったときに不安を感じるかについては自身で決定せよ。",
411
+ "【恐怖】 相手のことを恐れている。どういった経緯で恐れるようになったかについては自身で決定せよ。",
412
+ "【嫌悪】 相手のことを嫌悪している。どの程度の嫌悪であるかについては自身で決定せよ。"
413
+ ]
414
+ ),
415
+ "EPT" => SPTable.new(
416
+ "感情表P",
417
+ [
418
+ "【誠意】 相手に対して誠意を感じる。どういった経緯で誠意を感じたかについては自身で決定せよ。",
419
+ "【好感】 相手に対して好感を抱いている。どういった経緯で好感を抱くに至ったかについては自身で決定せよ。",
420
+ "【尊敬】 相手のことを尊敬している。どういった経緯で相手を尊敬したかについては自身で決定せよ。",
421
+ "【友情】 相手に対して友情を抱いている。どういった経緯で友情を抱くに至ったかについては自身で決定せよ。",
422
+ "【庇護】 相手を護りたいと思っている。どういった経緯で相手を庇護対象にしたかは自身で決定せよ。",
423
+ "【信頼】 相手のことを信頼している。どういった経緯で信頼するようになったかについては自身で決定せよ。",
424
+ "【期待】 相手に対して期待している。どういった経緯で期待を抱くようになったかについては自身で決定せよ。",
425
+ "【愛情】 相手に愛情や友愛を抱いている。どういった経緯で愛情を抱くに至ったかについては自身で決定せよ。"
426
+ ]
427
+ ),
428
+ "ODT" => SPTable.new(
429
+ "災厄表",
430
+ [
431
+ "【蒸気の不調】 スチームギアが不調になった!おそらくマグナイトが尽きかけてるのだ。ペナルティーを受けたPCは、そのフェイズの終了まで、スチームの抑圧を解放できない。",
432
+ "【卑劣な強襲】 突如として強力な不意討ちを受けた。おそらく、スチームギアによる特殊な攻撃だ。PC全員は【耐久値】を-3する(最小1)。",
433
+ "【非道な行為】 黒幕は気まぐれから、罪のない人をスチームギアで傷つけた。なんという非道な行為だ!PC全員は世界からの抑圧を2枚受ける。",
434
+ "【嫌な予感】 今回の蒸気事件は特に嫌な予感がする……以後、全てのエネミーは終了フェイズを迎えるまで、実行の《アビリティ》の成功数を+1する。",
435
+ "【敵役出現】 見知らぬ妨害者が現れた!以後、[【反抗LV】の平均以下]のエネミーが、そのフェイズに1人参加。戦闘不能にしない限り、メインを迎える度に実行を行ない、活劇フェイズにも参加する。",
436
+ "【迎撃準備】 黒幕は万が一に備えて、手下を武装させ始めた。以後、全てのエネミーはシナリオ中、【耐久値】を+3する。",
437
+ "【疑惑の目】 まずい。警察や政府がキミたちに対して疑惑の目を向け始めているようだ。PC全員は【理性値】を-2する(最小0)。",
438
+ "【絶望感】 突如として心の傷が痛み、信念が揺らいでしまう。ペナルティーを受けたPCは、そのフェイズの終了まで、パンクの抑圧を解放できない。"
439
+ ]
440
+ ),
441
+ "OST" => SPTable.new(
442
+ "場面表",
443
+ [
444
+ "【地下鉄】 途中まで、地下鉄を利用することにする。駅のホームは蒸気列車が放出する蒸気のせいで、湿り気と熱気を帯びていた。",
445
+ "【工業地帯】 工業地帯を横切る。開かれた窓の奥に視線を送ると、労働者たちが製造用蒸気機関を操り、真鍮製の煙突から蒸気が噴き上っている。",
446
+ "【店舗】 途中、店舗で簡単な買い物を済ませた。支払いは無論、パンチカードで一括。階差演算機関はすでに個人の予算残高すら管理下に置いている。",
447
+ "【ビッグ・ベン】 遠くから時刻を告げるビッグ・ベンの鐘が響くと、蒸気オルガンの薄暗い音色が、いつものようにロンドンの上空を覆った。",
448
+ "【人混み】 人混みのなかを進むと、ハンチング帽をかぶった少年たちが脇を駆け抜けた……彼らを護るためにも早く蒸気事件を解決しなければ。",
449
+ "【繁華街】 調査に向かった現場では、蒸気機械仕掛けの帯状装飾が点灯しており、帯が回転する度に様々な広告が表示された。",
450
+ "【大通り】 大通りに出ると、蒸気自動車が目前で行き交っていた。真鍮や錫で装飾された蒸気自動車は、まるで晩餐会に出入りする馬車のようだ。",
451
+ "【移動パブ】 途中、移動パブを見かけた。蒸気自動車に機関式サーバーを搭載したもので、周りには若いロンドン子たちが口に泡をつけながら騒いでいる。"
452
+ ]
453
+ ),
454
+ "OIT" => SPTable.new(
455
+ "交流表",
456
+ [
457
+ "【過去】 そういえば、相手の過去を知らない気がする…聞けば教えてくれるだろうか?",
458
+ "【特徴】 さっきから相手の特徴が気になる。相手から特徴にまつわる話を聞いてみようか?",
459
+ "【感情】 相手に対して抱いてる感情のことを伝えるべきだろうか?それとも、伝えないべきだろうか?",
460
+ "【蒸気事件】 相手に、今回の事件の印象について聞いてみよう。",
461
+ "【事件後】 今回の事件が終わったら、相手は何をするつもりなのだろう?",
462
+ "【関係性】 相手とは……いつからこうした関係だったろう?そもそも、相手は覚えているのだろうか?",
463
+ "【職業】 相手は、どんな経緯で今の職業となったのだろう。興味があるので、聞いてみようか?",
464
+ "【経緯】 相手はどうやってスチームギアを得たのだろう?その経緯の一部でも聞いてみようか?"
465
+ ]
466
+ ),
467
+ "OFT" => SPTable.new(
468
+ "激憤表",
469
+ [
470
+ "【憤怒】 これほど残虐な蒸気事件が起こったというのに、世界は一向に変わろうとしない。もはや世界への怒りは頂点へと達してしまった。PCはレヴォルトを失い、黒幕となる。",
471
+ "【破損】 怒りに任せて激闘を繰り返したため、スチームギアが破損した。もう、世界に反逆する力はない。以後、PCはスチームギアを失い、NPCとなる。",
472
+ "【偽装】 権力者からの圧力によって、社会的に抹殺されてしまった。が、それは想定済みだ。これからは別の人生を歩むことになる。PCの名前と職業を変更せよ。",
473
+ "【冷静】 今回の蒸気事件には少し思うところがあった。だが、しばらく時間を置くことで、理性的になることができた。キミはまだまだ戦える。特にペナルティーはない。",
474
+ "【重傷】 最後の戦いの際に負った傷が重症化してしまった。だが、しばらく治療に専念すれば復帰できるだろう。特にペナルティーはない。",
475
+ "【革命】 今回の事件を通じて、信念が揺らいだ。やはり、世界を変えるには圧倒的な”暴力”が必要なのだ。PCはレヴォルトを失い、黒幕となる。",
476
+ "【寝返り】 蒸気事件を通じて、世界の在り方に疑問を感じる。そんな矢先、目前にゾディアックの上級幹部が現れ、キミをスカウトしてきた。PCはレヴォルトを失い、黒幕となる。",
477
+ "【悪堕ち】 信念に従い、反逆を続けてきた。だが、蒸気事件が尽きる気配はない。反逆など無意味なのか。なら、この手で……PCはレヴォルトを失い、黒幕となる。"
478
+ ]
479
+ )
480
+ }.freeze
481
+
482
+ register_prefix(['SP.*'] + TABLES.keys)
483
+ end
484
+ end
485
+ end