bcdice 3.6.0 → 3.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +56 -0
  3. data/i18n/Arianrhod/ja_jp.yml +3 -0
  4. data/i18n/Emoklore/ja_jp.yml +7 -0
  5. data/i18n/FutariSousa/ja_jp.yml +431 -0
  6. data/i18n/LogHorizon/ja_jp.yml +1 -1
  7. data/i18n/SwordWorld/ja_jp.yml +1 -0
  8. data/i18n/SwordWorld/zh_hans.yml +7 -0
  9. data/i18n/SwordWorld2_0/zh_hans.yml +37 -0
  10. data/i18n/SwordWorld2_5/ja_jp.yml +1 -1
  11. data/i18n/SwordWorld2_5/zh_hans.yml +57 -0
  12. data/lib/bcdice/arithmetic/parser.rb +1 -1
  13. data/lib/bcdice/command/parser.rb +1 -1
  14. data/lib/bcdice/common_command/add_dice/parser.rb +106 -74
  15. data/lib/bcdice/common_command/add_dice.rb +1 -1
  16. data/lib/bcdice/common_command/barabara_dice/parser.rb +1 -1
  17. data/lib/bcdice/common_command/calc/parser.rb +1 -1
  18. data/lib/bcdice/common_command/d66_dice.rb +1 -1
  19. data/lib/bcdice/common_command/reroll_dice/parser.rb +1 -1
  20. data/lib/bcdice/common_command/tally_dice/parser.rb +1 -1
  21. data/lib/bcdice/common_command/upper_dice/parser.rb +1 -1
  22. data/lib/bcdice/game_system/AngelGear.rb +1 -1
  23. data/lib/bcdice/game_system/AnimaAnimus.rb +1 -1
  24. data/lib/bcdice/game_system/Arianrhod.rb +4 -4
  25. data/lib/bcdice/game_system/AssaultEngine.rb +3 -3
  26. data/lib/bcdice/game_system/Ayabito.rb +170 -4
  27. data/lib/bcdice/game_system/BeastBindTrinity.rb +1 -1
  28. data/lib/bcdice/game_system/BeginningIdol.rb +4 -2
  29. data/lib/bcdice/game_system/BeginningIdol2022.rb +184 -0
  30. data/lib/bcdice/game_system/BladeOfArcana.rb +3 -3
  31. data/lib/bcdice/game_system/Bloodorium.rb +68 -0
  32. data/lib/bcdice/game_system/ConvictorDrive.rb +117 -0
  33. data/lib/bcdice/game_system/Cthulhu7th_ChineseTraditional.rb +1 -1
  34. data/lib/bcdice/game_system/Cthulhu7th_Korean.rb +1 -1
  35. data/lib/bcdice/game_system/CyberpunkRed.rb +2 -6
  36. data/lib/bcdice/game_system/DeadlineHeroes.rb +1 -1
  37. data/lib/bcdice/game_system/DungeonsAndDragons5.rb +196 -0
  38. data/lib/bcdice/game_system/EmbryoMachine.rb +4 -4
  39. data/lib/bcdice/game_system/Emoklore.rb +8 -8
  40. data/lib/bcdice/game_system/FutariSousa.rb +31 -5
  41. data/lib/bcdice/game_system/GURPS.rb +1 -1
  42. data/lib/bcdice/game_system/GehennaAn.rb +2 -2
  43. data/lib/bcdice/game_system/GhostLive.rb +144 -0
  44. data/lib/bcdice/game_system/GoblinSlayer.rb +30 -8
  45. data/lib/bcdice/game_system/HunterTheReckoning5th.rb +152 -0
  46. data/lib/bcdice/game_system/IfIfIf.rb +648 -0
  47. data/lib/bcdice/game_system/Kutulu.rb +95 -0
  48. data/lib/bcdice/game_system/LostRoyal.rb +1 -1
  49. data/lib/bcdice/game_system/NobunagasBlackCastle.rb +237 -0
  50. data/lib/bcdice/game_system/OracleEngine.rb +1 -1
  51. data/lib/bcdice/game_system/Raisondetre.rb +1 -1
  52. data/lib/bcdice/game_system/RokumonSekai2.rb +1 -1
  53. data/lib/bcdice/game_system/SajinsenkiAGuS.rb +154 -0
  54. data/lib/bcdice/game_system/Sengensyou.rb +59 -0
  55. data/lib/bcdice/game_system/ShinkuuGakuen.rb +1 -1
  56. data/lib/bcdice/game_system/ShinobiGami.rb +14 -1
  57. data/lib/bcdice/game_system/SkynautsBouken.rb +93 -2
  58. data/lib/bcdice/game_system/StellarLife.rb +1 -1
  59. data/lib/bcdice/game_system/StrangerOfSwordCity.rb +1 -1
  60. data/lib/bcdice/game_system/SwordWorld.rb +2 -2
  61. data/lib/bcdice/game_system/SwordWorld2_0_SimplifiedChinese.rb +84 -0
  62. data/lib/bcdice/game_system/SwordWorld2_5_SimplifiedChinese.rb +95 -0
  63. data/lib/bcdice/game_system/SwordWorld_SimplifiedChinese.rb +29 -0
  64. data/lib/bcdice/game_system/TherapieSein.rb +2 -2
  65. data/lib/bcdice/game_system/Torg.rb +1 -1
  66. data/lib/bcdice/game_system/TorgEternity.rb +54 -18
  67. data/lib/bcdice/game_system/VampireTheMasquerade5th.rb +26 -12
  68. data/lib/bcdice/game_system/VisionConnect.rb +135 -0
  69. data/lib/bcdice/game_system/Warhammer4.rb +4 -0
  70. data/lib/bcdice/game_system/WorldOfDarkness.rb +54 -50
  71. data/lib/bcdice/game_system/cthulhu7th/full_auto.rb +1 -1
  72. data/lib/bcdice/game_system/filled_with/tresure_tables.rb +1 -1
  73. data/lib/bcdice/game_system/satasupe/tables.rb +1 -1
  74. data/lib/bcdice/game_system/sword_world/rating_parser.rb +1 -1
  75. data/lib/bcdice/game_system.rb +15 -0
  76. data/lib/bcdice/version.rb +1 -1
  77. metadata +26 -6
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class Kutulu < Base
6
+ # ゲームシステムの識別子
7
+ ID = 'Kutulu'
8
+
9
+ # ゲームシステム名
10
+ NAME = 'Kutulu'
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = 'くとうるう'
14
+
15
+ # ダイスボットの使い方
16
+ HELP_MESSAGE = <<~INFO_MESSAGETEXT
17
+ ■判定 nKU n: ダイス数
18
+
19
+ 例)3KU: ダイスを3個振って、その結果を表示(ギリギリでの成功も表示)
20
+
21
+ ■対抗判定 nKR n: ダイス数
22
+
23
+ 例)2KR: ダイスを2個振って、その結果を表示。対抗判定用の3桁の数字も出力。(大きい方が勝利)
24
+ INFO_MESSAGETEXT
25
+
26
+ register_prefix('\dK[UR]')
27
+
28
+ def initialize(command)
29
+ super(command)
30
+
31
+ @sort_barabara_dice = true # バラバラロール(Bコマンド)でソート有
32
+ end
33
+
34
+ def eval_game_system_specific_command(command)
35
+ resolute_action(command) || resolute_competition(command)
36
+ end
37
+
38
+ private
39
+
40
+ # アクティヴ能力の判定
41
+ # @param [String] command
42
+ # @return [Result]
43
+ def resolute_action(command)
44
+ m = /(\d)KU/.match(command)
45
+ return nil unless m
46
+
47
+ num_dices = m[1].to_i
48
+
49
+ dices = @randomizer.roll_barabara(num_dices, 6).sort
50
+ dice_text = dices.join(",")
51
+
52
+ output = "(#{num_dices}KU) > #{dice_text}"
53
+
54
+ success_num = dices.count { |val| val >= 4 }
55
+ counts_4 = dices.count(4)
56
+ if success_num > 0
57
+ output += " > 成功数#{success_num}"
58
+ if success_num == 1 && counts_4 == 1
59
+ output += " > *ギリギリでの成功"
60
+ end
61
+ return Result.success(output)
62
+ else
63
+ output += " > 失敗"
64
+ return Result.failure(output)
65
+ end
66
+ end
67
+
68
+ # 対抗判定用出力
69
+ # @param [String] command
70
+ # @return [Result]
71
+ def resolute_competition(command)
72
+ m = /(\d)KR/.match(command)
73
+ return nil unless m
74
+
75
+ num_dices = m[1].to_i
76
+
77
+ dices = @randomizer.roll_barabara(num_dices, 6).sort
78
+ dice_text = dices.join(",")
79
+
80
+ counts_6 = dices.count(6)
81
+ counts_5 = dices.count(5)
82
+ success_num = dices.count { |val| val >= 4 }
83
+ com_text = format("(%d%d%d)", success_num, counts_6, counts_5)
84
+
85
+ output = "(#{num_dices}KR) > #{dice_text} > #{com_text}"
86
+
87
+ if success_num > 0
88
+ return Result.success(output)
89
+ else
90
+ return Result.failure(output)
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -64,7 +64,7 @@ module BCDice
64
64
  def check_lostroyal(checking_table)
