bcdice 3.13.0 → 3.14.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +45 -0
  3. data/i18n/Arianrhod/ko_kr.yml +3 -0
  4. data/i18n/Cthulhu/en_us.yml +11 -0
  5. data/i18n/CyberpunkRed/ja_jp.yml +389 -0
  6. data/i18n/FinalFantasyXIV/en_us.yml +4 -0
  7. data/i18n/FinalFantasyXIV/ja_jp.yml +4 -0
  8. data/i18n/FutariSousa/ja_jp.yml +158 -1
  9. data/i18n/KizunaBullet/ja_jp.yml +653 -0
  10. data/i18n/MonotoneMuseum/ja_jp.yml +246 -14
  11. data/i18n/SkynautsBouken/ja_jp.yml +114 -0
  12. data/i18n/TensaiGunshiNiNaro/ja_jp.yml +126 -0
  13. data/i18n/UnsungDuet/ja_jp.yml +62 -0
  14. data/i18n/UnsungDuet/ko_kr.yml +62 -0
  15. data/i18n/en_us.yml +5 -0
  16. data/lib/bcdice/dice_table/range_table.rb +24 -0
  17. data/lib/bcdice/game_system/Agnostos.rb +248 -0
  18. data/lib/bcdice/game_system/AniMalus.rb +99 -59
  19. data/lib/bcdice/game_system/Arianrhod_Korean.rb +30 -0
  20. data/lib/bcdice/game_system/BlackJacket.rb +244 -0
  21. data/lib/bcdice/game_system/ConvictorDrive.rb +5 -4
  22. data/lib/bcdice/game_system/Cthulhu_English.rb +59 -0
  23. data/lib/bcdice/game_system/CyberpunkRed.rb +14 -4
  24. data/lib/bcdice/game_system/DivineCharger.rb +841 -0
  25. data/lib/bcdice/game_system/FinalFantasyXIV.rb +115 -0
  26. data/lib/bcdice/game_system/FinalFantasyXIV_English.rb +39 -0
  27. data/lib/bcdice/game_system/FullFace.rb +39 -10
  28. data/lib/bcdice/game_system/FutariSousa.rb +88 -8
  29. data/lib/bcdice/game_system/Insane_Korean.rb +1 -1
  30. data/lib/bcdice/game_system/InvisibleLiar.rb +79 -0
  31. data/lib/bcdice/game_system/KizunaBullet.rb +240 -0
  32. data/lib/bcdice/game_system/KyokoShinshoku.rb +51 -8
  33. data/lib/bcdice/game_system/MonotoneMuseum.rb +14 -1
  34. data/lib/bcdice/game_system/NRR.rb +2 -2
  35. data/lib/bcdice/game_system/ShuumatsuBargainWars.rb +203 -0
  36. data/lib/bcdice/game_system/SkynautsBouken.rb +45 -130
  37. data/lib/bcdice/game_system/SwordWorld.rb +1 -1
  38. data/lib/bcdice/game_system/TensaiGunshiNiNaro.rb +228 -0
  39. data/lib/bcdice/game_system/TheOneRing2nd.rb +406 -0
  40. data/lib/bcdice/game_system/TheUnofficialHollowKnightRPG.rb +185 -0
  41. data/lib/bcdice/game_system/TrailOfCthulhu.rb +139 -0
  42. data/lib/bcdice/game_system/UnsungDuet.rb +17 -75
  43. data/lib/bcdice/game_system/UnsungDuet_Korean.rb +41 -0
  44. data/lib/bcdice/game_system/Utakaze.rb +55 -2
  45. data/lib/bcdice/game_system/Warhammer4.rb +124 -3
  46. data/lib/bcdice/game_system/Yotabana.rb +62 -0
  47. data/lib/bcdice/game_system/cyberpunk_red/tables.rb +111 -473
  48. data/lib/bcdice/game_system/kizuna_bullet/tables.rb +171 -0
  49. data/lib/bcdice/game_system.rb +16 -0
  50. data/lib/bcdice/version.rb +1 -1
  51. metadata +30 -2
