bcdice 3.0.0.pre.alpha.1

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 (258) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +21 -0
  3. data/.github/.codecov.yaml +10 -0
  4. data/.github/workflows/coverage.yaml +21 -0
  5. data/.github/workflows/lint.yaml +13 -0
  6. data/.github/workflows/test.yml +20 -0
  7. data/.gitignore +14 -0
  8. data/.rubocop.yml +96 -0
  9. data/.rubocop_todo.yml +113 -0
  10. data/CHANGELOG.md +868 -0
  11. data/Gemfile +11 -0
  12. data/LICENSE +29 -0
  13. data/README.md +38 -0
  14. data/ROADMAP.md +30 -0
  15. data/Rakefile +118 -0
  16. data/bcdice.gemspec +27 -0
  17. data/bin/repl.rb +21 -0
  18. data/docs/README.txt +2028 -0
  19. data/docs/dicebot_sort_key.md +72 -0
  20. data/docs/how_to_make_dicebot.md +453 -0
  21. data/lib/bcdice.rb +8 -0
  22. data/lib/bcdice/arithmetic_evaluator.rb +167 -0
  23. data/lib/bcdice/base.rb +423 -0
  24. data/lib/bcdice/command_parser.rb +242 -0
  25. data/lib/bcdice/common_command.rb +23 -0
  26. data/lib/bcdice/common_command/add_dice.rb +54 -0
  27. data/lib/bcdice/common_command/add_dice/node.rb +488 -0
  28. data/lib/bcdice/common_command/add_dice/parser.rb +282 -0
  29. data/lib/bcdice/common_command/add_dice/randomizer.rb +48 -0
  30. data/lib/bcdice/common_command/barabara_dice.rb +57 -0
  31. data/lib/bcdice/common_command/calc.rb +39 -0
  32. data/lib/bcdice/common_command/choice.rb +35 -0
  33. data/lib/bcdice/common_command/d66_dice.rb +63 -0
  34. data/lib/bcdice/common_command/reroll_dice.rb +190 -0
  35. data/lib/bcdice/common_command/upper_dice.rb +165 -0
  36. data/lib/bcdice/common_command/version.rb +26 -0
  37. data/lib/bcdice/dice_table.rb +8 -0
  38. data/lib/bcdice/dice_table/chain_table.rb +33 -0
  39. data/lib/bcdice/dice_table/d66_grid_table.rb +26 -0
  40. data/lib/bcdice/dice_table/d66_range_table.rb +26 -0
  41. data/lib/bcdice/dice_table/d66_table.rb +34 -0
  42. data/lib/bcdice/dice_table/range_table.rb +267 -0
  43. data/lib/bcdice/dice_table/roll_result.rb +43 -0
  44. data/lib/bcdice/dice_table/sai_fic_skill_table.rb +32 -0
  45. data/lib/bcdice/dice_table/table.rb +35 -0
  46. data/lib/bcdice/enum.rb +15 -0
  47. data/lib/bcdice/format.rb +36 -0
  48. data/lib/bcdice/game_system.rb +187 -0
  49. data/lib/bcdice/game_system/AFF2e.rb +141 -0
  50. data/lib/bcdice/game_system/AceKillerGene.rb +55 -0
  51. data/lib/bcdice/game_system/Airgetlamh.rb +117 -0
  52. data/lib/bcdice/game_system/Alsetto.rb +124 -0
  53. data/lib/bcdice/game_system/Alshard.rb +27 -0
  54. data/lib/bcdice/game_system/AlterRaise.rb +282 -0
  55. data/lib/bcdice/game_system/Amadeus.rb +622 -0
  56. data/lib/bcdice/game_system/Amadeus_Korean.rb +501 -0
  57. data/lib/bcdice/game_system/AnimaAnimus.rb +96 -0
  58. data/lib/bcdice/game_system/Arianrhod.rb +50 -0
  59. data/lib/bcdice/game_system/ArsMagica.rb +149 -0
  60. data/lib/bcdice/game_system/Avandner.rb +101 -0
  61. data/lib/bcdice/game_system/BBN.rb +143 -0
  62. data/lib/bcdice/game_system/BadLife.rb +435 -0
  63. data/lib/bcdice/game_system/BarnaKronika.rb +188 -0
  64. data/lib/bcdice/game_system/BattleTech.rb +530 -0
  65. data/lib/bcdice/game_system/BeastBindTrinity.rb +348 -0
  66. data/lib/bcdice/game_system/BeginningIdol.rb +2527 -0
  67. data/lib/bcdice/game_system/BeginningIdol_Korean.rb +2378 -0
  68. data/lib/bcdice/game_system/BladeOfArcana.rb +252 -0
  69. data/lib/bcdice/game_system/BlindMythos.rb +460 -0
  70. data/lib/bcdice/game_system/BloodCrusade.rb +423 -0
  71. data/lib/bcdice/game_system/BloodMoon.rb +213 -0
  72. data/lib/bcdice/game_system/CardRanker.rb +249 -0
  73. data/lib/bcdice/game_system/ChaosFlare.rb +181 -0
  74. data/lib/bcdice/game_system/Chill.rb +163 -0
  75. data/lib/bcdice/game_system/Chill3.rb +52 -0
  76. data/lib/bcdice/game_system/CodeLayerd.rb +132 -0
  77. data/lib/bcdice/game_system/ColossalHunter.rb +569 -0
  78. data/lib/bcdice/game_system/CrashWorld.rb +81 -0
  79. data/lib/bcdice/game_system/Cthulhu.rb +252 -0
  80. data/lib/bcdice/game_system/Cthulhu7th.rb +767 -0
  81. data/lib/bcdice/game_system/Cthulhu7th_ChineseTraditional.rb +386 -0
  82. data/lib/bcdice/game_system/Cthulhu7th_Korean.rb +383 -0
  83. data/lib/bcdice/game_system/CthulhuTech.rb +263 -0
  84. data/lib/bcdice/game_system/Cthulhu_ChineseTraditional.rb +243 -0
  85. data/lib/bcdice/game_system/Cthulhu_Korean.rb +240 -0
  86. data/lib/bcdice/game_system/DarkBlaze.rb +207 -0
  87. data/lib/bcdice/game_system/DarkDaysDrive.rb +425 -0
  88. data/lib/bcdice/game_system/DarkSouls.rb +91 -0
  89. data/lib/bcdice/game_system/DeadlineHeroes.rb +583 -0
  90. data/lib/bcdice/game_system/DemonParasite.rb +524 -0
  91. data/lib/bcdice/game_system/DetatokoSaga.rb +310 -0
  92. data/lib/bcdice/game_system/DetatokoSaga_Korean.rb +310 -0
  93. data/lib/bcdice/game_system/DiceBot.rb +17 -0
  94. data/lib/bcdice/game_system/DiceOfTheDead.rb +111 -0
  95. data/lib/bcdice/game_system/DoubleCross.rb +373 -0
  96. data/lib/bcdice/game_system/DoubleCross_Korean.rb +371 -0
  97. data/lib/bcdice/game_system/Dracurouge.rb +1856 -0
  98. data/lib/bcdice/game_system/Dracurouge_Korean.rb +310 -0
  99. data/lib/bcdice/game_system/DungeonsAndDragons.rb +19 -0
  100. data/lib/bcdice/game_system/EarthDawn.rb +225 -0
  101. data/lib/bcdice/game_system/EarthDawn3.rb +275 -0
  102. data/lib/bcdice/game_system/EarthDawn4.rb +272 -0
  103. data/lib/bcdice/game_system/EclipsePhase.rb +51 -0
  104. data/lib/bcdice/game_system/Elric.rb +36 -0
  105. data/lib/bcdice/game_system/Elysion.rb +1213 -0
  106. data/lib/bcdice/game_system/EmbryoMachine.rb +227 -0
  107. data/lib/bcdice/game_system/EndBreaker.rb +132 -0
  108. data/lib/bcdice/game_system/EtrianOdysseySRS.rb +27 -0
  109. data/lib/bcdice/game_system/Fiasco.rb +123 -0
  110. data/lib/bcdice/game_system/Fiasco_Korean.rb +122 -0
  111. data/lib/bcdice/game_system/FilledWith.rb +1543 -0
  112. data/lib/bcdice/game_system/FullMetalPanic.rb +27 -0
  113. data/lib/bcdice/game_system/FutariSousa.rb +994 -0
  114. data/lib/bcdice/game_system/FutariSousa_Korean.rb +994 -0
  115. data/lib/bcdice/game_system/Garako.rb +559 -0
  116. data/lib/bcdice/game_system/GardenOrder.rb +451 -0
  117. data/lib/bcdice/game_system/GehennaAn.rb +136 -0
  118. data/lib/bcdice/game_system/GeishaGirlwithKatana.rb +120 -0
  119. data/lib/bcdice/game_system/GoblinSlayer.rb +168 -0
  120. data/lib/bcdice/game_system/GoldenSkyStories.rb +77 -0
  121. data/lib/bcdice/game_system/Gorilla.rb +44 -0
  122. data/lib/bcdice/game_system/GranCrest.rb +518 -0
  123. data/lib/bcdice/game_system/Gundog.rb +52 -0
  124. data/lib/bcdice/game_system/GundogRevised.rb +294 -0
  125. data/lib/bcdice/game_system/GundogZero.rb +261 -0
  126. data/lib/bcdice/game_system/Gurps.rb +403 -0
  127. data/lib/bcdice/game_system/GurpsFW.rb +2330 -0
  128. data/lib/bcdice/game_system/HarnMaster.rb +208 -0
  129. data/lib/bcdice/game_system/HatsuneMiku.rb +706 -0
  130. data/lib/bcdice/game_system/Hieizan.rb +48 -0
  131. data/lib/bcdice/game_system/HouraiGakuen.rb +270 -0
  132. data/lib/bcdice/game_system/HuntersMoon.rb +503 -0
  133. data/lib/bcdice/game_system/Illusio.rb +89 -0
  134. data/lib/bcdice/game_system/InfiniteFantasia.rb +51 -0
  135. data/lib/bcdice/game_system/Insane.rb +822 -0
  136. data/lib/bcdice/game_system/Insane_Korean.rb +773 -0
  137. data/lib/bcdice/game_system/IthaWenUa.rb +38 -0
  138. data/lib/bcdice/game_system/JamesBond.rb +45 -0
  139. data/lib/bcdice/game_system/Kamigakari.rb +394 -0
  140. data/lib/bcdice/game_system/Kamigakari_Korean.rb +428 -0
  141. data/lib/bcdice/game_system/KanColle.rb +938 -0
  142. data/lib/bcdice/game_system/KemonoNoMori.rb +258 -0
  143. data/lib/bcdice/game_system/KillDeathBusiness.rb +1420 -0
  144. data/lib/bcdice/game_system/KillDeathBusiness_Korean.rb +1510 -0
  145. data/lib/bcdice/game_system/KurayamiCrying.rb +49 -0
  146. data/lib/bcdice/game_system/LiveraDoll.rb +375 -0
  147. data/lib/bcdice/game_system/LogHorizon.rb +3567 -0
  148. data/lib/bcdice/game_system/LogHorizon_Korean.rb +1407 -0
  149. data/lib/bcdice/game_system/LostRecord.rb +30 -0
  150. data/lib/bcdice/game_system/LostRoyal.rb +242 -0
  151. data/lib/bcdice/game_system/MagicaLogia.rb +1148 -0
  152. data/lib/bcdice/game_system/MeikyuDays.rb +415 -0
  153. data/lib/bcdice/game_system/MeikyuKingdom.rb +466 -0
  154. data/lib/bcdice/game_system/MeikyuKingdomBasic.rb +269 -0
  155. data/lib/bcdice/game_system/MetalHead.rb +249 -0
  156. data/lib/bcdice/game_system/MetalHeadExtream.rb +917 -0
  157. data/lib/bcdice/game_system/MetallicGuardian.rb +31 -0
  158. data/lib/bcdice/game_system/MonotoneMuseum.rb +354 -0
  159. data/lib/bcdice/game_system/MonotoneMuseum_Korean.rb +304 -0
  160. data/lib/bcdice/game_system/Nechronica.rb +211 -0
  161. data/lib/bcdice/game_system/Nechronica_Korean.rb +160 -0
  162. data/lib/bcdice/game_system/NeverCloud.rb +74 -0
  163. data/lib/bcdice/game_system/NightWizard.rb +231 -0
  164. data/lib/bcdice/game_system/NightWizard3rd.rb +24 -0
  165. data/lib/bcdice/game_system/NightmareHunterDeep.rb +117 -0
  166. data/lib/bcdice/game_system/NinjaSlayer.rb +274 -0
  167. data/lib/bcdice/game_system/NjslyrBattle.rb +54 -0
  168. data/lib/bcdice/game_system/Nuekagami.rb +293 -0
  169. data/lib/bcdice/game_system/OneWayHeroics.rb +134 -0
  170. data/lib/bcdice/game_system/OracleEngine.rb +265 -0
  171. data/lib/bcdice/game_system/OrgaRain.rb +77 -0
  172. data/lib/bcdice/game_system/Oukahoushin3rd.rb +162 -0
  173. data/lib/bcdice/game_system/Paradiso.rb +323 -0
  174. data/lib/bcdice/game_system/Paranoia.rb +64 -0
  175. data/lib/bcdice/game_system/ParanoiaRebooted.rb +109 -0
  176. data/lib/bcdice/game_system/ParasiteBlood.rb +231 -0
  177. data/lib/bcdice/game_system/Pathfinder.rb +21 -0
  178. data/lib/bcdice/game_system/Peekaboo.rb +324 -0
  179. data/lib/bcdice/game_system/Pendragon.rb +39 -0
  180. data/lib/bcdice/game_system/PhantasmAdventure.rb +73 -0
  181. data/lib/bcdice/game_system/Postman.rb +185 -0
  182. data/lib/bcdice/game_system/PulpCthulhu.rb +184 -0
  183. data/lib/bcdice/game_system/Raisondetre.rb +171 -0
  184. data/lib/bcdice/game_system/RecordOfLodossWar.rb +58 -0
  185. data/lib/bcdice/game_system/RecordOfSteam.rb +149 -0
  186. data/lib/bcdice/game_system/RokumonSekai2.rb +110 -0
  187. data/lib/bcdice/game_system/RoleMaster.rb +24 -0
  188. data/lib/bcdice/game_system/RuneQuest.rb +47 -0
  189. data/lib/bcdice/game_system/RyuTuber.rb +266 -0
  190. data/lib/bcdice/game_system/Ryutama.rb +199 -0
  191. data/lib/bcdice/game_system/SRS.rb +348 -0
  192. data/lib/bcdice/game_system/SamsaraBallad.rb +111 -0
  193. data/lib/bcdice/game_system/Satasupe.rb +1173 -0
  194. data/lib/bcdice/game_system/ScreamHighSchool.rb +128 -0
  195. data/lib/bcdice/game_system/SevenFortressMobius.rb +34 -0
  196. data/lib/bcdice/game_system/ShadowRun.rb +26 -0
  197. data/lib/bcdice/game_system/ShadowRun4.rb +49 -0
  198. data/lib/bcdice/game_system/ShadowRun5.rb +80 -0
  199. data/lib/bcdice/game_system/SharedFantasia.rb +69 -0
  200. data/lib/bcdice/game_system/ShinMegamiTenseiKakuseihen.rb +85 -0
  201. data/lib/bcdice/game_system/ShinkuuGakuen.rb +506 -0
  202. data/lib/bcdice/game_system/ShinobiGami.rb +680 -0
  203. data/lib/bcdice/game_system/ShoujoTenrankai.rb +677 -0
  204. data/lib/bcdice/game_system/Skynauts.rb +324 -0
  205. data/lib/bcdice/game_system/SteamPunkers.rb +485 -0
  206. data/lib/bcdice/game_system/StellarKnights.rb +856 -0
  207. data/lib/bcdice/game_system/SterileLife.rb +452 -0
  208. data/lib/bcdice/game_system/StrangerOfSwordCity.rb +103 -0
  209. data/lib/bcdice/game_system/StratoShout.rb +316 -0
  210. data/lib/bcdice/game_system/StratoShout_Korean.rb +314 -0
  211. data/lib/bcdice/game_system/Strave.rb +223 -0
  212. data/lib/bcdice/game_system/SwordWorld.rb +491 -0
  213. data/lib/bcdice/game_system/SwordWorld2_0.rb +295 -0
  214. data/lib/bcdice/game_system/SwordWorld2_5.rb +121 -0
  215. data/lib/bcdice/game_system/TherapieSein.rb +93 -0
  216. data/lib/bcdice/game_system/TokumeiTenkousei.rb +96 -0
  217. data/lib/bcdice/game_system/TokyoGhostResearch.rb +122 -0
  218. data/lib/bcdice/game_system/TokyoNova.rb +19 -0
  219. data/lib/bcdice/game_system/Torg.rb +364 -0
  220. data/lib/bcdice/game_system/Torg1_5.rb +139 -0
  221. data/lib/bcdice/game_system/TorgEternity.rb +414 -0
  222. data/lib/bcdice/game_system/TrinitySeven.rb +364 -0
  223. data/lib/bcdice/game_system/TunnelsAndTrolls.rb +287 -0
  224. data/lib/bcdice/game_system/TwilightGunsmoke.rb +527 -0
  225. data/lib/bcdice/game_system/Utakaze.rb +153 -0
  226. data/lib/bcdice/game_system/VampireTheMasquerade5th.rb +132 -0
  227. data/lib/bcdice/game_system/Villaciel.rb +555 -0
  228. data/lib/bcdice/game_system/WARPS.rb +33 -0
  229. data/lib/bcdice/game_system/WaresBlade.rb +34 -0
  230. data/lib/bcdice/game_system/Warhammer.rb +336 -0
  231. data/lib/bcdice/game_system/WitchQuest.rb +275 -0
  232. data/lib/bcdice/game_system/WorldOfDarkness.rb +135 -0
  233. data/lib/bcdice/game_system/YankeeYogSothoth.rb +440 -0
  234. data/lib/bcdice/game_system/YearZeroEngine.rb +134 -0
  235. data/lib/bcdice/game_system/ZettaiReido.rb +142 -0
  236. data/lib/bcdice/game_system/meikyu_kingdom/item_table.rb +383 -0
  237. data/lib/bcdice/game_system/meikyu_kingdom/kingdom_name_table.rb +89 -0
  238. data/lib/bcdice/game_system/meikyu_kingdom/landscape_table.rb +196 -0
  239. data/lib/bcdice/game_system/meikyu_kingdom/name_tables.rb +223 -0
  240. data/lib/bcdice/game_system/meikyu_kingdom/placename_table.rb +214 -0
  241. data/lib/bcdice/game_system/meikyu_kingdom/tables.rb +610 -0
  242. data/lib/bcdice/game_system/meikyu_kingdom/word_table.rb +117 -0
  243. data/lib/bcdice/game_system/meikyu_kingdom_basic/item_table.rb +380 -0
  244. data/lib/bcdice/game_system/meikyu_kingdom_basic/kingdom_table.rb +184 -0
  245. data/lib/bcdice/game_system/meikyu_kingdom_basic/name_table.rb +417 -0
  246. data/lib/bcdice/game_system/meikyu_kingdom_basic/table.rb +912 -0
  247. data/lib/bcdice/game_system/meikyu_kingdom_basic/word_table.rb +121 -0
  248. data/lib/bcdice/game_system/one_way_heroics/dungeon_table.rb +67 -0
  249. data/lib/bcdice/game_system/one_way_heroics/random_event_table.rb +166 -0
  250. data/lib/bcdice/game_system/one_way_heroics/tables.rb +668 -0
  251. data/lib/bcdice/loader.rb +37 -0
  252. data/lib/bcdice/normalize.rb +38 -0
  253. data/lib/bcdice/preprocessor.rb +87 -0
  254. data/lib/bcdice/randomizer.rb +137 -0
  255. data/lib/bcdice/repl.rb +155 -0
  256. data/lib/bcdice/user_defined_dice_table.rb +153 -0
  257. data/lib/bcdice/version.rb +3 -0
  258. metadata +304 -0
