diff --git a/lib/bcdice/game_system/SwordWorld.rb b/lib/bcdice/game_system/SwordWorld.rb index 0fe88d638..29a549c49 100644 --- a/lib/bcdice/game_system/SwordWorld.rb +++ b/lib/bcdice/game_system/SwordWorld.rb @@ -119,7 +119,11 @@ def rating(string) # レーティング表 currentKey = (command.rate + round * command.rateup).clamp(0, keyMax) debug("currentKey", currentKey) - rateValue = newRates[dice][currentKey] + if dice > command.set_zero_val + rateValue = newRates[dice][currentKey] + else + rateValue = 0 + end debug("rateValue", rateValue) totalValue += rateValue @@ -343,6 +347,11 @@ def getResultText(rating_total, command, diceResults, diceResultTotals, if command.modifier_after_one_and_a_half != 0 text += Format.modifier(command.modifier_after_one_and_a_half) end + elsif command.double + text = "(#{text})*2" + if command.modifier_after_double != 0 + text += Format.modifier(command.modifier_after_double) + end end sequence.push(text) elsif command.half @@ -357,6 +366,12 @@ def getResultText(rating_total, command, diceResults, diceResultTotals, text += Format.modifier(command.modifier_after_one_and_a_half) end sequence.push(text) + elsif command.double + text = "#{rateResults.first}*2" + if command.modifier_after_double != 0 + text += Format.modifier(command.modifier_after_double) + end + sequence.push(text) end if round > 1 @@ -375,6 +390,11 @@ def getResultText(rating_total, command, diceResults, diceResultTotals, if command.modifier_after_one_and_a_half != 0 total += command.modifier_after_one_and_a_half end + elsif command.double + total = (total * 2).ceil + if command.modifier_after_double != 0 + total += command.modifier_after_double + end end total_text = total.to_s diff --git a/lib/bcdice/game_system/SwordWorld2_5.rb b/lib/bcdice/game_system/SwordWorld2_5.rb index 40df852dd..62cc48e38 100644 --- a/lib/bcdice/game_system/SwordWorld2_5.rb +++ b/lib/bcdice/game_system/SwordWorld2_5.rb @@ -34,18 +34,25 @@ class SwordWorld2_5 < SwordWorld2_0 ・レーティング表の半減 (HKx, KxH+N)  レーティング表の先頭または末尾に"H"をつけると、レーティング表を振って最終結果を半減させます。 -  末尾につけた場合、直後に修正ををつけることで、半減後の加減算を行うことができます。 +  末尾につけた場合、直後に修正をつけることで、半減後の加減算を行うことができます。  この際、複数の項による修正にはカッコで囲うことが必要です(カッコがないとパースに失敗します)  クリティカル値を指定しない場合、クリティカルなしと扱われます。  例)HK20  K20h  HK10-5@9  K10-5@9H  K20gfH  K20+8H+2  K20+8H+(1+1) ・レーティング表の1.5倍 (OHKx, KxOH+N)  レーティング表の先頭または末尾に"OH"をつけると、レーティング表を振って最終結果を1.5倍します。 -  末尾につけた場合、直後に修正ををつけることで、1.5倍後の加減算を行うことができます。 +  末尾につけた場合、直後に修正をつけることで、1.5倍後の加減算を行うことができます。  この際、複数の項による修正にはカッコで囲うことが必要です(カッコがないとパースに失敗します)  クリティカル値を指定しない場合、クリティカルなしと扱われます。  例)OHK20  K20oh  OHK10-5@9  K20+8OH+2  K20+8OH+(1+1) + ・レーティング表の2倍 (DBKx, KxDB+N) +  レーティング表の先頭または末尾に"DB"をつけると、レーティング表を振って最終結果を2倍します。 +  末尾につけた場合、直後に修正をつけることで、2倍後の加減算を行うことができます。 +  この際、複数の項による修正にはカッコで囲うことが必要です(カッコがないとパースに失敗します) +  クリティカル値を指定しない場合、クリティカル値10と扱われます。 +  例)DBK20  K20db  DBK10-5@9  K20+8DB+2  K20+8DB+(1+1) + ・ダイス目の修正(運命変転やクリティカルレイ、魔女の火用)  末尾に「$修正値」でダイス目に修正がかかります。  $+1と修正表記ならダイス目に+修正、$9のように固定値ならダイス目をその出目に差し替え。 @@ -70,6 +77,9 @@ class SwordWorld2_5 < SwordWorld2_0 ・威力表を1d+tfで参照 クリティカル後は2dで参照 tf3  例)k10tf3 k0+5tf4@13 k70+26tf3@9 + ・アビスカース「難しい」用に KxSZy 表記でy以下の出目の威力表を0に書き換え。 +  例) k10SZ4 k0+5@13sz6 k40+26@9sz3 + ・超越判定用に2d6ロールに 2D6@10 書式でクリティカル値付与が可能に。  例)2D6@10 2D6@10+11>=30 @@ -90,7 +100,7 @@ class SwordWorld2_5 < SwordWorld2_0  アビスカース表を出すことができます。 INFO_MESSAGE_TEXT - register_prefix('H?K', 'OHK', 'Gr', '2D6?@\d+', 'FT', 'TT', 'Dru', 'ABT') + register_prefix('H?K', 'OHK', 'DBK', 'Gr', '2D6?@\d+', 'FT', 'TT', 'Dru', 'ABT') def eval_game_system_specific_command(command) case command diff --git a/lib/bcdice/game_system/sword_world/rating_options.rb b/lib/bcdice/game_system/sword_world/rating_options.rb index a981e9e4c..9a550797e 100644 --- a/lib/bcdice/game_system/sword_world/rating_options.rb +++ b/lib/bcdice/game_system/sword_world/rating_options.rb @@ -31,6 +31,9 @@ class RatingOptions # @return [Integer, nil] attr_accessor :tmp_fixed_val + # @return [Integer, nil] + attr_accessor :set_zero_val + # @return [Integer, nil] attr_accessor :modifier @@ -40,6 +43,9 @@ class RatingOptions # @return [Integer, nil] attr_accessor :modifier_after_one_and_a_half + # @return [Integer, nil] + attr_accessor :modifier_after_double + def settable_first_roll_adjust_option? return first_modify.nil? && first_to.nil? && first_modify_ssp.nil? end diff --git a/lib/bcdice/game_system/sword_world/rating_parsed.rb b/lib/bcdice/game_system/sword_world/rating_parsed.rb index ae1305a05..e9a55287e 100644 --- a/lib/bcdice/game_system/sword_world/rating_parsed.rb +++ b/lib/bcdice/game_system/sword_world/rating_parsed.rb @@ -34,6 +34,9 @@ class RatingParsed # @return [Integer] attr_accessor :tmp_fixed_val + # @return [Integer] + attr_accessor :set_zero_val + # @return [Integer] attr_accessor :modifier @@ -43,6 +46,9 @@ class RatingParsed # @return [Integer, nil] attr_accessor :modifier_after_one_and_a_half + # @return [Integer, nil] + attr_accessor :modifier_after_double + def initialize(rate, modifier) @rate = rate @modifier = modifier @@ -55,8 +61,10 @@ def initialize(rate, modifier) @rateup = 0 @semi_fixed_val = 0 @tmp_fixed_val = 0 + @set_zero_val = 0 @modifier_after_half = nil @modifier_after_one_and_a_half = nil + @modifier_after_double = nil end # @return [Boolean] @@ -69,6 +77,11 @@ def one_and_a_half return !@modifier_after_one_and_a_half.nil? end + # @return [Boolean] + def double + return !@modifier_after_double.nil? + end + # @return [Integer] def min_critical if @semi_fixed_val <= 1 @@ -95,6 +108,7 @@ def to_s() output += "gf" if @greatest_fortune output += "sf[#{semi_fixed_val}]" if semi_fixed_val != 0 output += "tf[#{tmp_fixed_val}]" if tmp_fixed_val != 0 + output += "sz[#{set_zero_val}]" if set_zero_val != 0 output += "a[#{Format.modifier(kept_modify)}]" if kept_modify != 0 if @modifier != 0 diff --git a/lib/bcdice/game_system/sword_world/rating_parser.y b/lib/bcdice/game_system/sword_world/rating_parser.y index 505011c86..dcff44546 100644 --- a/lib/bcdice/game_system/sword_world/rating_parser.y +++ b/lib/bcdice/game_system/sword_world/rating_parser.y @@ -1,5 +1,5 @@ class RatingParser - token NUMBER K R H O G F S T PLUS MINUS ASTERISK SLASH PARENL PARENR BRACKETL BRACKETR AT SHARP DOLLAR TILDE + token NUMBER K R H O D B G F S T Z PLUS MINUS ASTERISK SLASH PARENL PARENR BRACKETL BRACKETR AT SHARP DOLLAR TILDE expect 4 @@ -13,7 +13,7 @@ class RatingParser | H rate option { _, rate, option = val - raise ParseError if option.modifier_after_one_and_a_half + raise ParseError if option.modifier_after_one_and_a_half or option.modifier_after_double option.modifier_after_half ||= Arithmetic::Node::Number.new(0) modifier = option.modifier || Arithmetic::Node::Number.new(0) result = parsed(rate, modifier.eval(@round_type), option) @@ -21,11 +21,19 @@ class RatingParser | O H rate option { _, _, rate, option = val - raise ParseError if option.modifier_after_half + raise ParseError if option.modifier_after_half or option.modifier_after_double option.modifier_after_one_and_a_half ||= Arithmetic::Node::Number.new(0) modifier = option.modifier || Arithmetic::Node::Number.new(0) result = parsed(rate, modifier.eval(@round_type), option) } + | D B rate option + { + _, _, rate, option = val + raise ParseError if option.modifier_after_half or option.modifier_after_one_and_a_half + option.modifier_after_double ||= Arithmetic::Node::Number.new(0) + modifier = option.modifier || Arithmetic::Node::Number.new(0) + result = parsed(rate, modifier.eval(@round_type), option) + } rate: K NUMBER @@ -123,6 +131,22 @@ class RatingParser option.modifier_after_one_and_a_half = term result = option } + | option D B + { + option, _, _ = val + raise ParseError unless option.modifier_after_double.nil? + + option.modifier_after_double = Arithmetic::Node::Number.new(0) + result = option + } + | option D B unary + { + option, _, _, term = val + raise ParseError unless option.modifier_after_double.nil? + + option.modifier_after_double = term + result = option + } | option R unary { option, _, term = val @@ -155,6 +179,14 @@ class RatingParser option.tmp_fixed_val = term.to_i result = option } + | option S Z NUMBER + { + option, _, _, term = val + raise ParseError unless [:v2_5].include?(@version) + + option.set_zero_val = term.to_i + result = option + } | option SHARP unary { option, _, term = val @@ -247,8 +279,10 @@ def parsed(rate, modifier, option) p.greatest_fortune = option.greatest_fortune if !option.greatest_fortune.nil? p.semi_fixed_val = option.semi_fixed_val&.clamp(1, 6) || 0 p.tmp_fixed_val = option.tmp_fixed_val&.clamp(1, 6) || 0 + p.set_zero_val = option.set_zero_val || 0 p.modifier_after_half = option.modifier_after_half&.eval(@round_type) p.modifier_after_one_and_a_half = option.modifier_after_one_and_a_half&.eval(@round_type) + p.modifier_after_double = option.modifier_after_double&.eval(@round_type) p.critical = option.critical&.eval(@round_type)&.clamp(0, 13) || (p.half || p.one_and_a_half ? 13 : 10) end end diff --git a/test/data/SwordWorld2_5.toml b/test/data/SwordWorld2_5.toml index 54b25952c..14edd1dfc 100644 --- a/test/data/SwordWorld2_5.toml +++ b/test/data/SwordWorld2_5.toml @@ -574,6 +574,119 @@ input = "ohk10h" output = "" rands = [] +[[ test ]] +game_system = "SwordWorld2.5" +input = "DBk10 DBKのクリティカル値は10" +output = "KeyNo.10c[10] > 2D:[6,6 5,3]=12,8 > (7,4)*2 > 1回転 > 22" +critical = true +rands = [ + { sides = 6, value = 6 }, + { sides = 6, value = 6 }, + { sides = 6, value = 5 }, + { sides = 6, value = 3 }, +] + +[[ test ]] +game_system = "SwordWorld2.5" +input = "k10db" +output = "KeyNo.10c[10] > 2D:[6,6 5,3]=12,8 > (7,4)*2 > 1回転 > 22" +critical = true +rands = [ + { sides = 6, value = 6 }, + { sides = 6, value = 6 }, + { sides = 6, value = 5 }, + { sides = 6, value = 3 }, +] + +[[ test ]] +game_system = "SwordWorld2.5" +input = "dbk10db" +output = "KeyNo.10c[10] > 2D:[2,6]=8 > 4*2 > 8" +rands = [ + { sides = 6, value = 2 }, + { sides = 6, value = 6 }, +] + +[[ test ]] +game_system = "SwordWorld2.5" +input = "dbk10[9]+10" +output = "KeyNo.10c[9]+10 > 2D:[5,3]=8 > (4+10)*2 > 28" +rands = [ + { sides = 6, value = 5 }, + { sides = 6, value = 3 }, +] + +[[ test ]] +game_system = "SwordWorld2.5" +input = "dbk10[9]+10" +output = "KeyNo.10c[9]+10 > 2D:[2,4]=6 > (3+10)*2 > 26" +rands = [ + { sides = 6, value = 2 }, + { sides = 6, value = 4 }, +] + +[[ test ]] +game_system = "SwordWorld2.5" +input = "dbK20+6@4" +output = "KeyNo.20c[4]+6 > 2D:[4,3 2,5 2,6 1,1]=7,7,8,2 > (5,5,6,**+6)*2 > 3回転 > 44" +critical = true +rands = [ + { sides = 6, value = 4 }, + { sides = 6, value = 3 }, + { sides = 6, value = 2 }, + { sides = 6, value = 5 }, + { sides = 6, value = 2 }, + { sides = 6, value = 6 }, + { sides = 6, value = 1 }, + { sides = 6, value = 1 }, +] + +[[ test ]] +game_system = "SwordWorld2.5" +input = "K20+6@4db" +output = "KeyNo.20c[4]+6 > 2D:[4,3 2,5 2,6 1,1]=7,7,8,2 > (5,5,6,**+6)*2 > 3回転 > 44" +critical = true +rands = [ + { sides = 6, value = 4 }, + { sides = 6, value = 3 }, + { sides = 6, value = 2 }, + { sides = 6, value = 5 }, + { sides = 6, value = 2 }, + { sides = 6, value = 6 }, + { sides = 6, value = 1 }, + { sides = 6, value = 1 }, +] + +[[ test ]] +game_system = "SwordWorld2.5" +input = "k20db+1+1" +output = "KeyNo.20c[10]+1 > 2D:[2,6]=8 > (6+1)*2+1 > 15" +rands = [ + { sides = 6, value = 2 }, + { sides = 6, value = 6 }, +] + +[[ test ]] +game_system = "SwordWorld2.5" +input = "k20db+(1+1)" +output = "KeyNo.20c[10] > 2D:[2,6]=8 > 6*2+2 > 14" +rands = [ + { sides = 6, value = 2 }, + { sides = 6, value = 6 }, +] + +[[ test ]] +game_system = "SwordWorld2.5" +input = "dbk10oh" +output = "" +rands = [] + +[[ test ]] +game_system = "SwordWorld2.5" +input = "ohk10db" +output = "" +rands = [] + [[ test ]] game_system = "SwordWorld2.5" input = "k20sf4 sf通常時" @@ -681,6 +794,62 @@ input = "k20sf1#8@2 クリティカル下限エラー sfが1の時の下限は3" output = "C値を3以上にしてください" rands = [] +[[ test ]] +game_system = "SwordWorld2.5" +input = "k20+5SZ4" +output = "KeyNo.20c[10]sz[4]+5 > 2D:[5,5 1,2]=10,3 > 8,0+5 > 1回転 > 13" +critical = true +rands = [ + { sides = 6, value = 5 }, + { sides = 6, value = 5 }, + { sides = 6, value = 1 }, + { sides = 6, value = 2 }, +] + +[[ test ]] +game_system = "SwordWorld2.5" +input = "k20sz4" +output = "KeyNo.20c[10]sz[4] > 2D:[3,2]=5 > 3" +rands = [ + { sides = 6, value = 3 }, + { sides = 6, value = 2 }, +] + +[[ test ]] +game_system = "SwordWorld2.5" +input = "k20tf3sz4" +output = "KeyNo.20c[10]tf[3]sz[4] > 2D:[1,3]=4 > 0" +rands = [ + { sides = 6, value = 1 }, +] + +[[ test ]] +game_system = "SwordWorld2.5" +input = "k20sz4sf3" +output = "KeyNo.20c[10]sf[3]sz[4] > 2D:[1,3]=4 > 0" +rands = [ + { sides = 6, value = 1 }, +] + +[[ test ]] +game_system = "SwordWorld2.5" +input = "k20$+1sz5" +output = "KeyNo.20c[10]m[+1]sz[5] > 2D:[3,1]=5 > 0" +rands = [ + { sides = 6, value = 3 }, + { sides = 6, value = 1 }, +] + +[[ test ]] +game_system = "SwordWorld2.5" +input = "k20sz4" +output = "KeyNo.20c[10]sz[4] > 2D:[1,1]=2 > ** > 自動的失敗" +fumble = true +rands = [ + { sides = 6, value = 1 }, + { sides = 6, value = 1 }, +] + [[ test ]] game_system = "SwordWorld2.5" input = "2D6@10+15>=30"