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,282 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bcdice/arithmetic_evaluator"
4
+ require "bcdice/normalize"
5
+ require "bcdice/common_command/add_dice/node"
6
+
7
+ module BCDice
8
+ module CommonCommand
9
+ class AddDice
10
+ # 加算ロールの構文解析器のクラス
11
+ class Parser
12
+ # 構文解析器を初期化する
13
+ # @param [String] expr 構文解析対象の文字列
14
+ def initialize(expr)
15
+ # 構文解析対象の文字列
16
+ @expr = expr
17
+ # 読み込んだトークンのインデックス
18
+ @idx = 0
19
+ # 構文解析エラーが発生したかどうか
20
+ @error = false
21
+ # 式にダイスロールが含まれるか
22
+ @contain_dice_roll = false
23
+
24
+ @is_secret = false
25
+ end
26
+
27
+ def secret?
28
+ @is_secret
29
+ end
30
+
31
+ # 構文解析を実行する
32
+ # @return [Node::Command, nil] 加算ロールコマンド
33
+ def parse()
34
+ lhs, cmp_op, rhs = @expr.partition(/[<>=]+/)
35
+
36
+ cmp_op = Normalize.comparison_operator(cmp_op)
37
+ if cmp_op && rhs.empty?
38
+ @error = true
39
+ return nil
40
+ end
41
+
42
+ if !rhs.empty? && rhs != "?"
43
+ ae = ArithmeticEvaluator.new(rhs)
44
+ rhs = ae.eval()
45
+
46
+ @error = ae.error?
47
+ end
48
+
49
+ @tokens = tokenize(lhs)
50
+ lhs = expr()
51
+
52
+ if @idx != @tokens.size || !@contain_dice_roll
53
+ @error = true
54
+ end
55
+
56
+ return AddDice::Node::Command.new(lhs, cmp_op, rhs)
57
+ end
58
+
59
+ # 構文解析エラーが発生したかどうかを返す
60
+ # @return [Boolean]
61
+ def error?
62
+ @error
63
+ end
64
+
65
+ private
66
+
67
+ # 構文解析対象の文字列をトークンの配列に変換する
68
+ # @return [Array<String>]
69
+ def tokenize(expr)
70
+ expr.gsub(%r{[\+\-\*/DURSKHL@()]}) { |e| " #{e} " }.split(" ")
71
+ end
72
+
73
+ # 式
74
+ def expr
75
+ @is_secret = consume("S")
76
+
77
+ return add()
78
+ end
79
+
80
+ # 加算、減算
81
+ def add
82
+ node = mul()
83
+
84
+ loop do
85
+ if consume("+")
86
+ op, rhs = sub_negative_number(:+, mul())
87
+ node = AddDice::Node::BinaryOp.new(node, op, rhs)
88
+ elsif consume("-")
89
+ op, rhs = sub_negative_number(:-, mul())
90
+ node = AddDice::Node::BinaryOp.new(node, op, rhs)
91
+ else
92
+ break
93
+ end
94
+ end
95
+
96
+ return node
97
+ end
98
+
99
+ # TODO: 処理の説明を書く
100
+ def sub_negative_number(op, rhs)
101
+ if rhs.is_a?(Node::Number) && rhs.literal < 0
102
+ if op == :+
103
+ return [:-, rhs.negate]
104
+ elsif op == :-
105
+ return [:+, rhs.negate]
106
+ end
107
+ end
108
+
109
+ [op, rhs]
110
+ end
111
+
112
+ # 乗算、除算
113
+ def mul
114
+ node = unary()
115
+
116
+ loop do
117
+ if consume("*")
118
+ node = AddDice::Node::BinaryOp.new(node, :*, unary())
119
+ elsif consume("/")
120
+ rhs = unary()
121
+ klass = divide_node_class()
122
+ node = klass.new(node, rhs)
123
+ else
124
+ break
125
+ end
126
+ end
127
+
128
+ return node
129
+ end
130
+
131
+ # 端数処理方法を示す記号を読み込み、対応する除算ノードのクラスを返す
132
+ # @return [Class] 除算ノードのクラス
133
+ def divide_node_class
134
+ if consume("U")
135
+ # 切り上げ
136
+ Node::DivideWithRoundingUp
137
+ elsif consume("R")
138
+ # 四捨五入
139
+ Node::DivideWithRoundingOff
140
+ else
141
+ # 切り捨て
142
+ Node::DivideWithRoundingDown
143
+ end
144
+ end
145
+
146
+ # 単項演算
147
+ def unary
148
+ if consume("+")
149
+ unary()
150
+ elsif consume("-")
151
+ node = unary()
152
+
153
+ case node
154
+ when Node::Negate
155
+ node.body
156
+ when Node::Number
157
+ node.negate()
158
+ else
159
+ AddDice::Node::Negate.new(node)
160
+ end
161
+ else
162
+ term()
163
+ end
164
+ end
165
+
166
+ # カッコ、ダイスロール
167
+ def term
168
+ if consume("(")
169
+ node = AddDice::Node::Parenthesis.new(add())
170
+ expect(")")
171
+
172
+ return node
173
+ else
174
+ dice_notation()
175
+ end
176
+ end
177
+
178
+ # ダイスロール、数値
179
+ def dice_notation
180
+ num = expect_number()
181
+ if consume("D")
182
+ times = num
183
+ sides = expect_number()
184
+
185
+ filter = dice_roll_filter()
186
+ if filter
187
+ # ダイスロール後のフィルタリングあり
188
+ n_filtering = expect_number()
189
+ @contain_dice_roll = true
190
+ return Node::DiceRollWithFilter.new(times, sides, n_filtering, filter)
191
+ end
192
+
193
+ # 通常のダイスロール
194
+ @contain_dice_roll = true
195
+ return Node::DiceRoll.new(times, sides)
196
+ end
197
+
198
+ return num
199
+ end
200
+
201
+ # ダイスロール:フィルタ処理
202
+ def dice_roll_filter
203
+ if consume("K", "H")
204
+ # 大きな出目から複数個取る
205
+ Node::DiceRollWithFilter::KEEP_HIGHEST
206
+ elsif consume("K", "L")
207
+ # 小さな出目から複数個取る
208
+ Node::DiceRollWithFilter::KEEP_LOWEST
209
+ elsif consume("D", "H")
210
+ # 大きな出目から複数個除く
211
+ Node::DiceRollWithFilter::DROP_HIGHEST
212
+ elsif consume("D", "L")
213
+ # 小さな出目から複数個除く
214
+ Node::DiceRollWithFilter::DROP_LOWEST
215
+ end
216
+ end
217
+
218
+ # トークンを消費する
219
+ #
220
+ # トークンと期待した文字列が合致していた場合、次のトークンに進む。
221
+ # 合致していなかった場合は、進まない。
222
+ #
223
+ # @param [String] expected 期待する文字列
224
+ # @return [true] トークンと期待した文字列が合致していた場合
225
+ # @return [false] トークンと期待した文字列が合致していなかった場合
226
+ def consume(*expected)
227
+ target = @tokens.slice(@idx, expected.length)
228
+ unless target == expected
229
+ return false
230
+ end
231
+
232
+ @idx += expected.length
233
+ return true
234
+ end
235
+
236
+ # 指定された文字列のトークンを要求する
237
+ #
238
+ # トークンと期待した文字列が合致していなかった場合、エラーとする。
239
+ # エラーの有無にかかわらず、次のトークンに進む。
240
+ #
241
+ # @param [String] str 期待する文字列
242
+ # @return [void]
243
+ def expect(str)
244
+ if @tokens[@idx] != str
245
+ @error = true
246
+ end
247
+
248
+ @idx += 1
249
+ end
250
+
251
+ # 整数のトークンを要求する
252
+ #
253
+ # 整数のトークンならば、対応する整数のノードを返す。
254
+ # そうでなければエラーとし、整数0のノードを返す。
255
+ #
256
+ # エラーの有無にかかわらず、次のトークンに進む。
257
+ #
258
+ # @return [Node::Number] 整数のノード
259
+ def expect_number()
260
+ unless integer?(@tokens[@idx])
261
+ @error = true
262
+ @idx += 1
263
+ return AddDice::Node::Number.new(0)
264
+ end
265
+
266
+ ret = @tokens[@idx].to_i
267
+ @idx += 1
268
+ return AddDice::Node::Number.new(ret)
269
+ end
270
+
271
+ # 文字列が整数かどうかを返す
272
+ # @param [String] str 対象文字列
273
+ # @return [Boolean]
274
+ def integer?(str)
275
+ # Ruby 1.9 以降では Kernel.#Integer を使うべき
276
+ # Ruby 1.8 にもあるが、基数を指定できない問題がある
277
+ !/^\d+$/.match(str).nil?
278
+ end
279
+ end
280
+ end
281
+ end
282
+ end
@@ -0,0 +1,48 @@
1
+ module BCDice
2
+ module CommonCommand
3
+ class AddDice
4
+ class Randomizer
5
+ attr_reader :dicebot, :cmp_op, :dice_list, :sides
6
+
7
+ def initialize(bcdice, dicebot, cmp_op)
8
+ @bcdice = bcdice
9
+ @dicebot = dicebot
10
+ @cmp_op = cmp_op
11
+ @sides = 0
12
+ @dice_list = []
13
+ end
14
+
15
+ # ダイスを振る
16
+ # @param [Integer] times ダイス数
17
+ # @param [Integer] sides 面数
18
+ # @return [Array<Array<Integer>>] 出目のグループの配列
19
+ def roll(times, sides)
20
+ # 振り足し分も含めた出目グループの配列
21
+ @dice_list = roll_once(times, sides)
22
+ return [@dice_list]
23
+ end
24
+
25
+ # ダイスを振る(振り足しなしの1回分)
26
+ # @param [Integer] times ダイス数
27
+ # @param [Integer] sides 面数
28
+ # @return [Array<Integer>] 出目の配列
29
+ def roll_once(times, sides)
30
+ @sides = sides if @sides < sides
31
+
32
+ if sides == 66 && @dicebot.enabled_d66?
33
+ return Array.new(times) { @bcdice.roll_d66(@dicebot.d66_sort_type) }
34
+ end
35
+
36
+ if sides == 9 && @dicebot.enabled_d9?
37
+ return Array.new(times) { @bcdice.roll_d9() }
38
+ end
39
+
40
+ dice_list = @bcdice.roll_barabara(times, sides)
41
+ dice_list.sort! if @dicebot.sort_add_dice?
42
+
43
+ return dice_list
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,57 @@
1
+ require "bcdice/format"
2
+
3
+ module BCDice
4
+ module CommonCommand
5
+ class BarabaraDice
6
+ PREFIX_PATTERN = /\d+B\d+/.freeze
7
+
8
+ def initialize(command, randomizer, game_system)
9
+ @command = command
10
+ @randomizer = randomizer
11
+ @game_system = game_system
12
+
13
+ @is_secret = false
14
+ end
15
+
16
+ def secret?
17
+ @is_secret
18
+ end
19
+
20
+ # @return [String, nil]
21
+ def eval()
22
+ m = /^(S)?(\d+B\d+(?:\+\d+B\d+)*)(?:([<>=]+)(\d+))?$/i.match(@command)
23
+ unless m
24
+ return nil
25
+ end
26
+
27
+ @is_secret = !m[1].nil?
28
+ lhs = m[2]
29
+ b_list = lhs.split("+")
30
+
31
+ cmp_op = Normalize.comparison_operator(m[3]) || @game_system.default_cmp_op
32
+ target_number = m[4]&.to_i || @game_system.default_target_number
33
+
34
+ dice_list = []
35
+ b_list.each do |literal|
36
+ times, sides = literal.split("B", 2).map(&:to_i)
37
+ list = @randomizer.roll_barabara(times, sides)
38
+ list.sort! if @game_system.sort_barabara_dice?
39
+ dice_list.concat(list)
40
+ end
41
+
42
+ count_of_1 = dice_list.count(1)
43
+ success_num = cmp_op ? dice_list.count { |dice| dice.send(cmp_op, target_number) } : 0
44
+ success_num_text = "成功数#{success_num}" if cmp_op
45
+
46
+ sequence = [
47
+ "(#{lhs}#{Format.comparison_operator(cmp_op)}#{target_number})",
48
+ dice_list.join(","),
49
+ success_num_text,
50
+ @game_system.grich_text(count_of_1, dice_list.size, success_num)
51
+ ].compact
52
+
53
+ return sequence.join(" > ")
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,39 @@
1
+ module BCDice
2
+ module CommonCommand
3
+ class Calc
4
+ PREFIX_PATTERN = /C/.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
+ @game_system = game_system
12
+
13
+ @is_secret = false
14
+ end
15
+
16
+ # @return [Boolean]
17
+ def secret?
18
+ @is_secret
19
+ end
20
+
21
+ # @return [String, nil]
22
+ def eval
23
+ m = %r{^(S)?C([\+\-\*/\d\(\)]+)$}i.match(@command)
24
+ unless m
25
+ return nil
26
+ end
27
+
28
+ @is_secret = !m[1].nil?
29
+ expr = ArithmeticEvaluator.new(m[2], round_type: @game_system.round_type)
30
+ value = expr.eval()
31
+ if expr.error?
32
+ return nil
33
+ end
34
+
35
+ return "計算結果 > #{value}"
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,35 @@
1
+ module BCDice
2
+ module CommonCommand
3
+ class Choice
4
+ PREFIX_PATTERN = /choice/.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
+ m = /^(S)?choice\[([^,]+(?:,[^,]+)+)\]$/i.match(@command)
20
+ unless m
21
+ return nil
22
+ end
23
+
24
+ @is_secret = !m[1].nil?
25
+ items = m[2].split(",").map(&:strip)
26
+
27
+ index = @randomizer.roll_index(items.size)
28
+ chosen = items[index]
29
+
30
+ expr = "choice[#{items.join(',')}]"
31
+ return "(#{expr}) > #{chosen}"
32
+ end
33
+ end
34
+ end
35
+ end