65
65
  keys = []
66
66
 
67
- (0...3).each do |_i|
67
+ 3.times do |_i|
68
68
  key = @randomizer.roll_once(6)
69
69
  keys << key
70
70
  end
@@ -0,0 +1,237 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bcdice/dice_table/table'
4
+
5
+ module BCDice
6
+ module GameSystem
7
+ class NobunagasBlackCastle < Base
8
+ # ゲームシステムの識別子
9
+ ID = 'NobunagasBlackCastle'
10
+
11
+ # ゲームシステム名
12
+ NAME = '信長の黒い城'
13
+
14
+ # ゲームシステム名の読みがな
15
+ SORT_KEY = 'のふなかのくろいしろ'
16
+
17
+ # ダイスボットの使い方
18
+ HELP_MESSAGE = <<~INFO_MESSAGETEXT
19
+ ■判定 sDRt s: 能力値 t:目標値
20
+
21
+ 例)+3DR12: 能力値+3、DR12で1d20を振って、その結果を表示(クリティカル・ファンブルも表示)
22
+
23
+ ■イニシアティヴ INS
24
+
25
+ 例)INS: 1d6を振って、イニシアティヴの結果を表示(PC先行を成功として表示)
26
+
27
+ ■NPC能力値作成 NPCST
28
+
29
+ 例)NPCST: 3d6を4回振って、各能力値とHPを表示
30
+
31
+
32
+ ■各種表
33
+
34
+ ・遭遇反応表(ERT)
35
+ ・武器表(SWT)/その他の奇妙な武器表(OSWT)
36
+ ・鎧表(ART)
37
+
38
+ INFO_MESSAGETEXT
39
+
40
+ def initialize(command)
41
+ super(command)
42
+
43
+ @sort_add_dice = true
44
+ @d66_sort_type = D66SortType::NO_SORT
45
+ end
46
+
47
+ def eval_game_system_specific_command(command)
48
+ resolute_action(command) || resolute_initiative(command) || roll_tables(command, TABLES) || make_npc_status(command)
49
+ end
50
+
51
+ private
52
+
53
+ def result_dr(total, dice_total, target)
54
+ if dice_total <= 1
55
+ Result.fumble("ファンブル")
56
+ elsif dice_total >= 20
57
+ Result.critical("クリティカル")
58
+ elsif total >= target
59
+ Result.success("成功")
60
+ else
61
+ Result.failure("失敗")
62
+ end
63
+ end
64
+
65
+ # DR判定
66
+ # @param [String] command
67
+ # @return [Result]
68
+ def resolute_action(command)
69
+ m = /^([+-]?\d*)DR(\d+)$/.match(command)
70
+ return nil unless m
71
+
72
+ num_status = m[1].to_i
73
+ num_target = m[2].to_i
74
+
75
+ total = @randomizer.roll_once(20)
76
+ total_status = total.to_s + with_symbol(num_status)
77
+ result = result_dr(total + num_status, total, num_target)
78
+
79
+ sequence = [
80
+ "(#{command})",
81
+ total_status,
82
+ total + num_status,
83
+ result.text,
84
+ ]
85
+
86
+ result.text = sequence.join(" > ")
87
+ return result
88
+ end
89
+
90
+ def with_symbol(number)
91
+ if number == 0
92
+ return "+0"
93
+ elsif number > 0
94
+ return "+#{number}"
95
+ else
96
+ return number.to_s
97
+ end
98
+ end
99
+
100
+ # イニシアティヴ判定
101
+ # @param [String] command
102
+ # @return [Result]
103
+ def resolute_initiative(command)
104
+ unless command == "INS"
105
+ return nil
106
+ end
107
+
108
+ total = @randomizer.roll_once(6)
109
+ result =
110
+ if total >= 4
111
+ Result.success("PC先行")
112
+ else
113
+ Result.failure("敵先行")
114
+ end
115
+
116
+ result.text = "(#{command}) > #{total} > #{result.text}"
117
+ return result
118
+ end
119
+
120
+ # NPC能力値作成
121
+ # @param [String] command
122
+ # @return [String]
123
+ def make_npc_status(command)
124
+ unless command == "NPCST"
125
+ return nil
126
+ end
127
+
128
+ pre = @randomizer.roll_sum(3, 6)
129
+ agi = @randomizer.roll_sum(3, 6)
130
+ str = @randomizer.roll_sum(3, 6)
131
+ tgh = @randomizer.roll_sum(3, 6)
132
+ hpd = @randomizer.roll_once(8)
133
+ hp = hpd + calc_status(tgh)
134
+ hp = 1 if hp < 1
135
+
136
+ text = [
137
+ "心#{with_symbol(calc_status(pre))}(#{pre})",
138
+ "技#{with_symbol(calc_status(agi))}(#{agi})",
139
+ "体#{with_symbol(calc_status(str))}(#{str})",
140
+ "耐久#{with_symbol(calc_status(tgh))}(#{tgh})",
141
+ "HP#{hp}(#{hpd})",
142
+ ].join(", ")
143
+
144
+ return "(#{command}) > #{text}"
145
+ end
146
+
147
+ def calc_status(st)
148
+ if st <= 4
149
+ return -3
150
+ elsif st <= 6
151
+ return -2
152
+ elsif st <= 8
153
+ return -1
154
+ elsif st <= 12
155
+ return 0
156
+ elsif st <= 14
157
+ return 1
158
+ elsif st <= 16
159
+ return 2
160
+ elsif st <= 20
161
+ return 3
162
+ end
163
+ end
164
+
165
+ # 各種表
166
+
167
+ TABLES = {
168
+ 'OSWT' => DiceTable::Table.new(
169
+ 'その他の奇妙な武器表',
170
+ '1D10',
171
+ [
172
+ '六尺棒(D4)',
173
+ '手槍(D4)',
174
+ '弓矢(D6)',
175
+ '鉄扇(D4)',
176
+ '大鉞(D8)',
177
+ '吹き矢(D2)+感染',
178
+ '鞭(D3)',
179
+ '熊手(D4)',
180
+ '石つぶて(D3)',
181
+ '丸太(D4)',
182
+ ]
183
+ ),
184
+ 'SWT' => DiceTable::Table.new(
185
+ '武器表',
186
+ '1D12',
187
+ [
188
+ '尖らせた骨の杭(D3)',
189
+ '竹槍(D4)',
190
+ '百姓から奪った鍬(D4)',
191
+ '脇差し(D4)',
192
+ '手裏剣 D6本(D4)',
193
+ '刀(D6)',
194
+ '鎖鎌(D6)',
195
+ '太刀(D8)',
196
+ '種子島銃(2D6) 弾丸(心+5)発',
197
+ '大槍(D8)',
198
+ '爆裂弾(D4) 心+3発',
199
+ '斬馬刀(D10)',
200
+ ]
201
+ ),
202
+ 'ART' => DiceTable::Table.new(
203
+ '鎧表',
204
+ '1D6',
205
+ [
206
+ '防具は、何もない',
207
+ '防具は、何もない',
208
+ '部分鎧(腹巻き) -D2ダメージ',
209
+ 'お貸し具足 -D3ダメージ',
210
+ '武者鎧 -D4ダメージ',
211
+ '大鎧 -D6ダメージ',
212
+ ]
213
+ ),
214
+ # 無理に高度なことをしなくても、表は展開して実装しても動く
215
+ 'ERT' => DiceTable::Table.new(
216
+ '遭遇反応表',
217
+ '2D6',
218
+ [
219
+ 'お前ら、殺す!',
220
+ 'お前ら、殺す!',
221
+ '憎悪の視線で睨んでくる。すきを見せれば、攻撃してくる。',
222
+ '憎悪の視線で睨んでくる。すきを見せれば、攻撃してくる。',
223
+ '憎悪の視線で睨んでくる。すきを見せれば、攻撃してくる。',
224
+ '警戒はしているが、特に、戦闘は望んでいない。怒らせなければ、自分たちの目的に沿って動く。',
225
+ '警戒はしているが、特に、戦闘は望んでいない。怒らせなければ、自分たちの目的に沿って動く。',
226
+ '中立。何かを与えたり、取引の材料を提示したりできれば、交渉できそうだ。',
227
+ '中立。何かを与えたり、取引の材料を提示したりできれば、交渉できそうだ。',
228
+ '好意的に会話できそうだ。向こうも取引したがっている。',
229
+ '好意的に会話できそうだ。向こうも取引したがっている。',
230
+ ]
231
+ ),
232
+ }.freeze
233
+
234
+ register_prefix('[+-]?\d*DR[\d]+', 'INS', 'NPCST', TABLES.keys)
235
+ end
236
+ end
237
+ end
@@ -46,7 +46,7 @@ MESSAGETEXT
46
46
  case command