@@ -0,0 +1,240 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bcdice/game_system/kizuna_bullet/tables"
4
+
5
+ module BCDice
6
+ module GameSystem
7
+ class KizunaBullet < Base
8
+ # ゲームシステムの識別子
9
+ ID = 'KizunaBullet'
10
+
11
+ # ゲームシステム名
12
+ NAME = 'キズナバレット'
13
+
14
+ # ゲームシステム名の読みがな
15
+ SORT_KEY = 'きすなはれつと'
16
+
17
+ # ダイスボットの使い方
18
+ HELP_MESSAGE = <<~MESSAGETEXT
19
+ ・ダイスロール
20
+ nDM…n個の6面ダイスを転がして、一番高い出目を採用します。
21
+ ・[調査判定]
22
+ nIN…n個の6面ダイスを転がして、一番高い出目が5以上なら成功します。([パートナーのヘルプ]使用可)
23
+ ・[鎮静判定]
24
+ SEn…2個の6面ダイスを転がして、出目の合計値がn([ヒビワレ]状態の[キズナ]の個数)より高いと成功します。([強制鎮静]使用可)
25
+ ・[解決] [アクション]のダメージと[アクシデント]のダメージ軽減
26
+ nSO…2+n個の6面ダイスを転がして、出目をすべて合計します。(nは減らした【励起値】。省略可能)
27
+ ・各種表
28
+ 日常表・場所 OP
29
+ 日常表・内容 OC
30
+ 日常表・場所と内容 OPC
31
+ 日常表(仕事)・場所 OWP
32
+ 日常表(仕事)・内容 OWC
33
+ 日常表(仕事)・場所と内容 OWPC
34
+ 日常表(休暇)・場所 OHP
35
+ 日常表(休暇)・内容 OHC
36
+ 日常表(休暇)・場所と内容 OHPC
37
+ 日常表(出張)・場所 OTP
38
+ 日常表(出張)・内容 OTC
39
+ 日常表(出張)・場所と内容 OTPC
40
+ ターンテーマ表 TT
41
+ ターンテーマ表・親密 TTI
42
+ ターンテーマ表・クール TTC
43
+ ターンテーマ表・主従 TTH
44
+ 遭遇表・場所 EP
45
+ 遭遇表・登場順 EO
46
+ 遭遇表・状況(初対面) EF
47
+ 遭遇表・状況(知り合い) EA
48
+ 遭遇表・決着 EE
49
+ 遭遇表・場所と登場順と状況(初対面)と決着 EFA
50
+ 遭遇表・場所と登場順と状況(知り合い)と決着 EAA
51
+ 交流表・場所 CP
52
+ 交流表・内容 CC
53
+ 交流表・場所と内容 CPC
54
+ 調査表・ベーシック IB
55
+ 調査表・ダイナミック ID
56
+ 調査表・ベーシックとダイナミック IBD
57
+ ハザード表 HA
58
+ 通常ダイジェスト キミたちに新しい命令が下った(調査が依頼された)。
59
+ 1:その事件の内容は…… NI1
60
+ 2:捜査に向かった場所は…… NI2
61
+ 3:犯人のキセキ使いは…… NI3
62
+ 4:起きた出来事は…… NI4
63
+ 5:バレットの間では…… NI5
64
+ 6:戦いの結末は…… NI6
65
+ 通常ダイジェスト キミたちは旅行(出張)である場所を訪れた。
66
+ 1:その場所とは…… NT1
67
+ 2:そこで始まったのは…… NT2
68
+ 3:極限状態のなかで…… NT3
69
+ 4:犯人のキセキ使いは…… NT4
70
+ 5:バレットの間では…… NT5
71
+ 6:戦いの結末は…… NT6
72
+ ホリデーダイジェスト キミたちは休日に出かけることにした。
73
+ 1:その場所とは…… HH1
74
+ 2:待ち合わせをしたら…… HH2
75
+ 3:そしてなんと…… HH3
76
+ 4:ふたりが決めたのは…… HH4
77
+ 5:結果的に…… HH5
78
+ 6:バレットは最後に…… HH6
79
+ ホリデーダイジェスト キミたちは奇妙な事件に出くわした。
80
+ 1:その場所とは…… HC1
81
+ 2:起きた事件は…… HC2
82
+ 3:犯人のキセキ使いは…… HC3
83
+ 4:犯人を追い詰めるべく…… HC4
84
+ 5:戦いの結果は…… HC5
85
+ 6:バレットは最後に…… HC6
86
+ MESSAGETEXT
87
+
88
+ TABLES = translate_tables(@locale)
89
+
90
+ def initialize(command)
91
+ super(command)
92
+
93
+ @sides_implicit_d = 6
94
+ @round_type = RoundType::CEIL
95
+ @d66_sort_type = D66SortType::NO_SORT
96
+ end
97
+
98
+ def eval_game_system_specific_command(command)
99
+ roll_max(command) || roll_investigate(command) || roll_sedative(command) || roll_solve(command) || roll_tables(command, self.class::TABLES)
100
+ end
101
+
102
+ private
103
+
104
+ # 最大値
105
+ def roll_max(command)
106
+ parser = Command::Parser.new("DM", round_type: @round_type)
107
+ .has_prefix_number
108
+ parsed = parser.parse(command)
109
+ unless parsed
110
+ return nil
111
+ end
112
+
113
+ # 最大値計算
114
+ dice_list = @randomizer.roll_barabara(parsed.prefix_number, 6)
115
+ max = dice_list.max
116
+
117
+ return Result.new.tap do |r|
118
+ # テキストを整形
119
+ r.text = "#{command} > [#{dice_list.join(',')}] > #{max}"
120
+ end
121
+ end
122
+
123
+ # 調査判定
124
+ def roll_investigate(command)
125
+ parser = Command::Parser.new("IN", round_type: @round_type)
126
+ .has_prefix_number
127
+ parsed = parser.parse(command)
128
+ unless parsed
129
+ return nil
130
+ end
131
+
132
+ texts = []
133
+ is_success = false
134
+ is_fumble = false
135
+
136
+ # 最大値計算
137
+ dice_list = @randomizer.roll_barabara(parsed.prefix_number, 6)
138
+ max = dice_list.max
139
+
140
+ if max >= 5
141
+ # 5以上の出目があった場合
142
+ # 成功フラグを立てる
143
+ is_success = true
144
+ # 成功メッセージを追加
145
+ texts.push(translate("KizunaBullet.INVESTIGATE.success"))
146
+ elsif max >= 3
147
+ # 3以上の出目があった場合
148
+ # 失敗メッセージを追加
149
+ texts.push(translate("KizunaBullet.INVESTIGATE.failure"))
150
+ # [パートナーのヘルプ]メッセージを追加
151
+ texts.push(translate("KizunaBullet.INVESTIGATE.partnerHelp"))
152
+ else
153
+ # 上記以外
154
+ # ファンブルフラグを立てる
155
+ is_fumble = true
156
+ # 失敗メッセージを追加
157
+ texts.push(translate("KizunaBullet.INVESTIGATE.failure"))
158
+ # ファンブルメッセージを追加
159
+ texts.push(translate("KizunaBullet.INVESTIGATE.fumble"))
160
+ end
161
+
162
+ return Result.new.tap do |r|
163
+ # テキストを整形
164
+ r.text = "#{command} > [#{dice_list.join(',')}] > #{texts.join('')}"
165
+ # 各種成否を格納
166
+ r.condition = is_success
167
+ r.fumble = is_fumble
168
+ end
169
+ end
170
+
171
+ # 鎮静判定
172
+ def roll_sedative(command)
173
+ parser = Command::Parser.new("SE", round_type: @round_type)
174
+ .has_suffix_number
175
+ parsed = parser.parse(command)
176
+ unless parsed
177
+ return nil
178
+ end
179
+
180
+ text = ''
181
+ is_success = false
182
+
183
+ # 合計値計算
184
+ sum = @randomizer.roll_sum(2, 6)
185
+
186
+ if parsed.suffix_number > 12
187
+ # 目標値が12より大きい場合
188
+ # [晶滅]メッセージを追加
189
+ text = translate("KizunaBullet.SEDATIVE.burst")
190
+ elsif parsed.suffix_number < 6
191
+ # 目標値が6より小さい場合
192
+ # [生存]メッセージを追加
193
+ text = translate("KizunaBullet.SEDATIVE.alive")
194
+ elsif sum > parsed.suffix_number
195
+ # 合計値が目標値より大きい場合
196
+ # 成功フラグを立てる
197
+ is_success = true
198
+ # 成功メッセージを追加
199
+ text = translate("KizunaBullet.SEDATIVE.success")
200
+ else
201
+ # 上記以外
202
+ # [強制鎮静]に必要な[キズナ]のチェック数の計算
203
+ # 目標値と出目の差分を計算
204
+ dif = parsed.suffix_number - sum
205
+ # チェック一つごとに結果に+2
206
+ check = (dif / 2) + 1
207
+ # 失敗メッセージを追加
208
+ text = translate("KizunaBullet.SEDATIVE.failure", check: check.to_s)
209
+ end
210
+
211
+ return Result.new.tap do |r|
212
+ # テキストを整形
213
+ r.text = "#{command} > #{sum} > #{text}"
214
+ # 各種成否を格納
215
+ r.condition = is_success
216
+ end
217
+ end
218
+
219
+ # 解決 [アクション]のダメージと[アクシデント]のダメージ軽減
220
+ def roll_solve(command)
221
+ parser = Command::Parser.new("SO", round_type: @round_type)
222
+ .enable_prefix_number
223
+ parsed = parser.parse(command)
224
+ unless parsed
225
+ return nil
226
+ end
227
+
228
+ # 合計値計算
229
+ sum = @randomizer.roll_sum(parsed.prefix_number.to_i + 2, 6)
230
+
231
+ return Result.new.tap do |r|
232
+ # テキストを整形
233
+ r.text = "#{command} > #{sum}"
234
+ end
235
+ end
236
+
237
+ register_prefix('\d+DM', '\d+IN', 'SE\d+', '\d*SO', TABLES.keys)
238
+ end
239
+ end
240
+ end
@@ -15,7 +15,7 @@ module BCDice
15
15
  # ダイスボットの使い方
