games_dice 0.0.3 → 0.0.5

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.
@@ -110,60 +110,64 @@ describe GamesDice::ComplexDie do
110
110
 
111
111
  it "should calculate an expected result" do
112
112
  die = GamesDice::ComplexDie.new(10, :rerolls => [GamesDice::RerollRule.new(10, :<=, :reroll_add),GamesDice::RerollRule.new(1, :>=, :reroll_subtract)] )
113
- die.expected_result.should be_within(1e-10).of 5.5
113
+ die.probabilities.expected.should be_within(1e-10).of 5.5
114
114
 
115
115
  die = GamesDice::ComplexDie.new(10, :rerolls => [GamesDice::RerollRule.new(1, :<=, :reroll_use_best, 1)] )
116
- die.expected_result.should be_within(1e-10).of 7.15
116
+ die.probabilities.expected.should be_within(1e-10).of 7.15
117
117
 
118
118
  die = GamesDice::ComplexDie.new(10, :rerolls => [GamesDice::RerollRule.new(1, :<=, :reroll_use_worst, 2)] )
119
- die.expected_result.should be_within(1e-10).of 3.025
119
+ die.probabilities.expected.should be_within(1e-10).of 3.025
120
120
 
121
121
  die = GamesDice::ComplexDie.new(6, :rerolls => [GamesDice::RerollRule.new(6, :<=, :reroll_add)] )
122
- die.expected_result.should be_within(1e-10).of 4.2
122
+ die.probabilities.expected.should be_within(1e-10).of 4.2
123
123
 
124
124
  die = GamesDice::ComplexDie.new(8, :rerolls => [GamesDice::RerollRule.new(1, :>=, :reroll_use_best)] )
125
- die.expected_result.should be_within(1e-10).of 5.0
125
+ die.probabilities.expected.should be_within(1e-10).of 5.0
126
126
 
127
127
  die = GamesDice::ComplexDie.new(4, :rerolls => [GamesDice::RerollRule.new(1, :>=, :reroll_replace, 1)] )
128
- die.expected_result.should be_within(1e-10).of 2.875
128
+ die.probabilities.expected.should be_within(1e-10).of 2.875
129
129
  end
130
130
 
131
131
  it "should calculate probabilities of each possible result" do
132
132
  die = GamesDice::ComplexDie.new(6, :rerolls => [GamesDice::RerollRule.new(7, :>, :reroll_add, 1)] )
133
- die.probabilities[11].should be_within(1e-10).of 2/36.0
134
- die.probabilities[8].should be_within(1e-10).of 5/36.0
135
- die.probabilities.values.inject(:+).should be_within(1e-9).of 1.0
133
+ probs = die.probabilities.to_h
134
+ probs[11].should be_within(1e-10).of 2/36.0
135
+ probs[8].should be_within(1e-10).of 5/36.0
136
+ probs.values.inject(:+).should be_within(1e-9).of 1.0
136
137
 
137
138
  die = GamesDice::ComplexDie.new(10, :rerolls => [GamesDice::RerollRule.new(10, :<=, :reroll_add)] )
138
- die.probabilities[8].should be_within(1e-10).of 0.1
139
- die.probabilities[10].should be_false
140
- die.probabilities[13].should be_within(1e-10).of 0.01
141
- die.probabilities[27].should be_within(1e-10).of 0.001
142
- die.probabilities.values.inject(:+).should be_within(1e-9).of 1.0
139
+ probs = die.probabilities.to_h
140
+ probs[8].should be_within(1e-10).of 0.1
141
+ probs[10].should be_false
142
+ probs[13].should be_within(1e-10).of 0.01
143
+ probs[27].should be_within(1e-10).of 0.001
144
+ probs.values.inject(:+).should be_within(1e-9).of 1.0
143
145
 
144
146
  die = GamesDice::ComplexDie.new(6, :rerolls => [GamesDice::RerollRule.new(1, :>=, :reroll_replace, 1)] )
145
- die.probabilities[1].should be_within(1e-10).of 1/36.0
146
- die.probabilities[2].should be_within(1e-10).of 7/36.0
147
- die.probabilities.values.inject(:+).should be_within(1e-9).of 1.0
147
+ probs = die.probabilities.to_h
148
+ probs[1].should be_within(1e-10).of 1/36.0
149
+ probs[2].should be_within(1e-10).of 7/36.0
150
+ probs.values.inject(:+).should be_within(1e-9).of 1.0
148
151
  end
