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

ソード・ワールドの威力表ダイスをパーサを使用したものに変更、半減後修正に対応 #373

Merged
merged 21 commits into from
Feb 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
be60cc7
パーサー作成
h-mikisato Jan 27, 2021
2ea85fe
パーサを使った形に書き換え
h-mikisato Jan 28, 2021
a2d5f1f
ダイステキストの作成およびサニタイズ処理をRatingParsedクラスに移管
h-mikisato Jan 28, 2021
5bdd1e4
ヘルプに半減後加算について記載
h-mikisato Jan 28, 2021
8883a8c
カッコのパターン追記
h-mikisato Jan 28, 2021
42c692f
複数箇所でのmodifierに対応
h-mikisato Jan 28, 2021
49591b9
rubocop
h-mikisato Jan 28, 2021
e653dcd
除算がバグっていたので修正、テスト追加
h-mikisato Jan 28, 2021
92f3005
2.5のヘルプテキストが不完全だったので修正
h-mikisato Jan 28, 2021
297e196
負数の処理をスキップしてしまっていたバグ修正
h-mikisato Jan 28, 2021
7c217a2
仕様が非直感的と指摘を受けたのでヘルプテキスト修正
h-mikisato Jan 28, 2021
c9cd903
レビュー反映
h-mikisato Jan 29, 2021
8aaeca0
rubocop
h-mikisato Jan 29, 2021
b2e7776
複数箇所でのmodifierの統合を許可しない
h-mikisato Jan 29, 2021
f1bddb3
コミット漏れ
h-mikisato Jan 29, 2021
657eddb
半減後加算修正なしの方のパースでエラー処理漏れ
h-mikisato Jan 30, 2021
2209b44
ヘルプメッセージがレビュー前の仕様だったので修正
h-mikisato Feb 2, 2021
bf95d5d
Merge branch 'master' into feature/sw_rating_racc
ysakasin Feb 25, 2021
1111cef
Remove set_round_type
ysakasin Feb 25, 2021
92db21a
sanitized_ではなくgetterで隠蔽する
ysakasin Feb 25, 2021
9e60567
SwordWorld#setRatingTable を削除
ysakasin Feb 25, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ lib/bcdice/common_command/barabara_dice/parser.rb
lib/bcdice/common_command/calc/parser.rb
lib/bcdice/common_command/reroll_dice/parser.rb
lib/bcdice/common_command/upper_dice/parser.rb
lib/bcdice/game_system/sword_world/rating_parser.rb
1 change: 1 addition & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ AllCops:
- lib/bcdice/common_command/calc/parser.rb
- lib/bcdice/common_command/reroll_dice/parser.rb
- lib/bcdice/common_command/upper_dice/parser.rb
- lib/bcdice/game_system/sword_world/rating_parser.rb

# Due to old Ruby 1.8.x
Style/Lambda:
Expand Down
1 change: 1 addition & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ RACC_TARGETS = [
"lib/bcdice/common_command/calc/parser.rb",
"lib/bcdice/common_command/reroll_dice/parser.rb",
"lib/bcdice/common_command/upper_dice/parser.rb",
"lib/bcdice/game_system/sword_world/rating_parser.rb",
].freeze

task racc: RACC_TARGETS
Expand Down
226 changes: 45 additions & 181 deletions lib/bcdice/game_system/SwordWorld.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require "bcdice/game_system/sword_world/rating_parser"

module BCDice
module GameSystem
class SwordWorld < Base
Expand All @@ -22,28 +24,6 @@ def initialize(command)
@rating_table = 0
end

# change_textで使うレーティング表コマンドの正規表現
#
# SW 2.5のダイスボットでも必要なため、共通化のために定数として定義する
RATING_TABLE_RE_FOR_CHANGE_TEXT = /\AS?H?K\d+/i.freeze

# コマンド実行前にメッセージを置換する
# @param [String] string 受信したメッセージ
# @return [String]
def replace_text(string)
return string unless RATING_TABLE_RE_FOR_CHANGE_TEXT.match?(string)

