bcdice 3.16.1 → 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 (149) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +111 -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/Dracurouge/ko_kr.yml +1284 -205
  15. data/i18n/Emoklore/ja_jp.yml +1 -0
  16. data/i18n/Emoklore/ko_kr.yml +1 -0
  17. data/i18n/FutariSousa/ja_jp.yml +70 -0
  18. data/i18n/FutariSousa/ko_kr.yml +157 -0
  19. data/i18n/HatsuneMiku/ja_jp.yml +579 -0
  20. data/i18n/HatsuneMiku/ko_kr.yml +579 -0
  21. data/i18n/Irisbane/ja_jp.yml +27 -0
  22. data/i18n/Irisbane/ko_kr.yml +27 -0
  23. data/i18n/JuinKansen/ja_jp.yml +168 -0
  24. data/i18n/JuinKansen/ko_kr.yml +168 -0
  25. data/i18n/KemonoNoMori/ja_jp.yml +229 -0
  26. data/i18n/KemonoNoMori/ko_kr.yml +229 -0
  27. data/i18n/KizunaBullet/ko_kr.yml +653 -0
  28. data/i18n/MagicPunk/ja_jp.yml +5 -0
  29. data/i18n/MagicPunk/ko_kr.yml +5 -0
  30. data/i18n/MorkBorg/ja_jp.yml +34 -0
  31. data/i18n/MorkBorg/ko_kr.yml +34 -0
  32. data/i18n/Nechronica/ko_kr.yml +43 -0
  33. data/i18n/NegikureNegimaki/ja_jp.yml +6 -0
  34. data/i18n/NegikureNegimaki/ko_kr.yml +6 -0
  35. data/i18n/Nuekagami/ja_jp.yml +219 -0
  36. data/i18n/Nuekagami/ko_kr.yml +219 -0
  37. data/i18n/Revulture/ja_jp.yml +8 -0
  38. data/i18n/Revulture/ko_kr.yml +8 -0
  39. data/i18n/SRS/ja_jp.yml +4 -0
  40. data/i18n/SRS/ko_kr.yml +4 -0
  41. data/i18n/ShinobiGami/ja_jp.yml +879 -0
  42. data/i18n/ShinobiGami/ko_kr.yml +876 -0
  43. data/i18n/StarryDolls/ja_jp.yml +456 -0
  44. data/i18n/StarryDolls/ko_kr.yml +456 -0
  45. data/i18n/StratoShout/ja_jp.yml +8 -8
  46. data/i18n/SwordWorld2_5/ja_jp.yml +48 -0
  47. data/i18n/Ventangle/ja_jp.yml +4 -0
  48. data/i18n/Ventangle/ko_kr.yml +4 -0
  49. data/i18n/YearZeroEngine/ja_jp.yml +12 -0
  50. data/i18n/YearZeroEngine/ko_kr.yml +12 -0
  51. data/i18n/ZombiLine/ja_jp.yml +27 -0
  52. data/i18n/ZombiLine/ko_kr.yml +27 -0
  53. data/i18n/ko_kr.yml +2 -0
  54. data/i18n/zh_hant.yml +2 -2
  55. data/lib/bcdice/dice_table/d66_left_range_table.rb +21 -0
  56. data/lib/bcdice/game_system/Aionia.rb +68 -19
  57. data/lib/bcdice/game_system/Airgetlamh.rb +64 -41
  58. data/lib/bcdice/game_system/Airgetlamh_Korean.rb +53 -0
  59. data/lib/bcdice/game_system/Alsetto.rb +63 -50
  60. data/lib/bcdice/game_system/Alsetto_Korean.rb +51 -0
  61. data/lib/bcdice/game_system/AnimaAnimus.rb +15 -32
  62. data/lib/bcdice/game_system/AnimaAnimus_Korean.rb +39 -0
  63. data/lib/bcdice/game_system/BlackJacket.rb +57 -113
  64. data/lib/bcdice/game_system/BlackJacket_Korean.rb +8 -206
  65. data/lib/bcdice/game_system/Bloodorium.rb +1 -1
  66. data/lib/bcdice/game_system/Bloodorium_Korean.rb +34 -0
  67. data/lib/bcdice/game_system/ChroniclesOfDarkness2e.rb +163 -0
  68. data/lib/bcdice/game_system/Cthulhu7th_Korean.rb +471 -300
  69. data/lib/bcdice/game_system/DeadlineHeroes_Korean.rb +273 -0
  70. data/lib/bcdice/game_system/Dracurouge_Korean.rb +25 -19
  71. data/lib/bcdice/game_system/DungeonsAndDragons5.rb +106 -73
  72. data/lib/bcdice/game_system/DungeonsAndDragons5_Korean.rb +53 -0
  73. data/lib/bcdice/game_system/DungeonsAndDragons_Korean.rb +61 -0
  74. data/lib/bcdice/game_system/Emoklore.rb +34 -9
  75. data/lib/bcdice/game_system/Emoklore_Korean.rb +10 -2
  76. data/lib/bcdice/game_system/FateCoreSystem.rb +10 -6
  77. data/lib/bcdice/game_system/FullMetalPanic_Korean.rb +28 -0
  78. data/lib/bcdice/game_system/FutariSousa.rb +37 -12
  79. data/lib/bcdice/game_system/FutariSousa_Korean.rb +25 -8
  80. data/lib/bcdice/game_system/GaiaCare.rb +40 -0
  81. data/lib/bcdice/game_system/GardenOrder.rb +2 -2
  82. data/lib/bcdice/game_system/GardenOrderReEdit.rb +849 -0
  83. data/lib/bcdice/game_system/GardenOrder_Korean.rb +839 -0
  84. data/lib/bcdice/game_system/HatsuneMiku.rb +51 -605
  85. data/lib/bcdice/game_system/HatsuneMiku_Korean.rb +56 -0
  86. data/lib/bcdice/game_system/HunterTheReckoning5th.rb +15 -11
  87. data/lib/bcdice/game_system/Irisbane.rb +17 -30
  88. data/lib/bcdice/game_system/Irisbane_Korean.rb +52 -0
  89. data/lib/bcdice/game_system/JuinKansen.rb +41 -208
  90. data/lib/bcdice/game_system/JuinKansen_Korean.rb +8 -213
  91. data/lib/bcdice/game_system/KemonoNoMori.rb +67 -276
  92. data/lib/bcdice/game_system/KemonoNoMori_Korean.rb +62 -0
  93. data/lib/bcdice/game_system/KinAriel.rb +117 -0
  94. data/lib/bcdice/game_system/KizunaBullet_Korean.rb +109 -0
  95. data/lib/bcdice/game_system/KutuluRevised.rb +94 -0
  96. data/lib/bcdice/game_system/LiverLabyrinth.rb +321 -0
  97. data/lib/bcdice/game_system/Lost.rb +89 -0
  98. data/lib/bcdice/game_system/MagicPunk.rb +85 -0
  99. data/lib/bcdice/game_system/MagicPunk_Korean.rb +39 -0
  100. data/lib/bcdice/game_system/MarvelHeroicRoleplaying.rb +144 -0
  101. data/lib/bcdice/game_system/MetallicGuardian_Korean.rb +28 -0
  102. data/lib/bcdice/game_system/MorkBorg.rb +170 -0
  103. data/lib/bcdice/game_system/MorkBorg_Korean.rb +49 -0
  104. data/lib/bcdice/game_system/NanimonaiMura.rb +112 -0
  105. data/lib/bcdice/game_system/Nechronica_Korean.rb +6 -6
  106. data/lib/bcdice/game_system/NegikureNegimaki.rb +140 -0
  107. data/lib/bcdice/game_system/NegikureNegimaki_Korean.rb +48 -0
  108. data/lib/bcdice/game_system/NeonUnderRealm.rb +122 -0
  109. data/lib/bcdice/game_system/NinjaSlayer2.rb +170 -49
  110. data/lib/bcdice/game_system/Nuekagami.rb +19 -261
  111. data/lib/bcdice/game_system/Nuekagami_Korean.rb +43 -0
  112. data/lib/bcdice/game_system/ParanoiaPerfect.rb +74 -0
  113. data/lib/bcdice/game_system/PastFutureParadox.rb +2245 -55
  114. data/lib/bcdice/game_system/PreciousDays.rb +170 -0
  115. data/lib/bcdice/game_system/Revulture.rb +8 -5
  116. data/lib/bcdice/game_system/Revulture_Korean.rb +7 -81
  117. data/lib/bcdice/game_system/Ryutama.rb +46 -46
  118. data/lib/bcdice/game_system/SRS.rb +4 -4
  119. data/lib/bcdice/game_system/SRS_Korean.rb +67 -0
  120. data/lib/bcdice/game_system/ShinobiGami.rb +154 -1047
  121. data/lib/bcdice/game_system/ShinobiGami_Korean.rb +102 -0
  122. data/lib/bcdice/game_system/StarryDolls.rb +70 -508
  123. data/lib/bcdice/game_system/StarryDolls_Korean.rb +80 -0
  124. data/lib/bcdice/game_system/StratoShout.rb +1 -1
  125. data/lib/bcdice/game_system/SwordWorld.rb +28 -2
  126. data/lib/bcdice/game_system/SwordWorld2_0.rb +1 -1
  127. data/lib/bcdice/game_system/SwordWorld2_5.rb +67 -3
  128. data/lib/bcdice/game_system/TacticalExorcist.rb +222 -0
  129. data/lib/bcdice/game_system/TenkaRyouran_Korean.rb +30 -0
  130. data/lib/bcdice/game_system/VampireTheMasquerade5th.rb +38 -33
  131. data/lib/bcdice/game_system/Ventangle.rb +8 -7
  132. data/lib/bcdice/game_system/Ventangle_Korean.rb +6 -95
  133. data/lib/bcdice/game_system/Warhammer4.rb +202 -6
  134. data/lib/bcdice/game_system/WerewolfTheApocalypse5th.rb +20 -15
  135. data/lib/bcdice/game_system/WorldEndScrapyard.rb +333 -0
  136. data/lib/bcdice/game_system/WorldsEndFrontline_Korean.rb +26 -0
  137. data/lib/bcdice/game_system/YearZeroEngine.rb +7 -7
  138. data/lib/bcdice/game_system/YearZeroEngine_Korean.rb +46 -0
  139. data/lib/bcdice/game_system/ZombiLine.rb +29 -36
  140. data/lib/bcdice/game_system/ZombiLine_Korean.rb +37 -0
  141. data/lib/bcdice/game_system/cthulhu7th_Korean/full_auto.rb +294 -0
  142. data/lib/bcdice/game_system/cthulhu7th_Korean/rollable.rb +43 -0
  143. data/lib/bcdice/game_system/sword_world/rating_options.rb +9 -0
  144. data/lib/bcdice/game_system/sword_world/rating_parsed.rb +19 -0
  145. data/lib/bcdice/game_system/sword_world/rating_parser.rb +229 -149
  146. data/lib/bcdice/game_system/sword_world/transcendent_test.rb +1 -0
  147. data/lib/bcdice/game_system.rb +42 -0
  148. data/lib/bcdice/version.rb +1 -1
  149. metadata +87 -2
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bcdice/game_system/MetallicGuardian'
4
+
5
+ module BCDice
6
+ module GameSystem
7
+ class MetallicGuardian_Korean < MetallicGuardian
8
+ # ゲームシステムの識別子
9
+ ID = 'MetallicGuardian:Korean'
10
+
11
+ # ゲームシステム名
12
+ NAME = '메탈릭 가디언 RPG'
13
+
14
+ # ゲームシステム名の読みがな
15
+ SORT_KEY = '国際化:Korean:메탈릭 가디언 RPG'
16
+
17
+ set_aliases_for_srs_roll('MG')
18
+
19
+ register_prefix_from_super_class()
20
+
21
+ def initialize(command)
22
+ super(command)
23
+
24
+ @locale = :ko_kr
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,170 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bcdice/dice_table/table'
4
+
5
+ module BCDice
6
+ module GameSystem
7
+ class MorkBorg < Base
8
+ # ゲームシステムの識別子
9
+ ID = 'MorkBorg'
10
+
11
+ # ゲームシステム名
12
+ NAME = 'MÖRK BORG'
13
+
14
+ # ゲームシステム名の読みがな
15
+ SORT_KEY = 'むるくほりい'
16
+
17
+ # ダイスボットの使い方
18
+ HELP_MESSAGE = <<~INFO_MESSAGETEXT
19
+ ■判定 sDRt s: 能力値(省略時:0) t:目標値
20
+
21
+ 例)+3DR12: 能力値+3、DR12で1d20を振って、その結果を表示(クリティカル・ファンブルも表示)
22
+
23
+ ■イニシアティヴ sINS s: 能力値(省略時:0. 個別のイニシアティブを使う場合)
24
+
25
+ 例)INS: 1d6を振って、イニシアティヴの結果を表示(PC先行を成功として表示)
26
+
27
+ ■モラル sMORt s: 能力値(省略時:0) t:相手クリーチャーのモラル値
28
+
29
+ 例)MOR8: 2d6を振って、モラル判定の結果を表示(モラル崩壊を成功として表示)
30
+
31
+
32
+ ■各種表
33
+
34
+ ・遭遇反応表 Reaction (ERT)
35
+ ・破損 Broken (BRO)
36
+
37
+ INFO_MESSAGETEXT
38
+
39
+ def initialize(command)
40
+ super(command)
41
+
42
+ @sort_add_dice = true
43
+ @d66_sort_type = D66SortType::NO_SORT
44
+ end
45
+
46
+ def eval_game_system_specific_command(command)
47
+ resolute_action(command) || resolute_initiative(command) || resolute_morale(command) || roll_tables(command, self.class::TABLES)
48
+ end
49
+
50
+ private
51
+
52
+ def result_dr(total, dice_total, target)
53
+ if dice_total <= 1
54
+ Result.fumble(translate('MorkBorg.fumble'))
55
+ elsif dice_total >= 20
56
+ Result.critical(translate('MorkBorg.critical'))
57
+ elsif total >= target
58
+ Result.success(translate('MorkBorg.success'))
59
+ else
60
+ Result.failure(translate('MorkBorg.failure'))
61
+ end
62
+ end
63
+
64
+ # DR判定
65
+ # @param [String] command
66
+ # @return [Result]
67
+ def resolute_action(command)
68
+ m = /^([+-]?\d+)?DR(\d+)$/.match(command)
69
+ return nil unless m
70
+
71
+ num_status = m[1].to_i
72
+ num_target = m[2].to_i
73
+
74
+ total = @randomizer.roll_once(20)
75
+ total_status = total.to_s + with_symbol(num_status)
76
+ result = result_dr(total + num_status, total, num_target)
77
+
78
+ sequence = [
79
+ "(#{command})",
80
+ total_status,
81
+ total + num_status,
82
+ result.text,
83
+ ]
84
+
85
+ result.text = sequence.join(" > ")
86
+ return result
87
+ end
88
+
89
+ def with_symbol(number)
90
+ if number == 0
91
+ return "+0"
92
+ elsif number > 0
93
+ return "+#{number}"
94
+ else
95
+ return number.to_s
96
+ end
97
+ end
98
+
99
+ # イニシアティヴ判定
100
+ # @param [String] command
101
+ # @return [Result]
102
+ def resolute_initiative(command)
103
+ m = /^([+-]?\d+)?INS$/.match(command)
104
+ return nil unless m
105
+
106
+ num_status = m[1].to_i
107
+
108
+ die = @randomizer.roll_once(6)
109
+ total = die + num_status
110
+ result =
111
+ if total >= 4
112
+ Result.success(translate('MorkBorg.pcs_go_first'))
113
+ else
114
+ Result.failure(translate('MorkBorg.enemies_go_first'))
115
+ end
116
+
117
+ result.text = "(#{command}) > #{die}#{with_symbol(num_status)} > #{total} > #{result.text}"
118
+ return result
119
+ end
120
+
121
+ # モラル判定
122
+ # @param [String] command
123
+ # @return [Result]
124
+ def resolute_morale(command)
125
+ m = /^([+-]?\d+)?MOR(\d+)$/.match(command)
126
+ return nil unless m
127
+
128
+ num_status = m[1].to_i
129
+ num_target = m[2].to_i
130
+
131
+ dice_list = @randomizer.roll_barabara(2, 6)
132
+ dice_total = dice_list.sum()
133
+ total = dice_total + num_status
134
+
135
+ die = ""
136
+ result =
137
+ if total <= num_target
138
+ Result.failure(translate('MorkBorg.maintain'))
139
+ else
140
+ die = @randomizer.roll_once(6)
141
+ if die >= 4
142
+ Result.success(translate('MorkBorg.surrender'))
143
+ else
144
+ Result.success(translate('MorkBorg.flee'))
145
+ end
146
+ end
147
+ result.text = "(#{command}) > #{dice_total}#{with_symbol(num_status)} > #{total} > #{die}#{result.text}"
148
+
149
+ return result
150
+ end
151
+
152
+ # 各種表
153
+
154
+ class << self
155
+ private
156
+
157
+ def translate_tables(locale)
158
+ {
159
+ 'ERT' => DiceTable::Table.from_i18n('MorkBorg.ERT', locale),
160
+ 'BRO' => DiceTable::Table.from_i18n('MorkBorg.BRO', locale),
161
+ }
162
+ end
163
+ end
164
+
165
+ TABLES = translate_tables(:ja_jp).freeze
166
+
167
+ register_prefix('([+-]?\d+)?DR[\d]+', '([+-]?\d+)?INS', '([+-]?\d+)?MOR', TABLES.keys)
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bcdice/game_system/MorkBorg'
4
+
5
+ module BCDice
6
+ module GameSystem
7
+ class MorkBorg_Korean < MorkBorg
8
+ # ゲームシステムの識別子
9
+ ID = 'MorkBorg:Korean'
10
+
11
+ # ゲームシステム名
12
+ NAME = '모크 보그(MÖRK BORG)'
13
+
14
+ # ゲームシステム名の読みがな
15
+ SORT_KEY = '国際化:Korean:모크 보그(MÖRK BORG)'
16
+
17
+ # ダイスボットの使い方
18
+ HELP_MESSAGE = <<~INFO_MESSAGETEXT
19
+ ■판정 sDRt s: 능력치(생략 시:0) t:목표값
20
+
21
+ 예)+3DR12: 능력치+3, DR12로 1d20을 굴려서 결과 표시(크리티컬·펌블도 표시)
22
+
23
+ ■이니셔티브 sINS s: 능력치(생략 시:0. 개별 이니셔티브를 사용하는 경우)
24
+
25
+ 예)INS: 1d6을 굴려서 이니셔티브 결과 표시(PC 선공을 성공으로 표시)
26
+
27
+ ■모럴 sMORt s: 능력치(생략 시:0) t:상대 크리처의 모럴 값
28
+
29
+ 예)MOR8: 2d6을 굴려서 모럴 판정 결과 표시(모럴 붕괴를 성공으로 표시)
30
+
31
+
32
+ ■각종 표
33
+
34
+ ・조우 반응표 Reaction (ERT)
35
+ ・파손(빈사표) Broken (BRO)
36
+
37
+ INFO_MESSAGETEXT
38
+
39
+ def initialize(command)
40
+ super(command)
41
+ @locale = :ko_kr
42
+ end
43
+
44
+ TABLES = translate_tables(:ko_kr).freeze
45
+
46
+ register_prefix_from_super_class()
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class NanimonaiMura < Base
6
+ # ゲームシステムの識別子
7
+ ID = "NanimonaiMura"
8
+
9
+ # ゲームシステム名
10
+ NAME = "なにもない村"
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = "なにもないむら"
14
+
15
+ # ダイスボットの使い方
16
+ HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
17
+ ・行為判定 xNMy
18
+  x個のD10を振り、2つの出目から達成値を作成して判定します。
19
+  達成値は成功度が最も高くなる組み合わせを自動選択し、同値なら低い値を優先します。
20
+  x: ダイス数(1以上)
21
+  y: 判定値(0以上)
22
+  例)4NM55 6NM199 2NM35
23
+ INFO_MESSAGE_TEXT
24
+
25
+ register_prefix('\d+NM\d+')
26
+
27
+ ResultData = Struct.new(:score, :success, :critical, :result_text, :success_level)
28
+
29
+ STAGE_NAMES = ['ノーマル', 'エピック', 'レジェンダリ', 'ミシック'].freeze
30
+ BASE_SUCCESS_LEVELS = [1, 11, 21, 31].freeze
31
+
32
+ def eval_game_system_specific_command(command)
33
+ roll_action(command)
34
+ end
35
+
36
+ private
37
+
38
+ def roll_action(command)
39
+ m = /\A(\d+)NM(\d+)\z/.match(command)
40
+ return nil unless m
41
+
42
+ dice_count = m[1].to_i
43
+ target = m[2].to_i
44
+ return nil if dice_count < 1
45
+
46
+ dice_list = @randomizer.roll_barabara(dice_count, 10).map { |value| normalize_d10(value) }
47
+ result = select_best_result(dice_list, target)
48
+
49
+ Result.new.tap do |r|
50
+ r.text = "#{command} (#{dice_count}D10) > [#{dice_list.join(',')}] > #{result.score} > #{result.result_text} > 成功度#{result.success_level}"
51
+ r.condition = result.success
52
+ r.critical = result.critical
53
+ end
54
+ end
55
+
56
+ def normalize_d10(value)
57
+ value == 10 ? 0 : value
58
+ end
59
+
60
+ def select_best_result(dice_list, target)
61
+ candidates =
62
+ if dice_list.size == 1
63
+ [build_result(dice_list.first * 10, target)]
64
+ else
65
+ [].tap do |results|
66
+ dice_list.each_index do |i|
67
+ dice_list.each_index do |j|
68
+ next if i == j
69
+
70
+ results << build_result(dice_list[i] * 10 + dice_list[j], target)
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ best_result = candidates.first
77
+
78
+ candidates.drop(1).each do |candidate|
79
+ next if candidate.success_level < best_result.success_level
80
+ next if candidate.success_level == best_result.success_level && candidate.score > best_result.score
81
+
82
+ best_result = candidate
83
+ end
84
+
85
+ best_result
86
+ end
87
+
88
+ def build_result(score, target)
89
+ if score > target
90
+ return ResultData.new(score, false, false, "失敗", 0)
91
+ end
92
+
93
+ diff = target - score
94
+ stage_index = [diff.div(100), STAGE_NAMES.size - 1].min
95
+ critical_bonus = zoro_bonus(score)
96
+ critical = !critical_bonus.nil?
97
+ success_level = BASE_SUCCESS_LEVELS[stage_index] + (critical_bonus || 0)
98
+ result_text = "#{STAGE_NAMES[stage_index]}#{critical ? '大成功' : '成功'}"
99
+
100
+ ResultData.new(score, true, critical, result_text, success_level)
101
+ end
102
+
103
+ def zoro_bonus(score)
104
+ tens = score.div(10)
105
+ ones = score % 10
106
+ return nil unless tens == ones
107
+
108
+ ones
109
+ end
110
+ end
111
+ end
112
+ end
@@ -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