Skip to content

Commit

Permalink
Merge pull request #373 from h-mikisato/feature/sw_rating_racc
Browse files Browse the repository at this point in the history
ソード・ワールドの威力表ダイスをパーサを使用したものに変更、半減後修正に対応
  • Loading branch information
ysakasin authored Feb 26, 2021
2 parents b23aa3c + 9e60567 commit a2cd6f6
Show file tree
Hide file tree
Showing 11 changed files with 641 additions and 265 deletions.
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

0 comments on commit a2cd6f6

Please sign in to comment.