bcdice 3.0.0 → 3.2.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 (183) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +79 -2
  3. data/README.md +32 -0
  4. data/i18n/MonotoneMuseum/ja_jp.yml +3 -3
  5. data/i18n/StellarKnights/ja_jp.yml +496 -0
  6. data/lib/bcdice/common_command/add_dice.rb +1 -1
  7. data/lib/bcdice/common_command/calc.rb +1 -1
  8. data/lib/bcdice/dice_table.rb +2 -0
  9. data/lib/bcdice/dice_table/d66_half_grid_table.rb +33 -0
  10. data/lib/bcdice/dice_table/d66_one_third_table.rb +34 -0
  11. data/lib/bcdice/dice_table/sai_fic_skill_table.rb +1 -1
  12. data/lib/bcdice/game_system.rb +4 -0
  13. data/lib/bcdice/game_system/AceKillerGene.rb +1 -1
  14. data/lib/bcdice/game_system/Ainecadette.rb +68 -0
  15. data/lib/bcdice/game_system/Airgetlamh.rb +1 -1
  16. data/lib/bcdice/game_system/AlchemiaStruggle.rb +1 -1
  17. data/lib/bcdice/game_system/Alsetto.rb +1 -1
  18. data/lib/bcdice/game_system/Alshard.rb +1 -1
  19. data/lib/bcdice/game_system/AlterRaise.rb +2 -2
  20. data/lib/bcdice/game_system/AngelGear.rb +123 -0
  21. data/lib/bcdice/game_system/AnimaAnimus.rb +1 -1
  22. data/lib/bcdice/game_system/Arianrhod.rb +6 -8
  23. data/lib/bcdice/game_system/ArsMagica.rb +1 -1
  24. data/lib/bcdice/game_system/Avandner.rb +1 -1
  25. data/lib/bcdice/game_system/BBN.rb +1 -1
  26. data/lib/bcdice/game_system/BadLife.rb +1 -1
  27. data/lib/bcdice/game_system/BarnaKronika.rb +1 -1
  28. data/lib/bcdice/game_system/BattleTech.rb +1 -1
  29. data/lib/bcdice/game_system/BeastBindTrinity.rb +2 -2
  30. data/lib/bcdice/game_system/BeginningIdol.rb +5 -5
  31. data/lib/bcdice/game_system/BeginningIdol_Korean.rb +5 -5
  32. data/lib/bcdice/game_system/BladeOfArcana.rb +1 -1
  33. data/lib/bcdice/game_system/BlindMythos.rb +1 -1
  34. data/lib/bcdice/game_system/BloodCrusade.rb +48 -49
  35. data/lib/bcdice/game_system/BloodMoon.rb +50 -8
  36. data/lib/bcdice/game_system/CardRanker.rb +10 -9
  37. data/lib/bcdice/game_system/ChaosFlare.rb +21 -15
  38. data/lib/bcdice/game_system/Chill.rb +10 -10
  39. data/lib/bcdice/game_system/Chill3.rb +9 -9
  40. data/lib/bcdice/game_system/CodeLayerd.rb +1 -1
  41. data/lib/bcdice/game_system/CrashWorld.rb +1 -1
  42. data/lib/bcdice/game_system/Cthulhu.rb +8 -4
  43. data/lib/bcdice/game_system/Cthulhu7th.rb +86 -342
  44. data/lib/bcdice/game_system/Cthulhu7th_ChineseTraditional.rb +2 -2
  45. data/lib/bcdice/game_system/Cthulhu7th_Korean.rb +2 -2
  46. data/lib/bcdice/game_system/CthulhuTech.rb +1 -1
  47. data/lib/bcdice/game_system/Cthulhu_ChineseTraditional.rb +1 -1
  48. data/lib/bcdice/game_system/Cthulhu_Korean.rb +1 -1
  49. data/lib/bcdice/game_system/DarkBlaze.rb +1 -12
  50. data/lib/bcdice/game_system/DarkDaysDrive.rb +8 -7
  51. data/lib/bcdice/game_system/DeadlineHeroes.rb +2 -2
  52. data/lib/bcdice/game_system/DemonParasite.rb +5 -13
  53. data/lib/bcdice/game_system/DesperateRun.rb +1 -1
  54. data/lib/bcdice/game_system/DiceOfTheDead.rb +1 -1
  55. data/lib/bcdice/game_system/DoubleCross.rb +2 -2
  56. data/lib/bcdice/game_system/Dracurouge.rb +1 -1
  57. data/lib/bcdice/game_system/EarthDawn.rb +1 -1
  58. data/lib/bcdice/game_system/EarthDawn3.rb +1 -1
  59. data/lib/bcdice/game_system/EarthDawn4.rb +1 -1
  60. data/lib/bcdice/game_system/EclipsePhase.rb +14 -14
  61. data/lib/bcdice/game_system/Elric.rb +18 -14
  62. data/lib/bcdice/game_system/Elysion.rb +3 -3
  63. data/lib/bcdice/game_system/EmbryoMachine.rb +9 -8
  64. data/lib/bcdice/game_system/Emoklore.rb +3 -3
  65. data/lib/bcdice/game_system/EtrianOdysseySRS.rb +1 -1
  66. data/lib/bcdice/game_system/Fiasco.rb +1 -1
  67. data/lib/bcdice/game_system/FilledWith.rb +205 -1272
  68. data/lib/bcdice/game_system/FullMetalPanic.rb +1 -1
  69. data/lib/bcdice/game_system/GURPS.rb +17 -28
  70. data/lib/bcdice/game_system/Garako.rb +12 -4
  71. data/lib/bcdice/game_system/GardenOrder.rb +1 -1
  72. data/lib/bcdice/game_system/GehennaAn.rb +1 -1
  73. data/lib/bcdice/game_system/GeishaGirlwithKatana.rb +1 -1
  74. data/lib/bcdice/game_system/GoblinSlayer.rb +1 -1
  75. data/lib/bcdice/game_system/Gorilla.rb +3 -9
  76. data/lib/bcdice/game_system/GranCrest.rb +18 -11
  77. data/lib/bcdice/game_system/Gundog.rb +9 -8
  78. data/lib/bcdice/game_system/GundogRevised.rb +10 -9
  79. data/lib/bcdice/game_system/GundogZero.rb +1 -1
  80. data/lib/bcdice/game_system/GurpsFW.rb +16 -16
  81. data/lib/bcdice/game_system/HarnMaster.rb +19 -26
  82. data/lib/bcdice/game_system/HatsuneMiku.rb +1 -1
  83. data/lib/bcdice/game_system/Hieizan.rb +12 -21
  84. data/lib/bcdice/game_system/HouraiGakuen.rb +1 -1
  85. data/lib/bcdice/game_system/HuntersMoon.rb +5 -10
  86. data/lib/bcdice/game_system/Illusio.rb +25 -34
  87. data/lib/bcdice/game_system/InfiniteFantasia.rb +19 -17
  88. data/lib/bcdice/game_system/Insane.rb +13 -20
  89. data/lib/bcdice/game_system/IthaWenUa.rb +8 -15
  90. data/lib/bcdice/game_system/JamesBond.rb +10 -10
  91. data/lib/bcdice/game_system/JekyllAndHyde.rb +1 -1
  92. data/lib/bcdice/game_system/Kamigakari.rb +1 -1
  93. data/lib/bcdice/game_system/KanColle.rb +4 -9
  94. data/lib/bcdice/game_system/KemonoNoMori.rb +1 -1
  95. data/lib/bcdice/game_system/KillDeathBusiness.rb +7 -15
  96. data/lib/bcdice/game_system/KurayamiCrying.rb +55 -2
  97. data/lib/bcdice/game_system/LogHorizon.rb +3 -3
  98. data/lib/bcdice/game_system/LostRoyal.rb +1 -1
  99. data/lib/bcdice/game_system/MeikyuDays.rb +11 -9
  100. data/lib/bcdice/game_system/MeikyuKingdom.rb +28 -28
  101. data/lib/bcdice/game_system/MeikyuKingdomBasic.rb +5 -5
  102. data/lib/bcdice/game_system/MetalHead.rb +12 -22
  103. data/lib/bcdice/game_system/MetalHeadExtream.rb +5 -5
  104. data/lib/bcdice/game_system/MetallicGuardian.rb +1 -1
  105. data/lib/bcdice/game_system/MonotoneMuseum.rb +9 -7
  106. data/lib/bcdice/game_system/Nechronica.rb +28 -21
  107. data/lib/bcdice/game_system/NeverCloud.rb +540 -5
  108. data/lib/bcdice/game_system/NightWizard.rb +1 -1
  109. data/lib/bcdice/game_system/NightWizard3rd.rb +1 -1
  110. data/lib/bcdice/game_system/NinjaSlayer.rb +4 -13
  111. data/lib/bcdice/game_system/NjslyrBattle.rb +8 -11
  112. data/lib/bcdice/game_system/OneWayHeroics.rb +1 -1
  113. data/lib/bcdice/game_system/OracleEngine.rb +1 -1
  114. data/lib/bcdice/game_system/OrgaRain.rb +17 -25
  115. data/lib/bcdice/game_system/Paradiso.rb +3 -3
  116. data/lib/bcdice/game_system/ParanoiaRebooted.rb +1 -1
  117. data/lib/bcdice/game_system/ParasiteBlood.rb +1 -1
  118. data/lib/bcdice/game_system/Peekaboo.rb +4 -9
  119. data/lib/bcdice/game_system/Pendragon.rb +7 -7
  120. data/lib/bcdice/game_system/PhantasmAdventure.rb +8 -8
  121. data/lib/bcdice/game_system/Postman.rb +2 -2
  122. data/lib/bcdice/game_system/PulpCthulhu.rb +1 -1
  123. data/lib/bcdice/game_system/Raisondetre.rb +2 -2
  124. data/lib/bcdice/game_system/RecordOfLodossWar.rb +1 -1
  125. data/lib/bcdice/game_system/RecordOfSteam.rb +1 -1
  126. data/lib/bcdice/game_system/Revulture.rb +123 -0
  127. data/lib/bcdice/game_system/RokumonSekai2.rb +1 -1
  128. data/lib/bcdice/game_system/RuneQuest.rb +8 -8
  129. data/lib/bcdice/game_system/Ryutama.rb +1 -1
  130. data/lib/bcdice/game_system/SRS.rb +1 -1
  131. data/lib/bcdice/game_system/SamsaraBallad.rb +1 -1
  132. data/lib/bcdice/game_system/Satasupe.rb +79 -860
  133. data/lib/bcdice/game_system/ScreamHighSchool.rb +2 -2
  134. data/lib/bcdice/game_system/SevenFortressMobius.rb +1 -1
  135. data/lib/bcdice/game_system/SharedFantasia.rb +20 -24
  136. data/lib/bcdice/game_system/ShinkuuGakuen.rb +2 -2
  137. data/lib/bcdice/game_system/ShinobiGami.rb +17 -9
  138. data/lib/bcdice/game_system/Skynauts.rb +4 -4
  139. data/lib/bcdice/game_system/SkynautsBouken.rb +228 -0
  140. data/lib/bcdice/game_system/SteamPunkers.rb +1 -1
  141. data/lib/bcdice/game_system/StellarKnights.rb +59 -696
  142. data/lib/bcdice/game_system/SterileLife.rb +2 -3
  143. data/lib/bcdice/game_system/StrangerOfSwordCity.rb +2 -2
  144. data/lib/bcdice/game_system/StratoShout.rb +8 -16
  145. data/lib/bcdice/game_system/Strave.rb +1 -1
  146. data/lib/bcdice/game_system/SwordWorld.rb +58 -185
  147. data/lib/bcdice/game_system/SwordWorld2_0.rb +22 -150
  148. data/lib/bcdice/game_system/SwordWorld2_5.rb +127 -41
  149. data/lib/bcdice/game_system/TherapieSein.rb +1 -1
  150. data/lib/bcdice/game_system/TokyoGhostResearch.rb +1 -1
  151. data/lib/bcdice/game_system/Torg.rb +1 -1
  152. data/lib/bcdice/game_system/TorgEternity.rb +2 -2
  153. data/lib/bcdice/game_system/TrinitySeven.rb +4 -4
  154. data/lib/bcdice/game_system/TunnelsAndTrolls.rb +1 -1
  155. data/lib/bcdice/game_system/TwilightGunsmoke.rb +1 -1
  156. data/lib/bcdice/game_system/UnsungDuet.rb +1 -1
  157. data/lib/bcdice/game_system/Utakaze.rb +1 -1
  158. data/lib/bcdice/game_system/VampireTheMasquerade5th.rb +1 -1
  159. data/lib/bcdice/game_system/Villaciel.rb +1 -1
  160. data/lib/bcdice/game_system/WARPS.rb +11 -9
  161. data/lib/bcdice/game_system/WaresBlade.rb +4 -9
  162. data/lib/bcdice/game_system/Warhammer.rb +16 -7
  163. data/lib/bcdice/game_system/Warhammer4.rb +16 -12
  164. data/lib/bcdice/game_system/WitchQuest.rb +1 -1
  165. data/lib/bcdice/game_system/WorldOfDarkness.rb +1 -1
  166. data/lib/bcdice/game_system/YankeeYogSothoth.rb +4 -9
  167. data/lib/bcdice/game_system/YearZeroEngine.rb +1 -1
  168. data/lib/bcdice/game_system/ZettaiReido.rb +1 -1
  169. data/lib/bcdice/game_system/cthulhu7th/full_auto.rb +294 -0
  170. data/lib/bcdice/game_system/cthulhu7th/rollable.rb +41 -0
  171. data/lib/bcdice/game_system/filled_with/enemy_data_tables.rb +322 -0
  172. data/lib/bcdice/game_system/filled_with/event_tables.rb +392 -0
  173. data/lib/bcdice/game_system/filled_with/tresure_tables.rb +179 -0
  174. data/lib/bcdice/game_system/meikyu_kingdom_basic/kingdom_table.rb +1 -1
  175. data/lib/bcdice/game_system/satasupe/tables.rb +723 -0
  176. data/lib/bcdice/game_system/sword_world/rating_lexer.rb +47 -0
  177. data/lib/bcdice/game_system/sword_world/rating_parsed.rb +99 -0
  178. data/lib/bcdice/game_system/sword_world/rating_parser.rb +457 -0
  179. data/lib/bcdice/game_system/sword_world/transcendent_test.rb +122 -0
  180. data/lib/bcdice/repl.rb +1 -1
  181. data/lib/bcdice/result.rb +26 -0
  182. data/lib/bcdice/version.rb +1 -1
  183. metadata +20 -4
