bcdice 3.0.0.pre.alpha.1 → 3.0.0.pre.alpha.2

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 (255) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +1 -1
  3. data/.rubocop.yml +12 -0
  4. data/.rubocop_todo.yml +1 -0
  5. data/CHANGELOG.md +34 -0
  6. data/Gemfile +6 -3
  7. data/Rakefile +52 -18
  8. data/bcdice.gemspec +2 -0
  9. data/i18n/Amadeus/ja_jp.yml +386 -0
  10. data/i18n/Amadeus/ko_kr.yml +148 -0
  11. data/i18n/Cthulhu/ja_jp.yml +11 -0
  12. data/i18n/Cthulhu/ko_kr.yml +11 -0
  13. data/i18n/Cthulhu/zh_hant.yml +11 -0
  14. data/i18n/DetatokoSaga/ja_jp.yml +74 -0
  15. data/i18n/DetatokoSaga/ko_kr.yml +74 -0
  16. data/i18n/DoubleCross/ja_jp.yml +53 -0
  17. data/i18n/DoubleCross/ko_kr.yml +53 -0
  18. data/i18n/Dracurouge/ja_jp.yml +1374 -0
  19. data/i18n/Dracurouge/ko_kr.yml +295 -0
  20. data/i18n/Fiasco/ja_jp.yml +10 -0
  21. data/i18n/Fiasco/ko_kr.yml +10 -0
  22. data/i18n/FutariSousa/ja_jp.yml +720 -0
  23. data/i18n/FutariSousa/ko_kr.yml +746 -0
  24. data/i18n/Insane/ja_jp.yml +454 -0
  25. data/i18n/Insane/ko_kr.yml +502 -0
  26. data/i18n/Kamigakari/ja_jp.yml +276 -0
  27. data/i18n/Kamigakari/ko_kr.yml +204 -0
  28. data/i18n/KillDeathBusiness/ja_jp.yml +1092 -0
  29. data/i18n/KillDeathBusiness/ko_kr.yml +1062 -0
  30. data/i18n/LogHorizon/ja_jp.yml +3082 -0
  31. data/i18n/LogHorizon/ko_kr.yml +923 -0
  32. data/i18n/MagicaLogia/ja_jp.yml +564 -0
  33. data/i18n/MonotoneMuseum/ja_jp.yml +525 -0
  34. data/i18n/MonotoneMuseum/ko_kr.yml +89 -0
  35. data/i18n/Nechronica/ja_jp.yml +57 -0
  36. data/i18n/Nechronica/ko_kr.yml +14 -0
  37. data/i18n/StratoShout/ja_jp.yml +160 -0
  38. data/i18n/StratoShout/ko_kr.yml +160 -0
  39. data/i18n/ja_jp.yml +5 -0
  40. data/i18n/ko_kr.yml +7 -0
  41. data/i18n/zh_hant.yml +3 -0
  42. data/lib/bcdice/arithmetic/node.rb +154 -0
  43. data/lib/bcdice/base.rb +87 -101
  44. data/lib/bcdice/common_command.rb +2 -0
  45. data/lib/bcdice/common_command/add_dice.rb +5 -41
  46. data/lib/bcdice/common_command/add_dice/node.rb +92 -16
  47. data/lib/bcdice/common_command/add_dice/parser.rb +374 -274
  48. data/lib/bcdice/common_command/add_dice/parser.y +153 -0
  49. data/lib/bcdice/common_command/add_dice/randomizer.rb +25 -33
  50. data/lib/bcdice/common_command/barabara_dice.rb +6 -47
  51. data/lib/bcdice/common_command/barabara_dice/node.rb +84 -0
  52. data/lib/bcdice/common_command/barabara_dice/parser.rb +336 -0
  53. data/lib/bcdice/common_command/barabara_dice/parser.y +107 -0
  54. data/lib/bcdice/common_command/calc.rb +7 -30
  55. data/lib/bcdice/common_command/calc/node.rb +30 -0
  56. data/lib/bcdice/common_command/calc/parser.rb +271 -0
  57. data/lib/bcdice/common_command/calc/parser.y +79 -0
  58. data/lib/bcdice/common_command/choice.rb +137 -19
  59. data/lib/bcdice/common_command/d66_dice.rb +48 -34
  60. data/lib/bcdice/common_command/lexer.rb +46 -0
  61. data/lib/bcdice/common_command/repeat.rb +102 -0
  62. data/lib/bcdice/common_command/reroll_dice.rb +8 -158
  63. data/lib/bcdice/common_command/reroll_dice/node.rb +198 -0
  64. data/lib/bcdice/common_command/reroll_dice/parser.rb +421 -0
  65. data/lib/bcdice/common_command/reroll_dice/parser.y +158 -0
  66. data/lib/bcdice/common_command/upper_dice.rb +10 -129
  67. data/lib/bcdice/common_command/upper_dice/node.rb +181 -0
  68. data/lib/bcdice/common_command/upper_dice/parser.rb +412 -0
  69. data/lib/bcdice/common_command/upper_dice/parser.y +143 -0
  70. data/lib/bcdice/common_command/version.rb +9 -17
  71. data/lib/bcdice/deprecated/checker.rb +78 -0
  72. data/lib/bcdice/dice_table/d66_grid_table.rb +8 -0
  73. data/lib/bcdice/dice_table/d66_table.rb +10 -0
  74. data/lib/bcdice/dice_table/sai_fic_skill_table.rb +75 -17
  75. data/lib/bcdice/dice_table/sai_fic_skill_table/category.rb +25 -0
  76. data/lib/bcdice/dice_table/sai_fic_skill_table/skill.rb +23 -0
  77. data/lib/bcdice/dice_table/table.rb +8 -0
  78. data/lib/bcdice/game_system.rb +7 -1
  79. data/lib/bcdice/game_system/AFF2e.rb +1 -1
  80. data/lib/bcdice/game_system/AceKillerGene.rb +2 -2
  81. data/lib/bcdice/game_system/Airgetlamh.rb +3 -3
  82. data/lib/bcdice/game_system/Alsetto.rb +1 -1
  83. data/lib/bcdice/game_system/Alshard.rb +1 -1
  84. data/lib/bcdice/game_system/AlterRaise.rb +2 -2
  85. data/lib/bcdice/game_system/Amadeus.rb +46 -507
  86. data/lib/bcdice/game_system/Amadeus_Korean.rb +12 -456
  87. data/lib/bcdice/game_system/AnimaAnimus.rb +1 -1
  88. data/lib/bcdice/game_system/Arianrhod.rb +0 -1
  89. data/lib/bcdice/game_system/ArsMagica.rb +1 -1
  90. data/lib/bcdice/game_system/Avandner.rb +1 -1
  91. data/lib/bcdice/game_system/BBN.rb +1 -1
  92. data/lib/bcdice/game_system/BadLife.rb +1 -1
  93. data/lib/bcdice/game_system/BarnaKronika.rb +1 -1
  94. data/lib/bcdice/game_system/BeastBindTrinity.rb +1 -2
  95. data/lib/bcdice/game_system/BeginningIdol.rb +2 -3
  96. data/lib/bcdice/game_system/BeginningIdol_Korean.rb +2 -3
  97. data/lib/bcdice/game_system/BladeOfArcana.rb +2 -2
  98. data/lib/bcdice/game_system/BlindMythos.rb +1 -1
  99. data/lib/bcdice/game_system/BloodCrusade.rb +0 -1
  100. data/lib/bcdice/game_system/BloodMoon.rb +0 -1
  101. data/lib/bcdice/game_system/CardRanker.rb +1 -2
  102. data/lib/bcdice/game_system/ChaosFlare.rb +1 -1
  103. data/lib/bcdice/game_system/Chill.rb +1 -1
  104. data/lib/bcdice/game_system/CodeLayerd.rb +1 -1
  105. data/lib/bcdice/game_system/ColossalHunter.rb +1 -2
  106. data/lib/bcdice/game_system/Comes.rb +50 -0
  107. data/lib/bcdice/game_system/CrashWorld.rb +1 -1
  108. data/lib/bcdice/game_system/Cthulhu.rb +94 -97
  109. data/lib/bcdice/game_system/Cthulhu7th.rb +108 -67
  110. data/lib/bcdice/game_system/Cthulhu7th_ChineseTraditional.rb +1 -1
  111. data/lib/bcdice/game_system/Cthulhu7th_Korean.rb +1 -1
  112. data/lib/bcdice/game_system/CthulhuTech.rb +8 -14
  113. data/lib/bcdice/game_system/Cthulhu_ChineseTraditional.rb +7 -190
  114. data/lib/bcdice/game_system/Cthulhu_Korean.rb +5 -186
  115. data/lib/bcdice/game_system/DarkBlaze.rb +9 -5
  116. data/lib/bcdice/game_system/DarkDaysDrive.rb +17 -15
  117. data/lib/bcdice/game_system/DarkSouls.rb +1 -1
  118. data/lib/bcdice/game_system/DeadlineHeroes.rb +2 -2
  119. data/lib/bcdice/game_system/DemonParasite.rb +1 -2
  120. data/lib/bcdice/game_system/DetatokoSaga.rb +48 -149
  121. data/lib/bcdice/game_system/DetatokoSaga_Korean.rb +6 -274
  122. data/lib/bcdice/game_system/DiceOfTheDead.rb +9 -6
  123. data/lib/bcdice/game_system/DoubleCross.rb +102 -81
  124. data/lib/bcdice/game_system/DoubleCross_Korean.rb +13 -330
  125. data/lib/bcdice/game_system/Dracurouge.rb +376 -1678
  126. data/lib/bcdice/game_system/Dracurouge_Korean.rb +16 -271
  127. data/lib/bcdice/game_system/EarthDawn.rb +1 -1
  128. data/lib/bcdice/game_system/EarthDawn3.rb +1 -1
  129. data/lib/bcdice/game_system/EarthDawn4.rb +1 -1
  130. data/lib/bcdice/game_system/Elysion.rb +3 -4
  131. data/lib/bcdice/game_system/EmbryoMachine.rb +1 -1
  132. data/lib/bcdice/game_system/Emoklore.rb +131 -0
  133. data/lib/bcdice/game_system/EndBreaker.rb +1 -2
  134. data/lib/bcdice/game_system/EtrianOdysseySRS.rb +1 -1
  135. data/lib/bcdice/game_system/Fiasco.rb +87 -70
  136. data/lib/bcdice/game_system/Fiasco_Korean.rb +7 -95
  137. data/lib/bcdice/game_system/FilledWith.rb +462 -566
  138. data/lib/bcdice/game_system/FullMetalPanic.rb +1 -1
  139. data/lib/bcdice/game_system/FutariSousa.rb +103 -938
  140. data/lib/bcdice/game_system/FutariSousa_Korean.rb +7 -948
  141. data/lib/bcdice/game_system/{Gurps.rb → GURPS.rb} +184 -217
  142. data/lib/bcdice/game_system/Garako.rb +131 -39
  143. data/lib/bcdice/game_system/GardenOrder.rb +2 -2
  144. data/lib/bcdice/game_system/GehennaAn.rb +1 -1
  145. data/lib/bcdice/game_system/GeishaGirlwithKatana.rb +1 -1
  146. data/lib/bcdice/game_system/GoblinSlayer.rb +1 -1
  147. data/lib/bcdice/game_system/GoldenSkyStories.rb +1 -1
  148. data/lib/bcdice/game_system/Gorilla.rb +1 -1
  149. data/lib/bcdice/game_system/GranCrest.rb +2 -3
  150. data/lib/bcdice/game_system/GundogRevised.rb +1 -1
  151. data/lib/bcdice/game_system/GundogZero.rb +1 -1
  152. data/lib/bcdice/game_system/GurpsFW.rb +2 -3
  153. data/lib/bcdice/game_system/HarnMaster.rb +2 -2
  154. data/lib/bcdice/game_system/HatsuneMiku.rb +1 -2
  155. data/lib/bcdice/game_system/HouraiGakuen.rb +1 -1
  156. data/lib/bcdice/game_system/HuntersMoon.rb +1 -2
  157. data/lib/bcdice/game_system/Illusio.rb +2 -2
  158. data/lib/bcdice/game_system/Insane.rb +90 -717
  159. data/lib/bcdice/game_system/Insane_Korean.rb +7 -719
  160. data/lib/bcdice/game_system/Kamigakari.rb +47 -242
  161. data/lib/bcdice/game_system/Kamigakari_Korean.rb +6 -394
  162. data/lib/bcdice/game_system/KanColle.rb +3 -3
  163. data/lib/bcdice/game_system/KemonoNoMori.rb +1 -1
  164. data/lib/bcdice/game_system/KillDeathBusiness.rb +162 -1144
  165. data/lib/bcdice/game_system/KillDeathBusiness_Korean.rb +6 -1459
  166. data/lib/bcdice/game_system/KurayamiCrying.rb +1 -1
  167. data/lib/bcdice/game_system/LiveraDoll.rb +2 -2
  168. data/lib/bcdice/game_system/LogHorizon.rb +350 -3379
  169. data/lib/bcdice/game_system/LogHorizon_Korean.rb +55 -1357
  170. data/lib/bcdice/game_system/LostRecord.rb +0 -1
  171. data/lib/bcdice/game_system/LostRoyal.rb +1 -2
  172. data/lib/bcdice/game_system/MagicaLogia.rb +158 -1044
  173. data/lib/bcdice/game_system/MeikyuDays.rb +1 -2
  174. data/lib/bcdice/game_system/MeikyuKingdom.rb +4 -4
  175. data/lib/bcdice/game_system/MeikyuKingdomBasic.rb +4 -5
  176. data/lib/bcdice/game_system/MetalHead.rb +1 -1
  177. data/lib/bcdice/game_system/MetalHeadExtream.rb +2 -2
  178. data/lib/bcdice/game_system/MetallicGuardian.rb +1 -1
  179. data/lib/bcdice/game_system/MonotoneMuseum.rb +38 -239
  180. data/lib/bcdice/game_system/MonotoneMuseum_Korean.rb +10 -270
  181. data/lib/bcdice/game_system/NSSQ.rb +159 -0
  182. data/lib/bcdice/game_system/Nechronica.rb +34 -73
  183. data/lib/bcdice/game_system/Nechronica_Korean.rb +11 -128
  184. data/lib/bcdice/game_system/NeverCloud.rb +1 -1
  185. data/lib/bcdice/game_system/NightWizard.rb +1 -1
  186. data/lib/bcdice/game_system/NightWizard3rd.rb +1 -1
  187. data/lib/bcdice/game_system/NinjaSlayer.rb +12 -11
  188. data/lib/bcdice/game_system/NjslyrBattle.rb +1 -1
  189. data/lib/bcdice/game_system/OneWayHeroics.rb +1 -2
  190. data/lib/bcdice/game_system/OracleEngine.rb +1 -1
  191. data/lib/bcdice/game_system/OrgaRain.rb +2 -2
  192. data/lib/bcdice/game_system/Paradiso.rb +1 -1
  193. data/lib/bcdice/game_system/Paranoia.rb +1 -1
  194. data/lib/bcdice/game_system/ParanoiaRebooted.rb +1 -1
  195. data/lib/bcdice/game_system/ParasiteBlood.rb +1 -1
  196. data/lib/bcdice/game_system/Peekaboo.rb +22 -122
  197. data/lib/bcdice/game_system/Postman.rb +2 -2
  198. data/lib/bcdice/game_system/PulpCthulhu.rb +3 -3
  199. data/lib/bcdice/game_system/Raisondetre.rb +2 -2
  200. data/lib/bcdice/game_system/RecordOfLodossWar.rb +1 -1
  201. data/lib/bcdice/game_system/RecordOfSteam.rb +1 -1
  202. data/lib/bcdice/game_system/RokumonSekai2.rb +1 -1
  203. data/lib/bcdice/game_system/RuinBreakers.rb +296 -0
  204. data/lib/bcdice/game_system/Ryutama.rb +1 -1
  205. data/lib/bcdice/game_system/SRS.rb +1 -2
  206. data/lib/bcdice/game_system/SamsaraBallad.rb +1 -1
  207. data/lib/bcdice/game_system/Satasupe.rb +1 -2
  208. data/lib/bcdice/game_system/ScreamHighSchool.rb +2 -2
  209. data/lib/bcdice/game_system/SevenFortressMobius.rb +1 -1
  210. data/lib/bcdice/game_system/ShadowRun5.rb +2 -2
  211. data/lib/bcdice/game_system/SharedFantasia.rb +1 -1
  212. data/lib/bcdice/game_system/ShinMegamiTenseiKakuseihen.rb +1 -1
  213. data/lib/bcdice/game_system/ShinkuuGakuen.rb +2 -2
  214. data/lib/bcdice/game_system/ShinobiGami.rb +1 -2
  215. data/lib/bcdice/game_system/ShoujoTenrankai.rb +2 -2
  216. data/lib/bcdice/game_system/Skynauts.rb +1 -1
  217. data/lib/bcdice/game_system/SteamPunkers.rb +1 -1
  218. data/lib/bcdice/game_system/StellarKnights.rb +1 -2
  219. data/lib/bcdice/game_system/SterileLife.rb +1 -1
  220. data/lib/bcdice/game_system/StrangerOfSwordCity.rb +1 -2
  221. data/lib/bcdice/game_system/StratoShout.rb +44 -247
  222. data/lib/bcdice/game_system/StratoShout_Korean.rb +6 -282
  223. data/lib/bcdice/game_system/Strave.rb +2 -2
  224. data/lib/bcdice/game_system/SwordWorld.rb +8 -9
  225. data/lib/bcdice/game_system/SwordWorld2_0.rb +2 -3
  226. data/lib/bcdice/game_system/SwordWorld2_5.rb +2 -3
  227. data/lib/bcdice/game_system/TherapieSein.rb +1 -1
  228. data/lib/bcdice/game_system/TokumeiTenkousei.rb +1 -1
  229. data/lib/bcdice/game_system/TokyoGhostResearch.rb +2 -2
  230. data/lib/bcdice/game_system/Torg.rb +2 -2
  231. data/lib/bcdice/game_system/Torg1_5.rb +1 -1
  232. data/lib/bcdice/game_system/TorgEternity.rb +1 -1
  233. data/lib/bcdice/game_system/TrinitySeven.rb +1 -1
  234. data/lib/bcdice/game_system/TunnelsAndTrolls.rb +1 -1
  235. data/lib/bcdice/game_system/TwilightGunsmoke.rb +1 -2
  236. data/lib/bcdice/game_system/UnsungDuet.rb +139 -0
  237. data/lib/bcdice/game_system/Utakaze.rb +1 -1
  238. data/lib/bcdice/game_system/VampireTheMasquerade5th.rb +1 -1
  239. data/lib/bcdice/game_system/Villaciel.rb +1 -2
  240. data/lib/bcdice/game_system/Warhammer.rb +1 -1
  241. data/lib/bcdice/game_system/Warhammer4.rb +329 -0
  242. data/lib/bcdice/game_system/WitchQuest.rb +1 -1
  243. data/lib/bcdice/game_system/WorldOfDarkness.rb +1 -1
  244. data/lib/bcdice/game_system/YankeeYogSothoth.rb +15 -15
  245. data/lib/bcdice/game_system/YearZeroEngine.rb +1 -1
  246. data/lib/bcdice/game_system/ZettaiReido.rb +1 -1
  247. data/lib/bcdice/game_system/filled_with/cook_tables.rb +119 -0
  248. data/lib/bcdice/game_system/filled_with/lot_tables.rb +155 -0
  249. data/lib/bcdice/loader.rb +6 -8
  250. data/lib/bcdice/preprocessor.rb +15 -40
  251. data/lib/bcdice/repl.rb +1 -1
  252. data/lib/bcdice/result.rb +83 -0
  253. data/lib/bcdice/translate.rb +11 -0
  254. data/lib/bcdice/version.rb +1 -1
  255. metadata +80 -4
