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

ナイトウィザードのリファクタリング #252

Merged
merged 7 commits into from
Aug 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
244 changes: 138 additions & 106 deletions src/diceBot/NightWizard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# frozen_string_literal: true

require "utils/normalize"
require "utils/format"
require "utils/command_parser"

class NightWizard < DiceBot
# ゲームシステムの識別子
Expand All @@ -22,159 +24,189 @@ class NightWizard < DiceBot
 例)12NW-5@7#2  1NW  50nw+5@7,10#2,5 50nw-5+10@7,10#2,5+15+25
INFO_MESSAGE_TEXT

setPrefixes(['\d+NW'])
setPrefixes(['([-+]?\d+)?NW.*', '2R6.*'])

def initialize
super
@sendMode = 2
@nw_command = "NW"
end

def changeText(string)
return string unless string =~ /NW/i

string = string.gsub(/([\-\d]+)NW([\+\-\d]*)@([,\d]+)#([,\d]+)([\+\-\d]*)/i) do
modify = Regexp.last_match(5).empty? ? "" : ",#{Regexp.last_match(5)}"
"2R6m[#{Regexp.last_match(1)}#{Regexp.last_match(2)}#{modify}]c[#{Regexp.last_match(3)}]f[#{Regexp.last_match(4)}]"
# @return [String, nil]
def rollDiceCommand(string)
cmd = parse_nw(string) || parse_2r6(string)
unless cmd
return nil
end

string = string.gsub(/([\-\d]+)NW([\+\-\d]*)/i) { "2R6m[#{Regexp.last_match(1)}#{Regexp.last_match(2)}]" }
string = string.gsub(/NW([\+\-\d]*)/i) { "2R6m[0#{Regexp.last_match(1)}]" }
total, interim_expr, status = roll_nw(cmd)
result =
if cmd.cmp_op
total.send(cmd.cmp_op, cmd.target_number) ? "成功" : "失敗"
end

sequence = [
"(#{cmd})",
interim_expr,
status,
total.to_s,
result,
].compact
return sequence.join(" > ")
end

def dice_command_xRn(string, nick_e)
return checkRoll(string, nick_e)
end
private

class Parsed
# @return [Array<Integer>] クリティカルになる出目の一覧
attr_accessor :critical_numbers

def checkRoll(string, nick_e)
debug('checkRoll string', string)
# @return [Array<Integer>] ファンブルになる出目の一覧
attr_accessor :fumble_numbers

output = '1'
# @return [Integer] ファンブルでない時に適用される修正値
attr_accessor :active_modify_number

num = '[,\d\+\-]+'
return output unless /(^|\s)S?(2R6m\[(#{num})\](c\[(#{num})\])?(f\[(#{num})\])?(([>=]+)(\d+))?)(\s|$)/i =~ string
# @return [Symbol, nil] 比較演算子
attr_accessor :cmp_op

debug('is valid string')
# @return [Integer, nil] 目標値
attr_accessor :target_number
end

string = Regexp.last_match(2)
base_and_modify = Regexp.last_match(3)
criticalText = Regexp.last_match(4)
criticalValue = Regexp.last_match(5)
fumbleText = Regexp.last_match(6)
fumbleValue = Regexp.last_match(7)
judgeText = Regexp.last_match(8)
judgeOperator = Regexp.last_match(9)
judgeValue = Regexp.last_match(10).to_i
class ParsedNW < Parsed
# @return [Integer] 判定の基礎値
attr_accessor :base

crit = "0"
fumble = "0"
cmp_op = nil
diff = 0
# @return [Integer] 修正値
attr_accessor :modify_number

if criticalText
crit = criticalValue
def initialize(command)
@command = command
end

if fumbleText
fumble = fumbleValue
end
if judgeText
diff = judgeValue
debug('judgeOperator', judgeOperator)
cmp_op = Normalize.comparison_operator(judgeOperator)
# 常に適用される修正値を返す
#
# @return [Integer]
def passive_modify_number
@base + @modify_number
end

base, modify = base_and_modify.split(/,/)
base = parren_killer("(0#{base})").to_i
modify = parren_killer("(0#{modify})").to_i
debug("base_and_modify, base, modify", base_and_modify, base, modify)

total, out_str = nw_dice(base, modify, crit, fumble)
# @return [String]
def to_s
base = @base.zero? ? nil : @base
modify_number = Format.modifier(@modify_number)
active_modify_number = Format.modifier(@active_modify_number)

output = "#{nick_e}: (#{string}) > #{out_str}"
if cmp_op
output += check_nDx(total, cmp_op, diff)
return "#{base}#{@command}#{modify_number}@#{@critical_numbers.join(',')}##{@fumble_numbers.join(',')}#{active_modify_number}#{@cmp_op}#{@target_number}"
end

return output
end

def getValueText(text)
value = text.to_i
return value.to_s if value < 0
class Parsed2R6 < Parsed
# @return [Integer] 常に適用される修正値
attr_accessor :passive_modify_number

return "+#{value}"
# @return [String]
def to_s
"2R6M[#{@passive_modify_number},#{@active_modify_number}]C[#{@critical_numbers.join(',')}]F[#{@fumble_numbers.join(',')}]#{@cmp_op}#{@target_number}"
end
end

def nw_dice(base, modify, criticalText, fumbleText)
debug("nw_dice : base, modify, criticalText, fumbleText", base, modify, criticalText, fumbleText)

@criticalValues = getValuesFromText(criticalText, [10])
@fumbleValues = getValuesFromText(fumbleText, [5])
total = 0
output = ""
# @return [ParsedNW, nil]
def parse_nw(string)
m = /^([-+]?\d+)?#{@nw_command}((?:[-+]\d+)+)?(?:@(\d+(?:,\d+)*))?(?:#(\d+(?:,\d+)*))?((?:[-+]\d+)+)?(?:([>=]+)(\d+))?$/.match(string)
unless m
return nil
end

debug('@criticalValues', @criticalValues)
debug('@fumbleValues', @fumbleValues)
ae = ArithmeticEvaluator.new

dice_n, dice_str, = roll(2, 6, 0)
command = ParsedNW.new(@nw_command)
command.base = m[1].to_i
command.modify_number = m[2] ? ae.eval(m[2]) : 0
command.critical_numbers = m[3] ? m[3].split(',').map(&:to_i) : [10]
command.fumble_numbers = m[4] ? m[4].split(',').map(&:to_i) : [5]
command.active_modify_number = m[5] ? ae.eval(m[5]) : 0
command.cmp_op = Normalize.comparison_operator(m[6])
command.target_number = m[7] && m[7].to_i

total = 0
return command
end

if @fumbleValues.include?(dice_n)
fumble_text, total = getFumbleTextAndTotal(base, modify, dice_str)
output = "#{fumble_text} > ファンブル > #{total}"
else
total = base + modify
total, output = checkCritical(total, dice_str, dice_n)
# @return [Parsed2R6, nil]
def parse_2r6(string)
m = /^2R6m\[([-+]?\d+(?:[-+]\d+)*)(?:,([-+]?\d+(?:[-+]\d+)*))?\](?:c\[(\d+(?:,\d+)*)\])?(?:f\[(\d+(?:,\d+)*)\])?(?:([>=]+)(\d+))?/i.match(string)
unless m
return nil
end

return total, output
end
ae = ArithmeticEvaluator.new

def getFumbleTextAndTotal(base, _modify, dice_str)
total = base
total += -10
text = "#{base}-10[#{dice_str}]"
return text, total
end
command = Parsed2R6.new
command.passive_modify_number = ae.eval(m[1])
command.active_modify_number = m[2] ? ae.eval(m[2]) : 0
command.critical_numbers = m[3] ? m[3].split(',').map(&:to_i) : [10]
command.fumble_numbers = m[4] ? m[4].split(',').map(&:to_i) : [5]
command.cmp_op = Normalize.comparison_operator(m[5])
command.target_number = m[6] && m[6].to_i

def setCriticalValues(text)
@criticalValues = getValuesFromText(text, [10])
return command
end

def getValuesFromText(text, default)
if text == "0"
return default
end
def roll_nw(parsed)
@critical_numbers = parsed.critical_numbers
@fumble_numbers = parsed.fumble_numbers

return text.split(/,/).collect { |i| i.to_i }
end
@total = 0
@interim_expr = ""
@status = nil

def checkCritical(total, dice_str, dice_n)
debug("addRollWhenCritical begin total, dice_str", total, dice_str)
output = total.to_s
status = roll_once_first()
while status == :critical
status = roll_once()
end

criticalText = ""
criticalValue = getCriticalValue(dice_n)
base =
if status == :fumble
fumble_base_number(parsed)
else
parsed.passive_modify_number + parsed.active_modify_number
end

while criticalValue
total += 10
output += "+10[#{dice_str}]"
@total += base
@interim_expr = base.to_s + @interim_expr

criticalText = "> クリティカル "
dice_n, dice_str, = roll(2, 6, 0)
return @total, @interim_expr, @status
end

criticalValue = getCriticalValue(dice_n)
debug("criticalValue", criticalValue)
# @return [Symbol, nil]
def roll_once(fumbleable = false)
dice_value, dice_str = roll(2, 6)

if fumbleable && @fumble_numbers.include?(dice_value)
@total -= 10
@interim_expr += "-10[#{dice_str}]"
@status = "ファンブル"
return :fumble
elsif @critical_numbers.include?(dice_value)
@total += 10
@interim_expr += "+10[#{dice_str}]"
@status = "クリティカル"
return :critical
else
@total += dice_value
@interim_expr += "+#{dice_value}[#{dice_str}]"
return nil
end
end

total += dice_n
output += "+#{dice_n}[#{dice_str}] #{criticalText}> #{total}"

return total, output
# @return [Symbol, nil]
def roll_once_first
roll_once(true)
end

def getCriticalValue(dice_n)
return @criticalValues.include?(dice_n)
# @return [Integer]
def fumble_base_number(parsed)
parsed.passive_modify_number
end
end
9 changes: 4 additions & 5 deletions src/diceBot/NightWizard3rd.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ class NightWizard3rd < NightWizard
# ゲームシステムの識別子
ID = 'NightWizard3rd'

def getFumbleTextAndTotal(base, modify, dice_str)
total = base + modify
total += -10
text = "#{base + modify}-10[#{dice_str}]"
return text, total
setPrefixes(['([-+]?\d+)?NW.*', '2R6.*'])

def fumble_base_number(parsed)
parsed.passive_modify_number + parsed.active_modify_number
end
end
16 changes: 3 additions & 13 deletions src/diceBot/SevenFortressMobius.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

require 'diceBot/NightWizard'

class SevenFortressMobius < DiceBot
class SevenFortressMobius < NightWizard
# ゲームシステムの識別子
ID = 'SevenFortressMobius'

Expand All @@ -22,20 +22,10 @@ class SevenFortressMobius < DiceBot
 例)12SFM-5@7#2  1SFM  50SFM+5@7,10#2,5 50SFM-5+10@7,10#2,5+15+25
INFO_MESSAGE_TEXT

setPrefixes(['\d*SFM'])
setPrefixes(['([-+]?\d+)?SFM.*', '2R6.*'])

def initialize
super
@nightWizardDiceBot = NightWizard.new
end

def changeText(string)
string = string.sub(/(\d*)SFM/i) { "#{Regexp.last_match(1)}NW" }

string = @nightWizardDiceBot.changeText(string)
end

def dice_command_xRn(string, nick_e)
return @nightWizardDiceBot.checkRoll(string, nick_e)
@nw_command = "SFM"
end
end
Loading