47
47
  when /\d+CL.*/i
48
48
  clutch_roll(command)
49
- when /\d+D6.*\$[+\-]?\d.*/
49
+ when /\d+D6.*\$[+-]?\d.*/
50
50
  damage_roll(command)
51
51
  when /\d+R6/
52
52
  r_roll(command)
@@ -52,7 +52,7 @@ module BCDice
52
52
 
53
53
  return checkRoll(diceCount, choiceCount, target)
54
54
 
55
- elsif command =~ /(-)?(\d+)?DD([1-9])?([+\-]\d+)?$/i
55
+ elsif command =~ /(-)?(\d+)?DD([1-9])?([+-]\d+)?$/i
56
56
  diceCount = (Regexp.last_match(2) || 1).to_i
57
57
  diceCount *= -1 unless Regexp.last_match(1).nil?
58
58
  armor = (Regexp.last_match(3) || 0).to_i
@@ -31,7 +31,7 @@ module BCDice
31
31
  end
32
32
 
33
33
  def replace_text(string)
34
- string = string.gsub(/(\d+)RS([+\-][+\-\d]+)<=(\d+)/i) { "3R6#{Regexp.last_match(2)}<=#{Regexp.last_match(3)}[#{Regexp.last_match(1)}]" }
34
+ string = string.gsub(/(\d+)RS([+-][+\-\d]+)<=(\d+)/i) { "3R6#{Regexp.last_match(2)}<=#{Regexp.last_match(3)}[#{Regexp.last_match(1)}]" }
35
35
  string = string.gsub(/(\d+)RS<=(\d+)/i) { "3R6<=#{Regexp.last_match(2)}[#{Regexp.last_match(1)}]" }