149
152
 
150
153
  it "should calculate aggregate probabilities" do
151
154
  die = GamesDice::ComplexDie.new(6, :rerolls => [GamesDice::RerollRule.new(7, :>, :reroll_add, 1)] )
152
- die.probability_gt(7).should be_within(1e-10).of 15/36.0
153
- die.probability_gt(-10).should == 1.0
154
- die.probability_gt(12).should == 0.0
155
-
156
- die.probability_ge(7).should be_within(1e-10).of 21/36.0
157
- die.probability_ge(2).should == 1.0
158
- die.probability_ge(15).should == 0.0
159
-
160
- die.probability_lt(7).should be_within(1e-10).of 15/36.0
161
- die.probability_lt(-10).should == 0.0
162
- die.probability_lt(13).should == 1.0
163
-
164
- die.probability_le(7).should be_within(1e-10).of 21/36.0
165
- die.probability_le(1).should == 0.0
166
- die.probability_le(12).should == 1.0
155
+ probs = die.probabilities
156
+ probs.p_gt(7).should be_within(1e-10).of 15/36.0
157
+ probs.p_gt(-10).should == 1.0
158
+ probs.p_gt(12).should == 0.0
159
+
160
+ probs.p_ge(7).should be_within(1e-10).of 21/36.0
161
+ probs.p_ge(2).should == 1.0
162
+ probs.p_ge(15).should == 0.0
163
+
164
+ probs.p_lt(7).should be_within(1e-10).of 15/36.0
165
+ probs.p_lt(-10).should == 0.0
166
+ probs.p_lt(13).should == 1.0
167
+
168
+ probs.p_le(7).should be_within(1e-10).of 21/36.0
169
+ probs.p_le(1).should == 0.0
170
+ probs.p_le(12).should == 1.0
167
171
  end
168
172
  end
169
173
 
@@ -192,34 +196,36 @@ describe GamesDice::ComplexDie do
192
196
 
193
197
  it "should calculate an expected result" do
194
198
  die = GamesDice::ComplexDie.new(10, :maps => [GamesDice::MapRule.new(7, :<=, 1, 'S'),GamesDice::MapRule.new(1, :>=, -1, 'F')] )
195
- die.expected_result.should be_within(1e-10).of 0.3
199
+ die.probabilities.expected.should be_within(1e-10).of 0.3
196
200
  end
197
201
 
198
202
  it "should calculate probabilities of each possible result" do
199
203
  die = GamesDice::ComplexDie.new(10, :maps => [GamesDice::MapRule.new(7, :<=, 1, 'S'),GamesDice::MapRule.new(1, :>=, -1, 'F')] )
200
- die.probabilities[1].should be_within(1e-10).of 0.4
201
- die.probabilities[0].should be_within(1e-10).of 0.5
202
- die.probabilities[-1].should be_within(1e-10).of 0.1
203
- die.probabilities.values.inject(:+).should be_within(1e-9).of 1.0
204
+ probs_hash = die.probabilities.to_h
205
+ probs_hash[1].should be_within(1e-10).of 0.4
206
+ probs_hash[0].should be_within(1e-10).of 0.5
207
+ probs_hash[-1].should be_within(1e-10).of 0.1
208
+ probs_hash.values.inject(:+).should be_within(1e-9).of 1.0
204
209
  end
205
210
 
206
211
  it "should calculate aggregate probabilities" do
207
212
  die = GamesDice::ComplexDie.new(10, :maps => [GamesDice::MapRule.new(7, :<=, 1, 'S'),GamesDice::MapRule.new(1, :>=, -1, 'F')] )