16
16
  HELP_MESSAGE = <<~MESSAGETEXT
17
17
  ・判定
18
-  ダイスを指定数ダイスロールして、最も高い出目を出力します。難易度を指定すると成否を判定します。
18
+  ダイスを指定数ダイスロールして、最も高い出目を出力します。難易度を指定すると成否を判定します。オプションでA、Dをつけると、[有利][不利]の条件で振れます(A=[有利]、D=[不利])。
19
19
  KS(x,y)
20
20
  x:ダイスサイズ。1=D4(能力値1、2以上の出目が出ていたとしても最大1)/2=D4(能力値2、3以上の出目が出ていたとしても最大2)/3=D4(能力値3、出目4が出ていたとしても最大3)/4=D4/6=D6/8=D8/10=D10/12=D12/20=D20
21
21
  y:ダイス数(省略:1)
@@ -25,6 +25,16 @@ module BCDice
25
25
  y:ダイス数(省略:1)
26
26
  z:難易度
27
27
 
28
+ KS(x,y)A>=z([有利]:KS(x,y)の判定を2回行い、それぞれの結果のより大きい方が結果となります)
29
+ x:ダイスサイズ。1=D4(能力値1、2以上の出目が出ていたとしても最大1)/2=D4(能力値2、3以上の出目が出ていたとしても最大2)/3=D4(能力値3、出目4が出ていたとしても最大3)/4=D4/6=D6/8=D8/10=D10/12=D12/20=D20
30
+ y:ダイス数(省略:1)
31
+ z:難易度
32
+
33
+ KS(x,y)D>=z([不利]:KS(x,y)の判定を2回行い、それぞれの結果のより小さい方が結果となります)
34
+ x:ダイスサイズ。1=D4(能力値1、2以上の出目が出ていたとしても最大1)/2=D4(能力値2、3以上の出目が出ていたとしても最大2)/3=D4(能力値3、出目4が出ていたとしても最大3)/4=D4/6=D6/8=D8/10=D10/12=D12/20=D20
35
+ y:ダイス数(省略:1)
36
+ z:難易度
37
+
28
38
  ・観測ロール
