spec/probability_spec.rb in games_dice-0.2.3 vs spec/probability_spec.rb in games_dice-0.2.4
- old
+ new
@@ -1,15 +1,13 @@
require 'games_dice'
require 'helpers'
describe GamesDice::Probabilities do
-
describe "class methods" do
-
describe "#new" do
- it "should create a new distribution from a hash" do
- p = GamesDice::Probabilities.new( { 1 => 1.0 } )
+ it "should create a new distribution from an array and offset" do
+ p = GamesDice::Probabilities.new( [1.0], 1 )
p.is_a?( GamesDice::Probabilities ).should be_true
p.to_h.should be_valid_distribution
end
end
@@ -29,42 +27,103 @@
end
end
describe "#add_distributions" do
it "should combine two distributions to create a third one" do
- d4a = GamesDice::Probabilities.new( { 1 => 1.0/4, 2 => 1.0/4, 3 => 1.0/4, 4 => 1.0/4 } )
- d4b = GamesDice::Probabilities.new( { 1 => 1.0/10, 2 => 2.0/10, 3 => 3.0/10, 4 => 4.0/10 } )
+ d4a = GamesDice::Probabilities.new( [ 1.0/4, 1.0/4, 1.0/4, 1.0/4 ], 1 )
+ d4b = GamesDice::Probabilities.new( [ 1.0/10, 2.0/10, 3.0/10, 4.0/10], 1 )
p = GamesDice::Probabilities.add_distributions( d4a, d4b )
p.to_h.should be_valid_distribution
end
it "should calculate a classic 2d6 distribution accurately" do
d6 = GamesDice::Probabilities.for_fair_die( 6 )
p = GamesDice::Probabilities.add_distributions( d6, d6 )
+ h = p.to_h
+ h.should be_valid_distribution
+ h[2].should be_within(1e-9).of 1.0/36
+ h[3].should be_within(1e-9).of 2.0/36
+ h[4].should be_within(1e-9).of 3.0/36
+ h[5].should be_within(1e-9).of 4.0/36
+ h[6].should be_within(1e-9).of 5.0/36
+ h[7].should be_within(1e-9).of 6.0/36
+ h[8].should be_within(1e-9).of 5.0/36
+ h[9].should be_within(1e-9).of 4.0/36
+ h[10].should be_within(1e-9).of 3.0/36
+ h[11].should be_within(1e-9).of 2.0/36
+ h[12].should be_within(1e-9).of 1.0/36
+ end
+ end
+
+ describe "#repeat_distribution" do
+ it "should output a valid distribution if params are valid" do
+ d4a = GamesDice::Probabilities.new( [ 1.0/4, 1.0/4, 1.0/4, 1.0/4 ], 1 )
+ d4b = GamesDice::Probabilities.new( [ 1.0/10, 2.0/10, 3.0/10, 4.0/10], 1 )
+ p = GamesDice::Probabilities.repeat_distribution( d4a, 7 )
p.to_h.should be_valid_distribution
- p.to_h[2].should be_within(1e-9).of 1.0/36
- p.to_h[3].should be_within(1e-9).of 2.0/36
- p.to_h[4].should be_within(1e-9).of 3.0/36
- p.to_h[5].should be_within(1e-9).of 4.0/36
- p.to_h[6].should be_within(1e-9).of 5.0/36
- p.to_h[7].should be_within(1e-9).of 6.0/36
- p.to_h[8].should be_within(1e-9).of 5.0/36
- p.to_h[9].should be_within(1e-9).of 4.0/36
- p.to_h[10].should be_within(1e-9).of 3.0/36
- p.to_h[11].should be_within(1e-9).of 2.0/36
- p.to_h[12].should be_within(1e-9).of 1.0/36
+ p = GamesDice::Probabilities.repeat_distribution( d4b, 12 )
+ p.to_h.should be_valid_distribution
end
+
+ it "should calculate a classic 3d6 distribution accurately" do
+ d6 = GamesDice::Probabilities.for_fair_die( 6 )
+ p = GamesDice::Probabilities.repeat_distribution( d6, 3 )
+ h = p.to_h
+ h.should be_valid_distribution
+ h[3].should be_within(1e-9).of 1.0/216
+ h[4].should be_within(1e-9).of 3.0/216
+ h[5].should be_within(1e-9).of 6.0/216
+ h[6].should be_within(1e-9).of 10.0/216
+ h[7].should be_within(1e-9).of 15.0/216
+ h[8].should be_within(1e-9).of 21.0/216
+ h[9].should be_within(1e-9).of 25.0/216
+ h[10].should be_within(1e-9).of 27.0/216
+ h[11].should be_within(1e-9).of 27.0/216
+ h[12].should be_within(1e-9).of 25.0/216
+ h[13].should be_within(1e-9).of 21.0/216
+ h[14].should be_within(1e-9).of 15.0/216
+ h[15].should be_within(1e-9).of 10.0/216
+ h[16].should be_within(1e-9).of 6.0/216
+ h[17].should be_within(1e-9).of 3.0/216
+ h[18].should be_within(1e-9).of 1.0/216
+ end
+ end # describe "#repeat_distribution"
+
+ describe "#add_distributions_mult" do
+ it "should combine two multiplied distributions to create a third one" do
+ d4a = GamesDice::Probabilities.new( [ 1.0/4, 1.0/4, 1.0/4, 1.0/4 ], 1 )
+ d4b = GamesDice::Probabilities.new( [ 1.0/10, 2.0/10, 3.0/10, 4.0/10], 1 )
+ p = GamesDice::Probabilities.add_distributions_mult( 2, d4a, -1, d4b )
+ p.to_h.should be_valid_distribution
+ end
+
+ it "should calculate a distribution for '1d6 - 1d4' accurately" do
+ d6 = GamesDice::Probabilities.for_fair_die( 6 )
+ d4 = GamesDice::Probabilities.for_fair_die( 4 )
+ p = GamesDice::Probabilities.add_distributions_mult( 1, d6, -1, d4 )
+ h = p.to_h
+ h.should be_valid_distribution
+ h[-3].should be_within(1e-9).of 1.0/24
+ h[-2].should be_within(1e-9).of 2.0/24
+ h[-1].should be_within(1e-9).of 3.0/24
+ h[0].should be_within(1e-9).of 4.0/24
+ h[1].should be_within(1e-9).of 4.0/24
+ h[2].should be_within(1e-9).of 4.0/24
+ h[3].should be_within(1e-9).of 3.0/24
+ h[4].should be_within(1e-9).of 2.0/24
+ h[5].should be_within(1e-9).of 1.0/24
+ end
end
end # describe "class methods"
describe "instance methods" do
let(:p2) { GamesDice::Probabilities.for_fair_die( 2 ) }
let(:p4) { GamesDice::Probabilities.for_fair_die( 4 ) }
let(:p6) { GamesDice::Probabilities.for_fair_die( 6 ) }
let(:p10) { GamesDice::Probabilities.for_fair_die( 10 ) }
- let(:pa) { GamesDice::Probabilities.new( { -1 => 0.4, 0 => 0.2, 1 => 0.4 } ) }
+ let(:pa) { GamesDice::Probabilities.new( [ 0.4, 0.2, 0.4 ], -1 ) }
describe "#p_eql" do
it "should return probability of getting a number inside the range" do
p2.p_eql(2).should be_within(1.0e-9).of 0.5
p4.p_eql(1).should be_within(1.0e-9).of 0.25
@@ -220,8 +279,28 @@
p10.expected.should be_within(1.0e-9).of 5.5
GamesDice::Probabilities.add_distributions( p6, p10 ).expected.should be_within(1.0e-9).of 9.0
end
end
- end # describe "instance methods"
+ describe "#given_ge" do
+ it "should return a new distribution with probabilities calculated assuming value is >= target" do
+ pd = p2.given_ge(2)
+ pd.to_h.should == { 2 => 1.0 }
+ pd = p10.given_ge(4)
+ pd.to_h.should be_valid_distribution
+ pd.p_eql( 3 ).should == 0.0
+ pd.p_eql( 10 ).should be_within(1.0e-9).of 0.1/0.7
+ end
+ end
+ describe "#given_le" do
+ it "should return a new distribution with probabilities calculated assuming value is <= target" do
+ pd = p2.given_le(2)
+ pd.to_h.should == { 1 => 0.5, 2 => 0.5 }
+ pd = p10.given_le(4)
+ pd.to_h.should be_valid_distribution
+ pd.p_eql( 3 ).should be_within(1.0e-9).of 0.1/0.4
+ pd.p_eql( 10 ).should == 0.0
+ end
+ end
+ end # describe "instance methods"
end