bcdice 3.15.0 → 3.17.0

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 (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +140 -0
  3. data/i18n/Airgetlamh/ja_jp.yml +5 -0
  4. data/i18n/Airgetlamh/ko_kr.yml +5 -0
  5. data/i18n/Alsetto/ja_jp.yml +5 -0
  6. data/i18n/Alsetto/ko_kr.yml +5 -0
  7. data/i18n/AnimaAnimus/ja_jp.yml +28 -0
  8. data/i18n/AnimaAnimus/ko_kr.yml +28 -0
  9. data/i18n/BlackJacket/ja_jp.yml +79 -0
  10. data/i18n/BlackJacket/ko_kr.yml +79 -0
  11. data/i18n/Bloodorium/ja_jp.yml +3 -0
  12. data/i18n/Bloodorium/ko_kr.yml +3 -0
  13. data/i18n/Cthulhu/ko_kr.yml +1 -1
  14. data/i18n/DoubleCross/ja_jp.yml +2 -2
  15. data/i18n/Dracurouge/ko_kr.yml +1284 -205
  16. data/i18n/Emoklore/ja_jp.yml +1 -0
  17. data/i18n/Emoklore/ko_kr.yml +8 -0
  18. data/i18n/FutariSousa/ja_jp.yml +70 -0
  19. data/i18n/FutariSousa/ko_kr.yml +157 -0
  20. data/i18n/HatsuneMiku/ja_jp.yml +579 -0
  21. data/i18n/HatsuneMiku/ko_kr.yml +579 -0
  22. data/i18n/Irisbane/ja_jp.yml +27 -0
  23. data/i18n/Irisbane/ko_kr.yml +27 -0
  24. data/i18n/JuinKansen/ja_jp.yml +168 -0
  25. data/i18n/JuinKansen/ko_kr.yml +168 -0
  26. data/i18n/KemonoNoMori/ja_jp.yml +229 -0
  27. data/i18n/KemonoNoMori/ko_kr.yml +229 -0
  28. data/i18n/KizunaBullet/ko_kr.yml +653 -0
  29. data/i18n/MagicPunk/ja_jp.yml +5 -0
  30. data/i18n/MagicPunk/ko_kr.yml +5 -0
  31. data/i18n/MorkBorg/ja_jp.yml +34 -0
  32. data/i18n/MorkBorg/ko_kr.yml +34 -0
  33. data/i18n/Nechronica/ko_kr.yml +43 -0
  34. data/i18n/NegikureNegimaki/ja_jp.yml +6 -0
  35. data/i18n/NegikureNegimaki/ko_kr.yml +6 -0
  36. data/i18n/Nuekagami/ja_jp.yml +219 -0
  37. data/i18n/Nuekagami/ko_kr.yml +219 -0
  38. data/i18n/Revulture/ja_jp.yml +8 -0
  39. data/i18n/Revulture/ko_kr.yml +8 -0
  40. data/i18n/SRS/ja_jp.yml +4 -0
  41. data/i18n/SRS/ko_kr.yml +4 -0
  42. data/i18n/ShinobiGami/ja_jp.yml +879 -0
  43. data/i18n/ShinobiGami/ko_kr.yml +876 -0
  44. data/i18n/SkynautsBouken/ja_jp.yml +28 -28
  45. data/i18n/StarryDolls/ja_jp.yml +456 -0
  46. data/i18n/StarryDolls/ko_kr.yml +456 -0
  47. data/i18n/StratoShout/ja_jp.yml +8 -8
  48. data/i18n/SwordWorld2_5/ja_jp.yml +48 -0
  49. data/i18n/Ventangle/ja_jp.yml +4 -0
  50. data/i18n/Ventangle/ko_kr.yml +4 -0
  51. data/i18n/YearZeroEngine/ja_jp.yml +12 -0
  52. data/i18n/YearZeroEngine/ko_kr.yml +12 -0
  53. data/i18n/ZombiLine/ja_jp.yml +27 -0
  54. data/i18n/ZombiLine/ko_kr.yml +27 -0
  55. data/i18n/ko_kr.yml +2 -0
  56. data/i18n/zh_hant.yml +2 -2
  57. data/lib/bcdice/dice_table/d66_left_range_table.rb +21 -0
  58. data/lib/bcdice/game_system/Aionia.rb +68 -19
  59. data/lib/bcdice/game_system/Airgetlamh.rb +64 -41
  60. data/lib/bcdice/game_system/Airgetlamh_Korean.rb +53 -0
  61. data/lib/bcdice/game_system/Alsetto.rb +63 -50
  62. data/lib/bcdice/game_system/Alsetto_Korean.rb +51 -0
  63. data/lib/bcdice/game_system/AnimaAnimus.rb +15 -32
  64. data/lib/bcdice/game_system/AnimaAnimus_Korean.rb +39 -0
  65. data/lib/bcdice/game_system/BlackJacket.rb +57 -113
  66. data/lib/bcdice/game_system/BlackJacket_Korean.rb +8 -206
  67. data/lib/bcdice/game_system/Bloodorium.rb +1 -1
  68. data/lib/bcdice/game_system/Bloodorium_Korean.rb +34 -0
  69. data/lib/bcdice/game_system/ChroniclesOfDarkness2e.rb +163 -0
  70. data/lib/bcdice/game_system/Cthulhu7th_Korean.rb +471 -300
  71. data/lib/bcdice/game_system/DeadlineHeroes_Korean.rb +273 -0
  72. data/lib/bcdice/game_system/Dracurouge_Korean.rb +25 -19
  73. data/lib/bcdice/game_system/DungeonsAndDragons5.rb +106 -73
  74. data/lib/bcdice/game_system/DungeonsAndDragons5_Korean.rb +53 -0
  75. data/lib/bcdice/game_system/DungeonsAndDragons_Korean.rb +61 -0
  76. data/lib/bcdice/game_system/EdgeFlippers.rb +315 -0
  77. data/lib/bcdice/game_system/Emoklore.rb +34 -9
  78. data/lib/bcdice/game_system/Emoklore_Korean.rb +50 -0
  79. data/lib/bcdice/game_system/FateCoreSystem.rb +10 -6
  80. data/lib/bcdice/game_system/FullMetalPanic_Korean.rb +28 -0
  81. data/lib/bcdice/game_system/FutariSousa.rb +37 -12
  82. data/lib/bcdice/game_system/FutariSousa_Korean.rb +25 -8
  83. data/lib/bcdice/game_system/GaiaCare.rb +40 -0
  84. data/lib/bcdice/game_system/Garactier.rb +1 -1
  85. data/lib/bcdice/game_system/GardenOrder.rb +2 -2
  86. data/lib/bcdice/game_system/GardenOrderReEdit.rb +849 -0
  87. data/lib/bcdice/game_system/GardenOrder_Korean.rb +839 -0
  88. data/lib/bcdice/game_system/HatsuneMiku.rb +51 -605
  89. data/lib/bcdice/game_system/HatsuneMiku_Korean.rb +56 -0
  90. data/lib/bcdice/game_system/HunterTheReckoning5th.rb +15 -11
  91. data/lib/bcdice/game_system/Irisbane.rb +17 -30
  92. data/lib/bcdice/game_system/Irisbane_Korean.rb +52 -0
  93. data/lib/bcdice/game_system/JuinKansen.rb +41 -208
  94. data/lib/bcdice/game_system/JuinKansen_Korean.rb +46 -0
  95. data/lib/bcdice/game_system/KemonoNoMori.rb +67 -276
  96. data/lib/bcdice/game_system/KemonoNoMori_Korean.rb +62 -0
  97. data/lib/bcdice/game_system/KinAriel.rb +117 -0
  98. data/lib/bcdice/game_system/KizunaBullet_Korean.rb +109 -0
  99. data/lib/bcdice/game_system/KutuluRevised.rb +94 -0
  100. data/lib/bcdice/game_system/LiverLabyrinth.rb +321 -0
  101. data/lib/bcdice/game_system/Lost.rb +89 -0
  102. data/lib/bcdice/game_system/MagicPunk.rb +85 -0
  103. data/lib/bcdice/game_system/MagicPunk_Korean.rb +39 -0
  104. data/lib/bcdice/game_system/MarvelHeroicRoleplaying.rb +144 -0
  105. data/lib/bcdice/game_system/MeikyuKingdomBasic.rb +122 -2
  106. data/lib/bcdice/game_system/MetallicGuardian_Korean.rb +28 -0
  107. data/lib/bcdice/game_system/MorkBorg.rb +170 -0
  108. data/lib/bcdice/game_system/MorkBorg_Korean.rb +49 -0
  109. data/lib/bcdice/game_system/NanimonaiMura.rb +112 -0
  110. data/lib/bcdice/game_system/Nechronica_Korean.rb +6 -6
  111. data/lib/bcdice/game_system/NegikureNegimaki.rb +140 -0
  112. data/lib/bcdice/game_system/NegikureNegimaki_Korean.rb +48 -0
  113. data/lib/bcdice/game_system/NeonUnderRealm.rb +122 -0
  114. data/lib/bcdice/game_system/NinjaSlayer2.rb +170 -49
  115. data/lib/bcdice/game_system/Nuekagami.rb +19 -261
  116. data/lib/bcdice/game_system/Nuekagami_Korean.rb +43 -0
  117. data/lib/bcdice/game_system/ParanoiaPerfect.rb +74 -0
  118. data/lib/bcdice/game_system/PastFutureParadox.rb +2245 -55
  119. data/lib/bcdice/game_system/PreciousDays.rb +170 -0
  120. data/lib/bcdice/game_system/Revulture.rb +8 -5
  121. data/lib/bcdice/game_system/Revulture_Korean.rb +51 -0
  122. data/lib/bcdice/game_system/Ryutama.rb +46 -46
  123. data/lib/bcdice/game_system/SRS.rb +4 -4
  124. data/lib/bcdice/game_system/SRS_Korean.rb +67 -0
  125. data/lib/bcdice/game_system/ShinobiGami.rb +154 -1047
  126. data/lib/bcdice/game_system/ShinobiGami_Korean.rb +102 -0
  127. data/lib/bcdice/game_system/StarryDolls.rb +70 -508
  128. data/lib/bcdice/game_system/StarryDolls_Korean.rb +80 -0
  129. data/lib/bcdice/game_system/StratoShout.rb +1 -1
  130. data/lib/bcdice/game_system/SwordWorld.rb +28 -2
  131. data/lib/bcdice/game_system/SwordWorld2_0.rb +1 -1
  132. data/lib/bcdice/game_system/SwordWorld2_5.rb +67 -3
  133. data/lib/bcdice/game_system/TacticalExorcist.rb +222 -0
  134. data/lib/bcdice/game_system/TenkaRyouran_Korean.rb +30 -0
  135. data/lib/bcdice/game_system/VampireTheMasquerade5th.rb +38 -33
  136. data/lib/bcdice/game_system/Ventangle.rb +8 -7
  137. data/lib/bcdice/game_system/Ventangle_Korean.rb +41 -0
  138. data/lib/bcdice/game_system/Warhammer4.rb +202 -6
  139. data/lib/bcdice/game_system/WerewolfTheApocalypse5th.rb +20 -15
  140. data/lib/bcdice/game_system/WorldEndScrapyard.rb +333 -0
  141. data/lib/bcdice/game_system/WorldsEndFrontline_Korean.rb +26 -0
  142. data/lib/bcdice/game_system/YearZeroEngine.rb +7 -7
  143. data/lib/bcdice/game_system/YearZeroEngine_Korean.rb +46 -0
  144. data/lib/bcdice/game_system/ZombiLine.rb +29 -36
  145. data/lib/bcdice/game_system/ZombiLine_Korean.rb +37 -0
  146. data/lib/bcdice/game_system/cthulhu7th_Korean/full_auto.rb +294 -0
  147. data/lib/bcdice/game_system/cthulhu7th_Korean/rollable.rb +43 -0
  148. data/lib/bcdice/game_system/meikyu_kingdom_basic/atoz_table.rb +1184 -0
  149. data/lib/bcdice/game_system/meikyu_kingdom_basic/randr236_table.rb +254 -0
  150. data/lib/bcdice/game_system/meikyu_kingdom_basic/table.rb +54 -0
  151. data/lib/bcdice/game_system/meikyu_kingdom_basic/tk_table.rb +755 -0
  152. data/lib/bcdice/game_system/sword_world/rating_options.rb +9 -0
  153. data/lib/bcdice/game_system/sword_world/rating_parsed.rb +19 -0
  154. data/lib/bcdice/game_system/sword_world/rating_parser.rb +229 -149
  155. data/lib/bcdice/game_system/sword_world/transcendent_test.rb +1 -0
  156. data/lib/bcdice/game_system.rb +47 -0
  157. data/lib/bcdice/version.rb +1 -1
  158. metadata +96 -2
@@ -17,16 +17,16 @@ module BCDice
17
17
  # ダイスボットの使い方
18
18
  HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
19
19
  ・판정 (nNC+m)
20
-  주사위 수n、수정치m으로 판정굴림을 행합니다.
20
+  주사위 수n, 수정치m으로 판정굴림을 행합니다.
21
21
   주사위 수가 2개 이상일 때에 파츠파손 수도 표시합니다.
22
22
  ・공격판정 (nNA+m)
23
-  주사위 수n、수정치m으로 공격판정굴림을 행합니다.
23
+  주사위 수n, 수정치m으로 공격판정굴림을 행합니다.
24
24
   명중부위와 주사위 수가 2개 이상일 때에 파츠파손 수도 표시합니다.
25
25
 
26
-
27
- ・姉妹への未練表 nm
28
- ・中立者への未練表 nmn
29
- ・敵への未練表 nme
26
+
27
+ ・자매에 대한 미련표 nm
28
+ ・중립자에 대한 미련표 nmn
29
+ ・적에 대한 미련표 nme
30
30
  INFO_MESSAGE_TEXT
31
31
 
32
32
  register_prefix_from_super_class()
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class NegikureNegimaki < Base
6
+ # ゲームシステムの識別子
7
+ ID = "NegikureNegimaki"
8
+
9
+ # ゲームシステム名
10
+ NAME = "ネジクレネジマキ"
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = "ねしくれねしまき"
14
+
15
+ # ダイスボットの使い方
16
+ HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
17
+ ■ 行為判定
18
+ nNNx#y: n個のD6を振り、x以上の出目の個数を成功レベルとして判定する
19
+ n: ダイス数(省略時1)
20
+ x: 難易度(省略時4)
21
+ y: 要求成功レベル(省略時1、0は1として扱う)
22
+
23
+ ■ 戦闘判定(アタック判定)
24
+ nNAx#y: n個のD6を振り、x以上を成功とする。y以上の成功は直撃ダメージになる
25
+ n: ダイス数(省略時1)
26
+ x: 難易度(省略時4)
27
+ y: クリティカル値(省略時6、0は1として扱う)
28
+ 通常ダメージ = 成功レベル - 直撃ダメージ
29
+ 直撃ダメージ = 成功した出目のうち y 以上の個数
30
+ ガッツ減少 = 出目 1 の個数
31
+
32
+ ■ ストライクの判定
33
+ nNS: n個のD6を振り、出目 1 の個数だけガッツ減少を算出する
34
+ n: ダイス数(省略時1)
35
+ ガッツ減少が 0 なら成功、1 以上なら失敗
36
+ INFO_MESSAGE_TEXT
37
+
38
+ register_prefix('\d*NN\d*(#\d+)?', '\d*NA\d*(#\d+)?', '\d*NS')
39
+
40
+ def eval_game_system_specific_command(command)
41
+ return eval_action_command(command) || eval_attack_command(command) || eval_guts_command(command)
42
+ end
43
+
44
+ private
45
+
46
+ def eval_action_command(command)
47
+ m = /\A(\d+)?NN(\d+)?(?:#(\d+))?\z/i.match(command)
48
+ return nil unless m
49
+
50
+ dice_count = m[1]&.to_i || 1
51
+ difficulty = m[2]&.to_i || 4
52
+ required_level = [m[3]&.to_i || 1, 1].max
53
+
54
+ return nil if dice_count.zero?
55
+
56
+ command_text = "(#{dice_count}NN#{difficulty}##{required_level})"
57
+
58
+ dice_list = @randomizer.roll_barabara(dice_count, 6)
59
+ success_level = dice_list.count { |value| value >= difficulty }
60
+ detail_text = "[#{dice_list.join(',')}]"
61
+
62
+ return build_result(command_text, detail_text, success_level, required_level)
63
+ end
64
+
65
+ def eval_attack_command(command)
66
+ m = /\A(\d+)?NA(\d+)?(?:#(\d+))?\z/i.match(command)
67
+ return nil unless m
68
+
69
+ dice_count = m[1]&.to_i || 1
70
+ difficulty = m[2]&.to_i || 4
71
+ critical_value = [m[3]&.to_i || 6, 1].max
72
+
73
+ return nil if dice_count.zero?
74
+
75
+ command_text = "(#{dice_count}NA#{difficulty}##{critical_value})"
76
+
77
+ dice_list = @randomizer.roll_barabara(dice_count, 6)
78
+ success_level = dice_list.count { |value| value >= difficulty }
79
+ direct_damage = dice_list.count { |value| value >= difficulty && value >= critical_value }
80
+ guts_loss = dice_list.count(1)
81
+ detail_text = "[#{dice_list.join(',')}]"
82
+
83
+ return build_attack_result(command_text, detail_text, success_level, direct_damage, guts_loss)
84
+ end
85
+
86
+ def eval_guts_command(command)
87
+ m = /\A(\d+)?NS\z/i.match(command)
88
+ return nil unless m
89
+
90
+ dice_count = m[1]&.to_i || 1
91
+ return nil if dice_count.zero?
92
+
93
+ command_text = "(#{dice_count}NS)"
94
+ dice_list = @randomizer.roll_barabara(dice_count, 6)
95
+ guts_loss = dice_list.count(1)
96
+ detail_text = "[#{dice_list.join(',')}]"
97
+
98
+ return build_guts_result(command_text, detail_text, guts_loss)
99
+ end
100
+
101
+ def build_result(command_text, detail_text, success_level, required_level)
102
+ success = success_level >= required_level
103
+ judge_text = success ? translate('success') : translate('failure')
104
+ result_level_text = translate('NegikureNegimaki.result_level', success_level: success_level, required_level: required_level)
105
+ text = "#{command_text} > #{detail_text} > #{result_level_text} > #{judge_text}"
106
+
107
+ if success
108
+ return Result.success(text)
109
+ end
110
+
111
+ return Result.failure(text)
112
+ end
113
+
114
+ def build_attack_result(command_text, detail_text, success_level, direct_damage, guts_loss)
115
+ normal_damage = [success_level - direct_damage, 0].max
116
+ success = success_level.positive?
117
+ damage_text = translate('NegikureNegimaki.damage', normal_damage: normal_damage, direct_damage: direct_damage)
118
+ damage_text += "/#{translate('NegikureNegimaki.guts_loss', guts_loss: guts_loss)}" if guts_loss.positive?
119
+ text = "#{command_text} > #{detail_text} > #{translate('NegikureNegimaki.success_level', success_level: success_level)} > #{damage_text}"
120
+
121
+ if success
122
+ return Result.success(text)
123
+ end
124
+
125
+ return Result.failure(text)
126
+ end
127
+
128
+ def build_guts_result(command_text, detail_text, guts_loss)
129
+ success = guts_loss.zero?
130
+ text = "#{command_text} > #{detail_text} > #{translate('NegikureNegimaki.guts_loss', guts_loss: guts_loss)}"
131
+
132
+ if success
133
+ return Result.success(text)
134
+ end
135
+
136
+ return Result.failure(text)
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bcdice/game_system/NegikureNegimaki'
4
+
5
+ module BCDice
6
+ module GameSystem
7
+ class NegikureNegimaki_Korean < NegikureNegimaki
8
+ # ゲームシステムの識別子
9
+ ID = 'NegikureNegimaki:Korean'
10
+
11
+ # ゲームシステム名
12
+ NAME = '네지쿠레 네지마키'
13
+
14
+ # ゲームシステム名の読みがな
15
+ SORT_KEY = '国際化:Korean:네지쿠레 네지마키'
16
+
17
+ # ダイスボットの使い方
18
+ HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
19
+ ■ 행위 판정
20
+ nNNx#y: n개의 D6을 굴려, x 이상의 주사위 결과값의 개수를 성공 레벨로 판정.
21
+ n: 주사위 수(생략 시 1)
22
+ x: 난이도(생략 시 4)
23
+ y: 요구 성공 레벨(생략 시 1, 0은 1로 처리)
24
+
25
+ ■ 전투 판정(공격 판정)
26
+ nNAx#y: n개의 D6을 굴려, x 이상을 성공으로 간주. y 이상의 성공은 직격 피해가 된다.
27
+ n: 주사위 수(생략 시 1)
28
+ x: 난이도(생략 시 4)
29
+ y: 크리티컬 값(생략 시 6, 0은 1로 처리)
30
+ 일반 피해 = 성공 레벨 - 직격 피해
31
+ 직격 피해 = 성공한 눈 중 y 이상의 개수
32
+ 거츠 감소 = 주사위 결과값 1의 개수
33
+
34
+ ■ 스트라이크 판정
35
+ nNS: n개의 D6을 굴려, 주사위 결과값 1의 개수만큼 거츠 감소를 산출한다
36
+ n: 주사위 수(생략 시 1)
37
+ 거츠 감소가 0이면 성공, 1 이상이면 실패
38
+ INFO_MESSAGE_TEXT
39
+
40
+ register_prefix_from_super_class()
41
+
42
+ def initialize(command)
43
+ super(command)
44
+ @locale = :ko_kr
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class NeonUnderRealm < Base
6
+ ID = "NeonUnderRealm"
7
+ NAME = "光都暗域〈ネオン・アンダーレルム〉"
8
+ SORT_KEY = "ねおんあんたあれるむ"
9
+
10
+ HELP_MESSAGE = <<~TEXT
11
+ ・判定(D10の出目が「目標値以下」を成功として数える)
12
+ [M]NU[N][±K][@L][±K']
13
+
14
+ M:判定ダイス数(省略不可)。「10+5+3-2」のような加減算を許可
15
+ N:目標値(1~10)。省略時は 5
16
+ K, K':達成値への補正。両方指定された場合はKを採用し、K'は無視される。(省略可)
17
+ L:気合の閾値(0~5)。省略時は 0(気合は常に0扱い)
18
+
19
+ ※Nが1~10の範囲外、またはLが0~5の範囲外の場合はコマンドとして処理しません(出力しません)
20
+ ※達成値 = max(0, 素の成功数 + K)
21
+ ※効果値 = ダイス数 - 素の成功数
22
+ ※素の成功数が0なら判定は失敗(達成値が補正で1以上でも失敗扱い)
23
+ ※成功は表示しません。素の成功数0または達成値0のときのみ「失敗」を表示します。
24
+
25
+ 例)
26
+ 4NU
27
+ 4NU7+2
28
+ 10+5+3-2NU5-1@2
29
+ TEXT
30
+
31
+ DEFAULT_THRESHOLD = 5
32
+ MIN_THRESHOLD = 1
33
+ MAX_THRESHOLD = 10
34
+ DEFAULT_KIAI_THRESHOLD = 0
35
+ MIN_KIAI_THRESHOLD = 0
36
+ MAX_KIAI_THRESHOLD = 5
37
+ DEFAULT_MODIFIER = 0
38
+
39
+ register_prefix('\d+([+\-]\d+)*NU')
40
+
41
+ # [M]NU[N]±[K]@[L]
42
+ def eval_game_system_specific_command(command)
43
+ m_expr, n_str, k_str, l_str = parse_command(command)
44
+ return nil unless m_expr
45
+
46
+ dice_count = eval_dice_count(m_expr)
47
+ return nil unless dice_count && dice_count >= 1
48
+
49
+ threshold = n_str&.to_i || DEFAULT_THRESHOLD
50
+ return nil unless (MIN_THRESHOLD..MAX_THRESHOLD).cover?(threshold)
51
+
52
+ modifier = k_str&.to_i || DEFAULT_MODIFIER
53
+
54
+ kiai_threshold = l_str&.to_i || DEFAULT_KIAI_THRESHOLD
55
+ return nil unless (MIN_KIAI_THRESHOLD..MAX_KIAI_THRESHOLD).cover?(kiai_threshold)
56
+
57
+ dice_list = @randomizer.roll_barabara(dice_count, 10).sort
58
+
59
+ raw_success = dice_list.count { |x| x <= threshold }
60
+ achieved = raw_success + modifier
61
+ achieved = 0 if achieved < 0
62
+
63
+ effect = dice_count - raw_success
64
+ kiai = kiai_threshold > 0 ? dice_list.count { |x| x <= kiai_threshold } : 0
65
+
66
+ expr_text = build_expr_text(dice_count, threshold, modifier, kiai_threshold, dice_list)
67
+
68
+ result_text_parts = [
69
+ "達成値:#{achieved}(成功数:#{raw_success})",
70
+ "効果値:#{effect}",
71
+ "気合:#{kiai}",
72
+ ]
73
+
74
+ # 素成功0なら失敗。または達成値0なら失敗。成功表示は不要。失敗表示はこのケースのみ。
75
+ result_text_parts << "失敗" if raw_success == 0 || achieved == 0
76
+
77
+ text = [
78
+ "(#{command.upcase})",
79
+ expr_text,
80
+ result_text_parts.join(" / "),
81
+ ].join(" > ")
82
+
83
+ result = Result.new(text)
84
+
85
+ # 成功条件:達成値>=1 かつ 素成功>=1
86
+ is_success = (achieved >= 1) && (raw_success >= 1)
87
+ result.success = is_success
88
+ result.failure = !is_success
89
+
90
+ result
91
+ end
92
+
93
+ private
94
+
95
+ # returns [m_expr, n_str, k_str, l_str] or [nil,...]
96
+ def parse_command(command)
97
+ # M は「加減算のみ」の式を許可(例:10+5+3-2)
98
+ # N は省略可、K は ±整数、L は @整数、K' は ±整数
99
+ m = /\A(?<m_expr>\d+(?:[+-]\d+)*)NU(?<n>\d+)?(?<k>[+-]\d+)?(?:@(?<l>\d+))?(?<j>[+-]\d+)?\z/.match(command)
100
+ return [nil, nil, nil, nil] unless m
101
+
102
+ # 修正値が K を優先
103
+ k = m[:k] || m[:j]
104
+
105
+ [m[:m_expr], m[:n], k, m[:l]]
106
+ end
107
+
108
+ def eval_dice_count(source)
109
+ BCDice::Arithmetic.eval(source, @round_type)
110
+ rescue StandardError
111
+ nil
112
+ end
113
+
114
+ def build_expr_text(dice_count, n, k, l, dice_list)
115
+ # 「MB10」表記に寄せる:xB10<=n±k@l[...]
116
+ k_text = Format.modifier(k)
117
+ l_text = l > 0 ? "@#{l}" : ""
118
+ "#{dice_count}B10<=#{n}#{k_text}#{l_text}[#{dice_list.join(',')}]"
119
+ end
120
+ end
121
+ end
122
+ end
@@ -13,20 +13,62 @@ module BCDice
13
13
  SORT_KEY = "にんしやすれいやあTRPG2"
14
14
 
15
15
  HELP_MESSAGE = <<~TEXT
16
- - K{x1},{x2},...,{xn}
17
- 難易度K([K]ids)の成功判定({x1}B6>=2)を、ダイス{x1}個({x2}~を指定した場合はそれぞれ個々に)で実行します。
18
- 先頭の文字を変えることで、難易度E([E]asy),N([N]ormal),H([H]ard),U([U]ltra-hard)もしくはUH([U]ltra-[H]ard)でも実行可能です。(以下も同様)
19
-
20
- - K{x1},{x2},...,{xn}[>={y}]
21
- K{x1}のロールの結果を使って、[]内で指定された条件を満たすダイスの個数を追加で出力します。
22
- 判定式は「>=」の他に「>」「<=」「<」「=」「!=」が利用可能です。
23
- [=5][=6]のように複数記述することで、それぞれで追加判定が可能です。
24
-
25
- - K{x1},{x2},...,{xn}[S] or K{x1},{x2},...,{xn}[S{y}]
26
- - K{x1},{x2},...,{xn}[C] or K{x1},{x2},...,{xn}[C{y}]
27
- いずれもK{x1},{x2},...,{xn}[>={y}]のショートカットです。({y}省略時は固定値6で処理します。)
28
- 出力時のテキストが、Sの場合は「サツバツ!」に、Cの場合は「クリティカル!」になります。
29
- こちらも複数記述することで、それぞれで追加判定が可能です。
16
+ --- 成功判定コマンド ---
17
+ 通常のダイスの「{ダイス個数}B6>={難易度ごとの目標出目}」を実行するための簡易入力コマンドです。
18
+
19
+ - K{x}
20
+ 難易度K([K]ids/目標値=2)の成功判定をダイス{x}個で実行します。
21
+ 先頭の文字を変えることで、難易度E([E]asy/目標値=3),N([N]ormal/目標値=4),H([H]ard/目標値=5),U([U]ltra-hard/目標値=6)もしくはUH([U]ltra-[H]ard/目標値=6)でも実行可能です。
22
+
23
+ - K{x1},N{x2},...,U{xn}
24
+ K{x}の複数ロール版。
25
+ カンマ(,)で区切って複数回入力すると、区切られたセットごとに成功判定を行います。
26
+ 2回目以降は難易度指定を省略可能で、省略した場合はひとつ前の難易度を引き継いで判定を行います。
27
+ 以下のコマンドについても同様の書式で複数ロールしての同時判定が可能です。
28
+
29
+ --- 追加判定コマンド ---
30
+ 以下のコマンド群は、成功判定コマンドの後ろに付けて実行してください。
31
+
32
+ - [>={y}]
33
+ - [>{y}]
34
+ - [<={y}]
35
+ - [<{y}]
36
+ - [={y}]
37
+ - [!={y}]
38
+ 成功判定コマンドでカンマ区切りで指定した各ロール結果に対して、[]内で指定された条件で追加判定を行います。
39
+ それぞれ、{y}以上(>=)、{y}より大きい(>)、{y}以下(<=)、{y}未満(<)、{y}のみ(=)、{y}以外(!=)を判定し、
40
+ ロール結果の中で条件を満たしたダイスの個数を「追加判定」というテキストと共に出力します。
41
+ [=5][=6]のように複数記述することで、ひとつのロールに対して複数パターンでの追加判定が可能です。
42
+ ※ 条件は一括でしか指定できないため、ロールごとに異なる条件を指定したい場合はコマンドを分けてください。以下も同様です。。
43
+
44
+ - [>={y1}{y2}...{yn}+]
45
+ 成功判定コマンドでカンマ区切りで指定した各ロール結果に対して、[>={y1}]~[>={yn}]の各条件で追加判定を行います。
46
+ 出目の中に条件を満たしたダイスが**全て**含まれていた場合、「追加判定成功!」というテキストを出力します。
47
+ 例えば[>=665+]とした場合、出目の中に6以上のダイスが2つと5以上のダイスが1つ含まれていれば成功扱いになります。
48
+
49
+ - [S{y}]
50
+ 成功判定コマンドでカンマ区切りで指定した各ロール結果に対して、[>={y}]と同等の追加判定を行います。
51
+ 条件を満たしたダイスの個数を「サツバツ判定」というテキストと共に出力します。
52
+ ※ {y}は省略可能、省略した場合は固定値6で処理します。
53
+
54
+ - [S{y1}{y2}...{yn}+]
55
+ - [S{y1}{y2}...{yn}/{z1}{z2}...{zn}+]
56
+ 成功判定コマンドでカンマ区切りで指定した各ロール結果に対して、[>={y1}{y2}...{yn}+]と[>={z1}{z2}...{zn}+]と同等の追加判定を行います。
57
+ {z1}~{zn}で条件を満たした場合、「ナムアミダブツ!」というテキストを出力します。
58
+ {z1}~{zn}の条件を満たせず、{y1}~{yn}で条件を満たした場合、「サツバツ!」というテキストを出力します。
59
+ ※ {z1}~{zn}を省略した場合は、「サツバツ!」の判定のみを行ないます。
60
+
61
+ - [C{y}]
62
+ 成功判定コマンドでカンマ区切りで指定した各ロール結果に対して、[>={y}]と同等の追加判定を行います。
63
+ 条件を満たしたダイスの個数を「クリティカル判定」というテキストと共に出力します。
64
+ ※ {y}は省略可能、省略した場合は固定値6で処理します。
65
+
66
+ - [C{y1}{y2}...{yx}+]
67
+ 成功判定コマンドでカンマ区切りで指定した各ロール結果に対して、[>={y1}{y2}...{yn}+]と同等の追加判定を行います。
68
+ 条件を条件を満たした場合、「クリティカル!」というテキストを出力します。
69
+
70
+ --- 定型文コマンド ---
71
+ 以下のコマンド群はそれぞれ単体で使用してください。
30
72
 
31
73
  - SB or SB@{x}
32
74
  {x}(1-6/省略時はd6)に対応したサツバツ([S]atz-[B]atz)・クリティカル表の内容を返します。
@@ -79,27 +121,118 @@ module BCDice
79
121
  # @param default [Integer]
80
122
  # @return [Integer]
81
123
  def s_to_i(string, default)
82
- return string.nil? ? default : string.to_i
124
+ return string.nil? || string.empty? ? default : string.to_i
83
125
  end
84
126
 
85
- # 判定結果の出力テキストと成功数のカウントを返す。
127
+ # 難易度判定の成功数を返す。
86
128
  # @param dice_array [Array<Integer>]
87
129
  # @param difficulty [Integer]
88
130
  # @param cmp_op [String]
89
- # @param title_text [String]
90
- # @return [String, Integer]
91
- def check_difficulty(dice_array, difficulty, cmp_op, title_text)
92
- success_num = 0
131
+ # @return Integer
132
+ def check_difficulty(dice_array, difficulty, cmp_op)
93
133
  success_dice = []
94
134
  dice_array.each do |dice_value|
95
135
  if dice_value.send(Normalize.comparison_operator(cmp_op), difficulty)
96
- success_num += 1
97
136
  success_dice.push(dice_value)
98
137
  end
99
138
  end
100
139
 
101
- success_dice_s = success_dice.empty? ? "" : "[#{success_dice.sort.reverse.join(',')}]"
102
- return "#{title_text}:#{success_num}#{success_dice_s}", success_num
140
+ return success_dice
141
+ end
142
+
143
+ # 難易度判定結果を返す。
144
+ # @param dice_array [Array<Integer>]
145
+ # @param difficulty [Integer]
146
+ # @param cmp_op [String]
147
+ # @return [boolean]
148
+ def check_difficulty_new(dice_array, difficulty, cmp_op)
149
+ if difficulty.nil? || dice_array.empty?
150
+ return false
151
+ end
152
+
153
+ # 難易度とダイスを昇順ソート
154
+ sorted_dice_array = dice_array.sort()
155
+ sorted_difficulty = difficulty.chars.sort()
156
+ debug("sorted_difficulty #{sorted_difficulty}")
157
+ debug("sorted_dice_array #{sorted_dice_array}")
158
+
159
+ # 出目が低い順に難易度を越えているかチェック
160
+ check_index = 0
161
+ sorted_dice_array.each do |dice_value|
162
+ if dice_value.send(Normalize.comparison_operator(cmp_op), sorted_difficulty[check_index].to_i)
163
+ check_index += 1
164
+ end
165
+ end
166
+
167
+ # 全難易度を突破していたら成功を返す
168
+ return check_index >= sorted_difficulty.size
169
+ end
170
+
171
+ # 追加判定の処理
172
+ # @param roll_result 判定対象とするロール結果の配列
173
+ # @param ap_commanc 追加判定のコマンド
174
+ # @return String
175
+ def proc_appendix(roll_result, ap_command)
176
+ debug("----- ap_command: #{ap_command}")
177
+ output_text = ''
178
+ case ap_command
179
+ when RE_COUNT_SATZ_BATZ
180
+ diff_condition = Regexp.last_match[1]
181
+ if ap_command.end_with?("+")
182
+ # サツバツ発生チェック
183
+ sb_condition = diff_condition.sub("\+", "").split("/")[0]
184
+ nm_condition = diff_condition.sub("\+", "").split("/")[1]
185
+ debug("sb_condition: #{sb_condition}")
186
+ debug("nm_condition: #{nm_condition}")
187
+
188
+ if check_difficulty_new(roll_result.last_dice_list, nm_condition, ">=")
189
+ output_text += ", ナムアミダブツ![#{ap_command}]"
190
+ elsif check_difficulty_new(roll_result.last_dice_list, sb_condition, ">=")
191
+ output_text += ", サツバツ![#{ap_command}]"
192
+ end
193
+
194
+ else
195
+ # サツバツ数カウント
196
+ diff_result_array = check_difficulty(roll_result.last_dice_list, s_to_i(diff_condition, 6), ">=")
197
+ output_text += ", サツバツ判定[#{ap_command}]:#{diff_result_array.size}"
198
+ unless diff_result_array.empty?
199
+ output_text += "[#{diff_result_array.sort.reverse.join(',')}]"
200
+ end
201
+ end
202
+ when RE_COUNT_CRITICAL
203
+ diff_condition = Regexp.last_match[1]
204
+ if ap_command.end_with?("+")
205
+ # クリティカル発生チェック
206
+ if check_difficulty_new(roll_result.last_dice_list, diff_condition.sub("\+", ""), ">=")
207
+ output_text += ", クリティカル![#{ap_command}]"
208
+ end
209
+ else
210
+ # クリティカル数カウント
211
+ diff_result_array = check_difficulty(roll_result.last_dice_list, s_to_i(diff_condition, 6), ">=")
212
+ output_text += ", クリティカル判定[#{ap_command}]:#{diff_result_array.size}"
213
+ unless diff_result_array.empty?
214
+ output_text += "[#{diff_result_array.sort.reverse.join(',')}]"
215
+ end
216
+ end
217
+ when RE_COUNT_JUDGE
218
+ diff_type = Regexp.last_match[1]
219
+ diff_condition = Regexp.last_match[2]
220
+ debug("#{diff_type} / #{diff_condition}")
221
+ if ap_command.end_with?("+")
222
+ # 追加判定チェック
223
+ if check_difficulty_new(roll_result.last_dice_list, diff_condition.sub("\+", ""), diff_type)
224
+ output_text += ", 追加判定成功![#{ap_command}]"
225
+ end
226
+ else
227
+ # 追加判定カウント
228
+ diff_result_array = check_difficulty(roll_result.last_dice_list, s_to_i(diff_condition, 6), diff_type)
229
+ output_text += ", 追加判定[#{ap_command}]:#{diff_result_array.size}"
230
+ unless diff_result_array.empty?
231
+ output_text += "[#{diff_result_array.sort.reverse.join(',')}]"
232
+ end
233
+ end
234
+ end
235
+ return output_text
103
236
  end
104
237
 
105
238
  # ダイス処理(2版用)
@@ -109,11 +242,16 @@ module BCDice
109
242
  output_text = ''
110
243
  total_success_num = 0
111
244
 
112
- difficulty = DIFFICULTY_SYMBOL_TO_INTEGER.fetch(match[1])
113
- appendix = match[3]
245
+ command = match[1]
246
+ appendix = match[2]
247
+ difficulty = 0
114
248
 
115
- match[2].split(",").each do |sub_command|
116
- dice_num = sub_command.to_i
249
+ command.split(",").each do |sub_command|
250
+ /^(UH|[KENHU])?(\d+)$/i.match(sub_command)
251
+ unless Regexp.last_match[1].nil?
252
+ difficulty = DIFFICULTY_SYMBOL_TO_INTEGER.fetch(Regexp.last_match[1])
253
+ end
254
+ dice_num = Regexp.last_match[2].to_i
117
255
 
118
256
  # D6バラバラロール
119
257
  roll_command = "#{dice_num}B6>=#{difficulty}"
@@ -127,24 +265,7 @@ module BCDice
127
265
  debug("---- appendix: [#{appendix}]")
128
266
  ap_command_array = appendix.split("\]\[")
129
267
  ap_command_array.each do |ap_command|
130
- debug("----- ap_command: #{ap_command}")
131
- case ap_command
132
- when RE_COUNT_SATZ_BATZ
133
- # サツバツ!カウント
134
- check_result = check_difficulty(roll_result.last_dice_list, s_to_i(Regexp.last_match[1], 6), ">=", "サツバツ!")
135
- output_text += ", #{check_result[0]}"
136
- success_num += check_result[1]
137
- when RE_COUNT_CRITICAL
138
- # クリティカル!カウント
139
- check_result = check_difficulty(roll_result.last_dice_list, s_to_i(Regexp.last_match[1], 6), ">=", "クリティカル!")
140
- output_text += ", #{check_result[0]}"
141
- success_num += check_result[1]
142
- when RE_COUNT_JUDGE
143
- # 追加判定カウント
144
- check_result = check_difficulty(roll_result.last_dice_list, Regexp.last_match[2].to_i, Regexp.last_match[1], "追加判定")
145
- output_text += ", #{check_result[0]}"
146
- success_num += check_result[1]
147
- end
268
+ output_text += proc_appendix(roll_result, ap_command)
148
269
  end
149
270
  end
150
271
  output_text += " \n"
@@ -266,11 +387,11 @@ module BCDice
266
387
  end
267
388
  end
268
389
 
269
- RE_COUNT_SATZ_BATZ = /S([1-6])?/i.freeze
270
- RE_COUNT_CRITICAL = /C([1-6])?/i.freeze
271
- RE_COUNT_JUDGE = /(=|!=|>=|>|<=|<)([1-6])/.freeze
390
+ RE_COUNT_SATZ_BATZ = %r{S([1-6]|[1-6]+(?:/[1-6]+)?\+)?$}i.freeze
391
+ RE_COUNT_CRITICAL = /C([1-6]|[1-6]+\+)?$/i.freeze
392
+ RE_COUNT_JUDGE = /(=|!=|>=|>|<=|<)([1-6]+\+|[1-6])/.freeze
272
393
 
273
- RE_JUDGE_DICEROLL = /^(UH|[KENHU])([\d,]+)(?:\[((?:(?:S([1-6])?|C([1-6])?|(=|!=|>=|>|<=|<)([1-6]))(?:\]\[)?)+)\])?$/i.freeze
394
+ RE_JUDGE_DICEROLL = %r{^((?:(?:UH|[KENHU])?\d+,?)+)(?:\[((?:(?:S([1-6]|[1-6]+(?:/[1-6]+)?\+)?|C([1-6]*\+?)?|(=|!=|>=|>|<=|<)([1-6]+\+?))(?:\]\[)?)+)\])?$}i.freeze
274
395
  RE_JUDGE_SATZ_BATZ = /^SB(?:@([1-6]))?$/i.freeze
275
396
  RE_JUDGE_WASSHOI = /^WS([1-9]|10|11|12)$/i.freeze
276
397
  RE_JUDGE_WASSHOI_ENTRY = /^WSE(?:@([1-6]))?$/i.freeze