@@ -0,0 +1,63 @@
1
+ module BCDice
2
+ module CommonCommand
3
+ class D66Dice
4
+ PREFIX_PATTERN = /D66/.freeze
5
+
6
+ def initialize(command, randomizer, game_system)
7
+ @command = command
8
+ @randomizer = randomizer
9
+ @game_system = game_system
10
+
11
+ @is_secret = false
12
+ end
13
+
14
+ def secret?
15
+ @is_secret
16
+ end
17
+
18
+ def eval
19
+ unless @game_system.enabled_d66?
20
+ return nil
21
+ end
22
+
23
+ m = /^(S)?D66([ANS])?$/i.match(@command)
24
+ unless m
25
+ return nil
26
+ end
27
+
28
+ @is_secret = !m[1].nil?
29
+ @sort_type = sort_type_from_suffix(m[2])
30
+
31
+ value = roll()
32
+
33
+ return "(D66#{m[2]}) > #{value}"
34
+ end
35
+
36
+ private
37
+
38
+ def roll()
39
+ dice_list = Array.new(2) { @randomizer.roll_once(6) }
40
+
41
+ case @sort_type
42
+ when :asc
43
+ dice_list.sort!
44
+ when :desc
45
+ dice_list.sort!.reverse!
46
+ end
47
+
48
+ return dice_list[0] * 10 + dice_list[1]
49
+ end
50
+
51
+ def sort_type_from_suffix(suffix)
52
+ case suffix
53
+ when "A", "S"
54
+ :asc
55
+ when "N"
56
+ :no_sort
57
+ else
58
+ @game_system.d66_sort_type
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,190 @@
1
+ require "bcdice/normalize"
2
+ require "bcdice/format"
3
+
4
+ module BCDice
5
+ module CommonCommand
6
+ # 個数振り足しダイス
7
+ #
8
+ # ダイスを振り、条件を満たした出目の個数だけダイスを振り足す。振り足しがなくなるまでこれを繰り返す。
9
+ # 成功条件を満たす出目の個数を調べ、成功数を表示する。
10
+ #
11
+ # 例
12
+ # 2R6+1R10[>3]>=5
13
+ # 2R6+1R10>=5@>3
14
+ #
15
+ # 振り足し条件は角カッコかコマンド末尾の @ で指定する。
16
+ # [>3] の場合、3より大きい出目が出たら振り足す。
17
+ # [3] のように数値のみ指定されている場合、成功条件の比較演算子を流用する。
18
+ # 上記の例の時、出目が
19
+ # "2R6" -> [5,6] [5,4] [1,3]
20
+ # "1R10" -> [9] [1]
21
+ # だとすると、 >=5 に該当するダイスは5つなので成功数5となる。
22
+ #
23
+ # 成功条件が書かれていない場合、成功数0として扱う。
24
+ # 振り足し条件が数値のみ指定されている場合、比較演算子は >= が指定されたとして振舞う。
25
+ class RerollDice
26
+ PREFIX_PATTERN = /\d+R\d+/.freeze
27
+ REROLL_LIMIT = 10000
28
+
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
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,165 @@
1
+ require "bcdice/arithmetic_evaluator"
2
+ require "bcdice/normalize"
3
+ require "bcdice/format"
4
+
5
+ module BCDice
6
+ module CommonCommand
7
+ # 上方無限ロール
8
+ #
9
+ # ダイスを1つ振る、その出目が閾値より大きければダイスを振り足すのを閾値未満の出目が出るまで繰り返す。
10
+ # これを指定したダイス数だけおこない、それぞれのダイスの合計値を求める。
11
+ # それらと目標値を比較し、成功した数を表示する。
12
+ #
13
+ # フォーマットは以下の通り
14
+ # 2U4+1U6[4]>=6
15
+ # 2U4+1U6>=6@4
16
+ #
17
+ # 閾値は角カッコで指定するか、コマンドの末尾に @6 のように指定する。
18
+ # 閾値の指定が重複した場合、角カッコが優先される。
19
+ # この時、出目が
20
+ # "2U4" -> 3[3], 10[4,4,2]
21
+ # "1U6" -> 6[4,2]
22
+ # だとすると、 >=6 に該当するダイスは2つなので成功数2となる。
23
+ #
24
+ # 2U4[4]+10>=6 のように修正値を指定できる。修正値は全てのダイスに補正を加え、以下のようになる。
25
+ # "2U4" -> 3[3]+10=13, 10[4,4,2]+10=20
26
+ #
27
+ # 比較演算子が書かれていない場合、ダイスの最大値と全ダイスの合計値が出力される。
28
+ # 全ダイスの合計値には補正値が1回だけ適用される
29
+ # 2U4[4]+10
30
+ # "2U4" -> 3[3]+10=13, 10[4,4,2]+10=20
31
+ # 最大値:20
32
+ # 合計値:23 = 3[3]+10[4,4,2]+10
33
+ class UpperDice
34
+ PREFIX_PATTERN = /\d+U\d+/.freeze
35
+
36
+ def initialize(command, bcdice, diceBot)
37
+ @string = command
38
+ @bcdice = bcdice
39
+ @diceBot = diceBot
40
+
41
+ @is_secret = false
42
+ end
43
+
44
+ def secret?
45
+ @is_secret
46
+ end
47
+
48
+ # 上方無限ロールを実行する
49
+ #
50
+ # @return [String, nil]
51
+ def eval
52
+ unless (m = /^S?(\d+U\d+(?:\+\d+U\d+)*)(?:\[(\d+)\])?([\+\-\d]*)(?:([<>=]+)(\d+))?(?:@(\d+))?/i.match(@string))
53
+ return nil
54
+ end
55
+
56
+ @is_secret = @string.start_with?("S")
57
+
58
+ @command = m[1]
59
+ @cmp_op = Normalize.comparison_operator(m[4])
60
+ @target_number = @cmp_op ? m[5].to_i : nil
61
+ @reroll_threshold = reroll_threshold(m[2] || m[6])
62
+
63
+ @modify_number = ArithmeticEvaluator.eval(m[3], round_type: @diceBot.round_type)
64
+
65
+ if @reroll_threshold <= 1
66
+ return "(#{expr()}) > 無限ロールの条件がまちがっています"
67
+ end
68
+
69
+ roll_list = []
70
+ @command.split("+").each do |u|
71
+ times, sides = u.split("U", 2).map(&:to_i)
72
+ roll_list.concat(roll(times, sides))
73
+ end
74
+
75
+ result =
76
+ if @cmp_op
77
+ success_count = roll_list.count do |e|
78
+ x = e[:sum] + @modify_number
79
+ x.send(@cmp_op, @target_number)
80
+ end
81
+ "成功数#{success_count}"
82
+ else
83
+ sum_list = roll_list.map { |e| e[:sum] }
84
+ total = sum_list.inject(0, :+) + @modify_number
85
+ max = sum_list.map { |i| i + @modify_number }.max
86
+ "#{max}/#{total}(最大/合計)"
87
+ end
88
+
89
+ sequence = [
90
+ "(#{expr()})",
91
+ dice_text(roll_list) + Format.modifier(@modify_number),
92
+ result
93
+ ]
94
+
95
+ return sequence.join(" > ")
96
+ end
97
+
98
+ private
99
+
100
+ # ダイスロールし、ダイスボットのソート設定に応じてソートする
101
+ #
102
+ # @param times [Integer] ダイスの個数
103
+ # @param sides [Integer] ダイスの面数
104
+ # @return [Array<Hash>]
105
+ def roll(times, sides)
106
+ ret = Array.new(times) do
107
+ list = roll_ones(sides)
108
+ {sum: list.inject(0, :+), list: list}
109
+ end
110
+
111
+ if @diceBot.sort_barabara_dice?
112
+ ret = ret.sort_by { |e| e[:sum] }
113
+ end
114
+
115
+ return ret
116
+ end
117
+
118
+ # 一つだけダイスロールする
119
+ #
120
+ # @param sides [Integer] ダイスの面数
121
+ # @return [Array<Integer>]
122
+ def roll_ones(sides)
123
+ dice_list = []
124
+
125
+ loop do
126
+ value = @bcdice.roll_once(sides)
127
+ dice_list.push(value)
128
+ break if value < @reroll_threshold
129
+ end
130
+
131
+ return dice_list
132
+ end
133
+
134
+ # ダイスロールの結果を文字列に変換する
135
+ # 振り足しがなければその数値、振り足しがあれば合計と各ダイスの出目を出力する
136
+ #
137
+ # @param roll_list [Array<Hash>]
138
+ # @return [String]
139
+ def dice_text(roll_list)
140
+ roll_list.map do |e|
141
+ if e[:list].size == 1
142
+ e[:sum]
143
+ else
144
+ "#{e[:sum]}[#{e[:list].join(',')}]"
145
+ end
146
+ end.join(",")
147
+ end
148
+
149
+ # 振り足しの閾値を得る
150
+ #
151
+ # @param target [String]
152
+ # @return [Integer]
153
+ def reroll_threshold(target)
154
+ target&.to_i || @diceBot.upper_dice_reroll_threshold.to_i
155
+ end
156
+
157
+ # パース済みのコマンドを文字列で表示する
158
+ #
159
+ # @return [String]
160
+ def expr
161
+ "#{@command}[#{@reroll_threshold}]#{Format.modifier(@modify_number)}#{Format.comparison_operator(@cmp_op)}#{@target_number}"
162
+ end
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,26 @@
1
+ module BCDice
2
+ module CommonCommand
3
+ class Version
4
+ PREFIX_PATTERN = /BCDiceVersion/.freeze
5
+
6
+ # @param command [String]
7
+ # @param _randomizer [Randomizer]
8
+ # @param _game_system [Base]
9
+ def initialize(command, _randomizer, _game_system)
10
+ @command = command
11
+ end
12
+
13
+ # @return [Boolean]
14
+ def secret?
15
+ false
16
+ end
17
+
18
+ # @return [String, nil]
19
+ def eval
20
+ if @command == "BCDICEVERSION"
21
+ "BCDice Ver#{BCDice::VERSION}"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,8 @@
1
+ require "bcdice/dice_table/roll_result"
2
+ require "bcdice/dice_table/chain_table"
3
+ require "bcdice/dice_table/d66_grid_table"
4
+ require "bcdice/dice_table/d66_range_table"
5
+ require "bcdice/dice_table/d66_table"
6
+ require "bcdice/dice_table/range_table"
7
+ require "bcdice/dice_table/sai_fic_skill_table"
8
+ require "bcdice/dice_table/table"