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

[Revulture] 『光砕のリヴァルチャー』のダイスボットを作成 #427

Merged
merged 17 commits into from
Apr 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
d792e12
[Revulture] とりあえずファイルを用意
Apr 21, 2021
33b58ef
[Revulture] 【アタック判定】のシンプルなダイスロールを追加
Apr 21, 2021
648d19c
[Revulture] 【アタック判定】のダイス数が2桁以上のテストケースを追加
Apr 21, 2021
7447e69
[Revulture] 【アタック判定】のダイス数に加算式を指定できるように
Apr 21, 2021
7f5ffb6
[Revulture] 【アタック判定】のダイス数に除算式を指定できるように
Apr 21, 2021
b8385cb
[Revulture] 【アタック判定】に「目標値」を指定できるように
Apr 21, 2021
5833cac
[Revulture] 【アタック判定】のヒット数が 0 なら失敗、 1 以上なら成功
Apr 21, 2021
278f952
[Revulture] 【アタック判定】に「クリティカルヒット」のルールを実装
Apr 21, 2021
102bf70
[Revulture] Reactor: コードの重複を減らした
Apr 21, 2021
4fb7946
[Revulture] 【アタック判定】で、目標値が指定されなくても、クリティカルヒットを計上するように
Apr 21, 2021
2284cc7
[Revulture] 【アタック判定】の目標値に加算式を指定できるように
Apr 21, 2021
4ce9ec1
[Revulture] 【アタック判定】に、一定以上のヒット数を条件とする追加ダメージを実装
Apr 21, 2021
f228996
[Revulture] 【アタック判定】に、特定の値に等しいヒット数を条件とする追加ダメージを実装
Apr 21, 2021
86e0cdb
[Revulture] 【アタック判定】に、追加ダメージの規則を複数同時に指定できるように
Apr 21, 2021
9613d18
[Revulture] 【アタック判定】のダイス数が 0 となる場合はメッセージにそれを明示する
Apr 21, 2021
a51b0ad
[Revulture] 【アタック判定】の追加ダメージ規則は目標値の指定を必須とする
Apr 21, 2021
f613a81
Rubyっぽく手直し
ysakasin Apr 22, 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 lib/bcdice/game_system.rb
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@
require "bcdice/game_system/Raisondetre"
require "bcdice/game_system/RecordOfLodossWar"
require "bcdice/game_system/RecordOfSteam"
require "bcdice/game_system/Revulture"
require "bcdice/game_system/RokumonSekai2"
require "bcdice/game_system/RoleMaster"
require "bcdice/game_system/RuinBreakers"
Expand Down
123 changes: 123 additions & 0 deletions lib/bcdice/game_system/Revulture.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# frozen_string_literal: true

module BCDice
module GameSystem
class Revulture < Base
# ゲームシステムの識別子
ID = 'Revulture'

# ゲームシステム名
NAME = '光砕のリヴァルチャー'

# ゲームシステム名の読みがな
SORT_KEY = 'こうさいのりうあるちやあ'

# ダイスボットの使い方
HELP_MESSAGE = <<~HELP
■アタック判定( xAT, xATK, xATTACK )
x: ダイス数(加算 + と除算 / を使用可能)
例) 3AT, 4ATK, 5+6ATTACK, 15/2AT

□アタック判定 目標値つき( xAT<=y, xATK<=y, xATTACK<=y )
x: ダイス数(加算 + と除算 / を使用可能)
y: 目標値( 1 以上 6 以下。加算 + を使用可能)
例) 3AT<=4, 3AT<=2+1

□アタック判定 目標値&追加ダメージつき( xAT<=y[>=a:+b], xATK<=y[>=a:+b], xATTACK<=y[z] )
x: ダイス数(加算 + と除算 / を使用可能)
y: 目標値( 1 以上 6 以下。加算 + を使用可能)
z: 追加ダメージの規則(詳細は後述)(※複数同時に指定可能)

▽追加ダメージの規則 [a:+b]
a: ヒット数が a なら
 =a (ヒット数が a に等しい)
 >=a (ヒット数が a 以上)
b: ダメージを b 点追加

例) 3AT<=4[>=2:+3] #ルールブックp056「グレングラントAR」
例) 2AT<=4[=1:+5][>=2:+8] #ルールブックp067「ファーボル・ドラゴンブレス」
HELP

ATTACK_ROLL_REG = %r{^(\d+([+/]\d+)*)?AT(TACK|K)?(<=([1-6](\+\d)*))?((\[>?=\d+:\+\d+\])+)?}i.freeze
register_prefix('\d+([+\/]\d+)*AT')

def eval_game_system_specific_command(command)
if (m = ATTACK_ROLL_REG.match(command))
roll_attack(m[1], m[5], m[7])
end
end

private

def roll_attack(dice_count_expression, border_expression, additional_damage_rules)
dice_count = Arithmetic.eval(dice_count_expression, round_type: RoundType::FLOOR)
border = Arithmetic.eval(border_expression, round_type: RoundType::FLOOR).clamp(1, 6) if border_expression

command = make_command_text(dice_count, border, additional_damage_rules)

if dice_count <= 0
return "#{command} > ダイス数が 0 です"
elsif border.nil? && additional_damage_rules
return "#{command} > 目標値が指定されていないため、追加ダメージを算出できません"
end

dices = @randomizer.roll_barabara(dice_count, 6).sort

critical_hit_count = dices.count(1)
hit_count = dices.count { |dice| dice <= border } + critical_hit_count if border
damage = calc_damage(hit_count, additional_damage_rules)

message_elements = []
message_elements << command
message_elements << dices.join(',')
message_elements << "クリティカル #{critical_hit_count}" if critical_hit_count > 0
message_elements << "ヒット数 #{hit_count}" if hit_count
message_elements << "ダメージ #{damage}" if damage

Result.new(message_elements.join(' > ')).tap do |r|
r.condition = hit_count > 0 if hit_count
r.critical = critical_hit_count > 0
end
end

def make_command_text(dice_count, border, additional_damage_rules)
command = "#{dice_count}attack"
command += "<=#{border}" if border
command += additional_damage_rules if additional_damage_rules

"(#{command})"
end

def calc_damage(hit_count, additional_damage_rules)
return nil unless additional_damage_rules

damage = hit_count
parse_additional_damage_rules(additional_damage_rules).each do |rule|
if rule[:condition].call(hit_count)
damage += rule[:additinal_damage]
end
end

damage
end

def parse_additional_damage_rules(source)
source.scan(/\[(>?=)(\d+):\+(\d+)\]/).map do |matched|
{
condition: make_additional_damage_condition(matched[0], matched[1].to_i),
additinal_damage: matched[2].to_i,
}
end
end

def make_additional_damage_condition(comparer, comparing_target)
case comparer
when '='
lambda { |hit_count| hit_count == comparing_target }
when '>='
lambda { |hit_count| hit_count >= comparing_target }
end
end
end
end
end
Loading