29
39
   [現実乖離]の段階に応じたダイスを指定数ダイスロールして、最も高い出目を出力します。
30
40
  KR(x)
@@ -62,19 +72,30 @@ module BCDice
62
72
  }.freeze
63
73
 
64
74
  def roll_check(command)
65
- m = /^KS(?:\((\d+),([-+\d]+)?\)|(\d+))(?:>=([-+\d]+))?$/.match(command)
75
+ m = /^KS(?:\(([-+\d]+),([-+\d]+)?\)|(\d+))([AD]?)(?:>=([-+\d]+))?$/.match(command)
66
76
  return nil unless m
67
77
 
68
- dice_size = m[1]&.to_i || m[3].to_i
78
+ dice_size = m[1] ? Arithmetic.eval(m[1], @round_type) : Arithmetic.eval(m[3], @round_type).to_i
69
79
  times = m[2] ? Arithmetic.eval(m[2], @round_type) : 1
70
- target = m[4] && Arithmetic.eval(m[4], @round_type)
80
+ target = m[5] && Arithmetic.eval(m[5], @round_type)
81
+
82
+ advantage = m[4]
71
83
 
72
84
  sides = DICE_SIZE_TO_SIDES[dice_size]
73
85
 
74
86
  return nil if sides.nil? || times.nil?
