Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SwordWorld2.0][SwordWorld2.5]レーティング表を1d6+nで参照する機能の追加 #515

Merged
merged 10 commits into from
Dec 1, 2021
8 changes: 6 additions & 2 deletions lib/bcdice/game_system/SwordWorld.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ def rating(string) # レーティング表
return "キーナンバーは#{keyMax}までです"
end

if command.infinite_roll?
return Result.new("C値を#{command.min_critical}以上にしてください")
end

newRates = getNewRates(rate_sw2_0)

output = "#{command} > "
Expand All @@ -83,7 +87,7 @@ def rating(string) # レーティング表
first_modify = command.first_modify

loop do
dice_raw, diceText = rollDice(command)
dice_raw, diceText = rollDice(command, round)
dice = dice_raw

if first_to != 0
Expand Down Expand Up @@ -295,7 +299,7 @@ def getNewRates(rate_sw2_0)
return newRates
end

def rollDice(_command)
def rollDice(_command, _round)
dice_list = @randomizer.roll_barabara(2, 6)
total = dice_list.sum()
dice_str = dice_list.join(",")
Expand Down
25 changes: 20 additions & 5 deletions lib/bcdice/game_system/SwordWorld2_0.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ class SwordWorld2_0 < SwordWorld
・グレイテストフォーチュンは末尾に gf
 例)K20gf K30+24@8GF K40+24@8$12r10gf

・威力表を1d+sfで参照 クリティカル後も継続 sf4
 例)k10sf4 k0+5SF4@13 k70+26sf3@9

・威力表を1d+tfで参照 クリティカル後は2dで参照 tf3
 例)k10tf3 k0+5TF4@13 k70+26tf3@9

・超越判定用に2d6ロールに 2D6@10 書式でクリティカル値付与が可能に。
 例)2D6@10 2D6@10+11>=30

Expand Down Expand Up @@ -108,14 +114,23 @@ def rating_parser
return RatingParser.new(version: :v2_0)
end

def rollDice(command)
def rollDice(command, round)
if command.semi_fixed_val > 0
dice = @randomizer.roll_once(6)
return dice + command.semi_fixed_val, "#{dice},#{command.semi_fixed_val}"
end
if round == 0 && command.tmp_fixed_val > 0
dice = @randomizer.roll_once(6)
return dice + command.tmp_fixed_val, "#{dice},#{command.tmp_fixed_val}"
end
unless command.greatest_fortune
return super(command)
return super(command, round)
end

dice = @randomizer.roll_once(6)

return dice * 2, "#{dice},#{dice}"
if command.greatest_fortune
dice = @randomizer.roll_once(6)
return dice * 2, "#{dice},#{dice}"
end
end

def growth(count = 1)
Expand Down
6 changes: 6 additions & 0 deletions lib/bcdice/game_system/SwordWorld2_5.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ class SwordWorld2_5 < SwordWorld2_0
・グレイテストフォーチュンは末尾に gf
 例)K20gf K30+24@8GF K40+24@8$12r5gf

・威力表を1d+sfで参照 クリティカル後も継続 sf4
 例)k10sf4 k0+5sf4@13 k70+26sf3@9

・威力表を1d+tfで参照 クリティカル後は2dで参照 tf3
 例)k10tf3 k0+5tf4@13 k70+26tf3@9

・超越判定用に2d6ロールに 2D6@10 書式でクリティカル値付与が可能に。
 例)2D6@10 2D6@10+11>=30

Expand Down
49 changes: 46 additions & 3 deletions lib/bcdice/game_system/sword_world/rating_parsed.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ class RatingParsed
# @return [Boolean]
attr_accessor :greatest_fortune

# @return [Integer, nil]
attr_writer :semi_fixed_val

# @return [Integer, nil]
attr_writer :tmp_fixed_val

# @return [Integer]
attr_accessor :modifier

Expand All @@ -33,11 +39,14 @@ class RatingParsed

def initialize
@critical = nil
@min_critical = nil
@kept_modify = nil
@first_to = nil
@first_modify = nil
@greatest_fortune = false
@rateup = nil
@semi_fixed_val = nil
@tmp_fixed_val = nil
end

# @return [Boolean]
Expand All @@ -47,9 +56,22 @@ def half