36
36
 
37
37
  return string
@@ -0,0 +1,154 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class SajinsenkiAGuS < Base
6
+ # ゲームシステムの識別子
7
+ ID = 'SajinsenkiAGuS'
8
+
9
+ # ゲームシステム名
10
+ NAME = '砂塵戦機アーガス'
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = 'さしんせんきああかす'
14
+
15
+ # ダイスボットの使い方
16
+ HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
17
+ ・一般判定Lv(チャンス出目0→判定0) nAG+x
18
+    nは習得レベル、Lv0の場合nの省略可能。xは判定値修正(数式による修正可)、省略した場合はレベル修正0
19
+    例)AG:習得レベル0の一般技能、1AG+1:習得レベル1・判定値修正+1の技能、AG+2-1:習得レベル0・判定値修正2-1の技能、(1-1)AG:習得レベル1・レベル修正-1の技能
20
+
21
+ ・適正距離での命中判定(チャンス出目0→判定0、HR算出)OM+y@z
22
+    yは命中補正値(数式可)、zはクリティカル値。クリティカル値省略時は0
23
+    HRの算出時には、HRが大きくなる場合に出目0を10に読み替えます。
24
+    例)OM+18-6@2:命中補正値+18-6でクリティカル値2、適正距離の判定
25
+
26
+ ・非適正距離での命中判定(チャンス出目0→判定0、HR算出)NM+y@z
27
+    yは命中補正値(数式可)、zはクリティカル値。クリティカル値省略時は0
28
+    HRの算出時には、HRが大きくなる場合に出目0を10に読み替えます。
29
+    例)NM+4-3:命中補正値+4-3で非適正距離の判定
30
+
31
+ ・クリティカル表 CR
32
+
33
+ ※通常の1D10などの10面ダイスにおいて出目10の読み替えはしません。コマンドのみです。
34
+
35
+ INFO_MESSAGE_TEXT
36
+ register_prefix('-?\d*AG', 'OM', 'NM', 'CR')
37
+
38
+ def eval_game_system_specific_command(command)
39
+ roll_ippan(command) || roll_hit_check(command) || roll_tables(command, TABLES)
40
+ end
41
+
42
+ private
43
+
44
+ def roll_ippan(command)
45
+ m = /^(-?\d+)?AG((?:[-+]\d+)*)$/.match(command)
46
+ return nil unless m
47
+
48
+ level = m[1].to_i
49
+ x = Arithmetic.eval(m[2], @round_type) || 0
50
+ target = level <= 0 ? 7 + x : 10 + level + x
51
+
52
+ dice_list = @randomizer.roll_barabara(2, 10).map { |d| d == 10 ? 0 : d }
53
+ total = dice_list.sum
54
+
55
+ return Result.new.tap do |result|
56
+ result.condition = total <= target
57
+
58
+ sequence = [
59
+ "(2D10<=#{target})",
60
+ "#{total}[#{dice_list.join(',')}]",
61
+ ("チャンス" if dice_list.include?(0)),
62
+ result.success? ? "成功" : "失敗"
63
+ ].compact
64
+
65
+ result.text = sequence.join(" > ")
66
+ end
67
+ end
68
+
69
+ # 命中判定&HR算出
70
+ def roll_hit_check(command)
71
+ parser = Command::Parser.new("OM", "NM", round_type: @round_type).enable_critical
72
+ parsed = parser.parse(command)
73
+ return nil unless parsed
74
+
75
+ if parsed.command == "OM"
76
+ return roll_om(parsed)
77
+ elsif parsed.command == "NM"
78
+ return roll_nm(parsed)
79
+ end
80
+ end
81
+
82
+ def roll_om(parsed)
83
+ target = parsed.modify_number
84
+ critical = parsed.critical || 0
85
+
86
+ dice_list = @randomizer.roll_barabara(2, 10).map { |v| v == 10 ? 0 : v }.sort.reverse
87
+
88
+ total = dice_list.sum()
89
+ criticals = dice_list.count { |v| v <= critical }
90
+ hr = calc_hr(target, dice_list)
91
+
92
+ return Result.new.tap do |r|
93
+ r.condition = total <= target
94
+ r.critical = criticals >= 1
95
+ r.text = [
96
+ "(2D10<=#{target})",
97
+ "#{total}[#{dice_list.join(',')}]",
98
+ ("チャンス" if dice_list.include?(0)),
99
+ r.success? ? "成功(HR=#{hr}、クリティカル#{criticals})" : "失敗",
100
+ ].compact.join(" > ")
101
+ end
102
+ end
103
+
104
+ def roll_nm(parsed)
105
+ target = parsed.modify_number
106
+ critical = parsed.critical || 0
107
+
108
+ dice_list = @randomizer.roll_barabara(3, 10).map { |v| v == 10 ? 0 : v }.sort.reverse
109
+
110
+ chosen_dice_list = dice_list.take(2)
111
+ total = chosen_dice_list.sum()
112
+ criticals = chosen_dice_list.count { |v| v <= critical }
113
+ hr = calc_hr(target, chosen_dice_list)
114
+
115
+ return Result.new.tap do |r|
116
+ r.condition = total <= target
117
+ r.critical = criticals >= 1
118
+ r.text = [
119
+ "(3D10<=#{target})",
120
+ "#{total}[#{dice_list[0]},#{dice_list[1]}&#{dice_list[2]}]",
121
+ ("チャンス" if chosen_dice_list.include?(0)),
122
+ r.success? ? "成功(HR=#{hr}、クリティカル#{criticals})" : "失敗",
123
+ ].compact.join(" > ")
124
+ end
125
+ end
126
+
127
+ def calc_hr(target, chosen_dice_list)
128
+ total = chosen_dice_list.sum()
129
+ a = (target - total).abs
130
+ b = (target - total - chosen_dice_list.count(0) * 10).abs
131
+ return [a, b].max
132
+ end
133
+
134
+ TABLES = {
135
+ "CR" => DiceTable::Table.new(
136
+ "クリティカル表",
137
+ "1D10",
138
+ [
139
+ "1:「小破」ダメージ+[5]。耐久値-[1]",
140
+ "2:「小破」ダメージ+[5]。耐久値-[1]",
141
+ "3:「小破」ダメージ+[5]。耐久値-[1]",
142
+ "4:「小破」ダメージ+[5]。耐久値-[1]",
143
+ "5:「兵装」損壊を受けるごとに[1D10]を振り、出目に応じた部位の兵装とオプションが《脱落》",
144
+ "6:「上体」攻撃系能力[白兵/ 火器/ 索敵]は各[- 損壊Lv]",
145
+ "7:「脚部」行動系・防御系能力[Iv 値(イニシア値)/ 最大MP/ 回避]は各[- 損壊Lv]",
146
+ "8:「搭乗者」搭乗者の〈最大HP〉および〈HP〉は[-(4 ×損壊Lv)]",
147
+ "9:「搭乗者」搭乗者の〈最大HP〉および〈HP〉は[-(4 ×損壊Lv)]",
148
+ "0:「小破」ダメージ+[5]。耐久値-[1]",
149
+ ]
150
+ )
151
+ }.freeze
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class Sengensyou < Base
6
+ # ゲームシステムの識別子
7
+ ID = 'Sengensyou'
8
+
9
+ # ゲームシステム名
10
+ NAME = '千幻抄'
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = 'せんけんしよう'
14
+
15
+ # ダイスボットの使い方
16
+ HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
17
+ ・SGS 命中判定・回避判定
18
+ INFO_MESSAGE_TEXT
19
+
20
+ register_prefix('SGS')
21
+
22
+ def eval_game_system_specific_command(command)
23
+ # 命中判定・回避判定
24
+ parser = Command::Parser.new('SGS', round_type: @round_type).restrict_cmp_op_to(nil)
25
+ command = parser.parse(command)
26
+
27
+ unless command
28
+ return nil
29
+ end
30
+
31
+ dice_list = @randomizer.roll_barabara(3, 6)
32
+ dice_total = dice_list.sum()
33
+ is_critical = dice_total >= 16
34
+ is_fumble = dice_total <= 5
35
+ additional_text =
36
+ if is_critical
37
+ "クリティカル"
38
+ elsif is_fumble
39
+ "ファンブル"
40
+ end
41
+ modify_text = "#{dice_total}#{Format.modifier(command.modify_number)}" if command.modify_number != 0
42
+ sequence = [
43
+ "(3D6#{Format.modifier(command.modify_number)})",
44
+ "#{dice_total}[#{dice_list.join(',')}]",
45
+ modify_text,
46
+ (dice_total + command.modify_number).to_s,
47
+ additional_text,
48
+ ].compact
49
+
50
+ result = Result.new.tap do |r|
51
+ r.text = sequence.join(" > ")
52
+ r.critical = is_critical
53
+ r.fumble = is_fumble
54
+ end
55
+ return result
56
+ end
57
+ end
58
+ end
59
+ end
@@ -39,7 +39,7 @@ module BCDice
39
39
  )