@@ -22,24 +22,24 @@ module BCDice
22
22
   例)SR7   sr13   SR(7+4)   Ssr10
23
23
  INFO_MESSAGE_TEXT
24
24
 
25
- register_prefix('SR\d+.*')
25
+ register_prefix('SR')
26
26
 
27
- def check_1D100(total, _dice_total, cmp_op, target)
28
- return '' if target == '?'
29
- return '' if cmp_op != :<=
27
+ def result_1d100(total, _dice_total, cmp_op, target)
28
+ return nil if target == '?'
29
+ return nil if cmp_op != :<=
30
30
 
31
31
  if total >= 100
32
- "ファンブル"
32
+ Result.fumble("ファンブル")
33
33
  elsif total > target
34
- "失敗"
34
+ Result.failure("失敗")
35
35
  elsif total >= (target * 0.9)
36
- "L成功"
36
+ Result.success("L成功")
37
37
  elsif total >= (target / 2)
38
- "M成功"
38
+ Result.success("M成功")
39
39
  elsif total >= (target / 10)
40
- "H成功"
40
+ Result.success("H成功")
41
41
  else
42
- "C成功"
42
+ Result.critical("C成功")
43
43
  end
44
44
  end
45
45
 
@@ -19,9 +19,9 @@ module BCDice
19
19
     Chill3 : (1D100<=50) > 55 > Botch
