Class: BCDice::DiceTable::RangeTable

Inherits:
Object
  • Object
show all
Defined in:
lib/bcdice/dice_table/range_table.rb

Overview

各項目について、Rangeを用いて出目の合計の範囲を指定する、表のクラス。

このクラスを使うと、表の定義を短く書ける。このクラスを使って表を定義するときは、各項目を以下の形で書く。

[出目の合計の範囲, 内容]

「出目の合計の範囲」には、Integerを要素とするRangeか、Integerを置ける。

roll メソッドで表を振ると、出目の合計値と対応する項目が選ばれる。

Examples:

表の定義(バトルテックの致命的命中表)

CRITICAL_TABLE = RangeTable.new(
  '致命的命中表',
  '2D6',
  [
    [2..7,   '致命的命中はなかった'],
    [8..9,   '1箇所の致命的命中'],
    [10..11, '2箇所の致命的命中'],
    [12,     'その部位が吹き飛ぶ(腕、脚、頭)または3箇所の致命的命中(胴)']
  ]
)

表を振った結果

CRITICAL_TABLE.roll(bcdice).formatted
# 出目の合計が7の場合 :"致命的命中表(7) > 致命的命中はなかった"
# 出目の合計が8の場合 :"致命的命中表(8) > 1箇所の致命的命中"
# 出目の合計が9の場合 :"致命的命中表(9) > 1箇所の致命的命中"
# 出目の合計が10の場合:"致命的命中表(10) > 2箇所の致命的命中"

Defined Under Namespace

Classes: Item, RollResult

Constant Summary collapse

DICE_ROLL_METHOD_RE =

項目を選ぶときのダイスロールの方法を表す正規表現

/\A(\d+)D(\d+)\z/i.freeze
DEFAULT_FORMATTER =

表を振った結果の整形処理(既定の処理)

lambda do |table, result|
  "#{table.name}(#{result.sum}) > #{result.content}"
end

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, dice_roll_method, items) {|table, result| ... } ⇒ RangeTable

表を初期化する

ブロックを与えると、独自の結果整形処理を指定できる。ブロックは振った表(table)と振った結果(result)を引数として受け取る。

Examples:

表の定義(バトルテックの致命的命中表)

CRITICAL_TABLE = RangeTable.new(
  '致命的命中表',
  '2D6',
  [
    [2..7,   '致命的命中はなかった'],
    [8..9,   '1箇所の致命的命中'],
    [10..11, '2箇所の致命的命中'],
    [12,     'その部位が吹き飛ぶ(腕、脚、頭)または3箇所の致命的命中(胴)']
  ]
)

独自の結果整形処理を指定する場合

CRITICAL_TABLE_WITH_FORMATTER = RangeTable.new(
  '致命的命中表',
  '2D6',
  [
    [2..7,   '致命的命中はなかった'],
    [8..9,   '1箇所の致命的命中'],
    [10..11, '2箇所の致命的命中'],
    [12,     'その部位が吹き飛ぶ(腕、脚、頭)または3箇所の致命的命中(胴)']
  ]
) do |table, result|
  "致命的命中発生? > #{result.sum}[#{result.values}] > #{result.content}"
end

CRITICAL_TABLE_WITH_FORMATTER.roll(bcdice).formatted
#=> "致命的命中発生? > 11[5,6] > 2箇所の致命的命中"

Parameters:

  • name (String)

    表の名前

  • dice_roll_method (String)

    項目を選ぶときのダイスロールの方法(+‘1D6’+ など)

  • items (Array<(Range, Object)>, Array<(Integer, Object)>)

    表の項目の配列。[出目の合計の範囲, 内容]

Yield Parameters:

Raises:

  • (ArgumentError)

    ダイスロール方法が正しい書式で指定されていなかった場合

  • (TypeError)

    範囲の型が正しくなかった場合

  • (RangeError)

    出目の合計の最小値がカバーされていなかった場合

  • (RangeError)

    出目の合計の最大値がカバーされていなかった場合

  • (RangeError)

    出目の合計の範囲にずれや重なりがあった場合



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/bcdice/dice_table/range_table.rb', line 140

def initialize(name, dice_roll_method, items, &formatter)
  @name = name.freeze
  @formatter = formatter || DEFAULT_FORMATTER

  m = DICE_ROLL_METHOD_RE.match(dice_roll_method)
  unless m
    raise(
      ArgumentError,
      "#{@name}: invalid dice roll method: #{dice_roll_method}"
    )
  end

  @num_of_dice = m[1].to_i
  @num_of_sides = m[2].to_i

  store(items)
end

Instance Attribute Details

#nameString (readonly)

Returns 表の名前.

Returns:

  • (String)

    表の名前



64
65
66
# File 'lib/bcdice/dice_table/range_table.rb', line 64

def name
  @name
end

#num_of_diceInteger (readonly)

Returns 振るダイスの個数.

Returns:

  • (Integer)

    振るダイスの個数



66
67
68
# File 'lib/bcdice/dice_table/range_table.rb', line 66

def num_of_dice
  @num_of_dice
end

#num_of_sidesInteger (readonly)

Returns 振るダイスの面数.

Returns:

  • (Integer)

    振るダイスの面数



68
69
70
# File 'lib/bcdice/dice_table/range_table.rb', line 68

def num_of_sides
  @num_of_sides
end

Class Method Details

.conv_string_range(x) ⇒ Object

Raises:

  • (TypeError)


79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/bcdice/dice_table/range_table.rb', line 79

def conv_string_range(x)
  case x
  when Integer
    return x
  when String
    return x.include?("..") ? Range.new(*x.split("..", 2).map { |n| Integer(n) }) : Integer(x)
  end

  raise(
    TypeError,
    "#{@name}: #{x} (#{x.class}) must be a String or an Integer"
  )
end

.from_i18n(key, locale) ⇒ Object



71
72
73
74
75
76
77
# File 'lib/bcdice/dice_table/range_table.rb', line 71

def from_i18n(key, locale)
  table = I18n.t(key, locale: locale)
  converted_items = table[:items].map do |item|
    [conv_string_range(item[0]), item[1]]
  end
  new(table[:name], table[:type], converted_items)
end

Instance Method Details

#fetch(value) ⇒ Item

指定された値に対応する項目を返す

Parameters:

  • value (Integer)

    値(出目の合計)

Returns:

  • (Item)

    指定された値に対応する項目

Raises:

  • (RangeError)

    範囲外の値が指定された場合



162
163
164
165
166
167
168
169
# File 'lib/bcdice/dice_table/range_table.rb', line 162

def fetch(value)
  item = @items.find { |i| i.range.include?(value) }
  unless item
    raise RangeError, "#{@name}: value is out of range: #{value}"
  end

  return item
end

#roll(randomizer) ⇒ RollResult

表を振る

Parameters:

  • randomizer (#roll_barabara)

    ランダマイザ

Returns:



174
175
176
177
178
179
180
181
182
# File 'lib/bcdice/dice_table/range_table.rb', line 174

def roll(randomizer)
  values = randomizer.roll_barabara(@num_of_dice, @num_of_sides)
  sum = values.sum()

  result = RollResult.new(sum, values, fetch(sum).content)
  result.formatted = @formatter[self, result]

  return result
end