40
40
 
41
41
  def eval_game_system_specific_command(command)
42
- m = /^([A-Z]+)([+\-]?\d+)?(?:>=(\d+))?$/i.match(command)
42
+ m = /^([A-Z]+)([+-]?\d+)?(?:>=(\d+))?$/i.match(command)
43
43
  unless m
44
44
  return nil
45
45
  end
@@ -41,6 +41,7 @@ module BCDice
41
41
    /夏の終わりシーン表 NTST/培養プラントシーン表  PLST
42
42
    ・忍秘伝  中忍試験シーン表 HC/滅びの塔シーン表 HT/影の街でシーン表 HK
43
43
    /夜行列車シーン表 HY/病院シーン表 HO/龍動シーン表 HR/密室シーン表 HM/催眠シーン表 HS
44
+  ・ファンブル表(旧文庫版) OFT
44
45
  ・D66ダイスあり
45
46
  INFO_MESSAGE_TEXT
46
47
 
@@ -584,6 +585,18 @@ module BCDice
584
585
  'FT' => DiceTable::Table.new(
585
586
  'ファンブル表',
586
587
  '1D6',
588
+ [
589
+ '何か調子がおかしい。そのサイクルの間、すべての行為判定にマイナス1の修正がつく。',
590
+ 'しまった! 好きな忍具を1つ失ってしまう。',
591
+ '情報が漏れる! あなた以外のキャラクターは、あなたの持っている【秘密】か【居所】の中から、好きなものをそれぞれ一つ知ることができる。',
592
+ '油断した! 術の制御に失敗し、好きな【生命力】を1点失う。',
593
+ '敵の陰謀か? 罠にかかり、ランダムに選んだ変調一つを受ける。変調は、変調表で決定すること。',
594
+ 'ふう。危ないところだった。特に何も起こらない。',
595
+ ]
596
+ ),
597
+ 'OFT' => DiceTable::Table.new(
598
+ 'ファンブル表(旧文庫版)',
599
+ '1D6',
587
600
  [
588
601
  '何か調子がおかしい。そのサイクルの間、すべての行為判定にマイナス1の修正がつく。',
589
602
  'しまった! 好きな忍具を1つ失ってしまう。',
@@ -634,7 +647,7 @@ module BCDice
634
647
  '1D6',
635
648
  [
636
649
  '故障:すべての忍具が使用不能になる。この効果は累積しない。各サイクルの終了時に、《絡繰術》で行為判定を行い、成功するとこの変調は無効化される。',
637
- 'マヒ:修得している特技の中からランダムに一つを選び、その特技が使用不能になる。この効果は、修得している特技の数だけ累積する。各サイクルの終了時に、《身体操術l》で行為判定を行い、成功するとこの変調はすべて無効化される。',
650
+ 'マヒ:修得している特技の中からランダムに一つを選び、その特技が使用不能になる。この効果は、修得している特技の数だけ累積する。各サイクルの終了時に、《身体操術》で行為判定を行い、成功するとこの変調はすべて無効化される。',
638
651
  '重傷:命中判定、情報判定、感情判定を行うたびに、接近戦ダメージを1点受ける。この効果は累積しない。各サイクルの終了時に、《生存術》で行為判定を行い、成功するとこの変調は無効化される。',
639
652
  '行方不明:メインフェイズ中、自分以外がシーンプレイヤーのシーンに登場することができなくなる。この効果は累積しない。各サイクルの終了時に、《経済力》で行為判定を行い、成功するとこの変調は無効化される。',
640
653
  '忘却:修得している【感情】の中からランダムに一つを選び、その【感情】を持っていないものとして扱う。この効果は、修得している【感情】の数だけ累積する。各サイクルの終了時に、《記憶術》で行為判定を行い、成功するとこの変調はすべて無効化される。',