20
20
  INFO_MESSAGE_TEXT
21
21
 
22
- def check_1D100(total, dice_total, cmp_op, target)
23
- return '' if target == '?'
24
- return '' unless cmp_op == :<=
22
+ def result_1d100(total, dice_total, cmp_op, target)
23
+ return nil if target == '?'
24
+ return nil unless cmp_op == :<=
25
25
 
26
26
  # ゾロ目ならC-ResultかBotch
27
27
  tens = (dice_total / 10) % 10
@@ -30,21 +30,21 @@ module BCDice
30
30
  if tens == ones
31
31
  if (total > target) || (dice_total == 100) # 00は必ず失敗
32
32
  if target > 100 # 目標値が100を超えている場合は、00を振ってもBotchにならない
33
- return "失敗"
33
+ return Result.failure("失敗")
34
34
  else
35
- return "Botch"
35
+ return Result.fumble("Botch")
36
36
  end
37
37
  else
38
- return "C成功"
38
+ return Result.critical("C成功")
39
39
  end
40
40
  elsif (total <= target) || (dice_total == 1) # 01は必ず成功
41
41
  if total <= (target / 2)
42
- return "H成功"
42
+ return Result.success("H成功")
43
43
  else
44
- return "L成功"
44
+ return Result.success("L成功")
45
45
  end
