games_dice 0.3.6 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.yardopts +7 -0
- data/CHANGELOG.md +53 -0
- data/ext/games_dice/probabilities.c +2 -0
- data/lib/games_dice/parser.rb +1 -1
- data/lib/games_dice/probabilities.rb +23 -4
- data/lib/games_dice/version.rb +1 -1
- data/spec/probability_spec.rb +122 -4
- metadata +119 -103
    
        data/.yardopts
    ADDED
    
    
    
        data/CHANGELOG.md
    ADDED
    
    | @@ -0,0 +1,53 @@ | |
| 1 | 
            +
            # GamesDice Changelog
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            ## 0.3.7
         | 
| 4 | 
            +
             | 
| 5 | 
            +
             * Compatibility between pure Ruby and native extension code when handling bad method params
         | 
| 6 | 
            +
             * Added this changelog to documentation
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            ## 0.3.6
         | 
| 9 | 
            +
             | 
| 10 | 
            +
             * Extension building skipped, with fallback to pure Ruby, for JRuby compatibility
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            ## 0.3.5
         | 
| 13 | 
            +
             | 
| 14 | 
            +
             * Adjust C code to avoid warnings about C90 compatibility (warnings seen on Travis)
         | 
| 15 | 
            +
             * Note MIT license in gemspec
         | 
| 16 | 
            +
             * Add class method GamesDice::Probabilities.implemented_in
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            ## 0.3.3
         | 
| 19 | 
            +
             | 
| 20 | 
            +
             * Standardised code for Ruby 1.8.7 compatibility in GamesDice::Probabilities
         | 
| 21 | 
            +
             * Bug fix for probability calculations where distributions are added with mulipliers e.g. '2d6 - 1d8'
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            ## 0.3.2
         | 
| 24 | 
            +
             | 
| 25 | 
            +
             * Bug fix for Ruby 1.8.7 compatibility in GamesDice::Probabilities
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            ## 0.3.1
         | 
| 28 | 
            +
             | 
| 29 | 
            +
             * Bug fix for Ruby 1.8.7 compatibility in GamesDice::Probabilities
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            ## 0.3.0
         | 
| 32 | 
            +
             | 
| 33 | 
            +
             * Implemented GamesDice::Probabilities as native extension
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            ## 0.2.4
         | 
| 36 | 
            +
             | 
| 37 | 
            +
             * Minor speed improvements to GamesDice::Probabilities
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            ## 0.2.3
         | 
| 40 | 
            +
             | 
| 41 | 
            +
             * More YARD documentation
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            ## 0.2.2
         | 
| 44 | 
            +
             | 
| 45 | 
            +
             * Extended YARD documentation
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            ## 0.2.1
         | 
| 48 | 
            +
             | 
| 49 | 
            +
             * Started basic YARD documentation
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            ## 0.2.0
         | 
| 52 | 
            +
             | 
| 53 | 
            +
             * First version with a complete feature set
         | 
| @@ -744,6 +744,8 @@ VALUE probabilities_for_fair_die( VALUE self, VALUE sides ) { | |
| 744 744 | 
             
            }
         | 
