MetalAdventures/src/metal_adventures/dice.rb

87 lines
2.6 KiB
Ruby

module MetalAdventures
class Dice
attr_accessor :n, :difficulty, :modifiers, :description, :result, :last_roll
# @param [Integer] n is the number of dice to roll
# @param [Integer] difficulty is the amount of success to get
# @param [Modifier] modifiers
def initialize(n:, difficulty: 1, modifiers: Modifiers.new, description: "nodescription")
@n = n
@difficulty = difficulty
@modifiers = modifiers
@description = description
end
# def add_difficulty!(add = 1)
# @difficulty += add
# end
# def remove_difficulty!(remove = 1)
# @difficulty -= remove
# end
# def add_die!(add = 1)
# @n += add
# end
# def remove_die!(remove = 1)
# @n -= remove
# end
def to_h
{ n: @n, difficulty: @difficulty, modifiers: @modifiers.to_h, description: @description }
end
# @return [Integer] the amount of success of a new roll
def roll
@modifiers.roll(@n)
end
# Roll the dice and generate a new result.
# This will overwrite @last_roll and @result.
# It should be used over {#roll} in most cases.
#
# see {#success?} {#last_roll} {#result}
def roll!
@last_roll = roll
@result = @last_roll.count { @modifiers.success?(_1) }
self
end
# @return [nil|true|false] if the last #roll! was a success or not
def success?
if @result
@result >= @difficulty
end
end
DEFAULT_PARSER_N = "(?<n>\\d+)"
DEFAULT_PARSER_D = "(?<difficulty>\\d+)"
DEFAULT_PARSER_M = "(?<modifiers>(?: +\\w+)*)"
DEFAULT_PARSER = %r{\A#{DEFAULT_PARSER_N} *(?:/ *#{DEFAULT_PARSER_D})?(?: *#{DEFAULT_PARSER_M})?(?: *:(?<description>.+))?\Z}.freeze
# @param [String] prefix must be a string that is matched before the dice to roll
def self.make_parser(prefix: "!roll ")
%r{\A#{prefix}#{DEFAULT_PARSER_N} *(?:/ *#{DEFAULT_PARSER_D})?(?: *#{DEFAULT_PARSER_M})?(?: *:(?<description>.+))?\Z}
end
# @param parser must be a regexp with named groups: n, difficulty (optiontal), modifiers.
# see {.marke_parser} for easy boilerplate
def self.parse(string, parser: DEFAULT_PARSER, will_raise: false)
match = string.match(parser)
if match.nil?
raise "Dice: Impossible to parse the string #{string}" if will_raise
return nil
end
Dice.new(
description: match["description"].to_s.strip,
n: match["n"].strip.to_i,
difficulty: (match["difficulty"] || "1").strip.to_i,
modifiers: Dice::Modifiers.new(*match["modifiers"].to_s.split(" ").map(&:strip)),
)
end
end
end