# @return [Integer]
def critical
crit = @critical || (half ? 13 : 10)
crit = 3 if crit < 3
return crit
return @critical || (half ? 13 : 10)
end

# @return [Integer]
def min_critical
min_critical = 3
unless @semi_fixed_val.nil?
if @kept_modify.nil?
min_critical = @semi_fixed_val + 2 if min_critical < @semi_fixed_val + 2
else
min_critical = @semi_fixed_val + @kept_modify + 2 if min_critical < @semi_fixed_val + @kept_modify + 2
end
min_critical = 3 if @semi_fixed_val == 1
end
min_critical = 13 if min_critical > 13
return min_critical
end

# @return [Integer]
Expand All @@ -67,6 +89,20 @@ def rateup
return @rateup || 0
end

# @return [Integer]
def semi_fixed_val
sf = @semi_fixed_val || 0
sf = 6 if sf > 6
return sf
end

# @return [Integer]
def tmp_fixed_val
tf = @tmp_fixed_val || 0
tf = 6 if tf > 6
return tf
end

# @return [Integer]
def kept_modify
return @kept_modify || 0
Expand All @@ -86,13 +122,20 @@ def to_s()
output += "m[#{first_to}]" if first_to != 0
output += "r[#{rateup}]" if rateup != 0
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 += "a[#{Format.modifier(kept_modify)}]" if kept_modify != 0

if @modifier != 0
output += Format.modifier(@modifier)
end
return output
end

# @return [Boolean]
def infinite_roll?
return critical < min_critical
end
end
end
end
Expand Down
31 changes: 29 additions & 2 deletions lib/bcdice/game_system/sword_world/rating_parser.y
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class RatingParser
token NUMBER K R H G F PLUS MINUS ASTERISK SLASH PARENL PARENR BRACKETL BRACKETR AT SHARP DOLLAR
token NUMBER K R H G F S T PLUS MINUS ASTERISK SLASH PARENL PARENR BRACKETL BRACKETR AT SHARP DOLLAR

expect 4