@@ -1,5 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bcdice/normalize"
2
4
  require "bcdice/format"
5
+ require "bcdice/common_command/reroll_dice/parser"
3
6
 
4
7
  module BCDice
5
8
  module CommonCommand
@@ -22,167 +25,14 @@ module BCDice
22
25
  #
23
26
  # 成功条件が書かれていない場合、成功数0として扱う。
24
27
  # 振り足し条件が数値のみ指定されている場合、比較演算子は >= が指定されたとして振舞う。
25
- class RerollDice
28
+ module RerollDice
26
29
  PREFIX_PATTERN = /\d+R\d+/.freeze
27
30
  REROLL_LIMIT = 10000
28
31
 
29
- def initialize(command, bcdice, diceBot)
30
- @command = command
31
- @bcdice = bcdice
32
- @diceBot = diceBot
33
-
34
- @is_secret = false
35
- end
36
-
37
- def secret?
38
- @is_secret
39
- end
40
-
41
- def eval()
42
- unless parse(@command)
43
- return nil
44
- end
45
-
46
- unless @reroll_threshold
47
- return msg_invalid_reroll_number(@command)
48
- end
49
-
50
- dice_queue = @notation.split("+").map do |xRn|
51
- x, n = xRn.split("R").map(&:to_i)
52
- [x, n, 0]
53
- end
54
-
55
- unless dice_queue.all? { |d| valid_reroll_rule?(d[1], @reroll_cmp_op, @reroll_threshold) }
56
- return msg_invalid_reroll_number(@command)
57
- end
58
-
59
- success_count = 0
60
- dice_str_list = []
61
- one_count = 0
62
- loop_count = 0
63
-
64
- dice_total_count = 0
65
-
66
- while !dice_queue.empty? && loop_count < REROLL_LIMIT
67
- # xRn
68
- x, n, depth = dice_queue.shift
69
- loop_count += 1
70
- dice_total_count += x
71
-
72
- dice_list = @bcdice.roll_barabara(x, n)
73
- dice_list.sort! if @diceBot.sort_barabara_dice?
74
- success_count += dice_list.count() { |val| val.send(@cmp_op, @target_number) } if @cmp_op
75
- reroll_count = dice_list.count() { |val| val.send(@reroll_cmp_op, @reroll_threshold) }
76
-
77
- dice_str_list.push(dice_list.join(","))
78
-
79
- if depth.zero?
80
- one_count += dice_list.count(1)
81
- end
82
-
83
- if reroll_count > 0
84
- dice_queue.push([reroll_count, n, depth + 1])
85
- end
86
- end
87
-
88
- sequence = [
89
- expr(),
90
- dice_str_list.join(" + "),
91
- "成功数#{success_count}",
92
- @diceBot.grich_text(one_count, dice_total_count, success_count),
93
- ].compact
94
-
95
- return sequence.join(" > ")
96
- end
97
-
98
- private
99
-
100
- # @param command [String]
101
- # @return [Boolean]
102
- def parse(command)
103
- m = /^S?(\d+R\d+(?:\+\d+R\d+)*)(?:\[([<>=]+)?(\d+)\])?(?:([<>=]+)(\d+))?(?:@([<>=]+)?(\d+))?$/.match(command)
104
- unless m
105
- return false
106
- end
107
-
108
- @is_secret = command.start_with?("S")
109
- @notation = m[1]
110
- @cmp_op = Normalize.comparison_operator(m[4]) || @diceBot.default_cmp_op
111
- @target_number = m[5]&.to_i || @diceBot.default_target_number
112
-
113
- @reroll_cmp_op = decide_reroll_cmp_op(m)
114
- @reroll_threshold = decide_reroll_threshold(m[3] || m[7], @target_number)
115
-
116
- return true
117
- end
118
-
119
- # @param m [MatchData]
120
- # @return [Symbol]
121
- def decide_reroll_cmp_op(m)
122
- bracket_op = m[2]
123
- bracket_number = m[3]
124
- at_op = m[6]
125
- at_number = m[7]
126
- cmp_op = m[4]
127
-
128
- op =
129
- if bracket_op && bracket_number
130
- bracket_op
131
- elsif at_op && at_number
132
- at_op
133
- else
134
- cmp_op
135
- end
136
-
137
- Normalize.comparison_operator(op) || :>=
138
- end
139
-
140
- # @param captured_threshold [String, nil]
141
- # @param target_number [Integer, nil]
142
- # @return [Integer]
143
- # @return [nil]
144
- def decide_reroll_threshold(captured_threshold, target_number)
145
- if captured_threshold
146
- captured_threshold.to_i
147
- elsif @diceBot.reroll_dice_reroll_threshold
148
- @diceBot.reroll_dice_reroll_threshold
149
- else
150
- target_number
151
- end
152
- end
153
-
154
- # @return [String]
155
- def expr()
156
- reroll_cmp_op_text = @cmp_op != @reroll_cmp_op ? Format.comparison_operator(@reroll_cmp_op) : nil
157
- cmp_op_text = Format.comparison_operator(@cmp_op)
158
-
159
- "(#{@notation}[#{reroll_cmp_op_text}#{@reroll_threshold}]#{cmp_op_text}#{@target_number})"
160
- end
161
-
162
- # @param command [String]
163
- # @return [String]
164
- def msg_invalid_reroll_number(command)
165
- "#{command} > 条件が間違っています。2R6>=5 あるいは 2R6[5] のように振り足し目標値を指定してください。"
166
- end
167
-
168
- # @param sides [Integer]
169
- # @param cmp_op [Symbol]
170
- # @param reroll_threshold [Integer]
171
- # @return [Boolean]
172
- def valid_reroll_rule?(sides, cmp_op, reroll_threshold) # 振り足しロールの条件確認
173
- case cmp_op
174
- when :<=
175
- reroll_threshold < sides
176
- when :<
177
- reroll_threshold <= sides
178
- when :>=
179
- reroll_threshold > 1
180
- when :>
181
- reroll_threshold >= 1
182
- when :'!='
183
- (1..sides).include?(reroll_threshold)
184
- else
185
- true
32
+ class << self
33
+ def eval(command, game_system, randomizer)
34
+ cmd = Parser.parse(command)
35
+ cmd&.eval(game_system, randomizer)
186
36
  end
