Skip to content

Commit

Permalink
ネクロニカのダイスボットを改善 (#440)
Browse files Browse the repository at this point in the history
* コンフリクト解決

* テストを修正

* マージミス修正

* 日本語テストが通るように

* ネクロニカのリファクタリング

* rubocop

* 1d10>=?でバグる問題を修正。prefix_numberを使用。

* game_systemの誤りを修正

* [Nechronica] リファクタリング

* [Nechronica] 1D10のテストケース不足分を再追加

Co-authored-by: SAKATA Sinji <[email protected]>
  • Loading branch information
GenKuzumochi and ysakasin authored May 25, 2021
1 parent 9f7434a commit a587a56
Show file tree
Hide file tree
Showing 3 changed files with 304 additions and 2,142 deletions.
148 changes: 57 additions & 91 deletions lib/bcdice/game_system/Nechronica.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ class Nechronica < Base
# ダイスボットの使い方
HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
・判定 (nNC+m)
 ダイス数n、修正値mで判定ロールを行います
 ダイス数n、修正値mで判定ロールを行います(省略=1)
 ダイス数が2以上の時のパーツ破損数も表示します。
・攻撃判定 (nNA+m)
 ダイス数n、修正値mで攻撃判定ロールを行います
 ダイス数n、修正値mで攻撃判定ロールを行います(省略=1)
 命中部位とダイス数が2以上の時のパーツ破損数も表示します。
Expand All @@ -37,126 +37,92 @@ def initialize(command)
@default_target_number = 6 # 目標値が空欄の時の目標値
end

private

def replace_text(string)
string = string.gsub(/(\d+)NC(10)?([+\-][+\-\d]+)/i) { "#{Regexp.last_match(1)}R10#{Regexp.last_match(3)}[0]" }
string = string.gsub(/(\d+)NC(10)?/i) { "#{Regexp.last_match(1)}R10[0]" }
string = string.gsub(/(\d+)NA(10)?([+\-][+\-\d]+)/i) { "#{Regexp.last_match(1)}R10#{Regexp.last_match(3)}[1]" }
string = string.gsub(/(\d+)NA(10)?/i) { "#{Regexp.last_match(1)}R10[1]" }

return string
def eval_game_system_specific_command(command)
roll_tables(command, self.class::TABLES) || nechronica_check(command)
end

public
def result_nd10(total, _dice_total, value_list, cmp_op, target)
# 後方互換を維持するため、1d10>=nを目標値nの1NCとして処理
if value_list.count != 1 || cmp_op != :>= || target.nil? || target == "?"
return nil
end

def eval_game_system_specific_command(command)
return roll_tables(command, self.class::TABLES) || nechronica_check(command)
result_nechronica([total], target)
end

private

def result_nd10(total, _dice_total, dice_list, cmp_op, target) # ゲーム別成功度判定(nD10)
return Result.nothing if target == '?'
return nil unless cmp_op == :>=

if total >= 11
Result.critical(translate("Nechronica.critical"))
elsif total >= target
Result.success(translate("success"))
elsif dice_list.count { |i| i <= 1 } == 0
def result_nechronica(value_list, target)
if value_list.max >= target
if value_list.max >= 11
Result.critical(translate("Nechronica.critical"))
else
Result.success(translate("success"))
end
elsif value_list.count { |i| i <= 1 } == 0
Result.failure(translate("failure"))
elsif dice_list.size > 1
fumble = translate("Nechronica.fumble")
elsif value_list.size > 1
break_all_parts = translate("Nechronica.break_all_parts")
fumble = translate("Nechronica.fumble")
Result.fumble("#{fumble}#{break_all_parts}")
else
Result.fumble(translate("Nechronica.fumble"))
end
end

def result_nd10_text(total, dice_list, target)
text = result_nd10(total, 0, dice_list, :>=, target)&.text
# Rコマンドの後方互換を維持する
def r_backward_compatibility(command)
m = command.match(/^(\d)?R10([+\-\d]+)?(\[(\d+)\])?$/)
return command unless m

if text.nil?
""
if m[4] == "1"
"#{m[1]}NA#{m[2]}"
else
"#{text}"
"#{m[1]}NC#{m[2]}"
end
end

def nechronica_check(string)
string = replace_text(string)
debug("nechronica_check string", string)

unless /(^|\s)S?((\d+)[rR]10([+\-\d]+)?(\[(\d+)\])?)(\s|$)/i =~ string
return nil
end

string = Regexp.last_match(2)
def nechronica_check(command)
command = r_backward_compatibility(command)
# 歴史的経緯で10を受理する
cmd = Command::Parser.new(/N[CA](10)?/, round_type: round_type)
.enable_prefix_number.parse(command)
return nil unless cmd

dice_n = 1
dice_n = Regexp.last_match(3).to_i if Regexp.last_match(3)
dice_count = [1, cmd.prefix_number.to_i].max
modify_number = cmd.modify_number || 0

battleMode = Regexp.last_match(6).to_i
dice = @randomizer.roll_barabara(dice_count, 10).sort
dice_mod = dice.map { |i| i + modify_number }
total = dice_mod.max

modText = Regexp.last_match(4)
mod = ArithmeticEvaluator.eval(modText)
na = get_hit_location(total) if cmd.command.start_with?("NA")

# 0=判定モード, 1=戦闘モード
isBattleMode = (battleMode == 1)
debug("nechronica_check string", string)
debug("isBattleMode", isBattleMode)
result = result_nechronica(dice_mod, 6)

diff = 6
sequence = [
"(#{cmd})",
"[#{dice.join(',')}]#{Format.modifier(modify_number)}",
"#{total}[#{dice_mod.join(',')}]",
result.text,
na,
].compact

dice = @randomizer.roll_barabara(dice_n, 10).sort
n_max = dice.max

total_n = n_max + mod

output = "(#{string}) > [#{dice.join(',')}]"
if mod < 0
output += mod.to_s
elsif mod > 0
output += "+#{mod}"
end

dice.map! { |i| i + mod }

dice_str = dice.join(",")
output += " > #{total_n}[#{dice_str}]"

output += result_nd10_text(total_n, dice, diff)

if isBattleMode
hit_loc = getHitLocation(total_n)
if hit_loc != '1'
output += " > #{hit_loc}"
end
end

return output
result.text = sequence.join(" > ")
return result
end

def getHitLocation(dice)
output = '1'

debug("getHitLocation dice", dice)
return output if dice <= 5
def get_hit_location(value)
return nil if value <= 5

table = translate("Nechronica.hit_location.table")
index = dice - 6
text = table[(value - 6).clamp(0, 5)]

addDamage = ""
if dice > 10
index = 5
addDamage = translate("Nechronica.hit_location.additional_damage", damage: dice - 10)
if value > 10
text + translate("Nechronica.hit_location.additional_damage", damage: value - 10)
else
text
end

output = table[index] + addDamage

return output
end

class << self
Expand All @@ -173,7 +139,7 @@ def translate_tables(locale)

TABLES = translate_tables(:ja_jp)

register_prefix('\d+NC', '\d+NA', '\d+R10', TABLES.keys)
register_prefix('\d?NC', '\d?NA', '\dR10', TABLES.keys)
end
end
end
Loading

0 comments on commit a587a56

Please sign in to comment.