string
.gsub(/\[(\d+)\]/) { "c[#{Regexp.last_match(1)}]" }
.gsub(/@(\d+)/) { "c[#{Regexp.last_match(1)}]" }
.gsub(/\$([-+]?\d+)/) { "m[#{Regexp.last_match(1)}]" }
.gsub(/r([-+]?\d+)/i) { "r[#{Regexp.last_match(1)}]" }
end

def getRatingCommandStrings
"cmCM"
end

def result_2d6(total, dice_total, _dice_list, cmp_op, target)
if dice_total >= 12
Result.critical("自動的成功")
Expand All @@ -64,60 +44,32 @@ def eval_game_system_specific_command(command)

private

def rating_parser
return RatingParser.new
end

#################### SWレーティング表 ########################
def rating(string) # レーティング表
string = replace_text(string)
debug("rating string", string)
command = rating_parser.parse(string)

commands = getRatingCommandStrings

m = /^S?(H?K[\d+\-]+([#{commands}]\[([\d+\-]+)\])*([\d+\-]*)([CMR]\[([\d+\-]+)\]|GF|H)*)/i.match(string)
unless m
unless command
debug("not matched")
return '1'
end

string = m[1]
half = string.include?("H")

rateUp, string = getRateUpFromString(string)
crit, string = getCriticalFromString(string, half)
firstDiceChanteTo, firstDiceChangeModify, string = getDiceChangesFromString(string)

key, addValue = getKeyAndAddValueFromString(string)

return '1' unless key =~ /(\d+)/

key = Regexp.last_match(1).to_i

# 2.0対応
rate_sw2_0 = getSW2_0_RatingTable

keyMax = rate_sw2_0.length - 1
debug("keyMax", keyMax)
if key > keyMax
if command.rate > keyMax
return "キーナンバーは#{keyMax}までです"
end

newRates = getNewRates(rate_sw2_0)

output = "KeyNo.#{key}"

output += "c[#{crit}]" if crit < 13
output += "m[#{firstDiceChangeModify}]" if firstDiceChangeModify != 0
output += "m[#{firstDiceChanteTo}]" if firstDiceChanteTo != 0
output += "r[#{rateUp}]" if rateUp != 0

output, values = getAdditionalString(string, output)

debug('output', output)

if addValue != 0
output += "+#{addValue}" if addValue > 0
output += addValue.to_s if addValue < 0
end

output += " > "
output = "#{command} > "

diceResultTotals = []
diceResults = []
Expand All @@ -126,17 +78,19 @@ def rating(string) # レーティング表
diceOnlyTotal = 0
totalValue = 0
round = 0
first_to = command.first_to
first_modify = command.first_modify

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

if firstDiceChanteTo != 0
dice = dice_raw = firstDiceChanteTo
firstDiceChanteTo = 0
elsif firstDiceChangeModify != 0
dice += firstDiceChangeModify.to_i
firstDiceChangeModify = 0
if first_to != 0
dice = dice_raw = first_to
first_to = 0
elsif first_modify != 0
dice += first_modify
first_modify = 0
end

# 出目がピンゾロの時にはそこで終了
Expand All @@ -149,12 +103,12 @@ def rating(string) # レーティング表
break
end

dice += getAdditionalDiceValue(dice, values)
dice += command.kept_modify if (command.kept_modify != 0) && (dice != 2)

dice = 2 if dice < 2
dice = 12 if dice > 12

currentKey = [key + round * rateUp, keyMax].min
currentKey = [command.rate + round * command.rateup, keyMax].min
debug("currentKey", currentKey)
rateValue = newRates[dice][currentKey]
debug("rateValue", rateValue)
Expand All @@ -168,79 +122,15 @@ def rating(string) # レーティング表

round += 1

break unless dice >= crit
break unless dice >= command.critical
end

output += getResultText(totalValue, addValue, diceResults, diceResultTotals,
rateResults, diceOnlyTotal, round, half)
output += getResultText(totalValue, command, diceResults, diceResultTotals,
rateResults, diceOnlyTotal, round)

return output
end

def getAdditionalString(_string, output)
values = {}
return output, values
end

def getAdditionalDiceValue(_dice, _values)
0
end

def getCriticalFromString(string, half)
crit = half ? 13 : 10

regexp = /c\[(\d+)\]/i

if regexp =~ string
crit = Regexp.last_match(1).to_i
crit = 3 if crit < 3 # エラートラップ(クリティカル値が3未満なら3とする)
string = string.gsub(regexp, '')
end

return crit, string
end

def getDiceChangesFromString(string)
firstDiceChanteTo = 0
firstDiceChangeModify = 0

regexp = /m\[([\d+\-]+)\]/i

if regexp =~ string
firstDiceChangeModify = Regexp.last_match(1)

unless /[+\-]/ =~ firstDiceChangeModify
firstDiceChanteTo = firstDiceChangeModify.to_i
firstDiceChangeModify = 0
end

string = string.gsub(regexp, '')
end

return firstDiceChanteTo, firstDiceChangeModify, string
end

def getRateUpFromString(string)
rateUp = 0
return rateUp, string
end

def getKeyAndAddValueFromString(string)
key = nil
addValue = 0

if /K(\d+)([\d+\-]*)/i =~ string # ボーナスの抽出
key = Regexp.last_match(1)
if Regexp.last_match(2)
addValue = ArithmeticEvaluator.eval(Regexp.last_match(2))
end
else
key = string
end

return key, addValue
end

def getSW2_0_RatingTable
rate_sw2_0 = [
# 0
Expand Down Expand Up @@ -397,23 +287,22 @@ def getNewRates(rate_sw2_0)
return newRates
end

def rollDice(_values)
def rollDice(_command)
dice_list = @randomizer.roll_barabara(2, 6)
total = dice_list.sum()
dice_str = dice_list.join(",")
return total, dice_str
end

# @param rating_total [Integer]
# @param modifier [Integer]
# @param command [SwordWorld::RatingParsed]
# @param diceResults [Array<String>]
# @param diceResultTotals [Array<String>]
# @param rateResults [Array<String>]
# @param dice_total [Integer]
# @param round [Integer]
# @param half [Boolean]
def getResultText(rating_total, modifier, diceResults, diceResultTotals,
rateResults, dice_total, round, half)
def getResultText(rating_total, command, diceResults, diceResultTotals,
rateResults, dice_total, round)
sequence = []

sequence.push("2D:[#{diceResults.join(' ')}]=#{diceResultTotals.join(',')}")
Expand All @@ -425,66 +314,41 @@ def getResultText(rating_total, modifier, diceResults, diceResultTotals,
end

# rate回数が1回で、修正値がない時には途中式と最終結果が一致するので、途中式を省略する
if rateResults.size > 1 || modifier != 0
text = rateResults.join(',') + Format.modifier(modifier)
if half
if rateResults.size > 1 || command.modifier != 0
text = rateResults.join(',') + Format.modifier(command.modifier)
if command.half
text = "(#{text})/2"
if command.modifier_after_half != 0
text += Format.modifier(command.modifier_after_half)
end
end
sequence.push(text)
elsif command.half
text = "#{rateResults.first}/2"
if command.modifier_after_half != 0
text += Format.modifier(command.modifier_after_half)
end
sequence.push(text)
elsif half
sequence.push("#{rateResults.first}/2")
end

if round > 1
round_text = "#{round - 1}回転"
sequence.push(round_text)
end

total = rating_total + modifier
if half
total = rating_total + command.modifier
if command.half
total = (total / 2.0).ceil
if command.modifier_after_half != 0
total += command.modifier_after_half
end
end

total_text = total.to_s
sequence.push(total_text)

return sequence.join(" > ")
end

def setRatingTable(tnick)
mode_str = ""
pre_mode = @rating_table

if /(\d+)/ =~ tnick
@rating_table = Regexp.last_match(1).to_i
if @rating_table > 1
mode_str = "2.0-mode"
@rating_table = 2
elsif @rating_table > 0
mode_str = "new-mode"
@rating_table = 1
else
mode_str = "old-mode"
@rating_table = 0
end
else
case tnick
when /old/i
@rating_table = 0
mode_str = "old-mode"
when /new/i
@rating_table = 1
mode_str = "new-mode"
when /2\.0/i
@rating_table = 2
mode_str = "2.0-mode"
end
end

return '1' if @rating_table == pre_mode

return "RatingTableを#{mode_str}に変更しました"
end
end
end
end
Loading