208
- die.probability_gt(-1).should be_within(1e-10).of 0.9
209
- die.probability_gt(-2).should == 1.0
210
- die.probability_gt(1).should == 0.0
211
-
212
- die.probability_ge(1).should be_within(1e-10).of 0.4
213
- die.probability_ge(-1).should == 1.0
214
- die.probability_ge(2).should == 0.0
215
-
216
- die.probability_lt(1).should be_within(1e-10).of 0.6
217
- die.probability_lt(-1).should == 0.0
218
- die.probability_lt(2).should == 1.0
219
-
220
- die.probability_le(-1).should be_within(1e-10).of 0.1
221
- die.probability_le(-2).should == 0.0
222
- die.probability_le(1).should == 1.0
213
+ probs = die.probabilities
214
+ probs.p_gt(-2).should == 1.0
215
+ probs.p_gt(-1).should be_within(1e-10).of 0.9
216
+ probs.p_gt(1).should == 0.0
217
+
218
+ probs.p_ge(1).should be_within(1e-10).of 0.4
219
+ probs.p_ge(-1).should == 1.0
220
+ probs.p_ge(2).should == 0.0
221
+
222
+ probs.p_lt(1).should be_within(1e-10).of 0.6
223
+ probs.p_lt(-1).should == 0.0
224
+ probs.p_lt(2).should == 1.0
225
+
226
+ probs.p_le(-1).should be_within(1e-10).of 0.1
227
+ probs.p_le(-2).should == 0.0
228
+ probs.p_le(1).should == 1.0
223
229
  end
224
230
  end
225
231
 
@@ -237,31 +243,34 @@ describe GamesDice::ComplexDie do
237
243
  end
238
244
 
239
245
  it "should calculate an expected result" do
240
- @die.expected_result.should be_within(1e-10).of 4/36.0
246
+ @die.probabilities.expected.should be_within(1e-10).of 4/36.0
241
247
  end
242
248
 
243
249
  it "should calculate probabilities of each possible result" do
244
- @die.probabilities[1].should be_within(1e-10).of 4/36.0
245
- @die.probabilities[0].should be_within(1e-10).of 32/36.0
246
- @die.probabilities.values.inject(:+).should be_within(1e-9).of 1.0
250
+ probs_hash = @die.probabilities.to_h
251
+ probs_hash[1].should be_within(1e-10).of 4/36.0
252
+ probs_hash[0].should be_within(1e-10).of 32/36.0
253
+ probs_hash.values.inject(:+).should be_within(1e-9).of 1.0
247
254
  end
248
255
 
249
256
  it "should calculate aggregate probabilities" do
250
- @die.probability_gt(0).should be_within(1e-10).of 4/36.0
251
- @die.probability_gt(-2).should == 1.0
252
- @die.probability_gt(1).should == 0.0
257
+ probs = @die.probabilities
258
+
259
+ probs.p_gt(0).should be_within(1e-10).of 4/36.0
260
+ probs.p_gt(-2).should == 1.0
261
+ probs.p_gt(1).should == 0.0
253
262
 
254
- @die.probability_ge(1).should be_within(1e-10).of 4/36.0
255
- @die.probability_ge(-1).should == 1.0
256
- @die.probability_ge(2).should == 0.0
263
+ probs.p_ge(1).should be_within(1e-10).of 4/36.0
264
+ probs.p_ge(-1).should == 1.0
265
+ probs.p_ge(2).should == 0.0
257
266
 
258
- @die.probability_lt(1).should be_within(1e-10).of 32/36.0
259
- @die.probability_lt(0).should == 0.0
260
- @die.probability_lt(2).should == 1.0
267
+ probs.p_lt(1).should be_within(1e-10).of 32/36.0
268
+ probs.p_lt(0).should == 0.0
269
+ probs.p_lt(2).should == 1.0
261
270
 
262
- @die.probability_le(0).should be_within(1e-10).of 32/36.0
263
- @die.probability_le(-1).should == 0.0
264
- @die.probability_le(1).should == 1.0
271
+ probs.p_le(0).should be_within(1e-10).of 32/36.0
272
+ probs.p_le(-1).should == 0.0
273
+ probs.p_le(1).should == 1.0
265
274
  end
266
275
 
267
276
  it "should apply mapping to final re-rolled result" do
@@ -0,0 +1,34 @@
1
+ require 'games_dice'
2
+
3
+ describe GamesDice::Dice do
4
+
5
+ describe "dice scheme" do
6
+
7
+ before :each do
8
+ srand(67809)
9
+ end
10
+
11
+ describe '1d10+2' do
12
+ let(:dice) { GamesDice::Dice.new( [ { :sides => 10, :ndice => 1 } ], 2 ) }
13
+
14
+ it "should simulate rolling a ten-sided die, and adding two to each result" do
15
+ [5,4,10,10,7,5,9].each do |expected_total|
16
+ dice.roll.should == expected_total
17
+ dice.result.should == expected_total
18
+ end
19
+ end
20
+ end
21
+
22
+ describe '2d6+6' do
23
+ let(:dice) { GamesDice::Dice.new( [ { :sides => 6, :ndice => 2 } ], 6) }
24
+
25
+ it "should simulate rolling two six-sided dice and adding six to the result" do
26
+ [15,12,17,15,13,13,16].each do |expected_total|
27
+ dice.roll.should == expected_total
28
+ dice.result.should == expected_total
29
+ end
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -24,8 +24,6 @@ describe GamesDice::Die do
24
24
  die.min.should == 1