Expand Down Expand Up @@ -101,11 +101,36 @@ class RatingParser
| option G F
{
option, _, _ = val
raise ParseError unless [:v2_5, :v2_0].include?(@version) && option[:greatest_fortune].nil?
raise ParseError unless [:v2_5, :v2_0].include?(@version)
raise ParseError unless option[:greatest_fortune].nil?
raise ParseError unless option[:semi_fixed_val].nil?
raise ParseError unless option[:tmp_fixed_val].nil?

option[:greatest_fortune] = true
result = option
}
| option S F NUMBER
{
option, _, _, term = val
raise ParseError unless [:v2_5, :v2_0].include?(@version)
raise ParseError unless option[:greatest_fortune].nil?
raise ParseError unless option[:semi_fixed_val].nil?
raise ParseError unless option[:tmp_fixed_val].nil?

option[:semi_fixed_val] = term.to_i
result = option
}
| option T F NUMBER
{
option, _, _, term = val
raise ParseError unless [:v2_5, :v2_0].include?(@version)
raise ParseError unless option[:greatest_fortune].nil?
raise ParseError unless option[:semi_fixed_val].nil?
raise ParseError unless option[:tmp_fixed_val].nil?

option[:tmp_fixed_val] = term.to_i
result = option
}
| option SHARP unary
{
option, _, term = val
Expand Down Expand Up @@ -196,6 +221,8 @@ def parsed(rate, modifier, option)
p.first_modify = option[:first_modify]
p.rateup = option[:rateup]&.eval(@round_type)
p.greatest_fortune = option.fetch(:greatest_fortune, false)
p.semi_fixed_val = option[:semi_fixed_val]
p.tmp_fixed_val = option[:tmp_fixed_val]
p.modifier = modifier.eval(@round_type)
p.modifier_after_half = option[:modifier_after_half]&.eval(@round_type)
end
Expand Down
113 changes: 113 additions & 0 deletions test/data/SwordWorld2_0.toml
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,36 @@ rands = [
{ sides = 6, value = 3 },
]

[[ test ]]
game_system = "SwordWorld2.0"
input = "K40+24sf4@8$12r10"
output = "KeyNo.40c[8]m[12]r[10]sf[4]+24 > 2D:[1,4 5,4 4,4 5,4 2,4]=12,9,8,9,6 > 13,12,13,17,13+24 > 4回転 > 92"
critical = true
rands = [
{ sides = 6, value = 1 },
{ sides = 6, value = 5 },
{ sides = 6, value = 4 },
{ sides = 6, value = 5 },
{ sides = 6, value = 2 },
]

[[ test ]]
game_system = "SwordWorld2.0"
input = "K40+24tf4@8$12r10"
output = "KeyNo.40c[8]m[12]r[10]tf[4]+24 > 2D:[1,4 4,5 5,4 3,5 5,2]=12,9,9,8,7 > 13,12,14,16,16+24 > 4回転 > 95"
critical = true
rands = [
{ sides = 6, value = 1 },
{ sides = 6, value = 4 },
{ sides = 6, value = 5 },
{ sides = 6, value = 5 },
{ sides = 6, value = 4 },
{ sides = 6, value = 3 },
{ sides = 6, value = 5 },
{ sides = 6, value = 5 },
{ sides = 6, value = 2 },
]

[[ test ]]
game_system = "SwordWorld2.0"
input = "K20+5"
Expand Down Expand Up @@ -300,6 +330,89 @@ rands = [
{ sides = 6, value = 1 },
]

[[ test ]]
game_system = "SwordWorld2.0"
input = "k20sf4 sf通常時"
output = "KeyNo.20c[10]sf[4] > 2D:[3,4]=7 > 5"
rands = [
{ sides = 6, value = 3 },
]

[[ test ]]
game_system = "SwordWorld2.0"
input = "k20tf4 tf通常時"
output = "KeyNo.20c[10]tf[4] > 2D:[3,4]=7 > 5"
rands = [
{ sides = 6, value = 3 },
]

[[ test ]]
game_system = "SwordWorld2.0"
input = "k20sf7 sfクリティカル時"
output = "KeyNo.20c[10]sf[6] > 2D:[5,6 4,6 3,6]=11,10,9 > 9,8,7 > 2回転 > 24"
critical = true
rands = [
{ sides = 6, value = 5 },
{ sides = 6, value = 4 },
{ sides = 6, value = 3 },
]

[[ test ]]
game_system = "SwordWorld2.0"
input = "k20tf7 tfクリティカル時"
output = "KeyNo.20c[10]tf[6] > 2D:[5,6 6,5 3,4]=11,11,7 > 9,9,5 > 2回転 > 23"
critical = true
rands = [
{ sides = 6, value = 5 },
{ sides = 6, value = 6 },
{ sides = 6, value = 5 },
{ sides = 6, value = 3 },
{ sides = 6, value = 4 },
]

[[ test ]]
game_system = "SwordWorld2.0"
input = "k20sf1@3 sf自動失敗時"
output = "KeyNo.20c[3]sf[1] > 2D:[1,1]=2 > ** > 自動的失敗"
fumble = true
rands = [
{ sides = 6, value = 1 },
]

[[ test ]]
game_system = "SwordWorld2.0"
input = "k20tf1@3 tf自動失敗時"
output = "KeyNo.20c[3]tf[1] > 2D:[1,1]=2 > ** > 自動的失敗"
fumble = true
rands = [
{ sides = 6, value = 1 },
]

[[ test ]]
game_system = "SwordWorld2.0"
input = "k20tf3@3 tfクリティカル自動失敗時"
output = "KeyNo.20c[3]tf[3] > 2D:[2,3 6,5 1,1]=5,11,2 > 3,9,** > 2回転 > 12"
critical = true
rands = [
{ sides = 6, value = 2 },
{ sides = 6, value = 6 },
{ sides = 6, value = 5 },
{ sides = 6, value = 1 },
{ sides = 6, value = 1 },
]

[[ test ]]
game_system = "SwordWorld2.0"
input = "k20@2 クリティカル下限エラー 通常の下限は3"
output = "C値を3以上にしてください"
rands = []

[[ test ]]
game_system = "SwordWorld2.0"
input = "k20sf2@2 クリティカル下限エラー sfが2以上の時はsf+2"
output = "C値を4以上にしてください"
rands = []

[[ test ]]
game_system = "SwordWorld2.0"
input = "2D6@10+15>=30"
Expand Down
Loading