46
46
  else
47
- return "失敗"
47
+ return Result.failure("失敗")
48
48
  end
49
49
  end
50
50
  end
@@ -30,7 +30,7 @@ module BCDice
30
30
  デフォルトダイス:10面
31
31
  MESSAGETEXT
32
32
 
33
- register_prefix('[+-]?\d*CL([+-]\d+)?[@\d]*.*')
33
+ register_prefix('[+-]?\d*CL([+-]\d+)?[@\d]*')
34
34
 
35
35
  def initialize(command)
36
36
  super(command)
@@ -19,7 +19,7 @@ module BCDice
19
19
  例・CW8
20
20
  INFO_MESSAGE_TEXT
21
21
 
22
- register_prefix('CW\d+')
22
+ register_prefix('CW')
23
23
 
24
24
  def eval_game_system_specific_command(command)
25
25
  result = nil
@@ -48,7 +48,7 @@ module BCDice
48
48
 
49
49
  INFO_MESSAGE_TEXT
50
50
 
51
- register_prefix('CC(B)?\(\d+\)', 'CC(B)?.*', 'RES(B)?.*', 'CBR(B)?\(\d+,\d+\)')
51
+ register_prefix('CCB?', 'RESB?', 'CBRB?')
52
52
 
53
53
  def initialize(command)
54
54
  super(command)
@@ -97,7 +97,11 @@ module BCDice
97
97
  private
98
98
 
99
99
  def getCheckResult(command)
