Class: GamesDice::Bunch
- Inherits:
-
Object
- Object
- GamesDice::Bunch
- Defined in:
- lib/games_dice/bunch.rb
Overview
This class models a number of identical dice, which may be either GamesDice::Die or GamesDice::ComplexDie objects.
An object of this class represents a fixed number of indentical dice that may be rolled and their values summed to make a total for the bunch.
Instance Attribute Summary collapse
-
#explain_result ⇒ String?
readonly
Explanation of result, or nil if no call to #roll yet.
-
#keep_mode ⇒ Symbol?
readonly
Can be nil, :keep_best or :keep_worst.
-
#keep_number ⇒ Integer?
readonly
Number of “best” or “worst” results to select when #keep_mode is not nil.
-
#label ⇒ String
readonly
Description that will be used in explanations with more than one bunch.
-
#maps ⇒ Array<GamesDice::MapRule>?
readonly
Sequence of map rules, or nil if mapping is not required.
-
#max ⇒ Integer
readonly
Maximum possible result from a call to #roll.
-
#min ⇒ Integer
readonly
Minimum possible result from a call to #roll.
-
#name ⇒ String
readonly
Name to help identify bunch.
-
#ndice ⇒ Integer
readonly
Number of dice to roll.
-
#rerolls ⇒ Array<GamesDice::RerollRule>?
readonly
Sequence of re-roll rules, or nil if re-rolls are not required.
-
#result ⇒ Integer?
readonly
Result of most-recent roll, or nil if no roll made yet.
-
#result_details ⇒ Array<GamesDice::DieResult>?
readonly
After calling #roll, this is an array of GamesDice::DieResult objects.
-
#single_die ⇒ GamesDice::Die, GamesDice::ComplexDie
readonly
Individual die from the bunch.
Instance Method Summary collapse
-
#initialize(options) ⇒ GamesDice::Bunch
constructor
The constructor accepts parameters that are suitable for either GamesDice::Die or GamesDice::ComplexDie and decides which of those classes to instantiate.
-
#probabilities ⇒ GamesDice::Probabilities
Calculates the probability distribution for the bunch.
-
#roll ⇒ Integer
Simulates rolling the bunch of identical dice.
Constructor Details
#initialize(options) ⇒ GamesDice::Bunch
The constructor accepts parameters that are suitable for either GamesDice::Die or GamesDice::ComplexDie and decides which of those classes to instantiate.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/games_dice/bunch.rb', line 34 def initialize( ) name_number_sides_from_hash( ) keep_mode_from_hash( ) if [:prng] raise ":prng does not support the rand() method" if ! [:prng].respond_to?(:rand) end if [:rerolls] || [:maps] @single_die = GamesDice::ComplexDie.new( @sides, complex_die_params_from_hash( ) ) else @single_die = GamesDice::Die.new( @sides, [:prng] ) end end |
Instance Attribute Details
#explain_result ⇒ String? (readonly)
Explanation of result, or nil if no call to #roll yet.
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/games_dice/bunch.rb', line 166 def explain_result return nil unless @result explanation = '' # With #keep_mode, we may need to show unused and used dice separately used_dice = result_details unused_dice = [] # Pick highest numbers and their associated details if @keep_mode && @keep_number < @ndice full_dice = result_details.sort_by { |die_result| die_result.total } case @keep_mode when :keep_best then used_dice = full_dice[-@keep_number..-1] unused_dice = full_dice[0..full_dice.length-1-@keep_number] when :keep_worst then used_dice = full_dice[0..(@keep_number-1)] unused_dice = full_dice[@keep_number..(full_dice.length-1)] end end # Show unused dice (if any) if @keep_mode || @single_die.maps explanation += result_details.map do |die_result| die_result.explain_value end.join(', ') if @keep_mode separator = @single_die.maps ? ', ' : ' + ' explanation += ". Keep: " + used_dice.map do |die_result| die_result.explain_total end.join( separator ) end if @single_die.maps explanation += ". Successes: #{@result}" end explanation += " = #{@result}" if @keep_mode && ! @single_die.maps && @keep_number > 1 else explanation += used_dice.map do |die_result| die_result.explain_value end.join(' + ') explanation += " = #{@result}" if @ndice > 1 end explanation end |
#keep_mode ⇒ Symbol? (readonly)
Can be nil, :keep_best or :keep_worst
63 64 65 |
# File 'lib/games_dice/bunch.rb', line 63 def keep_mode @keep_mode end |
#keep_number ⇒ Integer? (readonly)
Number of “best” or “worst” results to select when #keep_mode is not nil.
67 68 69 |
# File 'lib/games_dice/bunch.rb', line 67 def keep_number @keep_number end |
#label ⇒ String (readonly)
Description that will be used in explanations with more than one bunch
76 77 78 79 |
# File 'lib/games_dice/bunch.rb', line 76 def label return @name if @name != '' return @ndice.to_s + 'd' + @sides.to_s end |
#maps ⇒ Array<GamesDice::MapRule>? (readonly)
Sequence of map rules, or nil if mapping is not required.
91 92 93 |
# File 'lib/games_dice/bunch.rb', line 91 def maps @single_die.maps end |
#max ⇒ Integer (readonly)
Maximum possible result from a call to #roll
115 116 117 118 |
# File 'lib/games_dice/bunch.rb', line 115 def max n = @keep_mode ? [@keep_number,@ndice].min : @ndice return n * @single_die.max end |
#min ⇒ Integer (readonly)
Minimum possible result from a call to #roll
107 108 109 110 |
# File 'lib/games_dice/bunch.rb', line 107 def min n = @keep_mode ? [@keep_number,@ndice].min : @ndice return n * @single_die.min end |
#name ⇒ String (readonly)
Name to help identify bunch
51 52 53 |
# File 'lib/games_dice/bunch.rb', line 51 def name @name end |
#ndice ⇒ Integer (readonly)
Number of dice to roll
55 56 57 |
# File 'lib/games_dice/bunch.rb', line 55 def ndice @ndice end |
#rerolls ⇒ Array<GamesDice::RerollRule>? (readonly)
Sequence of re-roll rules, or nil if re-rolls are not required.
84 85 86 |
# File 'lib/games_dice/bunch.rb', line 84 def rerolls @single_die.rerolls end |
#result ⇒ Integer? (readonly)
Result of most-recent roll, or nil if no roll made yet.
71 72 73 |
# File 'lib/games_dice/bunch.rb', line 71 def result @result end |
#result_details ⇒ Array<GamesDice::DieResult>? (readonly)
After calling #roll, this is an array of GamesDice::DieResult objects. There is one from each #single_die rolled, allowing inspection of how the result was obtained.
99 100 101 102 |
# File 'lib/games_dice/bunch.rb', line 99 def result_details return nil unless @raw_result_details @raw_result_details.map { |r| r.is_a?(Integer) ? GamesDice::DieResult.new(r) : r } end |
#single_die ⇒ GamesDice::Die, GamesDice::ComplexDie (readonly)
Individual die from the bunch
59 60 61 |
# File 'lib/games_dice/bunch.rb', line 59 def single_die @single_die end |
Instance Method Details
#probabilities ⇒ GamesDice::Probabilities
Calculates the probability distribution for the bunch. When the bunch is composed of dice with open-ended re-roll rules, there are some arbitrary limits imposed to prevent large amounts of recursion.
124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/games_dice/bunch.rb', line 124 def probabilities return @probabilities if @probabilities if @keep_mode && @ndice > @keep_number @probabilities = @single_die.probabilities.repeat_n_sum_k( @ndice, @keep_number, @keep_mode ) else @probabilities = @single_die.probabilities.repeat_sum( @ndice ) end return @probabilities end |
#roll ⇒ Integer
Simulates rolling the bunch of identical dice
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/games_dice/bunch.rb', line 138 def roll @result = 0 @raw_result_details = [] @ndice.times do @result += @single_die.roll @raw_result_details << @single_die.result end if ! @keep_mode return @result end use_dice = if @keep_mode && @keep_number < @ndice case @keep_mode when :keep_best then @raw_result_details.sort[-@keep_number..-1] when :keep_worst then @raw_result_details.sort[0..(@keep_number-1)] end else @raw_result_details end @result = use_dice.inject(0) { |so_far, die_result| so_far + die_result } end |