75
87
 
76
- dice_list = @randomizer.roll_barabara(times, sides).sort
77
- value = dice_list.max.clamp(1, dice_size)
88
+ rolls = Array.new(advantage.empty? ? 1 : 2) { roll_check_once(times, dice_size, sides) }
89
+ values = rolls.map { |v| v[:value] }
90
+
91
+ value =
92
+ if advantage == "A"
93
+ values.max
94
+ elsif advantage == "D"
95
+ values.min
96
+ else
97
+ values.first
98
+ end
78
99
 
79
100
  result =
80
101
  if value == 1
@@ -90,8 +111,8 @@ module BCDice
90
111
  end
91
112
 
92
113
  result.text = [
93
- target ? "(KS(#{dice_size},#{times})>=#{target})" : "(KS(#{dice_size},#{times}))",
94
- ("#{value}[#{dice_list.join(',')}]" if times > 1),
114
+ target ? "(KS(#{dice_size},#{times})#{advantage}>=#{target})" : "(KS(#{dice_size},#{times})#{advantage})",
115
+ format_rolls(rolls),
95
116
  value,
96
117
  result.text,
97
118
  ].compact.join(" > ")
@@ -99,6 +120,28 @@ module BCDice
99
120
  return result
100
121
  end
101
122
 
123
+ def roll_check_once(times, dice_size, sides)
124
+ if times < 1
125
+ dice_list = @randomizer.roll_barabara(2, sides).sort
126
+ value = dice_list.min.clamp(1, dice_size)
127
+ else
128
+ dice_list = @randomizer.roll_barabara(times, sides).sort
129
+ value = dice_list.max.clamp(1, dice_size)
130
+ end
131
+
132
+ return {dice_list: dice_list, value: value}
133
+ end
134
+
135
+ def format_rolls(rolls)
136
+ if rolls.length == 1 && rolls.first[:dice_list].length == 1
137
+ return nil
138
+ end
139
+
140
+ rolls.map do |v|
141
+ v[:dice_list].length == 1 ? v[:value].to_s : "#{v[:value]}[#{v[:dice_list].join(',')}]"
142
+ end.join(", ")
143
+ end
144
+
102
145
  GENJITU_KAIRI_TO_SIDES = [4, 6, 8, 10, 12, 20].freeze