100
- m = %r{CCB?(\d+)?(?:<=([+-/*\d]+))?}i.match(command)
100
+ m = %r{^CCB?(\d+)?(?:<=([+-/*\d]+))?$}i.match(command)
101
+ unless m
102
+ return nil
103
+ end
104
+
101
105
  broken_num = m[1].to_i
102
106
  diff = ArithmeticEvaluator.eval(m[2])
103
107
 
@@ -189,7 +193,7 @@ module BCDice
189
193
  end
190
194
 
191
195
  def getRegistResult(command)
192
- m = /RES(B)?([-\d]+)/i.match(command)
196
+ m = /^RES(B)?([-\d]+)$/i.match(command)
193
197
  unless m
194
198
  return nil
195
199
  end
@@ -215,7 +219,7 @@ module BCDice
215
219
  end
216
220
 
217
221
  def getCombineRoll(command)
218
- m = /CBR(B)?\((\d+),(\d+)\)/i.match(command)
222
+ m = /^CBR(B)?\((\d+),(\d+)\)$/i.match(command)
219
223
  unless m
220
224
  return nil
221
225
  end
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "bcdice/game_system/cthulhu7th/rollable"
4
+ require "bcdice/game_system/cthulhu7th/full_auto"
5
+
3
6
  module BCDice
4
7
  module GameSystem
5
8
  class Cthulhu7th < Base
@@ -14,13 +17,19 @@ module BCDice
14
17
 
15
18
  # ダイスボットの使い方
16
19
  HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
17
- ※コマンドは入力内容の前方一致で検出しています。
18
20
  ・判定 CC(x)<=(目標値)
19
-  x:ボーナス・ペナルティダイス (2~-2)。省略可。
21
+  x:ボーナス・ペナルティダイス。省略可。
20
22
   目標値が無くても1D100は表示される。
21
23
   ファンブル/失敗/ レギュラー成功/ハード成功/
22
24
   イクストリーム成功/クリティカル を自動判定。
23
- 例)CC<=30 CC(2)<=50 CC(+2)<=50 CC(-1)<=75 CC-1<=50 CC1<=65 CC+1<=65 CC
25
+  例)CC<=30 CC(2)<=50 CC(+2)<=50 CC(-1)<=75 CC-1<=50 CC1<=65 CC+1<=65 CC
26
+
27
+ ・技能ロールの難易度指定 CC(x)<=(目標値)(難易度)
28
+  目標値の後に難易度を指定することで
29
+  成功/失敗/クリティカル/ファンブル を自動判定する。
30
+  難易度の指定:
31
+   r:レギュラー h:ハード e:イクストリーム c:クリティカル
32
+  例)CC<=70r CC1<=60h CC-2<=50e CC2<=99c
24
33
 
25
34
  ・組み合わせ判定 (CBR(x,y))
26
35
   目標値 x と y で%ロールを行い、成否を判定。
@@ -45,41 +54,36 @@ module BCDice
45
54
    強力でない呪文の場合 FCL/強力な呪文の場合 FCM
46
55
  INFO_MESSAGE_TEXT
47
56
 
48
- register_prefix('CC\(\d+\)', 'CC.*', 'CBR\(\d+,\d+\)', 'FAR.*', 'BMR', 'BMS', 'FCL', 'FCM', 'PH', 'MA')
49
-
50
- BONUS_DICE_RANGE = (-2..2).freeze
57
+ register_prefix('CC', 'CBR', 'FAR', 'BMR', 'BMS', 'FCL', 'FCM', 'PH', 'MA')
51
58
 
52
59
  def eval_game_system_specific_command(command)
53
60
  case command
54
61
  when /^CC/i
55
- return skill_roll(command)
62
+ skill_roll(command)
56
63
  when /^CBR/i
57
- return combine_roll(command)
64
+ combine_roll(command)
58
65
  when /^FAR/i
59
- return getFullAutoResult(command)
66
+ getFullAutoResult(command)
60
67
  when /^BMR/i # 狂気の発作(リアルタイム)
61
- return roll_bmr_table()
68
+ roll_bmr_table()
62
69
  when /^BMS/i # 狂気の発作(サマリー)
63
- return roll_bms_table()
70
+ roll_bms_table()
64
71
  when /^FCL/i # キャスティング・ロールのプッシュに失敗した場合(小)
65
- return roll_1d8_table("キャスティング・ロール失敗(小)表", FAILED_CASTING_L_TABLE)
72
+ roll_1d8_table("キャスティング・ロール失敗(小)表", FAILED_CASTING_L_TABLE)
66
73
  when /^FCM/i # キャスティング・ロールのプッシュに失敗した場合(大)
67
- return roll_1d8_table("キャスティング・ロール失敗(大)表", FAILED_CASTING_M_TABLE)
74
+ roll_1d8_table("キャスティング・ロール失敗(大)表", FAILED_CASTING_M_TABLE)
68
75
  when /^PH/i # 恐怖症表
69
- return roll_1d100_table("恐怖症表", PHOBIAS_TABLE)
76
+ roll_1d100_table("恐怖症表", PHOBIAS_TABLE)
70
77
  when /^MA/i # マニア表
71
- return roll_1d100_table("マニア表", MANIAS_TABLE)
72
- else
73
- return nil
78
+ roll_1d100_table("マニア表", MANIAS_TABLE)
74
79
  end
75
80
  end
76
81
 
77
- private
78
-
79
82
  class ResultLevel
80
83
  LEVEL = [
81
84
  :fumble,
82
85
  :failure,
86
+ :success,
83
87
  :regular_success,
84
88
  :hard_success,
85
89
  :extreme_success,
@@ -91,10 +95,43 @@ module BCDice
91
95
  extreme_success: "イクストリーム成功",
92
96
  hard_success: "ハード成功",
93
97
  regular_success: "レギュラー成功",
98
+ success: "成功",
94
99
  fumble: "ファンブル",
95
100
  failure: "失敗",
96
101
  }.freeze
97
102
 
103
+ def self.with_difficulty_level(total, difficulty)
104
+ fumble = difficulty < 50 ? 96 : 100
105
+
106
+ if total == 1
107
+ ResultLevel.new(:critical)
108
+ elsif total <= difficulty
109
+ ResultLevel.new(:success)
110
+ elsif total >= fumble
111
+ ResultLevel.new(:fumble)
112
+ else
113
+ ResultLevel.new(:failure)
114
+ end
115
+ end
116
+
117
+ def self.from_values(total, difficulty, fumbleable = false)
118
+ fumble = difficulty < 50 || fumbleable ? 96 : 100
119
+
120
+ if total == 1
121
+ ResultLevel.new(:critical)
122
+ elsif total <= (difficulty / 5)
123
+ ResultLevel.new(:extreme_success)
124
+ elsif total <= (difficulty / 2)
125
+ ResultLevel.new(:hard_success)
126
+ elsif total <= difficulty
127
+ ResultLevel.new(:regular_success)
128
+ elsif total >= fumble
129
+ ResultLevel.new(:fumble)
130
+ else
131
+ ResultLevel.new(:failure)
132
+ end
133
+ end
134
+
98
135
  def initialize(level)
99
136
  @level = level
100
137
  @level_index = LEVEL.index(level)
@@ -102,7 +139,7 @@ module BCDice
102
139
  end
103
140
 
104
141
  def success?
105
- @level_index >= LEVEL.index(:regular_success)
142
+ @level_index >= LEVEL.index(:success)
106
143
  end
107
144
 
108
145
  def failure?
@@ -122,6 +159,10 @@ module BCDice
122
159
  end
123
160
  end
124
161
 
162
+ private
163
+
164
+ include Rollable
165
+
125
166
  def roll_1d8_table(table_name, table)
126
167
  total_n = @randomizer.roll_once(8)
127
168
  index = total_n - 1
@@ -141,15 +182,26 @@ module BCDice
141
182
  end
142
183
 
143
184
  def skill_roll(command)
144
- m = /^CC([-+]?\d+)?(?:<=(\d+))?$/.match(command)
185
+ m = /^CC([-+]?\d+)?(?:<=(\d+)([RHEC])?)?$/.match(command)
145
186
  unless m
146
187
  return nil
147
188
  end
148
189
 
149
190
  bonus_dice = m[1].to_i
150
- difficulty = m[2].to_i
191
+ difficulty = m[2]&.to_i
192
+ difficulty_level = m[3]
193
+
194
+ if difficulty == 0
195
+ difficulty = nil
196
+ elsif difficulty_level == "H"
197
+ difficulty /= 2
198
+ elsif difficulty_level == "E"
199
+ difficulty /= 5
200
+ elsif difficulty_level == "C"
201
+ difficulty = 0
202
+ end
151
203
 
152
- if bonus_dice == 0 && difficulty == 0
204
+ if bonus_dice == 0 && difficulty.nil?
153
205
  dice = @randomizer.roll_once(100)
154
206
  return "1D100 > #{dice}"
155
207
  end
@@ -160,8 +212,13 @@ module BCDice
160
212
 
161
213
  total, total_list = roll_with_bonus(bonus_dice)
162
214
 
163
- expr = difficulty.zero? ? "1D100" : "1D100<=#{difficulty}"
164
- result = result_level(total, difficulty) unless difficulty.zero?
215
+ expr = difficulty.nil? ? "1D100" : "1D100<=#{difficulty}"
216
+ result =
217
+ if difficulty_level
218
+ ResultLevel.with_difficulty_level(total, difficulty)
219
+ elsif difficulty
220
+ ResultLevel.from_values(total, difficulty)
221
+ end
165
222
 
166
223
  sequence = [
167
224
  "(#{expr}) ボーナス・ペナルティダイス[#{bonus_dice}]",
@@ -180,54 +237,8 @@ module BCDice
180
237
  end
181
238
  end
182
239
 
183
- # 1D100の一の位用のダイスロール
184
- # 0から9までの値を返す
185
- #
186
- # @return [Integer]
187
- def roll_ones_d10
188
- dice = @randomizer.roll_once(10)
189
- return 0 if dice == 10
190
-
191
- return dice
192
- end
193
-
194
- # @param bonus [Integer] ボーナス・ペナルティダイスの数。負の数ならペナルティダイス。
195
- # @return [Array<(Integer, Array<Integer>)>]
196
- def roll_with_bonus(bonus)
197
- tens_list = Array.new(bonus.abs + 1) { @randomizer.roll_tens_d10 }
198
- ones = roll_ones_d10()
199
-
200
- dice_list = tens_list.map do |tens|
201
- dice = tens + ones
202
- dice == 0 ? 100 : dice
203
- end
204
-
205
- dice =
206
- if bonus >= 0
207
- dice_list.min
208
- else
209
- dice_list.max
210
- end
211
-
212
- return dice, dice_list
213
- end
214
-
215
- def result_level(total, difficulty, fumbleable = false)
216
- fumble = difficulty < 50 || fumbleable ? 96 : 100
217
-
218
- if total == 1
219
- ResultLevel.new(:critical)
220
- elsif total <= (difficulty / 5)
221
- ResultLevel.new(:extreme_success)
222
- elsif total <= (difficulty / 2)
223
- ResultLevel.new(:hard_success)
224
- elsif total <= difficulty
225
- ResultLevel.new(:regular_success)
226
- elsif total >= fumble
227
- ResultLevel.new(:fumble)
228
- else
229
- ResultLevel.new(:failure)
230
- end
240
+ def getFullAutoResult(command)
241
+ FullAuto.eval(command, @randomizer)
231
242
  end
232
243
 
233
244
  def combine_roll(command)
@@ -239,8 +250,8 @@ module BCDice
239
250
 
240
251
  total = @randomizer.roll_once(100)
241
252
 
242
- result_1 = result_level(total, difficulty_1)
243
- result_2 = result_level(total, difficulty_2)
253
+ result_1 = ResultLevel.from_values(total, difficulty_1)
254
+ result_2 = ResultLevel.from_values(total, difficulty_2)
244
255
 
245
256
  rank =
246
257
  if result_1.success? && result_2.success?
@@ -258,273 +269,6 @@ module BCDice
258
269
  end
259
270
  end
260
271
 
261
- def getFullAutoResult(command)
262
- return nil unless /^FAR\((-?\d+),(-?\d+),(-?\d+)(?:,(-?\d+)?)?(?:,(-?\w+)?)?(?:,(-?\d+)?)?\)/i =~ command
263
-
264
- bullet_count = Regexp.last_match(1).to_i
265
- diff = Regexp.last_match(2).to_i
266
- broken_number = Regexp.last_match(3).to_i
267
- bonus_dice_count = (Regexp.last_match(4) || 0).to_i
268
- stop_count = (Regexp.last_match(5) || "").to_s.downcase
269
- bullet_set_count_cap = (Regexp.last_match(6) || diff / 10).to_i
270
-
271
- output = ""
272
-
273
- # 最大で(8回*(PC技能値最大値/10))=72発しか撃てないはずなので上限
274
- bullet_count_limit = 100
275
- if bullet_count > bullet_count_limit
276
- output += "弾薬が多すぎます。装填された弾薬を#{bullet_count_limit}発に変更します。\n"
277
- bullet_count = bullet_count_limit
278
- end
279
-
280
- # ボレーの上限の設定がおかしい場合の注意表示
281
- if (bullet_set_count_cap > diff / 10) && (diff > 39) && !Regexp.last_match(6).nil?
282
- bullet_set_count_cap = diff / 10
283
- output += "ボレーの弾丸の数の上限は\[技能値÷10(切り捨て)\]発なので、それより高い数を指定できません。ボレーの弾丸の数を#{bullet_set_count_cap}発に変更します。\n"
284
- elsif (diff <= 39) && (bullet_set_count_cap > 3) && !Regexp.last_match(6).nil?
285
- bullet_set_count_cap = 3
286
- output += "技能値が39以下ではボレーの弾丸の数の上限および下限は3発です。ボレーの弾丸の数を#{bullet_set_count_cap}発に変更します。\n"
287
- end
288
-
289
- # ボレーの下限の設定がおかしい場合の注意表示およびエラー表示
290
- return "ボレーの弾丸の数は正の数です。" if (bullet_set_count_cap <= 0) && !Regexp.last_match(6).nil?
291
-
292
- if (bullet_set_count_cap < 3) && !Regexp.last_match(6).nil?
293
- bullet_set_count_cap = 3
294
- output += "ボレーの弾丸の数の下限は3発です。ボレーの弾丸の数を3発に変更します。\n"
295
- end
296
-
297
- return "弾薬は正の数です。" if bullet_count <= 0
298
- return "目標値は正の数です。" if diff <= 0
299
-
300
- if broken_number < 0
301
- output += "故障ナンバーは正の数です。マイナス記号を外します。\n"
302
- broken_number = broken_number.abs
303
- end
304
-
305
- unless BONUS_DICE_RANGE.include?(bonus_dice_count)
306
- return "エラー。ボーナス・ペナルティダイスの値は#{BONUS_DICE_RANGE.min}~#{BONUS_DICE_RANGE.max}です。"
307
- end
308
-
309
- output += "ボーナス・ペナルティダイス[#{bonus_dice_count}]"
310
- output += rollFullAuto(bullet_count, diff, broken_number, bonus_dice_count, stop_count, bullet_set_count_cap)
311
-
312
- return output
313
- end
314
-
315
- def rollFullAuto(bullet_count, diff, broken_number, dice_num, stop_count, bullet_set_count_cap)
316
- output = ""
317
- loopCount = 0
318
-
319
- counts = {
320
- hit_bullet: 0,
321
- impale_bullet: 0,
322
- bullet: bullet_count,
323
- }
324
-
325
- # 難易度変更用ループ
326
- (0..3).each do |more_difficulty|
327
- output += getNextDifficultyMessage(more_difficulty)
328
-
329
- # ペナルティダイスを減らしながらロール用ループ
330
- while dice_num >= BONUS_DICE_RANGE.min
331
-
332
- loopCount += 1
333
- hit_result, total, total_list = getHitResultInfos(dice_num, diff, more_difficulty)
334
- output += "\n#{loopCount}回目: > #{total_list.join(', ')} > #{hit_result}"
335
-
336
- if total >= broken_number
337
- output += " ジャム"
338
- return getHitResultText(output, counts)
339
- end
340
-
341
- hit_type = getHitType(more_difficulty, hit_result)
342
- hit_bullet, impale_bullet, lost_bullet = getBulletResults(counts[:bullet], hit_type, diff, bullet_set_count_cap)
343
-
344
- output += " (#{hit_bullet}発が命中、#{impale_bullet}発が貫通)"
345
-
346
- counts[:hit_bullet] += hit_bullet
347
- counts[:impale_bullet] += impale_bullet
348
- counts[:bullet] -= lost_bullet
349
-
350
- return getHitResultText(output, counts) if counts[:bullet] <= 0
351
-
352
- dice_num -= 1
353
- end
354
-
355
- # 指定された難易度となった場合、連射処理を途中で止める
356
- if shouldStopRollFullAuto?(stop_count, more_difficulty)
357
- output += "\n【指定の難易度となったので、処理を終了します。】"
358
- break
359
- end
360
-
361
- dice_num += 1
362
- end
363
-
364
- return getHitResultText(output, counts)
365
- end
366
-
367
- # 連射処理を止める条件(難易度の閾値)
368
- # @return [Hash<String, Integer>]
369
- #
370
- # 成功の種類の小文字表記 => 難易度の閾値
371
- ROLL_FULL_AUTO_DIFFICULTY_THRESHOLD = {
372
- # レギュラー
373
- 'r' => 0,
374
- # ハード
375
- 'h' => 1,
376
- # イクストリーム
377
- 'e' => 2
378
- }.freeze
379
-
380
- # 連射処理を止めるべきかどうかを返す
381
- # @param [String] stop_count 成功の種類
382
- # @param [Integer] difficulty 難易度
383
- # @return [Boolean]
384
- def shouldStopRollFullAuto?(stop_count, difficulty)
385
- difficulty_threshold = ROLL_FULL_AUTO_DIFFICULTY_THRESHOLD[stop_count]
386
- return difficulty_threshold && difficulty >= difficulty_threshold
387
- end
388
-
389
- def getHitResultInfos(dice_num, diff, more_difficulty)
390
- total, total_list = roll_with_bonus(dice_num)
391
-
392
- fumbleable = getFumbleable(more_difficulty)
393
- hit_result = result_level(total, diff, fumbleable).to_s
394
-
395
- return hit_result, total, total_list
396
- end
397
-
398
- def getHitResultText(output, counts)
399
- return "#{output}\n> #{counts[:hit_bullet]}発が通常命中、#{counts[:impale_bullet]}発が貫通、残弾#{counts[:bullet]}発"
400
- end
401
-
402
- def getHitType(more_difficulty, hit_result)
403
- successList, impaleBulletList = getSuccessListImpaleBulletList(more_difficulty)
404
-
405
- return :hit if successList.include?(hit_result)
406
- return :impale if impaleBulletList.include?(hit_result)
407
-
408
- return ""
409
- end
410
-
411
- def getBulletResults(bullet_count, hit_type, diff, bullet_set_count_cap)
412
- bullet_set_count = getSetOfBullet(diff, bullet_set_count_cap)
413
- hit_bullet_count_base = getHitBulletCountBase(diff, bullet_set_count)
414
- impale_bullet_count_base = (bullet_set_count / 2.to_f)
415
-
416
- lost_bullet_count = 0
417
- hit_bullet_count = 0
418
- impale_bullet_count = 0
419
-
420
- if !isLastBulletTurn(bullet_count, bullet_set_count)
421
-
422
- case hit_type
423
- when :hit
424
- hit_bullet_count = hit_bullet_count_base # 通常命中した弾数の計算
425
-
426
- when :impale
427
- impale_bullet_count = impale_bullet_count_base.floor # 貫通した弾数の計算
428
- hit_bullet_count = impale_bullet_count_base.ceil
429
- end
430
-
431
- lost_bullet_count = bullet_set_count
432
-
433
- else
434
-
435
- case hit_type
436
- when :hit
437
- hit_bullet_count = getLastHitBulletCount(bullet_count)
438
-
439
- when :impale
440
- impale_bullet_count = getLastHitBulletCount(bullet_count)
441
- hit_bullet_count = bullet_count - impale_bullet_count
442
- end
443
-
444
- lost_bullet_count = bullet_count
445
- end
446
-
447
- return hit_bullet_count, impale_bullet_count, lost_bullet_count
448
- end
449
-
450
- def getSuccessListImpaleBulletList(more_difficulty)
451
- successList = []
452
- impaleBulletList = []
453
-
454
- case more_difficulty
455
- when 0
456
- successList = ["ハード成功", "レギュラー成功"]
457
- impaleBulletList = ["クリティカル", "イクストリーム成功"]
458
- when 1
459
- successList = ["ハード成功"]
460
- impaleBulletList = ["クリティカル", "イクストリーム成功"]
461
- when 2
462
- successList = []
463
- impaleBulletList = ["クリティカル", "イクストリーム成功"]
464
- when 3
465
- successList = ["クリティカル"]
466
- impaleBulletList = []
467
- end
468
-
469
- return successList, impaleBulletList
470
- end
471
-
472
- def getNextDifficultyMessage(more_difficulty)
473
- case more_difficulty
474
- when 1
475
- return "\n【難易度がハードに変更】"
476
- when 2
477
- return "\n【難易度がイクストリームに変更】"
478
- when 3
479
- return "\n【難易度がクリティカルに変更】"
480
- end
481
-
482
- return ""
483
- end
484
-
485
- def getSetOfBullet(diff, bullet_set_count_cap)
486
- bullet_set_count = diff / 10
487
-
488
- if bullet_set_count_cap < bullet_set_count
489
- bullet_set_count = bullet_set_count_cap
490
- end
491
-
492
- if (diff >= 1) && (diff < 30)
493
- bullet_set_count = 3 # 技能値が29以下での最低値保障処理
494
- end
495
-
496
- return bullet_set_count
497
- end
498
-
499
- def getHitBulletCountBase(diff, bullet_set_count)
500
- hit_bullet_count_base = (bullet_set_count / 2)
501
-
502
- if (diff >= 1) && (diff < 30)
503
- hit_bullet_count_base = 1 # 技能値29以下での最低値保障
504
- end
505
-
506
- return hit_bullet_count_base
507
- end
508
-
509
- def isLastBulletTurn(bullet_count, bullet_set_count)
510
- ((bullet_count - bullet_set_count) < 0)
511
- end
512
-
513
- def getLastHitBulletCount(bullet_count)
514
- # 残弾1での最低値保障処理
515
- if bullet_count == 1
516
- return 1
517
- end
518
-
519
- count = (bullet_count / 2.to_f).floor
520
- return count
521
- end
522
-
523
- def getFumbleable(more_difficulty)
524
- # 成功が49以下の出目のみとなるため、ファンブル値は上昇
525
- return (more_difficulty >= 1)
526
- end
527
-
528
272
  # 表一式
529
273
  # 即時の恐怖症表
530
274
  def roll_bmr_table()