class Dice

Constants

InvalidModifier

Attributes

calculator[R]
raw_expression[R]
result[R]
rolls[R]

Public Class Methods

new(str) click to toggle source
# File lib/dice.rb, line 15
def initialize(str)
  @raw_expression = str
  @rolls = []

  @result = Integer(ExpressionParser::Parser.new.parse(parse))
end
roll(str) click to toggle source
# File lib/dice.rb, line 8
def roll(str)
  new(str).result
end

Public Instance Methods

to_s() click to toggle source
# File lib/dice.rb, line 22
def to_s
  raw_expression
end

Private Instance Methods

dice_groups(str) click to toggle source
# File lib/dice.rb, line 28
def dice_groups(str)
  str.scan(/\d{,3}d\d{,3}[^(\ |\+)]+/)
end
parse() click to toggle source
# File lib/dice.rb, line 32
def parse
  str = raw_expression.dup

  # Match groups of dices, calculate the groups and reinsert them
  dice_groups(str).each do |group|
    # Roll each dice
    dices, sides, modifier, modifier_amount = group.scan(/(\d+)d(\d+)(\D*)(\d*)/).flatten
    results = Integer(dices).times.collect do
      r = rand(Integer(sides)) + 1
      @rolls << r
      r
    end.sort

    # If a modifier is present, handle that
    if modifier.present?
      modifier_amount = Integer(modifier_amount.presence || 1)

      case modifier
      when 'dl' # Drop lowest N
        modifier_amount.times { results.shift }
      when 'dh' # Drop highest N
        modifier_amount.times { results.pop }
      when 'l' # Pick lowest
        results = [results.first]
      when 'h' # Pick highest
        results = [results.last]
      else
        raise InvalidModifier, "#{modifier} isn't a valid modifier for #{group}"
      end
    end

    # Sum dice results and reinsert the results in the original string
    str.gsub!(group, results.sum.to_s)
  end

  str
end