bcdice 3.8.0 → 3.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +49 -2
- data/README.md +0 -1
- data/lib/bcdice/game_system/Bloodorium.rb +1 -1
- data/lib/bcdice/game_system/CastleInGray.rb +6 -4
- data/lib/bcdice/game_system/CyberpunkRed.rb +2 -2
- data/lib/bcdice/game_system/DungeonsAndDragons5.rb +64 -10
- data/lib/bcdice/game_system/Emoklore.rb +3 -3
- data/lib/bcdice/game_system/HatsuneMiku.rb +42 -1
- data/lib/bcdice/game_system/HeroScale.rb +837 -0
- data/lib/bcdice/game_system/KemonoNoMori.rb +133 -1
- data/lib/bcdice/game_system/MonotoneMuseum.rb +4 -2
- data/lib/bcdice/game_system/NSSQ.rb +24 -11
- data/lib/bcdice/game_system/SRS.rb +79 -126
- data/lib/bcdice/game_system/ShinobiGami.rb +618 -161
- data/lib/bcdice/game_system/SkynautsBouken.rb +1 -1
- data/lib/bcdice/game_system/TenkaRyouran.rb +26 -0
- data/lib/bcdice/game_system/VampireTheMasquerade5th.rb +40 -12
- data/lib/bcdice/game_system/Ventangle.rb +133 -0
- data/lib/bcdice/game_system/WorldsEndFrontline.rb +20 -0
- data/lib/bcdice/game_system/cthulhu7th/rollable.rb +2 -0
- data/lib/bcdice/game_system/sword_world/transcendent_test.rb +2 -0
- data/lib/bcdice/game_system.rb +4 -0
- data/lib/bcdice/version.rb +1 -1
- metadata +7 -3
@@ -25,7 +25,7 @@ module BCDice
|
|
25
25
|
例2)KC6 → 目標値6の継続判定
|
26
26
|
・罠動作チェック+獲物表(P163): CTR
|
27
27
|
罠ごとに1D12を振り、12が出た場合には生き物が罠を動作させ、その影響を受けている。
|
28
|
-
|
28
|
+
・各種表(基本ルールブック)
|
29
29
|
・大失敗表(P120): FT
|
30
30
|
・能力値ランダム決定表(P121): RST
|
31
31
|
・ランダム所要時間表(P122): RTT
|
@@ -38,6 +38,16 @@ module BCDice
|
|
38
38
|
・食材採集表(P157): GFT
|
39
39
|
・水採集表(P157): GWT
|
40
40
|
・白の魔石効果表(P186): WST
|
41
|
+
・部位ダメージ関連の表(参照先ページはリプレイ&データブック「嚙神ノ宴」のもの)
|
42
|
+
・人間部位表(P216): HPT
|
43
|
+
・部位ダメージ段階表(P217): PDT
|
44
|
+
・四足動物部位表(P225): QPT
|
45
|
+
・無足動物部位表(P225): APT
|
46
|
+
・二足動物部位表(P226): TPT
|
47
|
+
・鳥部位表(P226): BPT
|
48
|
+
・頭足動物部位表(P227): CPT
|
49
|
+
・昆虫部位表(P227): IPT
|
50
|
+
・蜘蛛部位表(P228): SPT
|
41
51
|
MESSAGETEXT
|
42
52
|
|
43
53
|
def eval_game_system_specific_command(command)
|
@@ -237,6 +247,128 @@ module BCDice
|
|
237
247
|
'大型動物を召喚する',
|
238
248
|
]
|
239
249
|
),
|
250
|
+
'HPT' => DiceTable::RangeTable.new(
|
251
|
+
'人間部位表',
|
252
|
+
'1D12',
|
253
|
+
[
|
254
|
+
[1..2, '右腕部'],
|
255
|
+
[3..4, '左腕部'],
|
256
|
+
[5..6, '右脚部'],
|
257
|
+
[7..8, '左脚部'],
|
258
|
+
[9..11, '胴部'],
|
259
|
+
[12, '頭部'],
|
260
|
+
]
|
261
|
+
),
|
262
|
+
'PDT' => DiceTable::RangeTable.new(
|
263
|
+
'部位ダメージ段階表',
|
264
|
+
'1D12',
|
265
|
+
[
|
266
|
+
[1..6, '軽傷'],
|
267
|
+
[7..10, '重傷'],
|
268
|
+
[11, '破壊'],
|
269
|
+
[12, '喪失'],
|
270
|
+
]
|
271
|
+
),
|
272
|
+
'QPT' => DiceTable::RangeTable.new(
|
273
|
+
'四足動物部位表',
|
274
|
+
'1D12',
|
275
|
+
[
|
276
|
+
[1..2, '異形'],
|
277
|
+
[3, '武器'],
|
278
|
+
[4, '右前脚部'],
|
279
|
+
[5, '左前脚部'],
|
280
|
+
[6, '右後脚部'],
|
281
|
+
[7, '左後脚部'],
|
282
|
+
[8..10, '胴部'],
|
283
|
+
[11..12, '頭部'],
|
284
|
+
]
|
285
|
+
),
|
286
|
+
'APT' => DiceTable::RangeTable.new(
|
287
|
+
'無足動物部位表',
|
288
|
+
'1D12',
|
289
|
+
[
|
290
|
+
[1..3, '異形'],
|
291
|
+
[4..6, '武器'],
|
292
|
+
[7..10, '胴部'],
|
293
|
+
[11..12, '頭部'],
|
294
|
+
]
|
295
|
+
),
|
296
|
+
'TPT' => DiceTable::RangeTable.new(
|
297
|
+
'二足動物部位表',
|
298
|
+
'1D12',
|
299
|
+
[
|
300
|
+
[1, '異形'],
|
301
|
+
[2, '武器'],
|
302
|
+
[3, '右腕部'],
|
303
|
+
[4, '左腕部'],
|
304
|
+
[5..6, '右脚部'],
|
305
|
+
[7..8, '左脚部'],
|
306
|
+
[9..11, '胴部'],
|
307
|
+
[12, '頭部'],
|
308
|
+
]
|
309
|
+
),
|
310
|
+
'BPT' => DiceTable::RangeTable.new(
|
311
|
+
'鳥部位表',
|
312
|
+
'1D12',
|
313
|
+
[
|
314
|
+
[1, '異形'],
|
315
|
+
[2, '武器'],
|
316
|
+
[3..4, '右翼(右腕部)'],
|
317
|
+
[5..6, '左翼(左腕部)'],
|
318
|
+
[7, '右脚部'],
|
319
|
+
[8, '左脚部'],
|
320
|
+
[9..11, '胴部'],
|
321
|
+
[12, '頭部'],
|
322
|
+
]
|
323
|
+
),
|
324
|
+
'CPT' => DiceTable::RangeTable.new(
|
325
|
+
'頭足動物部位表',
|
326
|
+
'1D12',
|
327
|
+
[
|
328
|
+
[1, '異形'],
|
329
|
+
[2, '武器'],
|
330
|
+
[3, '右腕部'],
|
331
|
+
[4, '左腕部'],
|
332
|
+
[5..7, '右脚部'],
|
333
|
+
[8..10, '左脚部'],
|
334
|
+
[11, '胴部'],
|
335
|
+
[12, '頭部'],
|
336
|
+
]
|
337
|
+
),
|
338
|
+
'IPT' => DiceTable::RangeTable.new(
|
339
|
+
'昆虫部位表',
|
340
|
+
'1D12',
|
341
|
+
[
|
342
|
+
[1..2, '異形'],
|
343
|
+
[3, '武器'],
|
344
|
+
[4, '右前脚部'],
|
345
|
+
[5, '左前脚部'],
|
346
|
+
[6, '右中脚部'],
|
347
|
+
[7, '左中脚部'],
|
348
|
+
[8, '右後脚部'],
|
349
|
+
[9, '左後脚部'],
|
350
|
+
[10..11, '胴部'],
|
351
|
+
[12, '頭部'],
|
352
|
+
]
|
353
|
+
),
|
354
|
+
'SPT' => DiceTable::RangeTable.new(
|
355
|
+
'蜘蛛部位表',
|
356
|
+
'1D12',
|
357
|
+
[
|
358
|
+
[1, '異形'],
|
359
|
+
[2, '武器'],
|
360
|
+
[3, '右第一脚部'],
|
361
|
+
[4, '左第一脚部'],
|
362
|
+
[5, '右第二脚部'],
|
363
|
+
[6, '左第二脚部'],
|
364
|
+
[7, '右第三脚部'],
|
365
|
+
[8, '左第三脚部'],
|
366
|
+
[9, '右第四脚部'],
|
367
|
+
[10, '左第四脚部'],
|
368
|
+
[11, '胴部'],
|
369
|
+
[12, '頭部'],
|
370
|
+
]
|
371
|
+
),
|
240
372
|
}.freeze
|
241
373
|
|
242
374
|
register_prefix('K[AC]', 'CTR', TABLES.keys)
|
@@ -59,7 +59,7 @@ module BCDice
|
|
59
59
|
private
|
60
60
|
|
61
61
|
def check_roll(command)
|
62
|
-
m = /^(\d+)D6([+\-\d]*)>=(
|
62
|
+
m = /^(\d+)D6([+\-\d]*)>=(\?|\d+)(\[(\d+)?(,(\d+))?\])?$/i.match(command)
|
63
63
|
unless m
|
64
64
|
return nil
|
65
65
|
end
|
@@ -80,6 +80,8 @@ module BCDice
|
|
80
80
|
Result.fumble(translate("MonotoneMuseum.automatic_failure"))
|
81
81
|
elsif dice_value >= critical
|
82
82
|
Result.critical(translate("MonotoneMuseum.automatic_success"))
|
83
|
+
elsif target == 0
|
84
|
+
Result.success(nil)
|
83
85
|
elsif total >= target
|
84
86
|
Result.success(translate("success"))
|
85
87
|
else
|
@@ -91,7 +93,7 @@ module BCDice
|
|
91
93
|
"#{dice_value}[#{dice_str}]#{Format.modifier(modify_number)}",
|
92
94
|
total.to_s,
|
93
95
|
result.text,
|
94
|
-
]
|
96
|
+
].compact
|
95
97
|
|
96
98
|
result.text = sequence.join(" > ")
|
97
99
|
|
@@ -8,24 +8,26 @@ module BCDice
|
|
8
8
|
SORT_KEY = "えすああるえすしやないせかいしゆのめいきゆうTRPG"
|
9
9
|
|
10
10
|
HELP_MESSAGE = <<~MESSAGETEXT
|
11
|
-
■ 判定 (xSQ±y)
|
12
|
-
xD6の判定。3つ以上振ったとき、出目の高い2
|
11
|
+
■ 判定 (xSQ±y>=z)
|
12
|
+
xD6の判定。3つ以上振ったとき、出目の高い2つを表示します。絶対成功、絶対失敗も計算します。
|
13
|
+
2つのサイコロを使用して出目に1があった場合は、FPの獲得も表示します。3つ以上使用した場合は表示しません。
|
13
14
|
±y: yに修正値を入力。±の計算に対応。省略可能。
|
15
|
+
z: 目標値。省略可能。
|
14
16
|
|
15
17
|
■ ダメージロール (xDR(C)(+)y)
|
16
|
-
xD6
|
18
|
+
xD6のダメージロール。クリティカルヒットの自動判定を行います。Cを付けるとクリティカルアップ状態で計算できます。+を付けるとクリティカルヒット時のダイスが8個になります。
|
17
19
|
x: xに振るダイス数を入力。
|
18
20
|
y: yに耐性を入力。
|
19
21
|
例) 5DR3 5DRC4 5DRC+4
|
20
22
|
|
21
23
|
■ 回復ロール (xHRy)
|
22
|
-
xD6
|
24
|
+
xD6の回復ロール。クリティカルヒットが発生しません。
|
23
25
|
x: xに振るダイス数を入力。
|
24
26
|
y: yに耐性を入力。省略した場合3。
|
25
27
|
例) 2HR 10HR2
|
26
28
|
|
27
|
-
■
|
28
|
-
|
29
|
+
■ 採集ロール (TC±z,SC±z,GC±z)
|
30
|
+
少しだけ(T)、そこそこ(S)、ガッツリ(G)採取採掘伐採を行います。
|
29
31
|
z: zに追加でロールする回数を入力。省略可能。
|
30
32
|
例) TC SC+1 GC-1
|
31
33
|
MESSAGETEXT
|
@@ -40,27 +42,38 @@ module BCDice
|
|
40
42
|
|
41
43
|
# 判定
|
42
44
|
def roll_sq(command)
|
43
|
-
m = /(\d+)SQ([+\-\d]+)?/i.match(command)
|
45
|
+
m = /(\d+)SQ([+\-\d]+)?(([>=]+)(\d+))?/i.match(command)
|
44
46
|
return nil unless m
|
45
47
|
|
46
48
|
dice_count = m[1].to_i
|
47
49
|
modifier = ArithmeticEvaluator.eval(m[2])
|
50
|
+
target = m[5].nil? ? nil : m[5].to_i
|
48
51
|
|
49
52
|
dice_list = @randomizer.roll_barabara(dice_count, 6)
|
50
53
|
largest_two = dice_list.sort.reverse.take(2)
|
51
54
|
total = largest_two.sum + modifier
|
55
|
+
num_1 = dice_list.count(1)
|
52
56
|
|
53
57
|
additional_result =
|
54
58
|
if largest_two == [6, 6]
|
55
|
-
"
|
59
|
+
Result.critical(" > 絶対成功!")
|
56
60
|
elsif largest_two == [1, 1]
|
57
|
-
"
|
61
|
+
Result.fumble(" > 絶対失敗!")
|
62
|
+
elsif target && total >= target
|
63
|
+
Result.success(" > 成功")
|
64
|
+
elsif target && total < target
|
65
|
+
Result.failure(" > 失敗")
|
66
|
+
else
|
67
|
+
Result.new
|
58
68
|
end
|
59
69
|
|
70
|
+
# ダイス数が2個の場合は1の出目の数だけ【FP】を獲得できる
|
71
|
+
fp_result = dice_count == 2 && num_1 >= 1 ? " (【FP】#{num_1}獲得)" : ""
|
72
|
+
|
60
73
|
sequence = [
|
61
74
|
"(#{command})",
|
62
75
|
"[#{dice_list.join(',')}]#{Format.modifier(modifier)}",
|
63
|
-
"#{total}[#{largest_two.join(',')}]#{additional_result}",
|
76
|
+
"#{total}[#{largest_two.join(',')}]#{additional_result.text}#{fp_result}",
|
64
77
|
]
|
65
78
|
|
66
79
|
return sequence.join(" > ")
|
@@ -83,7 +96,7 @@ module BCDice
|
|
83
96
|
critical_target = critical_up ? 1 : 2
|
84
97
|
|
85
98
|
if dice_list.count(6) - dice_list.count(1) >= critical_target
|
86
|
-
result += "
|
99
|
+
result += " クリティカルヒット!\n"
|
87
100
|
result += additional_damage_roll(increase_critical_dice, resist)
|
88
101
|
end
|
89
102
|
|
@@ -16,27 +16,33 @@ module BCDice
|
|
16
16
|
|
17
17
|
HELP_MESSAGE_1 = <<~HELP_MESSAGE
|
18
18
|
・判定
|
19
|
-
・通常判定:2D6+m>=t[c,f]
|
19
|
+
・通常判定:2D6+m@c#f>=t または 2D6+m>=t[c,f]
|
20
20
|
修正値m、目標値t、クリティカル値c、ファンブル値fで判定ロールを行います。
|
21
|
-
修正値、クリティカル値、ファンブル値は省略可能です([]
|
21
|
+
修正値、クリティカル値、ファンブル値は省略可能です([]ごと省略可、@c・#fの指定は順不同)。
|
22
22
|
クリティカル値、ファンブル値の既定値は、それぞれ12、2です。
|
23
23
|
自動成功、自動失敗、成功、失敗を自動表示します。
|
24
24
|
|
25
25
|
例) 2d6>=10 修正値0、目標値10で判定
|
26
26
|
例) 2d6+2>=10 修正値+2、目標値10で判定
|
27
27
|
例) 2d6+2>=10[11] ↑をクリティカル値11で判定
|
28
|
+
例) 2d6+2@11>=10 ↑をクリティカル値11で判定
|
28
29
|
例) 2d6+2>=10[12,4] ↑をクリティカル値12、ファンブル値4で判定
|
30
|
+
例) 2d6+2@12#4>=10 ↑をクリティカル値12、ファンブル値4で判定
|
31
|
+
例) 2d6+2>=10[,4] ↑をクリティカル値12、ファンブル値4で判定(クリティカル値の省略)
|
32
|
+
例) 2d6+2#4>=10 ↑をクリティカル値12、ファンブル値4で判定(クリティカル値の省略)
|
29
33
|
HELP_MESSAGE
|
30
34
|
|
31
35
|
HELP_MESSAGE_2 = <<~HELP_MESSAGE
|
32
|
-
・クリティカルおよびファンブルのみの判定:2D6+m[c,f]
|
36
|
+
・クリティカルおよびファンブルのみの判定:2D6+m@c#f または 2D6+m[c,f]
|
33
37
|
目標値を指定せず、修正値m、クリティカル値c、ファンブル値fで判定ロールを行います。
|
34
|
-
修正値、クリティカル値、ファンブル値は省略可能です([]
|
38
|
+
修正値、クリティカル値、ファンブル値は省略可能です([]は省略不可、@c・#fの指定は順不同)。
|
35
39
|
自動成功、自動失敗を自動表示します。
|
36
40
|
|
37
41
|
例) 2d6[] 修正値0、クリティカル値12、ファンブル値2で判定
|
38
42
|
例) 2d6+2[11] 修正値+2、クリティカル値11、ファンブル値2で判定
|
43
|
+
例) 2d6+2@11 修正値+2、クリティカル値11、ファンブル値2で判定
|
39
44
|
例) 2d6+2[12,4] 修正値+2、クリティカル値12、ファンブル値4で判定
|
45
|
+
例) 2d6+2@12#4 修正値+2、クリティカル値12、ファンブル値4で判定
|
40
46
|
HELP_MESSAGE
|
41
47
|
|
42
48
|
HELP_MESSAGE_3 = <<~HELP_MESSAGE
|
@@ -50,18 +56,14 @@ module BCDice
|
|
50
56
|
|
51
57
|
# 成功判定のエイリアスコマンド定義用のクラスメソッドを提供するモジュール
|
52
58
|
module ClassMethods
|
59
|
+
# 成功判定のエイリアスコマンドの一覧
|
60
|
+
# @return [Array<String>]
|
61
|
+
attr_reader :aliases
|
62
|
+
|
53
63
|
# ダイスボットの説明文を返す
|
54
64
|
# @return [String]
|
55
65
|
attr_reader :help_message
|
56
66
|
|
57
|
-
# 目標値あり成功判定のエイリアスコマンドの正規表現を返す
|
58
|
-
# @return [Regexp, nil]
|
59
|
-
attr_reader :aliases_re_for_srs_roll_with_target_value
|
60
|
-
|
61
|
-
# 目標値なし成功判定のエイリアスコマンドの正規表現を返す
|
62
|
-
# @return [Regexp, nil]
|
63
|
-
attr_reader :aliases_re_for_srs_roll_without_target_value
|
64
|
-
|
65
67
|
# 成功判定のエイリアスコマンドを設定する
|
66
68
|
# @param [String] aliases エイリアスコマンド(可変長引数)
|
67
69
|
# @return [self]
|
@@ -70,71 +72,48 @@ module BCDice
|
|
70
72
|
# 実行時にそれが2D6に置換されるようになる。
|
71
73
|
def set_aliases_for_srs_roll(*aliases)
|
72
74
|
aliases_upcase = aliases.map(&:upcase)
|
73
|
-
aliases_part = aliases_upcase
|
74
|
-
.map { |a| Regexp.escape(a) }
|
75
|
-
.join('|')
|
76
|
-
|
77
|
-
@aliases_re_for_srs_roll_with_target_value = Regexp.new(
|
78
|
-
'\A' \
|
79
|
-
"(?:#{aliases_part})" \
|
80
|
-
'((?:[-+][-+\d]+)?>=\d+(?:\[\d*(?:,\d+)?\])?)\z'
|
81
|
-
)
|
82
|
-
|
83
|
-
@aliases_re_for_srs_roll_without_target_value = Regexp.new(
|
84
|
-
'\A' \
|
85
|
-
"(?:#{aliases_part})" \
|
86
|
-
'([-+][-+\d]+)?(\[\d*(?:,\d+)?\])?\z'
|
87
|
-
)
|
88
|
-
|
89
|
-
prepare_help_msg_for_aliases_for_srs_roll(aliases_upcase)
|
90
|
-
@help_message = concatenate_help_messages
|
91
75
|
|
76
|
+
@aliases = aliases_upcase.map { |a| Regexp.escape(a) }
|
77
|
+
@help_message = concatenate_help_messages(aliases_upcase)
|
92
78
|
return self
|
93
79
|
end
|
94
80
|
|
95
81
|
# 成功判定のエイリアスコマンドを未設定にする
|
96
82
|
# @return [self]
|
97
83
|
def clear_aliases_for_srs_roll
|
98
|
-
@
|
99
|
-
@aliases_re_for_srs_roll_without_target_value = nil
|
84
|
+
@aliases = []
|
100
85
|
@help_message = SRS::DEFAULT_HELP_MESSAGE
|
101
|
-
|
102
86
|
return self
|
103
87
|
end
|
104
88
|
|
105
89
|
private
|
106
90
|
|
107
|
-
#
|
91
|
+
# ダイスボットの説明文を結合する
|
108
92
|
# @param [Array<String>] aliases エイリアスコマンドの配列
|
109
|
-
# @return [
|
93
|
+
# @return [String] 結合された説明文
|
110
94
|
# @todo 現在は2文字のエイリアスコマンドに幅を合わせてある。
|
111
95
|
# エイリアスコマンドの文字数が変わる場合があれば、位置を調整するコードが
|
112
96
|
# 必要。
|
113
|
-
def
|
114
|
-
|
97
|
+
def concatenate_help_messages(aliases)
|
98
|
+
help_msg_for_aliases_for_target_value =
|
115
99
|
aliases
|
116
|
-
.map
|
100
|
+
.map do |a|
|
101
|
+
" 例) #{a}+2>=10 2d6+2>=10と同じ(#{a}が2D6のショートカットコマンド)\n"
|
102
|
+
end
|
117
103
|
.join()
|
118
|
-
|
119
|
-
@help_msg_for_aliases_for_srs_roll_without_target_value =
|
104
|
+
help_msg_for_aliases_for_without_target_value =
|
120
105
|
aliases
|
121
106
|
.map do |a|
|
122
107
|
" 例) #{a} 2d6[]と同じ(#{a}が2D6のショートカットコマンド)\n" \
|
123
|
-
" 例) #{a}+2
|
108
|
+
" 例) #{a}+2@12#4 2d6+2@12#4と同じ(#{a}が2D6のショートカットコマンド)\n"
|
124
109
|
end
|
125
110
|
.join()
|
126
111
|
|
127
|
-
return
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
def concatenate_help_messages
|
133
|
-
"#{SRS::HELP_MESSAGE_1}" \
|
134
|
-
"#{@help_msg_for_aliases_for_srs_roll_with_target_value}\n" \
|
135
|
-
"#{SRS::HELP_MESSAGE_2}" \
|
136
|
-
"#{@help_msg_for_aliases_for_srs_roll_without_target_value}\n" \
|
137
|
-
"#{SRS::HELP_MESSAGE_3}"
|
112
|
+
return "#{SRS::HELP_MESSAGE_1}" \
|
113
|
+
"#{help_msg_for_aliases_for_target_value}\n" \
|
114
|
+
"#{SRS::HELP_MESSAGE_2}" \
|
115
|
+
"#{help_msg_for_aliases_for_without_target_value}\n" \
|
116
|
+
"#{SRS::HELP_MESSAGE_3}"
|
138
117
|
end
|
139
118
|
end
|
140
119
|
|
@@ -153,16 +132,10 @@ module BCDice
|
|
153
132
|
DEFAULT_HELP_MESSAGE
|
154
133
|
end
|
155
134
|
|
156
|
-
#
|
157
|
-
# @return [
|
158
|
-
def
|
159
|
-
|
160
|
-
end
|
161
|
-
|
162
|
-
# 目標値なし成功判定のエイリアスコマンドの正規表現を返す
|
163
|
-
# @return [nil]
|
164
|
-
def aliases_re_for_srs_roll_without_target_value
|
165
|
-
nil
|
135
|
+
# 成功判定のエイリアスコマンドの一覧
|
136
|
+
# @return [Array<String>]
|
137
|
+
def aliases
|
138
|
+
[]
|
166
139
|
end
|
167
140
|
end
|
168
141
|
|
@@ -187,22 +160,17 @@ module BCDice
|
|
187
160
|
self.class.help_message
|
188
161
|
end
|
189
162
|
|
163
|
+
# 成功判定のエイリアスコマンドの一覧
|
164
|
+
# @return [Array<String>]
|
165
|
+
def aliases
|
166
|
+
self.class.aliases
|
167
|
+
end
|
168
|
+
|
190
169
|
# 既定のクリティカル値
|
191
170
|
DEFAULT_CRITICAL_VALUE = 12
|
192
171
|
# 既定のファンブル値
|
193
172
|
DEFAULT_FUMBLE_VALUE = 2
|
194
173
|
|
195
|
-
# 目標値あり成功判定の正規表現
|
196
|
-
SRS_ROLL_WITH_TARGET_VALUE_RE =
|
197
|
-
/\A2D6([-+][-+\d]+)?>=(\d+)(?:\[(\d+)?(?:,(\d+))?\])?\z/.freeze
|
198
|
-
# 目標値なし成功判定の正規表現
|
199
|
-
SRS_ROLL_WITHOUT_TARGET_VALUE_RE =
|
200
|
-
/\A2D6([-+][-+\d]+)?\[(\d+)?(?:,(\d+))?\]\z/.freeze
|
201
|
-
|
202
|
-
# 既定の閾値指定表記
|
203
|
-
SRS_ROLL_DEFAULT_THRESHOLDS =
|
204
|
-
"[#{DEFAULT_CRITICAL_VALUE},#{DEFAULT_FUMBLE_VALUE}]"
|
205
|
-
|
206
174
|
# 成功判定コマンドのノード
|
207
175
|
SRSRollNode = Struct.new(
|
208
176
|
:modifier, :critical_value, :fumble_value, :target_value
|
@@ -221,9 +189,15 @@ module BCDice
|
|
221
189
|
# @param [String] command 入力されたコマンド
|
222
190
|
# @return [Result, nil] ダイスロールコマンドの実行結果
|
223
191
|
def eval_game_system_specific_command(command)
|
224
|
-
|
225
|
-
|
226
|
-
|
192
|
+
legacy_c_f_match = /(.+)\[(.*)\]\z/.match(command)
|
193
|
+
node =
|
194
|
+
if legacy_c_f_match
|
195
|
+
parse_legacy(legacy_c_f_match[1], legacy_c_f_match[2])
|
196
|
+
else
|
197
|
+
parse(command)
|
198
|
+
end
|
199
|
+
|
200
|
+
if node
|
227
201
|
return execute_srs_roll(node)
|
228
202
|
end
|
229
203
|
|
@@ -232,67 +206,46 @@ module BCDice
|
|
232
206
|
|
233
207
|
private
|
234
208
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
thresholds = Regexp.last_match(2) || SRS_ROLL_DEFAULT_THRESHOLDS
|
245
|
-
|
246
|
-
return "2D6#{modifier}#{thresholds}"
|
247
|
-
else
|
248
|
-
return input
|
209
|
+
def parse(command)
|
210
|
+
prefix_re = Regexp.new(["2D6"].concat(aliases()).join('|'), Regexp::IGNORECASE)
|
211
|
+
parser = Command::Parser.new(prefix_re, round_type: @round_type)
|
212
|
+
.enable_critical
|
213
|
+
.enable_fumble
|
214
|
+
.restrict_cmp_op_to(nil, :>=)
|
215
|
+
cmd = parser.parse(command)
|
216
|
+
unless cmd
|
217
|
+
return nil
|
249
218
|
end
|
250
|
-
end
|
251
219
|
|
252
|
-
|
253
|
-
|
254
|
-
# @return [SRSRollNode, nil]
|
255
|
-
def parse(command)
|
256
|
-
case command
|
257
|
-
when SRS_ROLL_WITH_TARGET_VALUE_RE
|
258
|
-
return parse_srs_roll_with_target_value(Regexp.last_match)
|
259
|
-
when SRS_ROLL_WITHOUT_TARGET_VALUE_RE
|
260
|
-
return parse_srs_roll_without_target_value(Regexp.last_match)
|
261
|
-
else
|
220
|
+
if command.start_with?(/2D6/i) && cmd.critical.nil? && cmd.fumble.nil? && cmd.target_number.nil?
|
221
|
+
# fallback to default dice
|
262
222
|
return nil
|
263
223
|
end
|
264
|
-
end
|
265
224
|
|
266
|
-
|
267
|
-
|
268
|
-
# @return [Integer] 修正値
|
269
|
-
def eval_modifier(modifier_str)
|
270
|
-
return 0 unless modifier_str
|
225
|
+
cmd.critical ||= DEFAULT_CRITICAL_VALUE
|
226
|
+
cmd.fumble ||= DEFAULT_FUMBLE_VALUE
|
271
227
|
|
272
|
-
return
|
228
|
+
return SRSRollNode.new(cmd.modify_number, cmd.critical, cmd.fumble, cmd.target_number)
|
273
229
|
end
|
274
230
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
target_value = m[2].to_i
|
281
|
-
critical_value = m[3]&.to_i || DEFAULT_CRITICAL_VALUE
|
282
|
-
fumble_value = m[4]&.to_i || DEFAULT_FUMBLE_VALUE
|
231
|
+
def parse_legacy(command, c_f)
|
232
|
+
m = /^(-?\d+)?(?:,(-?\d+))?$/.match(c_f)
|
233
|
+
unless m
|
234
|
+
return nil
|
235
|
+
end
|
283
236
|
|
284
|
-
|
285
|
-
|
237
|
+
critical = m[1]&.to_i || DEFAULT_CRITICAL_VALUE
|
238
|
+
fumble = m[2]&.to_i || DEFAULT_FUMBLE_VALUE
|
286
239
|
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
240
|
+
prefix_re = Regexp.new(["2D6"].concat(aliases()).join('|'), Regexp::IGNORECASE)
|
241
|
+
parser = Command::Parser.new(prefix_re, round_type: @round_type)
|
242
|
+
.restrict_cmp_op_to(nil, :>=)
|
243
|
+
cmd = parser.parse(command)
|
244
|
+
unless cmd
|
245
|
+
return nil
|
246
|
+
end
|
294
247
|
|
295
|
-
return SRSRollNode.new(
|
248
|
+
return SRSRollNode.new(cmd.modify_number, critical, fumble, cmd.target_number)
|
296
249
|
end
|
297
250
|
|
298
251
|
# 成功判定を実行する
|