103
146
  REALITY_LINE_TO_TIMES = {
104
147
  3 => 1,
@@ -25,9 +25,16 @@ module BCDice
25
25
    クリティカル値、ファンブル値は省略可能です。([]ごと省略できます)
26
26
    自動成功、自動失敗、成功、失敗を自動表示します。
27
27
  ・各種表
28
+ 【改訂版環境】
29
+  ・感情表 MET
30
+  ・兆候表(戦闘時) MBOT/兆候表(非戦闘時) MNOT
31
+  ・歪み表 MDT
32
+  ・世界歪曲表 MWDT
33
+  ・永劫消失表 MEDT
34
+ 【旧版環境】
28
35
   ・感情表 ET/感情表 2.0 ET2
29
36
   ・兆候表 OT/兆候表ver2.0 OT2/兆候表ver3.0 OT3
30
-  ・歪み表 DT/歪み表ver2.0 DT2/歪み表(野外) DTO/歪み表(海) DTS/歪み表(館・城) DTM
37
+  ・歪み表 DT/歪み表ver2.0 DT2/歪み表(野外) DTO/歪み表(海) DTS/歪み表(館・城) DTM
31
38
   ・世界歪曲表 WDT/世界歪曲表2.0 WDT2
32
39
   ・永劫消失表 EDT
33
40
  ・D66ダイスあり
@@ -146,6 +153,12 @@ module BCDice
146
153
  "EDT" => DiceTable::Table.from_i18n("MonotoneMuseum.table.EDT", locale),
147
154
  "DTM" => MMTable.from_i18n("MonotoneMuseum.table.DTM", locale),
148
155
  "OT3" => DiceTable::Table.from_i18n("MonotoneMuseum.table.OT3", locale),
156
+ "MET" => DiceTable::D66GridTable.from_i18n("MonotoneMuseum.table.MET", locale),
157
+ "MBOT" => DiceTable::Table.from_i18n("MonotoneMuseum.table.MBOT", locale),
158
+ "MNOT" => DiceTable::Table.from_i18n("MonotoneMuseum.table.MNOT", locale),
159
+ "MDT" => MMTable.from_i18n("MonotoneMuseum.table.MDT", locale),
160
+ "MWDT" => DiceTable::Table.from_i18n("MonotoneMuseum.table.MWDT", locale),
161
+ "MEDT" => DiceTable::Table.from_i18n("MonotoneMuseum.table.MEDT", locale),
149
162
  }
150
163
  end
151
164
  end
@@ -97,10 +97,10 @@ module BCDice
97
97
  SUCCESSES = [:success, :critical, :miracle].freeze
98
98
  CRITICALS = [:critical, :miracle].freeze
99
99
 
100
- DISADVANTAGE = [:fumble, :fumble, :failure, :failure, :success, :success].freeze
100
+ DISADVANTAGE = [:fumble, :failure, :failure, :failure, :success, :success].freeze
101
101
  NORMAL = [:fumble, :failure, :failure, :failure, :success, :success, :success, :critical].freeze
102
102
  ADVANTAGE = [:fumble, :failure, :failure, :success, :success, :success, :success, :success, :critical, :critical].freeze
103
- EXTRA = [:fumble, :fumble, :fumble, :failure, :success, :success, :critical, :critical, :critical, :critical, :miracle, :miracle].freeze
103
+ EXTRA = [:fumble, :fumble, :failure, :failure, :success, :success, :critical, :critical, :critical, :critical, :miracle, :miracle].freeze
104
104
 
