Class: Dicey::DieFoundry
- Inherits:
-
Object
- Object
- Dicey::DieFoundry
- Includes:
- Mixins::RationalToInteger
- Defined in:
- lib/dicey/die_foundry.rb
Overview
Helper to create dice from string definitions. See #call and constants for available formats.
Constant Summary collapse
- SPECIAL =
Special characters disallowed in unquoted strings.
%{"',()+−-}- INTEGER =
Pattern for an integer number.
"(?:-?\\d++)"- NUMBER =
Pattern for a possibly fractional number.
"(?:-?\\d++(?:/\\d++|\\.\\d++)?)"- STRING =
Pattern for an "arbitrary" string or number.
%{(?:(?<string>[^#{SPECIAL}]++)|"(?<string>[^",]++)"|'(?<string>[^',]++)')}.freeze
- VALUE =
Pattern for a number or string (allowing negative numbers).
"(?:#{NUMBER}(?=[,)+−-]|\\z)|#{STRING})".freeze
- COUNT =
Pattern for matching a possible count.
"(?:(?<count>[1-9]\\d*+)?+[Dd])?+"- CONSTANT =
Pattern for matching an optional constant factor.
"(?<constant>(?<sign>[+−-])(?<constant_value>#{NUMBER})|" \ "(?<sign>\\+)(?<constant_value>#{STRING}))".freeze
- MOLDS =
Possible molds for the dice. They are matched in the order as written.
[ # Positive integer goes into the RegularDie mold. [/\A#{COUNT}(?<sides>[1-9]\d*+)#{CONSTANT}?\z/, :regular_mold], # Integer range goes into the NumericDie mold. [molder.("(?<begin>#{INTEGER})(?:[–—…]|\\.{2,3})(?<end>#{INTEGER})"), :range_mold], # List of numbers goes into the NumericDie mold. [molder.("(?<sides>#{INTEGER}(?:(?:,#{INTEGER})++,?+|,))"), :weirdly_shaped_mold], # Non-integers require special handling for precision. [molder.("(?<sides>#{NUMBER}(?:(?:,#{NUMBER})++,?+|,))"), :weirdly_precise_mold], # Lists of stuff are broken into AbstractDie. [molder.("(?<sides>#{VALUE}(?:(?:,#{VALUE})++,?+|,))"), :cursed_mold], # Sign-prefixed value goes into the StaticDie mold. [/\A#{COUNT}(?:#{CONSTANT}|\(#{CONSTANT}\))\z/, :static_mold], # Anything else is spilled on the floor. ].each(&:freeze).freeze
Instance Method Summary collapse
-
#call(definition) ⇒ AbstractDie+
(also: #cast)
Cast a die definition into a mold to make a die.
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
Rationalfor values to maintain precise results; - list of strings, possibly mixed with numbers (like "0.5,asdf" or "(👑,♠️,♥️,♣️,♦️,⚓️)"), which produces an AbstractDie with numbers treated the same as in previous cases, and other or quoted values treated as Strings.
- signed value (like "+3", "-3.6" or "(+ABC)"), which produces a StaticDie, non-numeric values are only allowed as positive values;
Any die definition can be prefixed with a count, like "2D6" or "1d1,3,5" to create an array. A plain "d"/"D" without an explicit count is ignored instead, creating a single die.
All die definitions (aside from plain signed value) can be suffixed with a signed value to add or subtract from the result, like "2D6+3" or "5dA,B,C+C". Only numbers can be subtracted.
78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/dicey/die_foundry.rb', line 78 def call(definition) matched, name = MOLDS.find do |(shape, mold)| match = shape.match(definition) break [match, mold] if match end raise DiceyError, "can not cast die from `#{definition}`!" unless name if matched[:constant] && name != :static_mold [__send__(name, matched), static_mold(matched, ignore_count: true)].flatten else __send__(name, matched) end end |