games_dice 0.0.3 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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