105
105
  ICON = {
106
106
  fumble: "💀",
@@ -0,0 +1,203 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class ShuumatsuBargainWars < Base
6
+ # ゲームシステムの識別子
7
+ ID = "ShuumatsuBargainWars"
8
+
9
+ # ゲームシステム名
10
+ NAME = "終末買い物戦争"
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = "しゆうまつはあけんうおおす"
14
+
15
+ HELP_MESSAGE = <<~TEXT
16
+ ・行為判定 (nBGk+y>=t)n:ダイス数、k:心根、y:修正値(省略可)、t:目標値
17
+ 例)3BG1>=3 2BG3+1>=4 4BG5-1>=3
18
+ ・アイテム表
19
+ ・RT 回復系アイテム表
20
+ ・CT 便利系アイテム表
21
+ ・WT 武器系アイテム表
22
+ ・WG ワゴン(全アイテムランダム)
23
+ ・ET イベント表
24
+ ・TT トラブル表
25
+ TEXT
26
+
27
+ def initialize(command)
28
+ super(command)
29
+ @sort_barabara_dice = true
30
+ @d66_sort_type = D66SortType::ASC
31
+ end
32
+
33
+ RecoveryItemTable = DiceTable::D66Table.new(
34
+ '回復系アイテム表',
35
+ D66SortType::ASC,
36
+ {
37
+ 11 => '飴玉',
38
+ 12 => 'エナジードリンク',
39
+ 13 => 'せんべい',
40
+ 14 => '餅',
41
+ 15 => 'ロウソク',
42
+ 16 => '酒',
43
+ 22 => '寿司',
44
+ 23 => 'ばんそうこう',
45
+ 24 => 'お布団',
46
+ 25 => 'カレー',
47
+ 26 => '消毒液',
48
+ 33 => '缶詰',
49
+ 34 => 'みたらし団子',
50
+ 35 => '骨付き肉',
51
+ 36 => 'ステーキ',
52
+ 44 => 'うちわ',
53
+ 45 => 'ぬいぐるみ',
54
+ 46 => 'のり',
55
+ 55 => '美容液',
56
+ 56 => '黄色いハンカチ',
57
+ 66 => '洗剤',
58
+ }
59
+ )
60
+
61
+ ConvenienceItemTable = DiceTable::D66Table.new(
62
+ '便利系アイテム表',
63
+ D66SortType::ASC,
64
+ {
65
+ 11 => 'ちくわ',
66
+ 12 => '焼き芋',
67
+ 13 => 'トイレットペーパー',
68
+ 14 => '熊手',
69
+ 15 => '胡椒',
70
+ 16 => '鏡',
71
+ 22 => '割りばし',
72
+ 23 => '輪ゴム',
73
+ 24 => '塩の結晶',
74
+ 25 => 'プチプチマット',
75
+ 26 => '長靴',
76
+ 33 => 'バケツ',
77
+ 34 => 'アルミホイル',
78
+ 35 => '下敷き',
79
+ 36 => '長芋',
80
+ 44 => '鉛筆',
81
+ 45 => 'まな板',
82
+ 46 => 'フライパン',
83
+ 55 => 'ほうき',
84
+ 56 => 'クラッカー',
85
+ 66 => '消臭スプレー',
86
+ }
87
+ )
88
+
89
+ WeaponItemTable = DiceTable::D66Table.new(
90
+ '武器系アイテム表',
91
+ D66SortType::ASC,
92
+ {
93
+ 11 => 'アズキアイス',
94
+ 12 => 'スプーン',
95
+ 13 => 'フォーク',
96
+ 14 => 'カミソリ',
97
+ 15 => '電池',
98
+ 16 => 'デッキブラシ',
99
+ 22 => '傘',
100
+ 23 => '物干し竿',
101
+ 24 => '鉄パイプ',
102
+ 25 => 'くぎ打ち機',
103
+ 26 => 'モンキーレンチ',
104
+ 33 => 'ハエタタキ',
105
+ 34 => '鎌',
106
+ 35 => '蛍光灯',
107
+ 36 => '包丁',
108
+ 44 => 'ハサミ',
109
+ 45 => 'ショベル',
110
+ 46 => '釣り竿',
111
+ 55 => '芝刈り機',
112
+ 56 => 'ステッキ',
113
+ 66 => '小麦粉',
114
+ }
115
+ )
116
+
117
+ TABLES = {
118
+ "ET" => DiceTable::Table.new(
119
+ "イベント表",
120
+ "2D6",
121
+ [
122
+ "ドッキン!一目惚れ!好きなキャラクターを1人選ぶ。このセッション中その相手との関係の深度を互いに3以上にすることができた場合、シナリオの結末に関係なく貴方は完全無欠のハッピーエンドを迎え経験点を100点得る。達成できなかった場合、エンディングフェイズで目が覚める。",
123
+ "おや?こんな所にアイテムが転がっている。ランダムに選んだアイテムを獲得する。そのアイテムの種別が支援・計画ならば[技術]/5の判定に成功すれば手番を消費せずそのアイテムを使用しても良い。",
124
+ "チームメンバーと二人っきりになる。ちょっといい雰囲気かも。好きなキャラクターを目標に選び、『関係』のチェックを外す事ができる。",
125
+ "あぶな~い!チームメンバーに危機が襲い掛かる。PCの中からランダムに1人を選び[武力]/5の判定を行う。成功すると互いに『関係』を結ぶことができる。失敗すると2人とも体力に1d6点のダメージ。",
126
+ "ちょっとお食事でも如何?自身の体力3点と活力1点を回復させる。",
127
+ "穏やかな時が流れる。このメンバーならこれからも上手くやっていけそうだ。ランダムにPCを選び『関係』を獲得する。",
128
+ "チームメンバーの意外な一面を覗く、まさかアイツあんな趣味があったなんて!PCの中からランダムで1人を選び[精神]/6で判定を行う。成功すると互いに『関係』を獲得する。失敗すると互いに活力が1点減少する。",
129
+ "仲間と意見が対立する。アイツにだけは負けられない!関係を持つPCの中からランダムで1人を選び、対象との関係の深度を1下げてもよい(0未満にならない)。下げた場合、以降のセッション中任意の能力値が1上昇したものとして判定を行う事ができる。この効果で実際に能力値は上がらない。",
130
+ "何かお手伝いをしよう。好きなキャラクターを1人選ぶ。この休憩中次に相手が判定を行う場合、その判定に修正値+1を加える。その後、目標は自分に対し『関係』を獲得する。",
131
+ "酒を発見、宴だぁああ!!!PCは全員回復アイテムの「酒」の効果を使用できる。その後、自分の持つ全ての『関係』をランダムな相手に同じ《深度》で取り直す。",
132
+ "不味い!敵襲だ!バナナワニにキリミウオが戦闘を仕掛けに来る。戦闘に勝利した場合、好きなアイテムを1つ得る。この処理が面倒ならば戦闘を行う代わりにPC達全員の体力の値を半分にし戦闘に勝利したものとして扱っても良い。"
133
+ ]
134
+ ),
135
+ "TT" => DiceTable::Table.new(
136
+ "トラブル表",
137
+ "1D6",
138
+ [
139
+ "緊張感からか焦りが生じる。以降スポットフェイズに行くまでの間あらゆる判定の成功度が1減少する。",
140
+ "カートの操作が効かなくなった!このラウンドは操作表を全員ダイスを振りランダムで決定する事。",
141
+ "派手な振動が起き頭をぶつける。全員1d6点のダメージを受ける。",
142
+ "集中力が切れて来た……全員の活力を1 点減少させる",
143
+ "激しく揺さぶられ荷物が落下する。カート内にあるアイテムを1 つ選ぶ。そのアイテムを失う。",
144
+ "不気味な超市場の雰囲気がパッセンジャー達の不安を煽る。特に何も起こらない。",
145
+ ]
146
+ ),
147
+ "RT" => RecoveryItemTable,
148
+ "CT" => ConvenienceItemTable,
149
+ "WT" => WeaponItemTable,
150
+ "WG" => DiceTable::ChainTable.new(
151
+ "ワゴン",
152
+ "1D6",
153
+ [
154
+ RecoveryItemTable,
155
+ RecoveryItemTable,
156
+ ConvenienceItemTable,
157
+ ConvenienceItemTable,
158
+ WeaponItemTable,
159
+ WeaponItemTable,
160
+ ]
161
+ ),
162
+ }.freeze
163
+
164
+ register_prefix('\d+BG', TABLES.keys)
165
+
166
+ def eval_game_system_specific_command(command)
167
+ return roll_bg(command) || roll_tables(command, TABLES)
168
+ end
169
+
170
+ private
171
+
172
+ def roll_bg(command)
173
+ parser = Command::Parser.new("BG", round_type: @round_type)
174
+ .has_prefix_number
175
+ .has_suffix_number
176
+ .restrict_cmp_op_to(:>=)
177
+ parsed = parser.parse(command)
178
+ return nil unless parsed
179
+
180
+ times = parsed.prefix_number
181
+ kokorone = parsed.suffix_number
182
+ correction = parsed.modify_number
183
+ target = parsed.target_number
184
+ dice_list = @randomizer.roll_barabara(times, 6).sort
185
+ success = dice_list.count { |number| number >= target - correction }
186
+ get_vitality = dice_list.count(kokorone)
187
+
188
+ result =
189
+ if dice_list.count(6) >= 2
190
+ Result.critical("スペシャル! 成功度#{success + 1}、活力#{get_vitality}獲得")
191
+ elsif dice_list.all?(1)
192
+ Result.fumble("ファンブル 活力をすべて失う")
193
+ else
194
+ Result.new("成功度#{success}、活力#{get_vitality}獲得")
195
+ end
196
+
197
+ result.text = "(#{parsed}) > [#{dice_list.join(',')}] > #{result.text}"
198
+
199
+ return result
200
+ end
201
+ end
202
+ end
203
+ end