diff --git a/lib/bcdice/dice_table.rb b/lib/bcdice/dice_table.rb index 94243cba9..db5459500 100644 --- a/lib/bcdice/dice_table.rb +++ b/lib/bcdice/dice_table.rb @@ -2,6 +2,7 @@ require "bcdice/dice_table/roll_result" require "bcdice/dice_table/chain_table" +require "bcdice/dice_table/chain_with_text" require "bcdice/dice_table/d66_grid_table" require "bcdice/dice_table/d66_half_grid_table" require "bcdice/dice_table/d66_one_third_table" diff --git a/lib/bcdice/dice_table/chain_table.rb b/lib/bcdice/dice_table/chain_table.rb index 7505c6710..4c5118400 100644 --- a/lib/bcdice/dice_table/chain_table.rb +++ b/lib/bcdice/dice_table/chain_table.rb @@ -26,9 +26,8 @@ def roll(randomizer) value = randomizer.roll_sum(@times, @sides) index = value - @times chosen = @items[index] - chosen = chosen.roll(randomizer) if chosen.respond_to?(:roll) - return RollResult.new(@name, value, chosen) + RollResult.new_with_chain(@name, value, chosen, randomizer) end end end diff --git a/lib/bcdice/dice_table/chain_with_text.rb b/lib/bcdice/dice_table/chain_with_text.rb new file mode 100644 index 000000000..3fb722695 --- /dev/null +++ b/lib/bcdice/dice_table/chain_with_text.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module BCDice + module DiceTable + # 表を連続して振る際にテキストを付加する + class ChainWithText + # 次のテーブルに遷移する前に表示するテキスト + # @return [String] + attr_reader :text + + # 次のテーブル + # @return [#roll] + attr_reader :table + + # @param text [String] + # @param table [#roll] + # @return [ChainWithText] + def initialize(text, table) + @text = text + @table = table + end + end + end +end diff --git a/lib/bcdice/dice_table/d66_table.rb b/lib/bcdice/dice_table/d66_table.rb index 3dcf598fa..b714b3c1f 100644 --- a/lib/bcdice/dice_table/d66_table.rb +++ b/lib/bcdice/dice_table/d66_table.rb @@ -38,8 +38,8 @@ def roll(randomizer) key = dice[0] * 10 + dice[1] chosen = @items[key] - chosen = chosen.roll(randomizer) if chosen.respond_to?(:roll) - RollResult.new(@name, key, chosen) + + RollResult.new_with_chain(@name, key, chosen, randomizer) end def choice(key) diff --git a/lib/bcdice/dice_table/roll_result.rb b/lib/bcdice/dice_table/roll_result.rb index e1a89130b..a2c7d5ebb 100644 --- a/lib/bcdice/dice_table/roll_result.rb +++ b/lib/bcdice/dice_table/roll_result.rb @@ -3,13 +3,27 @@ module BCDice module DiceTable class RollResult + class << self + def new_with_chain(table_name, value, result, randomizer) + if result.is_a?(ChainWithText) + new(table_name, value, result.text, result.table.roll(randomizer)) + elsif result.respond_to?(:roll) + new(table_name, value, result.roll(randomizer)) + else + new(table_name, value, result) + end + end + end + # @param table_name [String] # @param value [Integer] # @param body [String, RollResult] - def initialize(table_name, value, body) + # @param succ [RollResult, nil] + def initialize(table_name, value, body, succ = nil) @table_name = table_name @value = value @body = body + @succ = succ end # @return [String] @@ -21,14 +35,23 @@ def initialize(table_name, value, body) # @return [String, RollResult] attr_reader :body + # @return [RollResult, nil] + attr_reader :succ + # @return [String] def to_s - "#{@table_name}(#{@value}) > #{@body}" + if @succ + "#{@table_name}(#{@value}) > #{@body} > #{@succ}" + else + "#{@table_name}(#{@value}) > #{@body}" + end end # @return [String] def last_body - if @body.is_a?(RollResult) + if @succ + @succ.last_body + elsif @body.is_a?(RollResult) @body.last_body else @body diff --git a/lib/bcdice/game_system/Yggdrasill.rb b/lib/bcdice/game_system/Yggdrasill.rb index c1d8798c7..8798a115a 100644 --- a/lib/bcdice/game_system/Yggdrasill.rb +++ b/lib/bcdice/game_system/Yggdrasill.rb @@ -327,25 +327,6 @@ def roll(randomizer) end end - class ChainTable < DiceTable::Table - def initialize(name, type, items, additonal_table:, additonal_index:) - super(name, type, items) - - @additonal_table = additonal_table - @index = additonal_index - end - - def roll(randomizer) - value = randomizer.roll_sum(@times, @sides) - chosen = choice(value) - - return chosen unless @index.include?(value) - - body = "#{chosen.body} > #{@additonal_table.roll(randomizer)}" - DiceTable::RollResult.new(chosen.table_name, chosen.value, body) - end - end - PSY_TABLE = DiceTable::Table.new( "能力タイプ", "1D6", @@ -538,19 +519,17 @@ def roll(randomizer) '記憶崩壊【記憶に異常が起こる。記憶障害、記憶喪失、など】' ] ), - "FATAL2" => ChainTable.new( + "FATAL2" => DiceTable::ChainTable.new( "因子変化判定", "1D6", [ - '能力変化【能力がまったく別ものに変化する】', - '能力変化【能力がまったく別ものに変化する】', + DiceTable::ChainWithText.new('能力変化【能力がまったく別ものに変化する】', PSY_TABLE), + DiceTable::ChainWithText.new('能力変化【能力がまったく別ものに変化する】', PSY_TABLE), '因子抑制【能力変化は起こらない】', '因子抑制【能力変化は起こらない】', - '能力喪失・能力覚醒【能力を持つものは失い、ノーマルは能力に覚醒する。喪失者はノーマルのキャラ特性ポイントを1p獲得する。覚醒者はノーマルのキャラ特性ポイントを1p失い、キャラ特性を6つ取得していた場合は1つ喪失する】', - '能力喪失・能力覚醒【能力を持つものは失い、ノーマルは能力に覚醒する。喪失者はノーマルのキャラ特性ポイントを1p獲得する。覚醒者はノーマルのキャラ特性ポイントを1p失い、キャラ特性を6つ取得していた場合は1つ喪失する】', - ], - additonal_table: PSY_TABLE, - additonal_index: [1, 2, 5, 6] + DiceTable::ChainWithText.new('能力喪失・能力覚醒【能力を持つものは失い、ノーマルは能力に覚醒する。喪失者はノーマルのキャラ特性ポイントを1p獲得する。覚醒者はノーマルのキャラ特性ポイントを1p失い、キャラ特性を6つ取得していた場合は1つ喪失する】', PSY_TABLE), + DiceTable::ChainWithText.new('能力喪失・能力覚醒【能力を持つものは失い、ノーマルは能力に覚醒する。喪失者はノーマルのキャラ特性ポイントを1p獲得する。覚醒者はノーマルのキャラ特性ポイントを1p失い、キャラ特性を6つ取得していた場合は1つ喪失する】', PSY_TABLE), + ] ), "STAG" => DiceTable::D66Table.new( "ステージ決定", diff --git a/test/test_chained_result.rb b/test/test_chained_result.rb new file mode 100644 index 000000000..de1c1bc36 --- /dev/null +++ b/test/test_chained_result.rb @@ -0,0 +1,115 @@ +# frozen_string_literal: true + +require "test/unit" +require "bcdice" +require "bcdice/dice_table/chain_table" +require "bcdice/dice_table/chain_with_text" +require "bcdice/dice_table/d66_table" + +require_relative "randomizer_mock" + +class TestChainedResult < Test::Unit::TestCase + def setup + @test_sub_table_b = BCDice::DiceTable::Table.new( + "SubTableB", + "1D6", + [ + "U", + "V", + "W", + "X", + "Y", + "Z", + ] + ) + + @test_sub_table_a = BCDice::DiceTable::ChainTable.new( + "SubTableA", + "1D6", + [ + "H", + BCDice::DiceTable::ChainWithText.new("I", @test_sub_table_b), + "J", + "K", + BCDice::DiceTable::ChainWithText.new("L", @test_sub_table_b), + "M", + ] + ) + + @test_table = BCDice::DiceTable::ChainTable.new( + "MainTable", + "1D6", + [ + BCDice::DiceTable::ChainWithText.new("A", @test_sub_table_a), + "B", + BCDice::DiceTable::ChainWithText.new("C", @test_sub_table_b), + BCDice::DiceTable::ChainWithText.new("D", @test_sub_table_a), + "E", + BCDice::DiceTable::ChainWithText.new("F", @test_sub_table_b), + ] + ) + + @test_table_d66 = BCDice::DiceTable::D66Table.new( + "TableD66", + :asc, + { + 11 => "あ", + 12 => BCDice::DiceTable::ChainWithText.new("い", @test_sub_table_a), + 13 => "う", + 14 => "え", + 15 => "お", + 16 => "か", + 22 => "き", + 23 => "く", + 24 => "け", + 25 => "こ", + 26 => "さ", + 33 => BCDice::DiceTable::ChainWithText.new("し", @test_sub_table_a), + 34 => "す", + 35 => "せ", + 36 => "そ", + 44 => "た", + 45 => "ち", + 46 => "つ", + 55 => "て", + 56 => BCDice::DiceTable::ChainWithText.new("と", @test_sub_table_b), + 66 => "な", + } + ) + end + + def test_not_chain + randomizer = RandomizerMock.new([[2, 6]]) + assert_equal("MainTable(2) > B", @test_table.roll(randomizer).to_s) + end + + def test_single_chain_1 + randomizer = RandomizerMock.new([[1, 6], [3, 6]]) + assert_equal("MainTable(1) > A > SubTableA(3) > J", @test_table.roll(randomizer).to_s) + end + + def test_single_chain_2 + randomizer = RandomizerMock.new([[6, 6], [4, 6]]) + assert_equal("MainTable(6) > F > SubTableB(4) > X", @test_table.roll(randomizer).to_s) + end + + def test_double_chain + randomizer = RandomizerMock.new([[4, 6], [2, 6], [3, 6]]) + assert_equal("MainTable(4) > D > SubTableA(2) > I > SubTableB(3) > W", @test_table.roll(randomizer).to_s) + end + + def test_d66_single_chain_1 + randomizer = RandomizerMock.new([[3, 6], [3, 6], [6, 6]]) + assert_equal("TableD66(33) > し > SubTableA(6) > M", @test_table_d66.roll(randomizer).to_s) + end + + def test_d66_single_chain_2 + randomizer = RandomizerMock.new([[5, 6], [6, 6], [1, 6]]) + assert_equal("TableD66(56) > と > SubTableB(1) > U", @test_table_d66.roll(randomizer).to_s) + end + + def test_d66_double_chain + randomizer = RandomizerMock.new([[1, 6], [2, 6], [5, 6], [2, 6]]) + assert_equal("TableD66(12) > い > SubTableA(5) > L > SubTableB(2) > V", @test_table_d66.roll(randomizer).to_s) + end +end