25
25
  die.max.should == 6
26
26
  die.sides.should == 6
27
- die.probabilities.should == { 1 => 1.0/6, 2 => 1.0/6, 3 => 1.0/6, 4 => 1.0/6, 5 => 1.0/6, 6 => 1.0/6 }
28
- die.expected_result.should == 3.5
29
27
  end
30
28
 
31
29
  it "should accept any object with a rand(Integer) method as the second param" do
@@ -56,39 +54,37 @@ describe GamesDice::Die do
56
54
  end
57
55
  end
58
56
 
59
- describe "#expected_result" do
60
- it "should calculate correct weighted mean" do
61
- die = GamesDice::Die.new(20)
62
- die.expected_result.should be_within(1e-10).of 10.5
63
- end
64
- end
65
-
66
57
  describe "#probabilities" do
67
- it "should calculate probabilities accurately" do
58
+ it "should return the die's probability distribution as a GamesDice::Probabilities object" do
68
59
  die = GamesDice::Die.new(6)
69
- die.probabilities[1].should be_within(1e-10).of 1/6.0
70
- die.probabilities[2].should be_within(1e-10).of 1/6.0
71
- die.probabilities[3].should be_within(1e-10).of 1/6.0
72
- die.probabilities[4].should be_within(1e-10).of 1/6.0
73
- die.probabilities[5].should be_within(1e-10).of 1/6.0
74
- die.probabilities[6].should be_within(1e-10).of 1/6.0
75
- die.probabilities.values.inject(:+).should be_within(1e-9).of 1.0
60
+ die.probabilities.is_a?( GamesDice::Probabilities ).should be_true
61
+ probs = die.probabilities
62
+
63
+ probs.p_eql(1).should be_within(1e-10).of 1/6.0
64
+ probs.p_eql(2).should be_within(1e-10).of 1/6.0
65
+ probs.p_eql(3).should be_within(1e-10).of 1/6.0
66
+ probs.p_eql(4).should be_within(1e-10).of 1/6.0
67
+ probs.p_eql(5).should be_within(1e-10).of 1/6.0
68
+ probs.p_eql(6).should be_within(1e-10).of 1/6.0
69
+ probs.to_h.values.inject(:+).should be_within(1e-9).of 1.0
70
+
71
+ probs.p_gt(6).should == 0.0
72
+ probs.p_gt(-20).should == 1.0
73
+ probs.p_gt(4).should be_within(1e-10).of 2/6.0
76
74
 
77
- die.probability_gt(6).should == 0.0
78
- die.probability_gt(-20).should == 1.0
79
- die.probability_gt(4).should be_within(1e-10).of 2/6.0
75
+ probs.p_ge(20).should == 0.0
76
+ probs.p_ge(1).should == 1.0
77
+ probs.p_ge(4).should be_within(1e-10).of 0.5
80
78
 
81
- die.probability_ge(20).should == 0.0
82
- die.probability_ge(1).should == 1.0
83
- die.probability_ge(4).should be_within(1e-10).of 0.5
79
+ probs.p_le(6).should == 1.0
80
+ probs.p_le(-3).should == 0.0
81
+ probs.p_le(5).should be_within(1e-10).of 5/6.0
84
82
 
85
- die.probability_le(6).should == 1.0
86
- die.probability_le(-3).should == 0.0
87
- die.probability_le(5).should be_within(1e-10).of 5/6.0
83
+ probs.p_lt(7).should == 1.0
84
+ probs.p_lt(1).should == 0.0
85
+ probs.p_lt(3).should be_within(1e-10).of 2/6.0
88
86
 
89
- die.probability_lt(7).should == 1.0
90
- die.probability_lt(1).should == 0.0
91
- die.probability_lt(3).should be_within(1e-10).of 2/6.0
87
+ probs.expected.should be_within(1e-10).of 3.5
92
88
  end
93
89
  end
94
90
 