187
37
  end
188
38
  end
@@ -0,0 +1,198 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module CommonCommand
5
+ module RerollDice
6
+ module Node
7
+ class Command
8
+ def initialize(secret:, notations:, source:, cmp_op: nil, target_number: nil, reroll_cmp_op: nil, reroll_threshold: nil)
9
+ @secret = secret
10
+ @notations = notations
11
+ @cmp_op = cmp_op
12
+ @target_number_node = target_number
13
+ @reroll_cmp_op = reroll_cmp_op
14
+ @reroll_threshold_node = reroll_threshold
15
+ @source = source
16
+ end
17
+
18
+ def eval(game_system, randomizer)
19
+ round_type = game_system.round_type
20
+ cmp_op = @cmp_op || game_system.default_cmp_op
21
+ reroll_cmp_op = @reroll_cmp_op || cmp_op || :>=
22
+
23
+ target_number =
24
+ @target_number_node&.eval(round_type) ||
25
+ game_system.default_target_number
26
+
27
+ reroll_threshold =
28
+ @reroll_threshold_node&.eval(round_type) ||
29
+ game_system.reroll_dice_reroll_threshold ||
30
+ target_number
31
+
32
+ reroll_condition = RerollCondition.new(reroll_cmp_op, reroll_threshold)
33
+
34
+ dice_queue = @notations.map { |node| node.to_dice(round_type) }
35
+ unless dice_queue.all? { |d| reroll_condition.valid?(d.sides) }
36
+ return result_with_text("#{@source} > 条件が間違っています。2R6>=5 あるいは 2R6[5] のように振り足し目標値を指定してください。")
37
+ end
38
+
39
+ dice_list_list = roll(
40
+ dice_queue,
41
+ randomizer,
42
+ reroll_condition,
43
+ game_system.sort_barabara_dice?
44
+ )
45
+
46
+ dice_list = dice_list_list.flatten
47
+
48
+ # 振り足し分は出目1の個数をカウントしない
49
+ one_count = dice_list_list
50
+ .take(@notations.size)
51
+ .flatten
52
+ .count(1)
53
+
54
+ success_count =
55
+ if cmp_op
56
+ dice_list.count { |val| val.send(cmp_op, target_number) }
57
+ else
58
+ 0
59
+ end
60
+
61
+ sequence = [
62
+ expr(round_type, reroll_condition, cmp_op, target_number),
63
+ dice_list_list.map { |list| list.join(",") }.join(" + "),
64
+ "成功数#{success_count}",
65
+ game_system.grich_text(one_count, dice_list.size, success_count),
66
+ ].compact
67
+
68
+ result_with_text(sequence.join(" > "))
69
+ end
70
+
71
+ private
72
+
73
+ # ダイスロールを行う
74
+ # @param dice_queue [Array<Dice>] ダイスキュー
75
+ # @param randomizer [Randomizer] 乱数生成器
76
+ # @param reroll_condition [RerollCondition] 振り足し条件
77
+ # @param sort [Boolean] 出目を並び替えるか
78
+ # @return [Array<Array<Integer>>]
79
+ def roll(dice_queue, randomizer, reroll_condition, sort)
80
+ dice_list_list = []
81
+ loop_count = 0
82
+
83
+ while !dice_queue.empty? && loop_count < REROLL_LIMIT
84
+ dice = dice_queue.shift
85
+ loop_count += 1
86
+
87
+ dice_list = dice.roll(randomizer)
88
+ dice_list.sort! if sort
89
+ dice_list_list.push(dice_list)
90
+
91
+ reroll_count = dice_list.count { |val| reroll_condition.reroll?(val) }
92
+ if reroll_count > 0
93
+ dice_queue.push(Dice.new(reroll_count, dice.sides))
94
+ end
95
+ end
96
+
97
+ return dice_list_list
98
+ end
99
+
100
+ def expr(round_type, reroll_condition, cmp_op, target_number)
101
+ notation = @notations.map { |n| n.to_dice(round_type) }.join("+")
102
+
103
+ reroll_cmp_op_text =
104
+ if reroll_condition.cmp_op == cmp_op
105
+ ""
106
+ else
107
+ Format.comparison_operator(reroll_condition.cmp_op)
108
+ end
109
+
110
+ cmp_op_text = Format.comparison_operator(cmp_op)
111
+
112
+ "(#{notation}[#{reroll_cmp_op_text}#{reroll_condition.threshold}]#{cmp_op_text}#{target_number})"
113
+ end
114
+
115
+ def result_with_text(text)
116
+ Result.new.tap do |r|
117
+ r.secret = @secret
118
+ r.text = text
119
+ end
120
+ end
121
+ end
122
+
123
+ # 振り足し条件を表すクラス。
124
+ class RerollCondition
125
+ # @return [Symbol] 比較演算子
126
+ attr_reader :cmp_op
127
+ # @return [Integer] 振り足しの閾値
128
+ attr_reader :threshold
129
+
130
+ # @param cmp_op [Symbol] 比較演算子
131
+ # @param threshold [Integer] 振り足しの閾値
132
+ def initialize(cmp_op, threshold)
133
+ @cmp_op = cmp_op
134
+ @threshold = threshold
135
+ end
136
+
137
+ # @param sides [Integer] ダイスの面数
138
+ # @return [Boolean] 振り足し条件が妥当か
139
+ def valid?(sides)
140
+ return false unless @threshold
141
+
142
+ case @cmp_op
143
+ when :<=
144
+ @threshold < sides
145
+ when :<
146
+ @threshold <= sides
147
+ when :>=
148
+ @threshold > 1
149
+ when :>
150
+ @threshold >= 1
151
+ when :'!='
152
+ (1..sides).include?(@threshold)
153
+ else # :==
154
+ true
155
+ end
156
+ end
157
+
158
+ # @param value [Integer] 出目
159
+ # @return [Boolean] 振り足しを行うべきか
160
+ def reroll?(value)
161
+ value.send(@cmp_op, @threshold)
162
+ end
163
+ end
164
+
165
+ class Notation
166
+ def initialize(times, sides)
167
+ @times = times
168
+ @sides = sides
169
+ end
170
+
171
+ def to_dice(round_type)
172
+ times = @times.eval(round_type)
173
+ sides = @sides.eval(round_type)
174
+
175
+ Dice.new(times, sides)
176
+ end
177
+ end
178
+
179
+ class Dice
180
+ attr_reader :times, :sides
181
+
182
+ def initialize(times, sides)
183
+ @times = times
184
+ @sides = sides
185
+ end
186
+
187
+ def roll(randomizer)
188
+ randomizer.roll_barabara(times, sides)
189
+ end
190
+
191
+ def to_s
192
+ "#{times}R#{sides}"
193
+ end
194
+ end
195
+ end
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,421 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by Racc 1.5.1
4
+ # from Racc grammar file "".
5
+ #
6
+
7
+ require 'racc/parser.rb'
8
+
9
+
10
+ require "bcdice/common_command/lexer"
11
+ require "bcdice/common_command/barabara_dice/node"
12
+ require "bcdice/arithmetic/node"
13
+
14
+ module BCDice
15
+ module CommonCommand
16
+ module RerollDice
17
+ class Parser < Racc::Parser
18
+
19
+
20
+ def self.parse(source)
21
+ new.parse(source)
22
+ end
23
+
24
+ def parse(source)
25
+ @lexer = Lexer.new(source)
26
+ do_parse()
27
+ rescue ParseError
28
+ nil
29
+ end
30
+
31
+ private
32
+
33
+ def next_token
34
+ @lexer.next_token
35
+ end
36
+ ##### State transition tables begin ###
37
+
38
+ racc_action_table = [
39
+ 9, 3, 9, 9, 9, 15, 20, 21, 20, 21,
40
+ 8, 14, 8, 8, 8, 9, 9, 4, 13, 28,
41
+ 10, 39, 20, 21, 9, 8, 8, 31, 32, 9,
42
+ 20, 21, 33, 16, 8, 20, 21, 9, 24, 8,
43
+ 34, 35, 9, 20, 21, 31, 32, 8, 20, 21,
44
+ 9, 13, 8, 31, 32, 9, 20, 21, 34, 35,
45
+ 8, 20, 21, 9, nil, 8, 34, 35, 9, 20,
46
+ 21, 31, 32, 8, 20, 21, 9, nil, 8, nil,
47
+ 31, 32, 20, 21, 31, 32, 8, 40, nil, nil,
48
+ nil, 47, 51, 49, 50, 52 ]
49
+
50
+ racc_action_check = [
51
+ 14, 0, 24, 2, 15, 5, 14, 14, 24, 24,
52
+ 14, 5, 24, 2, 15, 16, 8, 1, 5, 14,
53
+ 4, 24, 8, 8, 13, 16, 8, 17, 17, 20,
54
+ 13, 13, 17, 7, 13, 20, 20, 21, 11, 20,
55
+ 18, 18, 28, 21, 21, 26, 26, 21, 28, 28,
56
+ 31, 12, 28, 38, 38, 32, 31, 31, 42, 42,
57
+ 31, 32, 32, 34, nil, 32, 43, 43, 35, 34,
58
+ 34, 46, 46, 34, 35, 35, 39, nil, 35, nil,
59
+ 27, 27, 39, 39, 41, 41, 39, 27, nil, nil,
60
+ nil, 41, 45, 45, 45, 45 ]
61
+
62
+ racc_action_pointer = [
63
+ -6, 17, 1, nil, 20, -3, nil, 30, 14, nil,
64
+ nil, 18, 30, 22, -2, 2, 13, 19, 30, nil,
65
+ 27, 35, nil, nil, 0, nil, 37, 72, 40, nil,
66
+ nil, 48, 53, nil, 61, 66, nil, nil, 45, 74,
67
+ nil, 76, 48, 56, nil, 89, 63, nil, nil, nil,
68
+ nil, nil, nil ]
69
+
70
+ racc_action_default = [
71
+ -4, -31, -31, -5, -31, -6, -13, -31, -31, -30,
72
+ 53, -1, -6, -31, -31, -31, -31, -31, -17, -20,
73
+ -31, -31, -28, -3, -31, -2, -7, -31, -31, -12,
74
+ -14, -31, -31, -29, -31, -31, -26, -27, -10, -31,
75
+ -8, -31, -15, -16, -18, -21, -11, -9, -19, -22,
76
+ -23, -24, -25 ]
77
+
78
+ racc_goto_table = [
79
+ 17, 7, 11, 36, 37, 26, 27, 1, 6, 25,
80
+ 42, 43, 2, 5, 7, 30, 38, 44, 45, 12,
81
+ 41, 29, 23, 48, nil, nil, nil, nil, nil, nil,
82
+ nil, 46 ]
83
+
84
+ racc_goto_check = [
85
+ 7, 9, 4, 11, 11, 7, 7, 1, 8, 4,
86
+ 10, 10, 2, 3, 9, 9, 7, 11, 11, 5,
87
+ 7, 8, 6, 12, nil, nil, nil, nil, nil, nil,
88
+ nil, 7 ]
89
+
90
+ racc_goto_pointer = [
91
+ nil, 7, 12, 11, -3, 14, 11, -8, 6, -1,
92
+ -21, -17, -22 ]
93
+
94
+ racc_goto_default = [
95
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, 22,
96
+ 18, 19, nil ]
97
+
98
+ racc_reduce_table = [
99
+ 0, 0, :racc_error,
100
+ 3, 23, :_reduce_1,
101
+ 4, 23, :_reduce_2,
102
+ 4, 23, :_reduce_3,
103
+ 0, 24, :_reduce_4,
104
+ 1, 24, :_reduce_5,
105
+ 0, 26, :_reduce_6,
106
+ 2, 26, :_reduce_7,
107
+ 3, 27, :_reduce_8,
108
+ 4, 27, :_reduce_9,
109
+ 2, 28, :_reduce_10,
110
+ 3, 28, :_reduce_11,
111
+ 3, 25, :_reduce_12,
112
+ 1, 25, :_reduce_13,
113
+ 3, 30, :_reduce_14,
114
+ 3, 29, :_reduce_15,
115
+ 3, 29, :_reduce_16,
116
+ 1, 29, :_reduce_none,
117
+ 3, 32, :_reduce_18,
118
+ 4, 32, :_reduce_19,
119
+ 1, 32, :_reduce_none,
120
+ 0, 34, :_reduce_21,
121
+ 1, 34, :_reduce_22,
122
+ 1, 34, :_reduce_23,
123
+ 1, 34, :_reduce_24,
124
+ 1, 34, :_reduce_25,
125
+ 2, 33, :_reduce_26,
126
+ 2, 33, :_reduce_27,
127
+ 1, 33, :_reduce_none,
128
+ 3, 31, :_reduce_29,
129
+ 1, 31, :_reduce_30 ]
130
+
131
+ racc_reduce_n = 31
132
+
133
+ racc_shift_n = 53
134
+
135
+ racc_token_table = {
136
+ false => 0,
137
+ :error => 1,
138
+ :NUMBER => 2,
139
+ :R => 3,
140
+ :U => 4,
141
+ :C => 5,
142
+ :F => 6,
143
+ :S => 7,
144
+ :PLUS => 8,
145
+ :MINUS => 9,
146
+ :ASTERISK => 10,
147
+ :SLASH => 11,
148
+ :PARENL => 12,
149
+ :PARENR => 13,
150
+ :BRACKETL => 14,
151
+ :BRACKETR => 15,
152
+ :LESS => 16,
153
+ :GREATER => 17,
154
+ :EQUAL => 18,
155
+ :NOT => 19,
156
+ :AT => 20,
157
+ :CMP_OP => 21 }
158
+
159
+ racc_nt_base = 22
160
+
161
+ racc_use_result_var = true
162
+
163
+ Racc_arg = [
164
+ racc_action_table,
165
+ racc_action_check,
166
+ racc_action_default,
167
+ racc_action_pointer,
168
+ racc_goto_table,
169
+ racc_goto_check,
170
+ racc_goto_default,
171
+ racc_goto_pointer,
172
+ racc_nt_base,
173
+ racc_reduce_table,
174
+ racc_token_table,
175
+ racc_shift_n,
176
+ racc_reduce_n,
177
+ racc_use_result_var ]
178
+
179
+ Racc_token_to_s_table = [
180
+ "$end",
181
+ "error",
182
+ "NUMBER",
183
+ "R",
184
+ "U",
185
+ "C",
186
+ "F",
187
+ "S",
188
+ "PLUS",
189
+ "MINUS",
190
+ "ASTERISK",
191
+ "SLASH",
192
+ "PARENL",
193
+ "PARENR",
194
+ "BRACKETL",
195
+ "BRACKETR",
196
+ "LESS",
197
+ "GREATER",
198
+ "EQUAL",
199
+ "NOT",
200
+ "AT",
201
+ "CMP_OP",
202
+ "$start",
203
+ "expr",
204
+ "secret",
205
+ "notations",
206
+ "target",
207
+ "bracket",
208
+ "at",
209
+ "add",
210
+ "dice",
211
+ "term",
212
+ "mul",
213
+ "unary",
214
+ "round_type" ]
215
+
216
+ Racc_debug_parser = false
217
+
218
+ ##### State transition tables end #####
219
+
220
+ # reduce 0 omitted
221
+
222
+ def _reduce_1(val, _values, result)
223
+ result = Node::Command.new(
224
+ secret: val[0],
225
+ notations: val[1],
226
+ cmp_op: val[2][:cmp_op],
227
+ target_number: val[2][:target],
228
+ source: @lexer.source
229
+ )
230
+
231
+ result
232
+ end
233
+
234
+ def _reduce_2(val, _values, result)
235
+ target = val[3]
236
+ threshold = val[2]
237
+ result = Node::Command.new(
238
+ secret: val[0],
239
+ notations: val[1],
240
+ cmp_op: target[:cmp_op],
241
+ target_number: target[:target],
242
+ reroll_cmp_op: threshold[:cmp_op],
243
+ reroll_threshold: threshold[:threshold],
244
+ source: @lexer.source
245
+ )
246
+
247
+ result
248
+ end
249
+
250
+ def _reduce_3(val, _values, result)
251
+ target = val[2]
252
+ threshold = val[3]
253
+ result = Node::Command.new(
254
+ secret: val[0],
255
+ notations: val[1],
256
+ cmp_op: target[:cmp_op],
257
+ target_number: target[:target],
258
+ reroll_cmp_op: threshold[:cmp_op],
259
+ reroll_threshold: threshold[:threshold],
260
+ source: @lexer.source
261
+ )
262
+
263
+ result
264
+ end
265
+
266
+ def _reduce_4(val, _values, result)
267
+ result = false
268
+ result
269
+ end
270
+
271
+ def _reduce_5(val, _values, result)
272
+ result = true
273
+ result
274
+ end
275
+
276
+ def _reduce_6(val, _values, result)
277
+ result = {}
278
+ result
279
+ end
280
+
281
+ def _reduce_7(val, _values, result)
282
+ cmp_op, target = val
283
+ raise ParseError unless cmp_op
284
+
285
+ result = {cmp_op: cmp_op, target: target}
286
+
287
+ result
288
+ end
289
+
290
+ def _reduce_8(val, _values, result)
291
+ result = {threshold: val[1]}
292
+ result
293
+ end
294
+
295
+ def _reduce_9(val, _values, result)
296
+ cmp_op = val[1]
297
+ threshold = val[2]
298
+ raise ParseError unless cmp_op
299
+
300
+ result = {cmp_op: cmp_op, threshold: threshold}
301
+
302
+ result
303
+ end
304
+
305
+ def _reduce_10(val, _values, result)
306
+ result = {threshold: val[1]}
307
+ result
308
+ end
309
+
310
+ def _reduce_11(val, _values, result)
311
+ cmp_op = val[1]
312
+ threshold = val[2]
313
+ raise ParseError unless cmp_op
314
+
315
+ result = {cmp_op: cmp_op, threshold: threshold}
316
+
317
+ result
318
+ end
319
+
320
+ def _reduce_12(val, _values, result)
321
+ notations = val[0]
322
+ notations.push(val[2])
323
+ result = notations
324
+
325
+ result
326
+ end
327
+
328
+ def _reduce_13(val, _values, result)
329
+ result = [val[0]]
330
+ result
331
+ end
332
+
333
+ def _reduce_14(val, _values, result)
334
+ times = val[0]
335
+ sides = val[2]
336
+ result = Node::Notation.new(times, sides)
337
+
338
+ result
339
+ end
340
+
341
+ def _reduce_15(val, _values, result)
342
+ result = Arithmetic::Node::BinaryOp.new(val[0], :+, val[2])
343
+ result
344
+ end
345
+
346
+ def _reduce_16(val, _values, result)
347
+ result = Arithmetic::Node::BinaryOp.new(val[0], :-, val[2])
348
+ result
349
+ end
350
+
351
+ # reduce 17 omitted
352
+
353
+ def _reduce_18(val, _values, result)
354
+ result = Arithmetic::Node::BinaryOp.new(val[0], :*, val[2])
355
+ result
356
+ end
357
+
358
+ def _reduce_19(val, _values, result)
359
+ divied_class = val[3]
360
+ result = divied_class.new(val[0], val[2])
361
+
362
+ result
363
+ end
364
+
365
+ # reduce 20 omitted
366
+
367
+ def _reduce_21(val, _values, result)
368
+ result = Arithmetic::Node::DivideWithGameSystemDefault
369
+ result
370
+ end
371
+
372
+ def _reduce_22(val, _values, result)
373
+ result = Arithmetic::Node::DivideWithCeil
374
+ result
375
+ end
376
+
377
+ def _reduce_23(val, _values, result)
378
+ result = Arithmetic::Node::DivideWithCeil
379
+ result
380
+ end
381
+
382
+ def _reduce_24(val, _values, result)
383
+ result = Arithmetic::Node::DivideWithRound
384
+ result
385
+ end
386
+
387
+ def _reduce_25(val, _values, result)
388
+ result = Arithmetic::Node::DivideWithFloor
389
+ result
390
+ end
391
+
392
+ def _reduce_26(val, _values, result)
393
+ result = val[1]
394
+ result
395
+ end
396
+
397
+ def _reduce_27(val, _values, result)
398
+ result = Arithmetic::Node::Negative.new(val[1])
399
+ result
400
+ end
401
+
402
+ # reduce 28 omitted
403
+
404
+ def _reduce_29(val, _values, result)
405
+ result = val[1]
406
+ result
407
+ end
408
+
409
+ def _reduce_30(val, _values, result)
410
+ result = Arithmetic::Node::Number.new(val[0])
411
+ result
412
+ end
413
+
414
+ def _reduce_none(val, _values, result)
415
+ val[0]
416
+ end
417
+
418
+ end # class Parser
419
+ end # module RerollDice
420
+ end # module CommonCommand
421
+ end # module BCDice