Class: Dicey::DieFoundry

Inherits:
Object
  • Object
show all
Includes:
Mixins::RationalToInteger
Defined in:
lib/dicey/die_foundry.rb

Overview

Helper class to define die definitions and automatically select the best one.

Constant Summary collapse

PREFIX =

Regexp for matching a possible count.

/(?:(?<count>[1-9]\d*+)?+d)?+/i
INTEGER =

Regexp for an integer number.

/(?:-?\d++)/
DECIMAL =

Regexp for a (possibly) fractional number.

/(?:-?\d++(?:\.\d++)?)/
STRING =

Regexp for an “arbitrary” string.

/(?:(?<side>[^"',()]++)|"(?<side>[^",]++)"|'(?<side>[^',]++)')/
MOLDS =

Possible molds for the dice. They are matched in the order as written.

[
  # Positive integer goes into the RegularDie mold.
  [/\A#{PREFIX}(?<sides>[1-9]\d*+)\z/, :regular_mold].freeze,
  # Integer range goes into the NumericDie mold.
  [/\A#{PREFIX}\(?(?<begin>#{INTEGER})(?:[-–—…]|\.{2,3})(?<end>#{INTEGER})\)?\z/,
   :range_mold].freeze,
  # List of numbers goes into the NumericDie mold.
  [/\A#{PREFIX}\(?(?<sides>#{INTEGER}(?:(?:,#{INTEGER})++,?+|,))\)?\z/,
   :weirdly_shaped_mold].freeze,
  # Non-integers require special handling for precision.
  [/\A#{PREFIX}\(?(?<sides>#{DECIMAL}(?:(?:,#{DECIMAL})++,?+|,))\)?\z/,
   :weirdly_precise_mold].freeze,
  # Lists of stuff are broken into AbstractDie.
  [/\A#{PREFIX}\(?(?<sides>#{STRING}(?:(?:,#{STRING})++,?+|,))\)?\z/, :cursed_mold].freeze,
  # Anything else is spilled on the floor.
].freeze

Instance Method Summary collapse

Instance Method Details

#call(definition) ⇒ AbstractDie+ Also known as: cast

Cast a die definition into a mold to make a die.

Following definitions are recognized:

  • positive integer (like “6” or “20”), which produces a RegularDie;

  • integer range (like “3-6” or “(-5..5)”), which produces a NumericDie;

  • list of integers (like “3,4,5”, “(-1,0,1)”, or “2,”), which produces a NumericDie;

  • list of decimal numbers (like “0.5,0.2,0.8” or “(2.0,)”), which produces a NumericDie, but uses Rational for values to maintain precise results;

  • list of strings, possibly mixed with numbers (like “0.5,asdf” or “(👑,♠️,♥️,♣️,♦️,⚓️)”), which produces an AbstractDie with strings converted to Symbols and numbers treated the same as in previous cases.

Any die definition can be prefixed with a count, like “2D6” or “1d1,3,5” to create an array. A plain “d” without an explicit count is ignored instead, creating a single die.

Parameters:

  • definition (String)

    die shape

Returns:

Raises:



58
59
60
61
62
63
64
65
66
67
# File 'lib/dicey/die_foundry.rb', line 58

def call(definition)
  matched, name =
    MOLDS.reduce(nil) do |_, (shape, mold)|
      match = shape.match(definition)
      break [match, mold] if match
    end
  raise DiceyError, "can not cast die from `#{definition}`!" unless name

  __send__(name, matched)
end