@@ -0,0 +1,265 @@
1
+ require 'games_dice'
2
+
3
+ # A valid distribution is:
4
+ # A hash
5
+ # Keys are all Integers
6
+ # Values are all positive Floats, between 0.0 and 1.0
7
+ # Sum of values is 1.0
8
+ RSpec::Matchers.define :be_valid_distribution do
9
+ match do |given|
10
+ @error = nil
11
+ if ! given.is_a?(Hash)
12
+ @error = "distribution should be a Hash, but it is a #{given.class}"
13
+ elsif given.keys.any? { |k| ! k.is_a?(Fixnum) }
14
+ bad_key = given.keys.first { |k| ! k.is_a?(Fixnum) }
15
+ @error = "all keys should be Fixnums, but found '#{bad_key.inspect}' which is a #{bad_key.class}"
16
+ elsif given.values.any? { |v| ! v.is_a?(Float) }
17
+ bad_value = given.values.first { |v| ! v.is_a?(Float) }
18
+ @error = "all values should be Floats, but found '#{bad_value.inspect}' which is a #{bad_value.class}"
19
+ elsif given.values.any? { |v| v < 0.0 || v > 1.0 }
20
+ bad_value = given.values.first { |v| v < 0.0 || v > 1.0 }
21
+ @error = "all values should be in range (0.0..1.0), but found #{bad_value}"
22
+ elsif (1.0 - given.values.inject(:+)).abs > 1e-6
23
+ total_probs = given.values.inject(:+)
24
+ @error = "sum of values should be 1.0, but got #{total_probs}"
25
+ end
26
+ ! @error
27
+ end
28
+
29
+ failure_message_for_should do |given|
30
+ @error ? @error : 'Distribution is valid and complete'
31
+ end
32
+
33
+ failure_message_for_should_not do |given|
34
+ @error ? @error : 'Distribution is valid and complete'
35
+ end
36
+
37
+ description do |given|
38
+ "a hash describing a complete discrete probability distribution of integers"
39
+ end
40
+ end
41
+
42
+ describe GamesDice::Probabilities do
43
+
44
+ describe "class methods" do
45
+
46
+ describe "#new" do
47
+ it "should create a new distribution from a hash" do
48
+ p = GamesDice::Probabilities.new( { 1 => 1.0 } )
49
+ p.is_a?( GamesDice::Probabilities ).should be_true
50
+ p.to_h.should be_valid_distribution
51
+ end
52
+ end
53
+
54
+ describe "#for_fair_die" do
55
+ it "should create a new distribution based on number of sides" do
56
+ p2 = GamesDice::Probabilities.for_fair_die( 2 )
57
+ p2.is_a?( GamesDice::Probabilities ).should be_true
58
+ p2.to_h.should == { 1 => 0.5, 2 => 0.5 }
59
+ (1..20).each do |sides|
60
+ p = GamesDice::Probabilities.for_fair_die( sides )
61
+ p.is_a?( GamesDice::Probabilities ).should be_true
62
+ h = p.to_h
63
+ h.should be_valid_distribution
64
+ h.keys.count.should == sides
65
+ h.values.each { |v| v.should be_within(1e-10).of 1.0/sides }
66
+ end
67
+ end
68
+ end
69
+
70
+ describe "#add_distributions" do
71
+ it "should combine two distributions to create a third one" do
72
+ d4a = GamesDice::Probabilities.new( { 1 => 1.0/4, 2 => 1.0/4, 3 => 1.0/4, 4 => 1.0/4 } )
73
+ d4b = GamesDice::Probabilities.new( { 1 => 1.0/10, 2 => 2.0/10, 3 => 3.0/10, 4 => 4.0/10 } )
74
+ p = GamesDice::Probabilities.add_distributions( d4a, d4b )
75
+ p.to_h.should be_valid_distribution
76
+ end
77
+
78
+ it "should calculate a classic 2d6 distribution accurately" do
79
+ d6 = GamesDice::Probabilities.for_fair_die( 6 )
80
+ p = GamesDice::Probabilities.add_distributions( d6, d6 )
81
+ p.to_h.should be_valid_distribution
82
+ p.to_h[2].should be_within(1e-9).of 1.0/36
83
+ p.to_h[3].should be_within(1e-9).of 2.0/36
84
+ p.to_h[4].should be_within(1e-9).of 3.0/36
85
+ p.to_h[5].should be_within(1e-9).of 4.0/36
86
+ p.to_h[6].should be_within(1e-9).of 5.0/36
87
+ p.to_h[7].should be_within(1e-9).of 6.0/36
88
+ p.to_h[8].should be_within(1e-9).of 5.0/36
89
+ p.to_h[9].should be_within(1e-9).of 4.0/36
90
+ p.to_h[10].should be_within(1e-9).of 3.0/36
91
+ p.to_h[11].should be_within(1e-9).of 2.0/36
92
+ p.to_h[12].should be_within(1e-9).of 1.0/36
93
+ end
94
+ end
95
+
96
+ end # describe "class methods"
97
+
98
+ describe "instance methods" do
99
+ let(:p2) { GamesDice::Probabilities.for_fair_die( 2 ) }
100
+ let(:p4) { GamesDice::Probabilities.for_fair_die( 4 ) }
101
+ let(:p6) { GamesDice::Probabilities.for_fair_die( 6 ) }
102
+ let(:p10) { GamesDice::Probabilities.for_fair_die( 10 ) }
103
+ let(:pa) { GamesDice::Probabilities.new( { -1 => 0.4, 0 => 0.2, 1 => 0.4 } ) }
104
+
105
+ describe "#p_eql" do
106
+ it "should return probability of getting a number inside the range" do
107
+ p2.p_eql(2).should be_within(1.0e-9).of 0.5
108
+ p4.p_eql(1).should be_within(1.0e-9).of 0.25
109
+ p6.p_eql(6).should be_within(1.0e-9).of 1.0/6
110
+ p10.p_eql(3).should be_within(1.0e-9).of 0.1
111
+ pa.p_eql(-1).should be_within(1.0e-9).of 0.4
112
+ end
113
+
114
+ it "should return 0.0 for values not covered by distribution" do
115
+ p2.p_eql(3).should == 0.0
116
+ p4.p_eql(-1).should == 0.0
117
+ p6.p_eql(8).should == 0.0
118
+ p10.p_eql(11).should == 0.0
119
+ pa.p_eql(2).should == 0.0
120
+ end
121
+ end # describe "#p_eql"
122
+
123
+ describe "#p_gt" do
124
+ it "should return probability of getting a number greater than target" do
125
+ p2.p_gt(1).should be_within(1.0e-9).of 0.5
126
+ p4.p_gt(3).should be_within(1.0e-9).of 0.25
127
+ p6.p_gt(2).should be_within(1.0e-9).of 4.0/6
128
+ p10.p_gt(6).should be_within(1.0e-9).of 0.4
129
+
130
+ # Trying more than one, due to unusual error seen in complex_die_spec when calculating probabilities
131
+ pa.p_gt(-2).should be_within(1.0e-9).of 1.0
132
+ pa.p_gt(-1).should be_within(1.0e-9).of 0.6
133
+ pa.p_gt(0).should be_within(1.0e-9).of 0.4
134
+ pa.p_gt(1).should be_within(1.0e-9).of 0.0
135
+ end
136
+
137
+ it "should return 0.0 when the target number is equal or higher than maximum possible" do
138
+ p2.p_gt(2).should == 0.0
139
+ p4.p_gt(5).should == 0.0
140
+ p6.p_gt(6).should == 0.0
141
+ p10.p_gt(20).should == 0.0
142
+ pa.p_gt(3).should == 0.0
143
+ end
144
+
145
+ it "should return 1.0 when the target number is lower than minimum" do
146
+ p2.p_gt(0).should == 1.0
147
+ p4.p_gt(-5).should == 1.0
148
+ p6.p_gt(0).should == 1.0
149
+ p10.p_gt(-200).should == 1.0
150
+ pa.p_gt(-2).should == 1.0
151
+ end
152
+ end # describe "#p_gt"
153
+
154
+ describe "#p_ge" do
155
+ it "should return probability of getting a number greater than or equal to target" do
156
+ p2.p_ge(2).should be_within(1.0e-9).of 0.5
157
+ p4.p_ge(3).should be_within(1.0e-9).of 0.5
158
+ p6.p_ge(2).should be_within(1.0e-9).of 5.0/6
159
+ p10.p_ge(6).should be_within(1.0e-9).of 0.5
160
+ end
161
+
162
+ it "should return 0.0 when the target number is higher than maximum possible" do
163
+ p2.p_ge(6).should == 0.0
164
+ p4.p_ge(5).should == 0.0
165
+ p6.p_ge(7).should == 0.0
166
+ p10.p_ge(20).should == 0.0
167
+ end
168
+
169
+ it "should return 1.0 when the target number is lower than or equal to minimum possible" do
170
+ p2.p_ge(1).should == 1.0
171
+ p4.p_ge(-5).should == 1.0
172
+ p6.p_ge(1).should == 1.0
173
+ p10.p_ge(-200).should == 1.0
174
+ end
175
+ end # describe "#p_ge"
176
+
177
+ describe "#p_le" do
178
+ it "should return probability of getting a number less than or equal to target" do
179
+ p2.p_le(1).should be_within(1.0e-9).of 0.5
180
+ p4.p_le(2).should be_within(1.0e-9).of 0.5
181
+ p6.p_le(2).should be_within(1.0e-9).of 2.0/6
182
+ p10.p_le(6).should be_within(1.0e-9).of 0.6
183
+ end
184
+
185
+ it "should return 1.0 when the target number is higher than or equal to maximum possible" do
186
+ p2.p_le(6).should == 1.0
187
+ p4.p_le(4).should == 1.0
188
+ p6.p_le(7).should == 1.0
189
+ p10.p_le(10).should == 1.0
190
+ end
191
+
192
+ it "should return 0.0 when the target number is lower than minimum possible" do
193
+ p2.p_le(0).should == 0.0
194
+ p4.p_le(-5).should == 0.0
195
+ p6.p_le(0).should == 0.0
196
+ p10.p_le(-200).should == 0.0
197
+ end
198
+ end # describe "#p_le"
199
+
200
+ describe "#p_lt" do
201
+ it "should return probability of getting a number less than target" do
202
+ p2.p_lt(2).should be_within(1.0e-9).of 0.5
203
+ p4.p_lt(3).should be_within(1.0e-9).of 0.5
204
+ p6.p_lt(2).should be_within(1.0e-9).of 1/6.0
205
+ p10.p_lt(6).should be_within(1.0e-9).of 0.5
206
+ end
207
+
208
+ it "should return 1.0 when the target number is higher than maximum possible" do
209
+ p2.p_lt(6).should == 1.0
210
+ p4.p_lt(5).should == 1.0
211
+ p6.p_lt(7).should == 1.0
212
+ p10.p_lt(20).should == 1.0
213
+ end
214
+
215
+ it "should return 0.0 when the target number is lower than or equal to minimum possible" do
216
+ p2.p_lt(1).should == 0.0
217
+ p4.p_lt(-5).should == 0.0
218
+ p6.p_lt(1).should == 0.0
219
+ p10.p_lt(-200).should == 0.0
220
+ end
221
+ end # describe "#p_lt"
222
+
223
+ describe "#to_h" do
224
+ # This is used loads in other tests
225
+ it "should represent a valid distribution with each integer result associated with its probability" do
226
+ p2.to_h.should be_valid_distribution
227
+ p4.to_h.should be_valid_distribution
228
+ p6.to_h.should be_valid_distribution
229
+ p10.to_h.should be_valid_distribution
230
+ end
231
+ end
232
+
233
+ describe "#min" do
234
+ it "should return lowest possible result allowed by distribution" do
235
+ p2.min.should == 1
236
+ p4.min.should == 1
237
+ p6.min.should == 1
238
+ p10.min.should == 1
239
+ GamesDice::Probabilities.add_distributions( p6, p10 ).min.should == 2
240
+ end
241
+ end
242
+
243
+ describe "#max" do
244
+ it "should return highest possible result allowed by distribution" do
245
+ p2.max.should == 2
246
+ p4.max.should == 4
247
+ p6.max.should == 6
248
+ p10.max.should == 10
249
+ GamesDice::Probabilities.add_distributions( p6, p10 ).max.should == 16
250
+ end
251
+ end
252
+
253
+ describe "#expected" do
254
+ it "should return the weighted mean value" do
255
+ p2.expected.should be_within(1.0e-9).of 1.5
256
+ p4.expected.should be_within(1.0e-9).of 2.5
257
+ p6.expected.should be_within(1.0e-9).of 3.5
258
+ p10.expected.should be_within(1.0e-9).of 5.5
259
+ GamesDice::Probabilities.add_distributions( p6, p10 ).expected.should be_within(1.0e-9).of 9.0
260
+ end
261
+ end
262
+
263
+ end # describe "instance methods"
264
+
265
+ end