| 745 745 |  | 
| 746 746 | 
             
            VALUE probabilities_from_h( VALUE self, VALUE hash ) {
         | 
| 747 | 
            +
              Check_Type( hash, T_HASH );
         | 
| 748 | 
            +
             | 
| 747 749 | 
             
              VALUE obj = pl_alloc( Probabilities );
         | 
| 748 750 | 
             
              ProbabilityList *pl = get_probability_list( obj );
         | 
| 749 751 | 
             
              double error;
         | 
    
        data/lib/games_dice/parser.rb
    CHANGED
    
    | @@ -68,7 +68,7 @@ class GamesDice::Parser < Parslet::Parser | |
| 68 68 | 
             
              root :expressions
         | 
| 69 69 |  | 
| 70 70 | 
             
              # Parses a string description in the dice mini-language, and returns data for feeding into
         | 
| 71 | 
            -
              # GamesDice::Dice  | 
| 71 | 
            +
              # GamesDice::Dice constructor.
         | 
| 72 72 | 
             
              # @param [String] dice_description Text to parse e.g. '1d6'
         | 
| 73 73 | 
             
              # @return [Hash] Analysis of dice_description
         | 
| 74 74 | 
             
              def parse dice_description
         | 
| @@ -27,7 +27,7 @@ class GamesDice::Probabilities | |
| 27 27 | 
             
              def initialize( probs = [1.0], offset = 0 )
         | 
| 28 28 | 
             
                # This should *probably* be validated in future, but that would impact performance
         | 
| 29 29 | 
             
                @probs = check_probs_array probs.clone
         | 
| 30 | 
            -
                @offset = offset
         | 
| 30 | 
            +
                @offset = Integer(offset)
         | 
| 31 31 | 
             
              end
         | 
| 32 32 |  | 
| 33 33 | 
             
              # @!visibility private
         | 
| @@ -41,7 +41,7 @@ class GamesDice::Probabilities | |
| 41 41 | 
             
              # @yieldparam [Float] probability Probability of result, in range 0.0..1.0
         | 
| 42 42 | 
             
              # @return [GamesDice::Probabilities] this object
         | 
| 43 43 | 
             
              def each
         | 
| 44 | 
            -
                @probs.each_with_index { |p,i| yield( i+@offset, p ) }
         | 
| 44 | 
            +
                @probs.each_with_index { |p,i| yield( i+@offset, p ) if p > 0.0 }
         | 
| 45 45 | 
             
                return self
         | 
| 46 46 | 
             
              end
         | 
| 47 47 |  | 
| @@ -156,6 +156,7 @@ class GamesDice::Probabilities | |
| 156 156 | 
             
              #   and the matching value is probability of getting that result
         | 
| 157 157 | 
             
              # @return [GamesDice::Probabilities]
         | 
| 158 158 | 
             
              def self.from_h prob_hash
         | 
| 159 | 
            +
                raise TypeError, "from_h expected a Hash" unless prob_hash.is_a? Hash
         | 
| 159 160 | 
             
                probs, offset = prob_h_to_ao( prob_hash )
         | 
| 160 161 | 
             
                GamesDice::Probabilities.new( probs, offset )
         | 
| 161 162 | 
             
              end
         | 
| @@ -166,6 +167,7 @@ class GamesDice::Probabilities | |
| 166 167 | 
             
              def self.for_fair_die sides
         | 
| 167 168 | 
             
                sides = Integer(sides)
         | 
| 168 169 | 
             
                raise ArgumentError, "sides must be at least 1" unless sides > 0
         | 
| 170 | 
            +
                raise ArgumentError, "sides can be at most 100000" if sides > 100000
         | 
| 169 171 | 
             
                GamesDice::Probabilities.new( Array.new( sides, 1.0/sides ), 1 )
         | 
| 170 172 | 
             
              end
         | 
| 171 173 |  | 
| @@ -175,6 +177,10 @@ class GamesDice::Probabilities | |
| 175 177 | 
             
              # @param [GamesDice::Probabilities] pd_b Second distribution
         | 
| 176 178 | 
             
              # @return [GamesDice::Probabilities]
         | 
| 177 179 | 
             
              def self.add_distributions pd_a, pd_b
         | 
| 180 | 
            +
                unless pd_a.is_a?( GamesDice::Probabilities ) && pd_b.is_a?( GamesDice::Probabilities )
         | 
| 181 | 
            +
                  raise TypeError, "parameter to add_distributions is not a GamesDice::Probabilities"
         | 
| 182 | 
            +
                end
         | 
| 183 | 
            +
             | 
| 178 184 | 
             
                combined_min = pd_a.min + pd_b.min
         | 
| 179 185 | 
             
                combined_max = pd_a.max + pd_b.max
         | 
| 180 186 | 
             
                new_probs = Array.new( 1 + combined_max - combined_min, 0.0 )
         | 
| @@ -199,6 +205,13 @@ class GamesDice::Probabilities | |
| 199 205 | 
             
              # @param [GamesDice::Probabilities] pd_b Second distribution
         | 
| 200 206 | 
             
              # @return [GamesDice::Probabilities]
         | 
| 201 207 | 
             
              def self.add_distributions_mult m_a, pd_a, m_b, pd_b
         | 
| 208 | 
            +
                unless pd_a.is_a?( GamesDice::Probabilities ) && pd_b.is_a?( GamesDice::Probabilities )
         | 
| 209 | 
            +
                  raise TypeError, "parameter to add_distributions_mult is not a GamesDice::Probabilities"
         | 
| 210 | 
            +
                end
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                m_a = Integer(m_a)
         | 
| 213 | 
            +
                m_b = Integer(m_b)
         | 
| 214 | 
            +
             | 
| 202 215 | 
             
                combined_min, combined_max = [
         | 
| 203 216 | 
             
                  m_a * pd_a.min + m_b * pd_b.min, m_a * pd_a.max + m_b * pd_b.min,
         | 
| 204 217 | 
             
                  m_a * pd_a.min + m_b * pd_b.max, m_a * pd_a.max + m_b * pd_b.max,
         | 
| @@ -232,6 +245,7 @@ class GamesDice::Probabilities | |
| 232 245 | 
             
              def repeat_sum n
         | 
| 233 246 | 
             
                n = Integer( n )
         | 
| 234 247 | 
             
                raise "Cannot combine probabilities less than once" if n < 1
         | 
| 248 | 
            +
                raise "Probability distribution too large" if ( n * @probs.count ) > 1000000
         | 
| 235 249 | 
             
                revbin = n.to_s(2).reverse.each_char.to_a.map { |c| c == '1' }
         | 
| 236 250 | 
             
                pd_power = self
         | 
| 237 251 | 
             
                pd_result = nil
         | 
| @@ -259,6 +273,8 @@ class GamesDice::Probabilities | |
| 259 273 | 
             
                n = Integer( n )
         | 
| 260 274 | 
             
                k = Integer( k )
         | 
| 261 275 | 
             
                raise "Cannot combine probabilities less than once" if n < 1
         | 
| 276 | 
            +
                # Technically this is a limitation of C code, but Ruby version is most likely slow and inaccurate beyond 170
         | 
| 277 | 
            +
                raise "Too many dice to calculate numbers of arrangements" if n > 170
         | 
| 262 278 | 
             
                if k >= n
         | 
| 263 279 | 
             
                  return repeat_sum( n )
         | 
| 264 280 | 
             
                end
         | 
| @@ -294,6 +310,7 @@ class GamesDice::Probabilities | |
| 294 310 | 
             
              private
         | 
| 295 311 |  | 
| 296 312 | 
             
              def check_probs_array probs_array
         | 
| 313 | 
            +
                raise TypeError unless probs_array.is_a?( Array )
         | 
| 297 314 | 
             
                probs_array.map!{ |n| Float(n) }
         | 
| 298 315 | 
             
                total = probs_array.inject(0.0) do |t,x|
         | 
| 299 316 | 
             
                  if x < 0.0 || x > 1.0
         | 
| @@ -351,8 +368,10 @@ class GamesDice::Probabilities | |
| 351 368 | 
             
              def self.prob_h_to_ao h
         | 
| 352 369 | 
             
                rmin,rmax = h.keys.minmax
         | 
| 353 370 | 
             
                o = rmin
         | 
| 354 | 
            -
                 | 
| 355 | 
            -
                 | 
| 371 | 
            +
                s = 1 + rmax - rmin
         | 
| 372 | 
            +
                raise ArgumentError, "Range of possible results too large" if s > 1000000
         | 
| 373 | 
            +
                a = Array.new( s, 0.0 )
         | 
| 374 | 
            +
                h.each { |k,v| a[k-rmin] = Float(v) }
         | 
| 356 375 | 
             
                [a,o]
         | 
| 357 376 | 
             
              end
         | 
| 358 377 |  | 
    
        data/lib/games_dice/version.rb
    CHANGED
    
    
    
        data/spec/probability_spec.rb
    CHANGED
    
    | @@ -9,6 +9,20 @@ describe GamesDice::Probabilities do | |
| 9 9 | 
             
                    pr.should be_a GamesDice::Probabilities
         | 
| 10 10 | 
             
                    pr.to_h.should be_valid_distribution
         | 
| 11 11 | 
             
                  end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  it "should raise an error if passed incorrect parameter types" do
         | 
| 14 | 
            +
                    lambda { GamesDice::Probabilities.new( [ nil ], 20 ) }.should raise_error TypeError
         | 
| 15 | 
            +
                    lambda { GamesDice::Probabilities.new( [0.3,nil,0.5], 7 ) }.should raise_error TypeError
         | 
| 16 | 
            +
                    lambda { GamesDice::Probabilities.new( [0.3,0.2,0.5], {} ) }.should raise_error TypeError
         | 
| 17 | 
            +
                    lambda { GamesDice::Probabilities.new( {:x=>:y}, 17 ) }.should raise_error TypeError
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  it "should raise an error if distribution is incomplete or inaccurate" do
         | 
| 21 | 
            +
                    lambda { GamesDice::Probabilities.new( [0.3,0.2,0.6], 3 ) }.should raise_error ArgumentError
         | 
| 22 | 
            +
                    lambda { GamesDice::Probabilities.new( [], 1 ) }.should raise_error ArgumentError
         | 
| 23 | 
            +
                    lambda { GamesDice::Probabilities.new( [0.9], 1 ) }.should raise_error ArgumentError
         | 
| 24 | 
            +
                    lambda { GamesDice::Probabilities.new( [-0.9,0.2,0.9], 1 ) }.should raise_error ArgumentError
         | 
| 25 | 
            +
                  end
         | 
| 12 26 | 
             
                end
         | 
| 13 27 |  | 
| 14 28 | 
             
                describe "#for_fair_die" do
         | 
| @@ -25,6 +39,15 @@ describe GamesDice::Probabilities do | |
| 25 39 | 
             
                      h.values.each { |v| v.should be_within(1e-10).of 1.0/sides }
         | 
| 26 40 | 
             
                    end
         | 
| 27 41 | 
             
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  it "should raise an error if number of sides is not an integer" do
         | 
| 44 | 
            +
                    lambda { GamesDice::Probabilities.for_fair_die( {} ) }.should raise_error TypeError
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  it "should raise an error if number of sides is too low or too high" do
         | 
| 48 | 
            +
                    lambda { GamesDice::Probabilities.for_fair_die( 0 ) }.should raise_error ArgumentError
         | 
| 49 | 
            +
                    lambda { GamesDice::Probabilities.for_fair_die( 1000001 ) }.should raise_error ArgumentError
         | 
| 50 | 
            +
                  end
         | 
| 28 51 | 
             
                end
         | 
| 29 52 |  | 
| 30 53 | 
             
                describe "#add_distributions" do
         | 
| @@ -52,6 +75,13 @@ describe GamesDice::Probabilities do | |
| 52 75 | 
             
                    h[11].should be_within(1e-9).of 2.0/36
         | 
| 53 76 | 
             
                    h[12].should be_within(1e-9).of 1.0/36
         | 
| 54 77 | 
             
                  end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                  it "should raise an error if either parameter is not a GamesDice::Probabilities object" do
         | 
| 80 | 
            +
                    d10 = GamesDice::Probabilities.for_fair_die( 10 )
         | 
| 81 | 
            +
                    lambda { GamesDice::Probabilities.add_distributions( '', 6 ) }.should raise_error TypeError
         | 
| 82 | 
            +
                    lambda { GamesDice::Probabilities.add_distributions( d10, 6 ) }.should raise_error TypeError
         | 
| 83 | 
            +
                    lambda { GamesDice::Probabilities.add_distributions( '', d10 ) }.should raise_error TypeError
         | 
| 84 | 
            +
                  end
         | 
| 55 85 | 
             
                end
         | 
| 56 86 |  | 
| 57 87 | 
             
                describe "#add_distributions_mult" do
         | 
| @@ -90,6 +120,20 @@ describe GamesDice::Probabilities do | |
| 90 120 | 
             
                    h[10].should be_within(1e-9).of 0.7 * 0.2 + 0.3 * 0.3
         | 
| 91 121 | 
             
                    h[12].should be_within(1e-9).of 0.3 * 0.2
         | 
| 92 122 | 
             
                  end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                  it "should raise an error if passed incorrect objects for distributions" do
         | 
| 125 | 
            +
                    d10 = GamesDice::Probabilities.for_fair_die( 10 )
         | 
| 126 | 
            +
                    lambda { GamesDice::Probabilities.add_distributions_mult( 1, '', -1,  6 ) }.should raise_error TypeError
         | 
| 127 | 
            +
                    lambda { GamesDice::Probabilities.add_distributions_mult( 2, d10, 3, 6 ) }.should raise_error TypeError
         | 
| 128 | 
            +
                    lambda { GamesDice::Probabilities.add_distributions_mult( 1, '', -1, d10 ) }.should raise_error TypeError
         | 
| 129 | 
            +
                  end
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                  it "should raise an error if passed incorrect objects for multipliers" do
         | 
| 132 | 
            +
                    d10 = GamesDice::Probabilities.for_fair_die( 10 )
         | 
| 133 | 
            +
                    lambda { GamesDice::Probabilities.add_distributions_mult( {}, d10, [],  d10 ) }.should raise_error TypeError
         | 
| 134 | 
            +
                    lambda { GamesDice::Probabilities.add_distributions_mult( [7], d10, 3, d10 ) }.should raise_error TypeError
         | 
| 135 | 
            +
                    lambda { GamesDice::Probabilities.add_distributions_mult( 1, d10, {}, d10 ) }.should raise_error TypeError
         | 
| 136 | 
            +
                  end
         | 
| 93 137 | 
             
                end
         | 
| 94 138 |  | 
| 95 139 | 
             
                describe "#from_h" do
         | 
| @@ -99,9 +143,21 @@ describe GamesDice::Probabilities do | |
| 99 143 | 
             
                  end
         | 
| 100 144 |  | 
| 101 145 | 
             
                  it "should raise an ArgumentError when called with a non-valid hash" do
         | 
| 102 | 
            -
                    # lambda { GamesDice::Probabilities.from_h( :foo ) }.should raise_error ArgumentError
         | 
| 103 146 | 
             
                    lambda { GamesDice::Probabilities.from_h( { 7 => 0.5, 9 => 0.6 } ) }.should raise_error ArgumentError
         | 
| 104 147 | 
             
                  end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                  it "should raise an TypeError when called with data that is not a hash" do
         | 
| 150 | 
            +
                    lambda { GamesDice::Probabilities.from_h( :foo ) }.should raise_error TypeError
         | 
| 151 | 
            +
                  end
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                  it "should raise a TypeError when called when keys and values are not all integers and floats" do
         | 
| 154 | 
            +
                    lambda { GamesDice::Probabilities.from_h( { 'x' => 0.5, 9 => 0.5 } ) }.should raise_error
         | 
| 155 | 
            +
                    lambda { GamesDice::Probabilities.from_h( { 7 => [], 9 => 0.5 } ) }.should raise_error TypeError
         | 
| 156 | 
            +
                  end
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                  it "should raise an ArgumentError when results are spread very far apart" do
         | 
| 159 | 
            +
                    lambda { GamesDice::Probabilities.from_h( { 0 => 0.5, 2000000 => 0.5 } ) }.should raise_error ArgumentError
         | 
| 160 | 
            +
                  end
         | 
| 105 161 | 
             
                end
         | 
| 106 162 |  | 
| 107 163 | 
             
                describe "#implemented_in" do
         | 
| @@ -120,7 +176,20 @@ describe GamesDice::Probabilities do | |
| 120 176 | 
             
                let(:pr10) { GamesDice::Probabilities.for_fair_die( 10 ) }
         | 
| 121 177 | 
             
                let(:pra) { GamesDice::Probabilities.new( [ 0.4, 0.2, 0.4 ], -1 ) }
         | 
| 122 178 |  | 
| 123 | 
            -
                #  | 
| 179 | 
            +
                describe "#each" do
         | 
| 180 | 
            +
                  it "should iterate through all result/probability pairs" do
         | 
| 181 | 
            +
                    yielded = []
         | 
| 182 | 
            +
                    pr4.each { |r,p| yielded << [r,p] }
         | 
| 183 | 
            +
                    yielded.should == [ [1,0.25], [2,0.25], [3,0.25], [4,0.25] ]
         | 
| 184 | 
            +
                  end
         | 
| 185 | 
            +
             | 
| 186 | 
            +
                  it "should skip zero probabilities" do
         | 
| 187 | 
            +
                    pr_plus_minus = GamesDice::Probabilities.new( [ 0.5, 0.0, 0.5 ], -1 )
         | 
| 188 | 
            +
                    yielded = []
         | 
| 189 | 
            +
                    pr_plus_minus .each { |r,p| yielded << [r,p] }
         | 
| 190 | 
            +
                    yielded.should == [ [-1,0.5], [1,0.5] ]
         | 
| 191 | 
            +
                  end
         | 
| 192 | 
            +
                end
         | 
| 124 193 |  | 
| 125 194 | 
             
                describe "#p_eql" do
         | 
| 126 195 | 
             
                  it "should return probability of getting a number inside the range" do
         | 
| @@ -138,6 +207,10 @@ describe GamesDice::Probabilities do | |
| 138 207 | 
             
                    pr10.p_eql(11).should == 0.0
         | 
| 139 208 | 
             
                    pra.p_eql(2).should == 0.0
         | 
| 140 209 | 
             
                  end
         | 
| 210 | 
            +
             | 
| 211 | 
            +
                  it "should raise a TypeError if asked for probability of non-Integer" do
         | 
| 212 | 
            +
                    lambda { pr2.p_eql( [] ) }.should raise_error TypeError
         | 
| 213 | 
            +
                  end
         | 
| 141 214 | 
             
                end # describe "#p_eql"
         | 
| 142 215 |  | 
| 143 216 | 
             
                describe "#p_gt" do
         | 
| @@ -169,6 +242,10 @@ describe GamesDice::Probabilities do | |
| 169 242 | 
             
                    pr10.p_gt(-200).should == 1.0
         | 
| 170 243 | 
             
                    pra.p_gt(-2).should == 1.0
         | 
| 171 244 | 
             
                  end
         | 
| 245 | 
            +
             | 
| 246 | 
            +
                  it "should raise a TypeError if asked for probability of non-Integer" do
         | 
| 247 | 
            +
                    lambda { pr2.p_gt( {} ) }.should raise_error TypeError
         | 
| 248 | 
            +
                  end
         | 
| 172 249 | 
             
                end # describe "#p_gt"
         | 
| 173 250 |  | 
| 174 251 | 
             
                describe "#p_ge" do
         | 
| @@ -192,6 +269,10 @@ describe GamesDice::Probabilities do | |
| 192 269 | 
             
                    pr6.p_ge(1).should == 1.0
         | 
| 193 270 | 
             
                    pr10.p_ge(-200).should == 1.0
         | 
| 194 271 | 
             
                  end
         | 
| 272 | 
            +
             | 
| 273 | 
            +
                  it "should raise a TypeError if asked for probability of non-Integer" do
         | 
| 274 | 
            +
                    lambda { pr4.p_ge( {} ) }.should raise_error TypeError
         | 
| 275 | 
            +
                  end
         | 
| 195 276 | 
             
                end # describe "#p_ge"
         | 
| 196 277 |  | 
| 197 278 | 
             
                describe "#p_le" do
         | 
| @@ -215,6 +296,10 @@ describe GamesDice::Probabilities do | |
| 215 296 | 
             
                    pr6.p_le(0).should == 0.0
         | 
| 216 297 | 
             
                    pr10.p_le(-200).should == 0.0
         | 
| 217 298 | 
             
                  end
         | 
| 299 | 
            +
             | 
| 300 | 
            +
                  it "should raise a TypeError if asked for probability of non-Integer" do
         | 
| 301 | 
            +
                    lambda { pr4.p_le( [] ) }.should raise_error TypeError
         | 
| 302 | 
            +
                  end
         | 
| 218 303 | 
             
                end # describe "#p_le"
         | 
| 219 304 |  | 
| 220 305 | 
             
                describe "#p_lt" do
         | 
| @@ -238,6 +323,10 @@ describe GamesDice::Probabilities do | |
| 238 323 | 
             
                    pr6.p_lt(1).should == 0.0
         | 
| 239 324 | 
             
                    pr10.p_lt(-200).should == 0.0
         | 
| 240 325 | 
             
                  end
         | 
| 326 | 
            +
             | 
| 327 | 
            +
                  it "should raise a TypeError if asked for probability of non-Integer" do
         | 
| 328 | 
            +
                    lambda { pr6.p_lt( {} ) }.should raise_error TypeError
         | 
| 329 | 
            +
                  end
         | 
| 241 330 | 
             
                end # describe "#p_lt"
         | 
| 242 331 |  | 
| 243 332 | 
             
                describe "#to_h" do
         | 
| @@ -281,7 +370,7 @@ describe GamesDice::Probabilities do | |
| 281 370 | 
             
                end
         | 
| 282 371 |  | 
| 283 372 | 
             
                describe "#given_ge" do
         | 
| 284 | 
            -
             | 
| 373 | 
            +
                  it "should return a new distribution with probabilities calculated assuming value is >= target" do
         | 
| 285 374 | 
             
                    pd = pr2.given_ge(2)
         | 
| 286 375 | 
             
                    pd.to_h.should == { 2 => 1.0 }
         | 
| 287 376 | 
             
                    pd = pr10.given_ge(4)
         | 
| @@ -289,10 +378,14 @@ describe GamesDice::Probabilities do | |
| 289 378 | 
             
                    pd.p_eql( 3 ).should == 0.0
         | 
| 290 379 | 
             
                    pd.p_eql( 10 ).should be_within(1.0e-9).of 0.1/0.7
         | 
| 291 380 | 
             
                  end
         | 
| 381 | 
            +
             | 
| 382 | 
            +
                  it "should raise a TypeError if asked for probability of non-Integer" do
         | 
| 383 | 
            +
                    lambda { pr10.given_ge( [] ) }.should raise_error TypeError
         | 
| 384 | 
            +
                  end
         | 
| 292 385 | 
             
                end
         | 
| 293 386 |  | 
| 294 387 | 
             
                describe "#given_le" do
         | 
| 295 | 
            -
             | 
| 388 | 
            +
                  it "should return a new distribution with probabilities calculated assuming value is <= target" do
         | 
| 296 389 | 
             
                    pd = pr2.given_le(2)
         | 
| 297 390 | 
             
                    pd.to_h.should == { 1 => 0.5, 2 => 0.5 }
         | 
| 298 391 | 
             
                    pd = pr10.given_le(4)
         | 
| @@ -300,6 +393,10 @@ describe GamesDice::Probabilities do | |
| 300 393 | 
             
                    pd.p_eql( 3 ).should be_within(1.0e-9).of 0.1/0.4
         | 
| 301 394 | 
             
                    pd.p_eql( 10 ).should == 0.0
         | 
| 302 395 | 
             
                  end
         | 
| 396 | 
            +
             | 
| 397 | 
            +
                  it "should raise a TypeError if asked for probability of non-Integer" do
         | 
| 398 | 
            +
                    lambda { pr10.given_le( {} ) }.should raise_error TypeError
         | 
| 399 | 
            +
                  end
         | 
| 303 400 | 
             
                end
         | 
| 304 401 |  | 
| 305 402 | 
             
                describe "#repeat_sum" do
         | 
| @@ -312,6 +409,16 @@ describe GamesDice::Probabilities do | |
| 312 409 | 
             
                    pr.to_h.should be_valid_distribution
         | 
| 313 410 | 
             
                  end
         | 
| 314 411 |  | 
| 412 | 
            +
                  it "should raise an error if any param is unexpected type" do
         | 
| 413 | 
            +
                    d6 = GamesDice::Probabilities.for_fair_die( 6 )
         | 
| 414 | 
            +
                    lambda{ d6.repeat_sum( {} ) }.should raise_error TypeError
         | 
| 415 | 
            +
                  end
         | 
| 416 | 
            +
             | 
| 417 | 
            +
                  it "should raise an error if distribution would have more than a million results" do
         | 
| 418 | 
            +
                    d1000 = GamesDice::Probabilities.for_fair_die( 1000 )
         | 
| 419 | 
            +
                    lambda{ d1000.repeat_sum( 11000 ) }.should raise_error
         | 
| 420 | 
            +
                  end
         | 
| 421 | 
            +
             | 
| 315 422 | 
             
                  it "should calculate a '3d6' distribution accurately" do
         | 
| 316 423 | 
             
                    d6 = GamesDice::Probabilities.for_fair_die( 6 )
         | 
| 317 424 | 
             
                    pr = d6.repeat_sum( 3 )
         | 
| @@ -346,6 +453,17 @@ describe GamesDice::Probabilities do | |
| 346 453 | 
             
                    pr.to_h.should be_valid_distribution
         | 
| 347 454 | 
             
                  end
         | 
| 348 455 |  | 
| 456 | 
            +
                  it "should raise an error if any param is unexpected type" do
         | 
| 457 | 
            +
                    d6 = GamesDice::Probabilities.for_fair_die( 6 )
         | 
| 458 | 
            +
                    lambda{ d6.repeat_n_sum_k( {}, 10 ) }.should raise_error TypeError
         | 
| 459 | 
            +
                    lambda{ d6.repeat_n_sum_k( 10, {} ) }.should raise_error TypeError
         | 
| 460 | 
            +
                  end
         | 
| 461 | 
            +
             | 
| 462 | 
            +
                  it "should raise an error if n is greater than 170" do
         | 
| 463 | 
            +
                    d6 = GamesDice::Probabilities.for_fair_die( 6 )
         | 
| 464 | 
            +
                    lambda{ d6.repeat_n_sum_k( 171, 10 ) }.should raise_error
         | 
| 465 | 
            +
                  end
         | 
| 466 | 
            +
             | 
| 349 467 | 
             
                  it "should calculate a '4d6 keep best 3' distribution accurately" do
         | 
| 350 468 | 
             
                    d6 = GamesDice::Probabilities.for_fair_die( 6 )
         | 
| 351 469 | 
             
                    pr = d6.repeat_n_sum_k( 4, 3 )
         | 
    
        metadata
    CHANGED
    
    | @@ -1,123 +1,138 @@ | |
| 1 | 
            -
            --- !ruby/object:Gem::Specification
         | 
| 1 | 
            +
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: games_dice
         | 
| 3 | 
            -
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
               | 
| 3 | 
            +
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            +
              hash: 29
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 | 
            +
              segments: 
         | 
| 7 | 
            +
              - 0
         | 
| 8 | 
            +
              - 3
         | 
| 9 | 
            +
              - 7
         | 
| 10 | 
            +
              version: 0.3.7
         | 
| 6 11 | 
             
            platform: ruby
         | 
| 7 | 
            -
            authors:
         | 
| 12 | 
            +
            authors: 
         | 
| 8 13 | 
             
            - Neil Slater
         | 
| 9 14 | 
             
            autorequire: 
         | 
| 10 15 | 
             
            bindir: bin
         | 
| 11 16 | 
             
            cert_chain: []
         | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 17 | 
            +
             | 
| 18 | 
            +
            date: 2013-07-17 00:00:00 Z
         | 
| 19 | 
            +
            dependencies: 
         | 
| 20 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 15 21 | 
             
              name: rspec
         | 
| 16 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 17 | 
            -
                none: false
         | 
| 18 | 
            -
                requirements:
         | 
| 19 | 
            -
                - - ! '>='
         | 
| 20 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 21 | 
            -
                    version: 2.13.0
         | 
| 22 | 
            -
              type: :development
         | 
| 23 22 | 
             
              prerelease: false
         | 
| 24 | 
            -
               | 
| 23 | 
            +
              requirement: &id001 !ruby/object:Gem::Requirement 
         | 
| 25 24 | 
             
                none: false
         | 
| 26 | 
            -
                requirements:
         | 
| 27 | 
            -
                - -  | 
| 28 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 25 | 
            +
                requirements: 
         | 
| 26 | 
            +
                - - ">="
         | 
| 27 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 28 | 
            +
                    hash: 59
         | 
| 29 | 
            +
                    segments: 
         | 
| 30 | 
            +
                    - 2
         | 
| 31 | 
            +
                    - 13
         | 
| 32 | 
            +
                    - 0
         | 
| 29 33 | 
             
                    version: 2.13.0
         | 
| 30 | 
            -
            - !ruby/object:Gem::Dependency
         | 
| 31 | 
            -
              name: rake
         | 
| 32 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 33 | 
            -
                none: false
         | 
| 34 | 
            -
                requirements:
         | 
| 35 | 
            -
                - - ! '>='
         | 
| 36 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 37 | 
            -
                    version: 1.9.1
         | 
| 38 34 | 
             
              type: :development
         | 
| 35 | 
            +
              version_requirements: *id001
         | 
| 36 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 37 | 
            +
              name: rake
         | 
| 39 38 | 
             
              prerelease: false
         | 
| 40 | 
            -
               | 
| 39 | 
            +
              requirement: &id002 !ruby/object:Gem::Requirement 
         | 
| 41 40 | 
             
                none: false
         | 
| 42 | 
            -
                requirements:
         | 
| 43 | 
            -
                - -  | 
| 44 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 41 | 
            +
                requirements: 
         | 
| 42 | 
            +
                - - ">="
         | 
| 43 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 44 | 
            +
                    hash: 49
         | 
| 45 | 
            +
                    segments: 
         | 
| 46 | 
            +
                    - 1
         | 
| 47 | 
            +
                    - 9
         | 
| 48 | 
            +
                    - 1
         | 
| 45 49 | 
             
                    version: 1.9.1
         | 
| 46 | 
            -
            - !ruby/object:Gem::Dependency
         | 
| 47 | 
            -
              name: yard
         | 
| 48 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 49 | 
            -
                none: false
         | 
| 50 | 
            -
                requirements:
         | 
| 51 | 
            -
                - - ! '>='
         | 
| 52 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 53 | 
            -
                    version: 0.8.6
         | 
| 54 50 | 
             
              type: :development
         | 
| 51 | 
            +
              version_requirements: *id002
         | 
| 52 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 53 | 
            +
              name: yard
         | 
| 55 54 | 
             
              prerelease: false
         | 
| 56 | 
            -
               | 
| 55 | 
            +
              requirement: &id003 !ruby/object:Gem::Requirement 
         | 
| 57 56 | 
             
                none: false
         | 
| 58 | 
            -
                requirements:
         | 
| 59 | 
            -
                - -  | 
| 60 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 57 | 
            +
                requirements: 
         | 
| 58 | 
            +
                - - ">="
         | 
| 59 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 60 | 
            +
                    hash: 51
         | 
| 61 | 
            +
                    segments: 
         | 
| 62 | 
            +
                    - 0
         | 
| 63 | 
            +
                    - 8
         | 
| 64 | 
            +
                    - 6
         | 
| 61 65 | 
             
                    version: 0.8.6
         | 
| 62 | 
            -
            - !ruby/object:Gem::Dependency
         | 
| 63 | 
            -
              name: rake-compiler
         | 
| 64 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 65 | 
            -
                none: false
         | 
| 66 | 
            -
                requirements:
         | 
| 67 | 
            -
                - - ! '>='
         | 
| 68 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 69 | 
            -
                    version: '0'
         | 
| 70 66 | 
             
              type: :development
         | 
| 67 | 
            +
              version_requirements: *id003
         | 
| 68 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 69 | 
            +
              name: rake-compiler
         | 
| 71 70 | 
             
              prerelease: false
         | 
| 72 | 
            -
               | 
| 73 | 
            -
                none: false
         | 
| 74 | 
            -
                requirements:
         | 
| 75 | 
            -
                - - ! '>='
         | 
| 76 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 77 | 
            -
                    version: '0'
         | 
| 78 | 
            -
            - !ruby/object:Gem::Dependency
         | 
| 79 | 
            -
              name: redcarpet
         | 
| 80 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 71 | 
            +
              requirement: &id004 !ruby/object:Gem::Requirement 
         | 
| 81 72 | 
             
                none: false
         | 
| 82 | 
            -
                requirements:
         | 
| 83 | 
            -
                - -  | 
| 84 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 85 | 
            -
                     | 
| 73 | 
            +
                requirements: 
         | 
| 74 | 
            +
                - - ">="
         | 
| 75 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 76 | 
            +
                    hash: 3
         | 
| 77 | 
            +
                    segments: 
         | 
| 78 | 
            +
                    - 0
         | 
| 79 | 
            +
                    version: "0"
         | 
| 86 80 | 
             
              type: :development
         | 
| 81 | 
            +
              version_requirements: *id004
         | 
| 82 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 83 | 
            +
              name: redcarpet
         | 
| 87 84 | 
             
              prerelease: false
         | 
| 88 | 
            -
               | 
| 85 | 
            +
              requirement: &id005 !ruby/object:Gem::Requirement 
         | 
| 89 86 | 
             
                none: false
         | 
| 90 | 
            -
                requirements:
         | 
| 91 | 
            -
                - -  | 
| 92 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 87 | 
            +
                requirements: 
         | 
| 88 | 
            +
                - - ">="
         | 
| 89 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 90 | 
            +
                    hash: 3
         | 
| 91 | 
            +
                    segments: 
         | 
| 92 | 
            +
                    - 2
         | 
| 93 | 
            +
                    - 3
         | 
| 94 | 
            +
                    - 0
         | 
| 93 95 | 
             
                    version: 2.3.0
         | 
| 94 | 
            -
            -  | 
| 96 | 
            +
                - - <
         | 
| 97 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 98 | 
            +
                    hash: 7
         | 
| 99 | 
            +
                    segments: 
         | 
| 100 | 
            +
                    - 3
         | 
| 101 | 
            +
                    - 0
         | 
| 102 | 
            +
                    - 0
         | 
| 103 | 
            +
                    version: 3.0.0
         | 
| 104 | 
            +
              type: :development
         | 
| 105 | 
            +
              version_requirements: *id005
         | 
| 106 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 95 107 | 
             
              name: parslet
         | 
| 96 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 97 | 
            -
                none: false
         | 
| 98 | 
            -
                requirements:
         | 
| 99 | 
            -
                - - ! '>='
         | 
| 100 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 101 | 
            -
                    version: 1.5.0
         | 
| 102 | 
            -
              type: :runtime
         | 
| 103 108 | 
             
              prerelease: false
         | 
| 104 | 
            -
               | 
| 109 | 
            +
              requirement: &id006 !ruby/object:Gem::Requirement 
         | 
| 105 110 | 
             
                none: false
         | 
| 106 | 
            -
                requirements:
         | 
| 107 | 
            -
                - -  | 
| 108 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 111 | 
            +
                requirements: 
         | 
| 112 | 
            +
                - - ">="
         | 
| 113 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 114 | 
            +
                    hash: 3
         | 
| 115 | 
            +
                    segments: 
         | 
| 116 | 
            +
                    - 1
         | 
| 117 | 
            +
                    - 5
         | 
| 118 | 
            +
                    - 0
         | 
| 109 119 | 
             
                    version: 1.5.0
         | 
| 110 | 
            -
             | 
| 111 | 
            -
               | 
| 112 | 
            -
             | 
| 120 | 
            +
              type: :runtime
         | 
| 121 | 
            +
              version_requirements: *id006
         | 
| 122 | 
            +
            description: A library for simulating dice. Use it to construct dice-rolling systems used in role-playing and board games.
         | 
| 123 | 
            +
            email: 
         | 
| 113 124 | 
             
            - slobo777@gmail.com
         | 
| 114 125 | 
             
            executables: []
         | 
| 115 | 
            -
             | 
| 126 | 
            +
             | 
| 127 | 
            +
            extensions: 
         | 
| 116 128 | 
             
            - ext/games_dice/extconf.rb
         | 
| 117 129 | 
             
            extra_rdoc_files: []
         | 
| 118 | 
            -
             | 
| 130 | 
            +
             | 
| 131 | 
            +
            files: 
         | 
| 119 132 | 
             
            - .gitignore
         | 
| 120 133 | 
             
            - .travis.yml
         | 
| 134 | 
            +
            - .yardopts
         | 
| 135 | 
            +
            - CHANGELOG.md
         | 
| 121 136 | 
             
            - Gemfile
         | 
| 122 137 | 
             
            - LICENSE.txt
         | 
| 123 138 | 
             
            - README.md
         | 
| @@ -151,38 +166,39 @@ files: | |
| 151 166 | 
             
            - spec/readme_spec.rb
         | 
| 152 167 | 
             
            - spec/reroll_rule_spec.rb
         | 
| 153 168 | 
             
            homepage: https://github.com/neilslater/games_dice
         | 
| 154 | 
            -
            licenses:
         | 
| 169 | 
            +
            licenses: 
         | 
| 155 170 | 
             
            - MIT
         | 
| 156 171 | 
             
            post_install_message: 
         | 
| 157 172 | 
             
            rdoc_options: []
         | 
| 158 | 
            -
             | 
| 173 | 
            +
             | 
| 174 | 
            +
            require_paths: 
         | 
| 159 175 | 
             
            - lib
         | 
| 160 | 
            -
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 176 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement 
         | 
| 161 177 | 
             
              none: false
         | 
| 162 | 
            -
              requirements:
         | 
| 163 | 
            -
              - -  | 
| 164 | 
            -
                - !ruby/object:Gem::Version
         | 
| 165 | 
            -
                   | 
| 166 | 
            -
                  segments:
         | 
| 178 | 
            +
              requirements: 
         | 
| 179 | 
            +
              - - ">="
         | 
| 180 | 
            +
                - !ruby/object:Gem::Version 
         | 
| 181 | 
            +
                  hash: 3
         | 
| 182 | 
            +
                  segments: 
         | 
| 167 183 | 
             
                  - 0
         | 
| 168 | 
            -
                   | 
| 169 | 
            -
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 184 | 
            +
                  version: "0"
         | 
| 185 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement 
         | 
| 170 186 | 
             
              none: false
         | 
| 171 | 
            -
              requirements:
         | 
| 172 | 
            -
              - -  | 
| 173 | 
            -
                - !ruby/object:Gem::Version
         | 
| 174 | 
            -
                   | 
| 175 | 
            -
                  segments:
         | 
| 187 | 
            +
              requirements: 
         | 
| 188 | 
            +
              - - ">="
         | 
| 189 | 
            +
                - !ruby/object:Gem::Version 
         | 
| 190 | 
            +
                  hash: 3
         | 
| 191 | 
            +
                  segments: 
         | 
| 176 192 | 
             
                  - 0
         | 
| 177 | 
            -
                   | 
| 193 | 
            +
                  version: "0"
         | 
| 178 194 | 
             
            requirements: []
         | 
| 195 | 
            +
             | 
| 179 196 | 
             
            rubyforge_project: 
         | 
| 180 197 | 
             
            rubygems_version: 1.8.24
         | 
| 181 198 | 
             
            signing_key: 
         | 
| 182 199 | 
             
            specification_version: 3
         | 
| 183 | 
            -
            summary: Simulates and explains dice rolls from simple "1d6" to complex "roll 7 ten-sided
         | 
| 184 | 
            -
             | 
| 185 | 
            -
            test_files:
         | 
| 200 | 
            +
            summary: Simulates and explains dice rolls from simple "1d6" to complex "roll 7 ten-sided dice, take best 3, results of 10 roll again and add on".
         | 
| 201 | 
            +
            test_files: 
         | 
| 186 202 | 
             
            - spec/bunch_spec.rb
         | 
| 187 203 | 
             
            - spec/complex_die_spec.rb
         | 
| 188 204 | 
             
            - spec/dice_spec.rb
         |