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


34
35
36
37
38
39
40
# File 'lib/games_dice/dice.rb', line 34

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>)

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

def bunch_multipliers
  @bunch_multipliers
end

#bunchesArray<GamesDice::Bunch> (readonly)

Bunches of dice that are components of the object

Returns:


48
49
50
# File 'lib/games_dice/dice.rb', line 48

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.


104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/games_dice/dice.rb', line 104

def explain_result
  return nil unless @result
  explanations = @bunches.map { |bunch| bunch.label + ": " + bunch.explain_result }

  if explanations.count == 0
    return @offset.to_s
  end

  if explanations.count == 1
    if @offset !=0
      return explanations[0] + '. ' + array_to_sum( [ @bunches[0].result, @offset ] )
    else
      return explanations[0]
    end
  end

  bunch_values = @bunch_multipliers.zip(@bunches).map { |m,b| m * b.result }
  bunch_values << @offset if @offset != 0
  explanations << array_to_sum( bunch_values )
  return explanations.join('. ')
end

#maxInteger (readonly)

Maximum possible result from a call to #roll

Returns:

  • (Integer)

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

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

#minInteger (readonly)

Minimum possible result from a call to #roll

Returns:

  • (Integer)

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

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

#minmaxArray<Integer> (readonly)

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

Returns:

  • (Array<Integer>)

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

def minmax
  [min,max]
end

#nameString (readonly)

Name to help identify dice

Returns:

  • (String)

44
45
46
# File 'lib/games_dice/dice.rb', line 44

def name
  @name
end

#offsetInteger (readonly)

Fixed offset added to sum of all bunches.

Returns:

  • (Integer)

57
58
59
# File 'lib/games_dice/dice.rb', line 57

def offset
  @offset
end

#resultInteger? (readonly)

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

Returns:

  • (Integer, nil)

61
62
63
# File 'lib/games_dice/dice.rb', line 61

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:


94
95
96
97
98
99
100
# File 'lib/games_dice/dice.rb', line 94

def probabilities
  return @probabilities if @probabilities
  probs = @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


65
66
67
# File 'lib/games_dice/dice.rb', line 65

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