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

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