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,211 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bcdice/dice_table/table'
4
+
5
+ module BCDice
6
+ module GameSystem
7
+ class Nechronica < Base
8
+ # ゲームシステムの識別子
9
+ ID = 'Nechronica'
10
+
11
+ # ゲームシステム名
12
+ NAME = 'ネクロニカ'
13
+
14
+ # ゲームシステム名の読みがな
15
+ SORT_KEY = 'ねくろにか'
16
+
17
+ # ダイスボットの使い方
18
+ HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
19
+ ・判定 (nNC+m)
20
+  ダイス数n、修正値mで判定ロールを行います。
21
+  ダイス数が2以上の時のパーツ破損数も表示します。
22
+ ・攻撃判定 (nNA+m)
23
+  ダイス数n、修正値mで攻撃判定ロールを行います。
24
+  命中部位とダイス数が2以上の時のパーツ破損数も表示します。
25
+
26
+
27
+ ・姉妹への未練表 nm
28
+ ・中立者への未練表 nmn
29
+ ・敵への未練表 nme
30
+ INFO_MESSAGE_TEXT
31
+
32
+ def initialize(command)
33
+ super(command)
34
+
35
+ @sort_add_dice = true
36
+ @sort_barabara_dice = true
37
+ @default_target_number = 6 # 目標値が空欄の時の目標値
38
+ end
39
+
40
+ private
41
+
42
+ def replace_text(string)
43
+ string = string.gsub(/(\d+)NC(10)?([\+\-][\+\-\d]+)/i) { "#{Regexp.last_match(1)}R10#{Regexp.last_match(3)}[0]" }
44
+ string = string.gsub(/(\d+)NC(10)?/i) { "#{Regexp.last_match(1)}R10[0]" }
45
+ string = string.gsub(/(\d+)NA(10)?([\+\-][\+\-\d]+)/i) { "#{Regexp.last_match(1)}R10#{Regexp.last_match(3)}[1]" }
46
+ string = string.gsub(/(\d+)NA(10)?/i) { "#{Regexp.last_match(1)}R10[1]" }
47
+
48
+ return string
49
+ end
50
+
51
+ public
52
+
53
+ def eval_game_system_specific_command(command)
54
+ return roll_tables(command, TABLES) || nechronica_check(command)
55
+ end
56
+
57
+ private
58
+
59
+ def check_nD10(total, _dice_total, dice_list, cmp_op, target) # ゲーム別成功度判定(nD10)
60
+ return '' if target == '?'
61
+ return '' unless cmp_op == :>=
62
+
63
+ if total >= 11
64
+ " > 大成功"
65
+ elsif total >= target
66
+ " > 成功"
67
+ elsif dice_list.count { |i| i <= 1 } == 0
68
+ " > 失敗"
69
+ elsif dice_list.size > 1
70
+ " > 大失敗 > 使用パーツ全損"
71
+ else
72
+ " > 大失敗"
73
+ end
74
+ end
75
+
76
+ def nechronica_check(string)
77
+ string = replace_text(string)
78
+ debug("nechronica_check string", string)
79
+
80
+ unless /(^|\s)S?((\d+)[rR]10([\+\-\d]+)?(\[(\d+)\])?)(\s|$)/i =~ string
81
+ return nil
82
+ end
83
+
84
+ string = Regexp.last_match(2)
85
+
86
+ dice_n = 1
87
+ dice_n = Regexp.last_match(3).to_i if Regexp.last_match(3)
88
+
89
+ battleMode = Regexp.last_match(6).to_i
90
+
91
+ modText = Regexp.last_match(4)
92
+ mod = ArithmeticEvaluator.eval(modText)
93
+
94
+ # 0=判定モード, 1=戦闘モード
95
+ isBattleMode = (battleMode == 1)
96
+ debug("nechronica_check string", string)
97
+ debug("isBattleMode", isBattleMode)
98
+
99
+ diff = 6
100
+
101
+ dice = @randomizer.roll_barabara(dice_n, 10).sort
102
+ n_max = dice.max
103
+
104
+ total_n = n_max + mod
105
+
106
+ output = "(#{string}) > [#{dice.join(',')}]"
107
+ if mod < 0
108
+ output += mod.to_s
109
+ elsif mod > 0
110
+ output += "+#{mod}"
111
+ end
112
+
113
+ dice.map! { |i| i + mod }
114
+
115
+ dice_str = dice.join(",")
116
+ output += " > #{total_n}[#{dice_str}]"
117
+
118
+ output += check_nD10(total_n, dice_n, dice, :>=, diff)
119
+
120
+ if isBattleMode
121
+ hit_loc = getHitLocation(total_n)
122
+ if hit_loc != '1'
123
+ output += " > #{hit_loc}"
124
+ end
125
+ end
126
+
127
+ return output
128
+ end
129
+
130
+ def getHitLocation(dice)
131
+ output = '1'
132
+
133
+ debug("getHitLocation dice", dice)
134
+ return output if dice <= 5
135
+
136
+ table = [
137
+ '防御側任意',
138
+ '脚(なければ攻撃側任意)',
139
+ '胴(なければ攻撃側任意)',
140
+ '腕(なければ攻撃側任意)',
141
+ '頭(なければ攻撃側任意)',
142
+ '攻撃側任意',
143
+ ]
144
+ index = dice - 6
145
+
146
+ addDamage = ""
147
+ if dice > 10
148
+ index = 5
149
+ addDamage = "(追加ダメージ#{dice - 10})"
150
+ end
151
+
152
+ output = table[index] + addDamage
153
+
154
+ return output
155
+ end
156
+
157
+ TABLES = {
158
+ 'NM' => DiceTable::Table.new(
159
+ '姉妹への未練表',
160
+ '1D10',
161
+ [
162
+ '【嫌悪】[発狂:敵対認識]敵に命中しなかった攻撃は全て、射程内にいるなら嫌悪の対象に命中する。(防御側任意)',
163
+ '【独占】[発狂:独占衝動]戦闘開始時と終了時に1つずつ、対象はパーツを選んで損傷する。',
164
+ '【依存】[発狂:幼児退行]最大行動値が減少する(-2)',
165
+ '【執着】[発狂:追尾監視]戦闘開始時と終了時に1つずつ、対象はあなたへの未練に狂気点を得る。',
166
+ '【恋心】[発狂:自傷行動]戦闘開始時と終了時に1つずつ、あなたはパーツを選んで損傷する。',
167
+ '【対抗】[発狂:過剰競争]戦闘開始時と終了時に1つずつ、あなたは任意の未練に狂気点を追加で得る。',
168
+ '【友情】[発狂:共鳴依存]セッション終了時、対象にあなたよりも多く損傷したパーツがある際、あなたは損傷パーツ数が対象と同じになるまで、パーツを損傷させる。',
169
+ '【保護】[発狂:常時密着]あなたが対象と別エリアにいるなら「移動以外の効果を持つマニューバ」を宣言できない。「自身と対象」以外を移動マニューバの対象にできない。',
170
+ '【憧憬】[発狂:贋作妄想]あなたが対象と同エリアにいるなら「移動以外の効果を持つマニューバ」を宣言できない。「自身と対象」以外を移動マニューバの対象にできない。',
171
+ '【信頼】[発狂:疑心暗鬼]あなた以外の全ての姉妹の最大行動値が減少する(-1)',
172
+ ]
173
+ ),
174
+ 'NMN' => DiceTable::Table.new(
175
+ '中立者への未練表',
176
+ '1D10',
177
+ [
178
+ '【忌避】[発狂:隔絶意識]あなたは未練の対象ないしサヴァントと同じエリアにいる間、「移動以外の効果を持つマニューバ」を宣言できない。また、「自身と未練の対象ないしサヴァント」以外を移動マニューバの対象にできない。',
179
+ '【嫉妬】[発狂:不協和音]全ての姉妹は行動判定に修正-1を受ける。',
180
+ '【依存】[発狂:幼児退行]最大行動値が減少する(-2)',
181
+ '【憐憫】[発狂:過情移入]あなたは「サヴァント」に対する攻撃判定の出目に修正-1を受ける。',
182
+ '【感謝】[発狂:病的返礼]発狂した際、あなたは任意の基本パーツ2つ(なければ最もレベルの低い強化パーツ1つ)を損傷する。',
183
+ '【悔恨】[発狂:自業自棄]あなたが失敗した攻撃判定は全て、あなた自身の任意の箇所にダメージを与える。',
184
+ '【期待】[発狂:希望転結]あなたは狂気点を追加して振り直しを行う際、出目に修正-1を受ける。(この効果は累積する)',
185
+ '【保護】[発狂:生前回帰]あなたは「レギオン」をマニューバの対象に選べない。',
186
+ '【尊敬】[発狂:神化崇拝]あなたは「他の姉妹」をマニューバの対象に選べない。',
187
+ '【信頼】[発狂:疑心暗鬼]あなた以外の全ての姉妹の最大行動値が減少する(-1)',
188
+ ]
189
+ ),
190
+ 'NME' => DiceTable::Table.new(
191
+ '敵への未練表',
192
+ '1D10',
193
+ [
194
+ '【恐怖】[発狂:認識拒否]あなたは、行動判定・狂気判定の出目に修正-1を受ける。',
195
+ '【隷属】[発狂:造反有理]あなたが失敗した攻撃判定は全て、大失敗として扱う。',
196
+ '【不安】[発狂:挙動不審]最大行動値が減少する(-2)',
197
+ '【憐憫】[発狂:感情移入]あなたは「サヴァント」に対する攻撃判定の出目に修正-1を受ける。',
198
+ '【愛憎】[発狂:凶愛心中]あなたは狂気判定・攻撃判定で大成功するごとに[判定値-10]個の自身のパーツを選び、損傷させる。',
199
+ '【悔恨】[発狂:自業自棄]あなたが失敗した攻撃判定は全て、あなた自身の任意の箇所にダメージを与える。',
200
+ '【軽蔑】[発狂:眼中不在]同エリアの手駒があなたに対して行う攻撃判定の出目は修正+1を受ける。',
201
+ '【憤怒】[発狂:激情暴走]あなたは、攻撃判定・狂気判定の出目に修正-1を受ける。',
202
+ '【怨念】[発狂:不倶戴天]あなたは逃走判定ができない。あなたが「自身と未練の対象」以外を対象にしたマニューバを使用する際、行動値1点を追加で減らさなくてはいけない。',
203
+ '【憎悪】[発狂:痕跡破壊]この未練を発狂した際、あなた以外の姉妹から1人選ぶ。その姉妹は任意のパーツを2つ損傷する。',
204
+ ]
205
+ )
206
+ }.freeze
207
+
208
+ register_prefix(['\d+NC.*', '\d+NA.*', '\d+R10.*'] + TABLES.keys)
209
+ end
210
+ end
211
+ end
@@ -0,0 +1,160 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class Nechronica_Korean < Base
6
+ # ゲームシステムの識別子
7
+ ID = 'Nechronica:Korean'
8
+
9
+ # ゲームシステム名
10
+ NAME = '네크로니카'
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = '国際化:Korean:네크로니카'
14
+
15
+ # ダイスボットの使い方
16
+ HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
17
+ ・판정 (nNC+m)
18
+  주사위 수n、수정치m으로 판정굴림을 행합니다.
19
+  주사위 수가 2개 이상일 때에 파츠파손 수도 표시합니다.
20
+ ・공격판정 (nNA+m)
21
+  주사위 수n、수정치m으로 공격판정굴림을 행합니다.
22
+  명중부위와 주사위 수가 2개 이상일 때에 파츠파손 수도 표시합니다.
23
+ INFO_MESSAGE_TEXT
24
+
25
+ register_prefix(['\d+NC.*', '\d+NA.*', '\d+R10.*'])
26
+
27
+ def initialize(command)
28
+ super(command)
29
+
30
+ @sort_add_dice = true
31
+ @sort_barabara_dice = true
32
+ @default_target_number = 6 # 목표치가 딱히 없을때의 난이도
33
+ end
34
+
35
+ def replace_text(string)
36
+ string = string.gsub(/(\d+)NC(10)?([\+\-][\+\-\d]+)/i) { "#{Regexp.last_match(1)}R10#{Regexp.last_match(3)}[0]" }
37
+ string = string.gsub(/(\d+)NC(10)?/i) { "#{Regexp.last_match(1)}R10[0]" }
38
+ string = string.gsub(/(\d+)NA(10)?([\+\-][\+\-\d]+)/i) { "#{Regexp.last_match(1)}R10#{Regexp.last_match(3)}[1]" }
39
+ string = string.gsub(/(\d+)NA(10)?/i) { "#{Regexp.last_match(1)}R10[1]" }
40
+
41
+ return string
42
+ end
43
+
44
+ def check_nD10(total, _dice_total, dice_list, cmp_op, target)
45
+ return '' if target == '?'
46
+ return '' unless cmp_op == :>=
47
+
48
+ if total >= 11
49
+ " > 대성공"
50
+ elsif total >= target
51
+ " > 성공"
52
+ elsif dice_list.count { |i| i <= 1 } == 0
53
+ " > 실패"
54
+ elsif dice_list.size > 1
55
+ " > 대실패 > 사용파츠 전부 손실"
56
+ else
57
+ " > 대실패"
58
+ end
59
+ end
60
+
61
+ def eval_game_system_specific_command(string)
62
+ string = replace_text(string)
63
+
64
+ debug("nechronica_check string", string)
65
+
66
+ unless /(^|\s)S?((\d+)[rR]10([\+\-\d]+)?(\[(\d+)\])?)(\s|$)/i =~ string
67
+ debug("nechronica_check unmuched")
68
+ return nil
69
+ end
70
+
71
+ string = Regexp.last_match(2)
72
+
73
+ dice_n = 1
74
+ dice_n = Regexp.last_match(3).to_i if Regexp.last_match(3)
75
+
76
+ battleMode = Regexp.last_match(6).to_i
77
+
78
+ modText = Regexp.last_match(4)
79
+ mod = ArithmeticEvaluator.eval(modText)
80
+
81
+ # 0=판정모드, 1=전투모드
82
+ isBattleMode = (battleMode == 1)
83
+ debug("nechronica_check string", string)
84
+ debug("isBattleMode", isBattleMode)
85
+
86
+ diff = 6
87
+
88
+ dice = @randomizer.roll_barabara(dice_n, 10).sort
89
+ n_max = dice.max
90
+
91
+ total_n = n_max + mod
92
+
93
+ output = "(#{string}) > [#{dice.join(',')}]"
94
+ if mod < 0
95
+ output += mod.to_s
96
+ elsif mod > 0
97
+ output += "+#{mod}"
98
+ end
99
+
100
+ n1 = 0
101
+ cnt_max = 0
102
+
103
+ dice.length.times do |i|
104
+ dice[i] += mod
105
+ n1 += 1 if dice[i] <= 1
106
+ cnt_max += 1 if dice[i] >= 10
107
+ end
108
+
109
+ dice_str = dice.join(",")
110
+ output += " > #{total_n}[#{dice_str}]"
111
+
112
+ dice_total = dice.inject(&:+)
113
+ output += check_nD10(total_n, dice_total, dice, :>=, diff)
114
+
115
+ debug("dice_n, n1, total_n diff", dice_n, n1, total_n, diff)
116
+
117
+ # β판의 실장
118
+ # if( (dice_n > 1) and (n1 >= 1) and (total_n <= diff) )
119
+ # output += " > 파손#{n1}"
120
+ # end
121
+
122
+ if isBattleMode
123
+ hit_loc = getHitLocation(total_n)
124
+ if hit_loc != '1'
125
+ output += " > #{hit_loc}"
126
+ end
127
+ end
128
+
129
+ return output
130
+ end
131
+
132
+ def getHitLocation(dice)
133
+ output = '1'
134
+
135
+ debug("getHitLocation dice", dice)
136
+ return output if dice <= 5
137
+
138
+ table = [
139
+ '방어측 임의',
140
+ '다리(없으면 공격측 임의)',
141
+ '몸통(없으면 공격측 임의)',
142
+ '팔(없으면 공격측 임의)',
143
+ '머리(없으면 공격측 임의)',
144
+ '공격측 임의',
145
+ ]
146
+ index = dice - 6
147
+
148
+ addDamage = ""
149
+ if dice > 10
150
+ index = 5
151
+ addDamage = "(추가 데미지#{dice - 10})"
152
+ end
153
+
154
+ output = table[index] + addDamage
155
+
156
+ return output
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class NeverCloud < Base
6
+ # ゲームシステムの識別子
7
+ ID = 'NeverCloud'
8
+
9
+ # ゲームシステム名
10
+ NAME = 'ネバークラウドTRPG'
11
+
12
+ # ゲームシステム名の読みがな
13
+ #
14
+ # 「ゲームシステム名の読みがなの設定方法」(docs/dicebot_sort_key.md)を参考にして
15
+ # 設定してください
16
+ SORT_KEY = 'ねはあくらうとTRPG'
17
+
18
+ # ダイスボットの使い方
19
+ HELP_MESSAGE = <<~MESSAGETEXT
20
+ ・判定(xNC±y>=z)
21
+  xD6の判定を行います。ファンブル、クリティカルの場合、その旨を出力します。
22
+  x:振るダイスの数。
23
+  ±y:固定値・修正値。省略可能。
24
+  z:目標値。省略可能。
25
+  例) 2NC+2>=5 1NC
26
+ MESSAGETEXT
27
+
28
+ # ダイスボットで使用するコマンドを配列で列挙する
29
+ register_prefix(['\d+NC.*', '\d+D6?([\+\-\d]*)>=\d+'])
30
+
31
+ def eval_game_system_specific_command(command)
32
+ m = /^(\d+)(?:NC|D6?)((?:[-+]\d+)*)(>=(\d+))?$/i.match(command)
33
+ unless m
34
+ return nil
35
+ end
36
+
37
+ dice_count = m[1].to_i
38
+ modify_str = m[2]
39
+ modify_number = ArithmeticEvaluator.eval(modify_str)
40
+ cmp_str = m[3]
41
+ target = m[4]&.to_i
42
+
43
+ if modify_number == 0
44
+ modify_str = ''
45
+ end
46
+
47
+ dice_list = @randomizer.roll_barabara(dice_count, 6)
48
+ dice_value = dice_list.sum()
49
+ dice_str = dice_list.join(",")
50
+
51
+ total = dice_value + modify_number
52
+
53
+ result =
54
+ if dice_list.count(1) == dice_count
55
+ total = 0
56
+ "ファンブル"
57
+ elsif dice_list.count(6) >= 2
58
+ "クリティカル"
59
+ elsif target
60
+ total >= target ? "成功" : "失敗"
61
+ end
62
+
63
+ sequence = [
64
+ "(#{dice_count}D6#{modify_str}#{cmp_str})",
65
+ "#{dice_value}[#{dice_str}]#{modify_str}",
66
+ total,
67
+ result
68
+ ].compact
69
+
70
+ return sequence.join(" > ")
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,231 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bcdice/normalize"
4
+ require "bcdice/format"
5
+ require "bcdice/command_parser"
6
+
7
+ module BCDice
8
+ module GameSystem
9
+ class NightWizard < Base
10
+ # ゲームシステムの識別子
11
+ ID = 'NightWizard'
12
+
13
+ # ゲームシステム名
14
+ NAME = 'ナイトウィザード The 2nd Edition'
15
+
16
+ # ゲームシステム名の読みがな
17
+ SORT_KEY = 'ないとういさあと2'
18
+
19
+ # ダイスボットの使い方
20
+ HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
21
+ ・判定用コマンド (aNW+b@x#y$z+c)
22
+   a : 基本値
23
+   b : 常時に準じる特技による補正
24
+   c : 常時以外の特技、および支援効果による補正(ファンブル時には適用されない)
25
+   x : クリティカル値のカンマ区切り(省略時 10)
26
+   y : ファンブル値のカンマ区切り(省略時 5)
27
+   z : プラーナによる達成値補正のプラーナ消費数(ファンブル時には適用されない)
28
+  クリティカル値、ファンブル値が無い場合は1や13などのあり得ない数値を入れてください。
29
+  例)12NW-5@7#2$3 1NW 50nw+5@7,10#2,5 50nw-5+10@7,10#2,5+15+25
30
+ INFO_MESSAGE_TEXT
31
+
32
+ register_prefix(['([-+]?\d+)?NW.*', '2R6.*'])
33
+
34
+ def initialize(command)
35
+ super(command)
36
+
37
+ @nw_command = "NW"
38
+ end
39
+
40
+ # @return [String, nil]
41
+ def eval_game_system_specific_command(string)
42
+ cmd = parse_nw(string) || parse_2r6(string)
43
+ unless cmd
44
+ return nil
45
+ end
46
+
47
+ total, interim_expr, status = roll_nw(cmd)
48
+ result =
49
+ if cmd.cmp_op
50
+ total.send(cmd.cmp_op, cmd.target_number) ? "成功" : "失敗"
51
+ end
52
+
53
+ sequence = [
54
+ "(#{cmd})",
55
+ interim_expr,
56
+ status,
57
+ total.to_s,
58
+ result,
59
+ ].compact
60
+ return sequence.join(" > ")
61
+ end
62
+
63
+ private
64
+
65
+ class Parsed
66
+ # @return [Array<Integer>] クリティカルになる出目の一覧
67
+ attr_accessor :critical_numbers
68
+
69
+ # @return [Array<Integer>] ファンブルになる出目の一覧
70
+ attr_accessor :fumble_numbers
71
+
72
+ # @return [Integer, nil] プラーナによる補正
73
+ attr_accessor :prana
74
+
75
+ # @return [Integer] ファンブルでない時に適用される修正値
76
+ attr_accessor :active_modify_number
77
+
78
+ # @return [Symbol, nil] 比較演算子
79
+ attr_accessor :cmp_op
80
+
81
+ # @return [Integer, nil] 目標値
82
+ attr_accessor :target_number
83
+ end
84
+
85
+ class ParsedNW < Parsed
86
+ # @return [Integer] 判定の基礎値
87
+ attr_accessor :base
88
+
89
+ # @return [Integer] 修正値
90
+ attr_accessor :modify_number
91
+
92
+ def initialize(command)
93
+ @command = command
94
+ end
95
+
96
+ # 常に適用される修正値を返す
97
+ #
98
+ # @return [Integer]
99
+ def passive_modify_number
100
+ @base + @modify_number
101
+ end
102
+
103
+ # @return [String]
104
+ def to_s
105
+ base = @base.zero? ? nil : @base
106
+ modify_number = Format.modifier(@modify_number)
107
+ active_modify_number = Format.modifier(@active_modify_number)
108
+ dollar = @prana && "$#{@prana}"
109
+
110
+ return "#{base}#{@command}#{modify_number}@#{@critical_numbers.join(',')}##{@fumble_numbers.join(',')}#{dollar}#{active_modify_number}#{@cmp_op}#{@target_number}"
111
+ end
112
+ end
113
+
114
+ class Parsed2R6 < Parsed
115
+ # @return [Integer] 常に適用される修正値
116
+ attr_accessor :passive_modify_number
117
+
118
+ # @return [String]
119
+ def to_s
120
+ "2R6M[#{@passive_modify_number},#{@active_modify_number}]C[#{@critical_numbers.join(',')}]F[#{@fumble_numbers.join(',')}]#{@cmp_op}#{@target_number}"
121
+ end
122
+ end
123
+
124
+ # @return [ParsedNW, nil]
125
+ def parse_nw(string)
126
+ m = /^([-+]?\d+)?#{@nw_command}((?:[-+]\d+)+)?(?:@(\d+(?:,\d+)*))?(?:#(\d+(?:,\d+)*))?(?:\$(\d+(?:,\d+)*))?((?:[-+]\d+)+)?(?:([>=]+)(\d+))?$/.match(string)
127
+ unless m
128
+ return nil
129
+ end
130
+
131
+ command = ParsedNW.new(@nw_command)
132
+ command.base = m[1].to_i
133
+ command.modify_number = ArithmeticEvaluator.eval(m[2])
134
+ command.critical_numbers = m[3] ? m[3].split(',').map(&:to_i) : [10]
135
+ command.fumble_numbers = m[4] ? m[4].split(',').map(&:to_i) : [5]
136
+ command.prana = m[5]&.to_i
137
+ command.active_modify_number = ArithmeticEvaluator.eval(m[6])
138
+ command.cmp_op = Normalize.comparison_operator(m[7])
139
+ command.target_number = m[8]&.to_i
140
+
141
+ return command
142
+ end
143
+
144
+ # @return [Parsed2R6, nil]
145
+ def parse_2r6(string)
146
+ m = /^2R6m\[([-+]?\d+(?:[-+]\d+)*)(?:,([-+]?\d+(?:[-+]\d+)*))?\](?:c\[(\d+(?:,\d+)*)\])?(?:f\[(\d+(?:,\d+)*)\])?(?:([>=]+)(\d+))?/i.match(string)
147
+ unless m
148
+ return nil
149
+ end
150
+
151
+ command = Parsed2R6.new
152
+ command.passive_modify_number = ArithmeticEvaluator.eval(m[1])
153
+ command.active_modify_number = ArithmeticEvaluator.eval(m[2])
154
+ command.critical_numbers = m[3] ? m[3].split(',').map(&:to_i) : [10]
155
+ command.fumble_numbers = m[4] ? m[4].split(',').map(&:to_i) : [5]
156
+ command.cmp_op = Normalize.comparison_operator(m[5])
157
+ command.target_number = m[6]&.to_i
158
+
159
+ return command
160
+ end
161
+
162
+ def roll_nw(parsed)
163
+ @critical_numbers = parsed.critical_numbers
164
+ @fumble_numbers = parsed.fumble_numbers
165
+
166
+ @total = 0
167
+ @interim_expr = ""
168
+ @status = nil
169
+
170
+ status = roll_once_first()
171
+ while status == :critical
172
+ status = roll_once()
173
+ end
174
+
175
+ if status != :fumble && parsed.prana
176
+ dice_list = @randomizer.roll_barabara(parsed.prana, 6)
177
+ prana_bonus = dice_list.sum()
178
+ prana_list = dice_list.join(",")
179
+
180
+ @total += prana_bonus
181
+ @interim_expr += "+#{prana_bonus}[#{prana_list}]"
182
+ end
183
+
184
+ base =
185
+ if status == :fumble
186
+ fumble_base_number(parsed)
187
+ else
188
+ parsed.passive_modify_number + parsed.active_modify_number
189
+ end
190
+
191
+ @total += base
192
+ @interim_expr = base.to_s + @interim_expr
193
+
194
+ return @total, @interim_expr, @status
195
+ end
196
+
197
+ # @return [Symbol, nil]
198
+ def roll_once(fumbleable = false)
199
+ dice_list = @randomizer.roll_barabara(2, 6)
200
+ dice_value = dice_list.sum()
201
+ dice_str = dice_list.join(",")
202
+
203
+ if fumbleable && @fumble_numbers.include?(dice_value)
204
+ @total -= 10
205
+ @interim_expr += "-10[#{dice_str}]"
206
+ @status = "ファンブル"
207
+ return :fumble
208
+ elsif @critical_numbers.include?(dice_value)
209
+ @total += 10
210
+ @interim_expr += "+10[#{dice_str}]"
211
+ @status = "クリティカル"
212
+ return :critical
213
+ else
214
+ @total += dice_value
215
+ @interim_expr += "+#{dice_value}[#{dice_str}]"
216
+ return nil
217
+ end
218
+ end
219
+
220
+ # @return [Symbol, nil]
221
+ def roll_once_first
222
+ roll_once(true)
223
+ end
224
+
225
+ # @return [Integer]
226
+ def fumble_base_number(parsed)
227
+ parsed.passive_modify_number
228
+ end
229
+ end
230
+ end
231
+ end