Class: GamesDice::Dice

Inherits:
Object
  • Object
show all
Defined in:
lib/games_dice/dice.rb

Overview

This class models a combination of GamesDice::Bunch objects plus a fixed offset.

An object of this class is a dice "recipe" that specifies the numbers and types of dice that can be rolled to generate an integer value.

Examples:

'3d6+6' hitpoints, whatever that means in the game you are playing

d = GamesDice::Dice.new( [{:ndice => 3, :sides => 6}], 6, 'Hit points' )
d.roll # => 20
d.result # => 20
d.explain_result # => "3d6: 3 + 5 + 6 = 14. 14 + 6 = 20"
d.probabilities.expected # => 16.5

Roll d20 twice, take best result, and add 5.

d = GamesDice::Dice.new( [{:ndice => 2, :sides => 20 , :keep_mode => :keep_best, :keep_number => 1}], 5 )
d.roll # => 21
d.result # => 21
d.explain_result # => "2d20: 4, 16. Keep: 16. 16 + 5 = 21"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(bunches, offset = 0, name = '') ⇒ GamesDice::Dice

The first parameter is an array of values that are passed to GamesDice::Bunch constructors.

Parameters:

  • bunches (Array<Hash>)

    Array of options for creating bunches

  • offset (Integer) (defaults to: 0)

    Total offset

  • name (String) (defaults to: '')

    Optional label for the dice

Options Hash (bunches):

  • :ndice (Integer)

    Number of dice in the bunch, mandatory

  • :sides (Integer)

    Number of sides on a single die in the bunch, mandatory

  • :name (String)

    Optional name for the bunch

  • :rerolls (Array<GamesDice::RerollRule,Array>)

    Optional rules that cause the die to roll again

  • :maps (Array<GamesDice::MapRule,Array>)

    Optional rules to convert a value into a final result for the die

  • :prng (#rand)

    Optional alternative source of randomness to Ruby's built-in #rand, passed to GamesDice::Die's constructor

  • :keep_mode (Symbol)

    Optional, either :keep_best or :keep_worst

  • :keep_number (Integer)

    Optional number of dice to keep when :keep_mode is not nil

  • :multiplier (Integer)

    Optional, defaults to 1, and typically 1 or -1 to describe whether the Bunch total is to be added or subtracted



40
41
42
43
44
45
46
# File 'lib/games_dice/dice.rb', line 40

def initialize(bunches, offset = 0, name = '')
  @name = name
  @offset = offset
  @bunches = bunches.map { |b| GamesDice::Bunch.new(b) }
  @bunch_multipliers = bunches.map { |b| b[:multiplier] || 1 }
  @result = nil
end

Instance Attribute Details

#bunch_multipliersArray<Integer> (readonly)

Multipliers for each bunch of identical dice. Typically 1 or -1 to represent groups of dice that are either added or subtracted from the total.

Returns:

  • (Array<Integer>)


59
60
61
# File 'lib/games_dice/dice.rb', line 59

def bunch_multipliers
  @bunch_multipliers
end

#bunchesArray<GamesDice::Bunch> (readonly)

Bunches of dice that are components of the object

Returns:



54
55
56
# File 'lib/games_dice/dice.rb', line 54

def bunches
  @bunches
end

#explain_resultString? (readonly)

Returns Explanation of result, or nil if no call to #roll yet.

Returns:

  • (String, nil)

    Explanation of result, or nil if no call to #roll yet.



111
112
113
114
115
116
117
118
119
120
121
# File 'lib/games_dice/dice.rb', line 111

def explain_result
  return nil unless @result

  explanations = @bunches.map { |bunch| "#{bunch.label}: #{bunch.explain_result}" }

  return @offset.to_s if explanations.none?

  return simple_explanation(explanations.first) if explanations.one?

  multi_explanations(explanations)
end

#maxInteger (readonly)

Maximum possible result from a call to #roll

Returns:

  • (Integer)


85
86
87
# File 'lib/games_dice/dice.rb', line 85

def max
  @max ||= @offset + bunches_weighted_sum(:max)
end

#minInteger (readonly)

Minimum possible result from a call to #roll

Returns:

  • (Integer)


78
79
80
# File 'lib/games_dice/dice.rb', line 78

def min
  @min ||= @offset + bunches_weighted_sum(:min)
end

#minmaxArray<Integer> (readonly)

Convenience method, same as [dice.min, dice.max]

Returns:

  • (Array<Integer>)


92
93
94
# File 'lib/games_dice/dice.rb', line 92

def minmax
  [min, max]
end

#nameString (readonly)

Name to help identify dice

Returns:

  • (String)


50
51
52
# File 'lib/games_dice/dice.rb', line 50

def name
  @name
end

#offsetInteger (readonly)

Fixed offset added to sum of all bunches.

Returns:

  • (Integer)


63
64
65
# File 'lib/games_dice/dice.rb', line 63

def offset
  @offset
end

#resultInteger? (readonly)

Result of most-recent roll, or nil if no roll made yet.

Returns:

  • (Integer, nil)


67
68
69
# File 'lib/games_dice/dice.rb', line 67

def result
  @result
end

Instance Method Details

#probabilitiesGamesDice::Probabilities

Calculates the probability distribution for the dice. When the dice include components with open-ended re-roll rules, there are some arbitrary limits imposed to prevent large amounts of recursion.

Returns:



100
101
102
103
104
105
106
107
# File 'lib/games_dice/dice.rb', line 100

def probabilities
  return @probabilities if @probabilities

  @bunch_multipliers.zip(@bunches).inject(GamesDice::Probabilities.new([1.0], @offset)) do |probs, mb|
    m, b = mb
    GamesDice::Probabilities.add_distributions_mult(1, probs, m, b.probabilities)
  end
end

#rollInteger

Simulates rolling dice

Returns:

  • (Integer)

    Sum of all rolled dice



71
72
73
# File 'lib/games_dice/dice.rb', line 71

def roll
  @result = @offset + bunches_weighted_sum(:roll)
end