games_dice 0.0.2 → 0.0.3

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.
@@ -0,0 +1,46 @@
1
+ module GamesDice
2
+ # convert integer die result into value used in a game (e.g. 1 for a 'success')
3
+ class MapRule
4
+
5
+ # trigger_op, trigger_value, mapped_value and mapped_name set the attributes of the same name
6
+ # rule = RPGMapRule.new( 6, :<=, 1, 'Success' ) # score 1 for a result of 6 or more
7
+ def initialize trigger_value, trigger_op, mapped_value=0, mapped_name=''
8
+
9
+ if ! trigger_value.respond_to?( trigger_op )
10
+ raise ArgumentError, "trigger_value #{trigger_value.inspect} cannot respond to trigger_op #{trigger_value.inspect}"
11
+ end
12
+
13
+ @trigger_value = trigger_value
14
+ @trigger_op = trigger_op
15
+ raise TypeError if ! mapped_value.is_a? Numeric
16
+ @mapped_value = Integer(mapped_value)
17
+ @mapped_name = mapped_name.to_s
18
+ end
19
+
20
+ # an Integer value or Range that will be mapped to a single value. #trigger_op is called against it
21
+ attr_reader :trigger_value
22
+
23
+ # a valid symbol for a method, which will be called against #trigger_value with the current
24
+ # die result as a param. If the operator returns true for a specific die result, then the
25
+ # mapped_value will be used in its stead. If the operator returns nil or false, the map is not
26
+ # triggered. All other values will be returned as the result of the map (allowing you to
27
+ # specify any method that takes an integer as input and returns something else as the end result)
28
+ attr_reader :trigger_op
29
+
30
+ # an integer value
31
+ attr_reader :mapped_value
32
+
33
+ # a string description of the mapping, e.g. 'S' for a success
34
+ attr_reader :mapped_name
35
+
36
+ # runs the rule against test_value, returning either a new value, or nil if the rule does not apply
37
+ def map_from test_value
38
+ op_result = @trigger_value.send( @trigger_op, test_value )
39
+ return nil unless op_result
40
+ if op_result == true
41
+ return @mapped_value
42
+ end
43
+ return op_result
44
+ end
45
+ end # class MapRule
46
+ end # module GamesDice
@@ -0,0 +1,64 @@
1
+ module GamesDice
2
+
3
+ # specifies when and how a ComplexDie should be re-rolled
4
+ class RerollRule
5
+
6
+ # allowed reasons for making a reroll
7
+ TYPES = {
8
+ :reroll_add => '+',
9
+ :reroll_new_die => '*',
10
+ :reroll_new_keeper => '*',
11
+ :reroll_subtract => '-',
12
+ :reroll_replace => '|',
13
+ :reroll_use_best => '/',
14
+ :reroll_use_worst => '\\',
15
+ }
16
+
17
+ # trigger_op, trigger_value, type and limit set the attributes of the same name
18
+ # rule = GamesDice::RerollRule.new( 10, :<=, :reroll_add ) # an 'exploding' die
19
+ def initialize trigger_value, trigger_op, type, limit=nil
20
+
21
+ if ! trigger_value.respond_to?( trigger_op )
22
+ raise ArgumentError, "trigger_value #{trigger_value.inspect} cannot respond to trigger_op #{trigger_value.inspect}"
23
+ end
24
+
25
+ unless TYPES.has_key?(type)
26
+ raise ArgumentError, "Unrecognised reason for a re-roll #{type}"
27
+ end
28
+
29
+ @trigger_value = trigger_value
30
+ @trigger_op = trigger_op
31
+ @type = type
32
+ @limit = limit ? Integer(limit) : 1000
33
+ @limit = 1 if @type == :reroll_subtract
34
+ end
35
+
36
+ # a valid symbol for a method, which will be called against #trigger_value with the current
37
+ # die result as a param. It should return true or false
38
+ attr_reader :trigger_op
39
+
40
+ # an Integer value or Range that will cause the reroll to occur. #trigger_op is called against it
41
+ attr_reader :trigger_value
42
+
43
+ # a symbol, should be one of the following:
44
+ # :reroll_add - add result of reroll to running total, and ignore :reroll_subtract for this die
45
+ # :reroll_new_die - roll a new die of the same type
46
+ # :reroll_new_keeper - roll a new die of the same type, and keep the result
47
+ # :reroll_subtract - subtract result of reroll from running total, and reverse sense of any further :reroll_add results
48
+ # :reroll_replace - use the new value in place of existing value for the die
49
+ # :reroll_use_best - use the new value if it is higher than the erxisting value
50
+ # :reroll_use_worst - use the new value if it is higher than the existing value
51
+ attr_reader :type
52
+
53
+ # maximum number of times this rule should be applied to a single die. If type is:reroll_subtract,
54
+ # this value is always 1. A default value of 100 is used if not set in the constructor
55
+ attr_reader :limit
56
+
57
+ # runs the rule against a test value, returning truth value from calling the trigger_op method
58
+ def applies? test_value
59
+ @trigger_value.send( @trigger_op, test_value ) ? true : false
60
+ end
61
+
62
+ end # class RerollRule
63
+
64
+ end # module GamesDice
@@ -1,3 +1,3 @@
1
1
  module GamesDice
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1,414 @@
1
+ require 'games_dice'
2
+
3
+ describe GamesDice::Bunch do
4
+
5
+ describe "dice scheme" do
6
+
7
+ before :each do
8
+ srand(67809)
9
+ end
10
+
11
+ describe '1d10' do
12
+ let(:dice) { GamesDice::Bunch.new( :sides => 10, :ndice => 1 ) }
13
+
14
+ it "should simulate rolling a ten-sided die" do
15
+ [3,2,8,8,5,3,7].each do |expected_total|
16
+ dice.roll.should == expected_total
17
+ dice.result.should == expected_total
18
+ end
19
+ end
20
+
21
+ it "should concisely explain each result" do
22
+ ["3", "2", "8", "8"].each do |expected_explain|
23
+ dice.roll
24
+ dice.explain_result.should == expected_explain
25
+ end
26
+ end
27
+
28
+ it "should calculate correct min, max = 1,10" do
29
+ dice.min.should == 1
30
+ dice.max.should == 10
31
+ end
32
+
33
+ it "should have a mean value of 5.5" do
34
+ dice.expected_result.should be_within(1e-10).of 5.5
35
+ end
36
+
37
+ it "should calculate probabilities correctly" do
38
+ dice.probabilities[1].should be_within(1e-10).of 0.1
39
+ dice.probabilities[2].should be_within(1e-10).of 0.1
40
+ dice.probabilities[3].should be_within(1e-10).of 0.1
41
+ dice.probabilities[4].should be_within(1e-10).of 0.1
42
+ dice.probabilities[5].should be_within(1e-10).of 0.1
43
+ dice.probabilities[6].should be_within(1e-10).of 0.1
44
+ dice.probabilities[7].should be_within(1e-10).of 0.1
45
+ dice.probabilities[8].should be_within(1e-10).of 0.1
46
+ dice.probabilities[9].should be_within(1e-10).of 0.1
47
+ dice.probabilities[10].should be_within(1e-10).of 0.1
48
+ dice.probabilities.values.inject(:+).should be_within(1e-9).of 1.0
49
+ end
50
+ end
51
+
52
+ describe '2d6' do
53
+ let(:dice) { GamesDice::Bunch.new( :sides => 6, :ndice => 2 ) }
54
+
55
+ it "should simulate rolling two six-sided dice and adding them" do
56
+ [9,6,11,9,7,7,10].each do |expected_total|
57
+ dice.roll.should == expected_total
58
+ dice.result.should == expected_total
59
+ end
60
+ end
61
+
62
+ it "should concisely explain each result" do
63
+ ["3 + 6 = 9","2 + 4 = 6","5 + 6 = 11","3 + 6 = 9","2 + 5 = 7","6 + 1 = 7","5 + 5 = 10",].each do |expected_explain|
64
+ dice.roll
65
+ dice.explain_result.should == expected_explain
66
+ end
67
+ end
68
+
69
+ it "should calculate correct min, max = 2,12" do
70
+ dice.min.should == 2
71
+ dice.max.should == 12
72
+ end
73
+
74
+ it "should have a mean value of 7.0" do
75
+ dice.expected_result.should be_within(1e-10).of 7.0
76
+ end
77
+
78
+ it "should calculate probabilities correctly" do
79
+ dice.probabilities[2].should be_within(1e-10).of 1/36.0
80
+ dice.probabilities[3].should be_within(1e-10).of 2/36.0
81
+ dice.probabilities[4].should be_within(1e-10).of 3/36.0
82
+ dice.probabilities[5].should be_within(1e-10).of 4/36.0
83
+ dice.probabilities[6].should be_within(1e-10).of 5/36.0
84
+ dice.probabilities[7].should be_within(1e-10).of 6/36.0
85
+ dice.probabilities[8].should be_within(1e-10).of 5/36.0
86
+ dice.probabilities[9].should be_within(1e-10).of 4/36.0
87
+ dice.probabilities[10].should be_within(1e-10).of 3/36.0
88
+ dice.probabilities[11].should be_within(1e-10).of 2/36.0
89
+ dice.probabilities[12].should be_within(1e-10).of 1/36.0
90
+ dice.probabilities.values.inject(:+).should be_within(1e-9).of 1.0
91
+ end
92
+ end
93
+
94
+ describe '20d10' do
95
+ let(:dice) { GamesDice::Bunch.new( :sides => 10, :ndice => 20 ) }
96
+
97
+ it "should simulate rolling twenty ten-sided dice and adding them" do
98
+ [132,103,102,124,132,96,111].each do |expected_total|
99
+ dice.roll.should == expected_total
100
+ dice.result.should == expected_total
101
+ end
102
+ end
103
+
104
+ it "should concisely explain each result" do
105
+ ["3 + 2 + 8 + 8 + 5 + 3 + 7 + 7 + 6 + 10 + 7 + 6 + 9 + 5 + 5 + 8 + 10 + 9 + 5 + 9 = 132",
106
+ "3 + 9 + 1 + 4 + 3 + 5 + 7 + 1 + 10 + 4 + 7 + 7 + 6 + 5 + 2 + 7 + 4 + 9 + 7 + 2 = 103",
107
+ "6 + 1 + 1 + 3 + 1 + 4 + 9 + 6 + 3 + 10 + 9 + 10 + 8 + 4 + 1 + 4 + 2 + 1 + 10 + 9 = 102",
108
+ ].each do |expected_explain|
109
+ dice.roll
110
+ dice.explain_result.should == expected_explain
111
+ end
112
+ end
113
+
114
+ it "should calculate correct min, max = 20,200" do
115
+ dice.min.should == 20
116
+ dice.max.should == 200
117
+ end
118
+
119
+ it "should have a mean value of 110.0" do
120
+ dice.expected_result.should be_within(1e-8).of 110.0
121
+ end
122
+
123
+ it "should calculate probabilities correctly" do
124
+ dice.probabilities[20].should be_within(1e-26).of 1e-20
125
+ dice.probabilities[110].should be_within(1e-10).of 0.0308191892
126
+ dice.probabilities.values.inject(:+).should be_within(1e-9).of 1.0
127
+ end
128
+ end
129
+
130
+ describe '4d6 keep best 3' do
131
+ let(:dice) { GamesDice::Bunch.new( :sides => 6, :ndice => 4, :keep_mode => :keep_best, :keep_number => 3 ) }
132
+
133
+ it "should simulate rolling four six-sided dice and adding the best three values" do
134
+ [13,17,13,12,13,10,14].each do |expected_total|
135
+ dice.roll.should == expected_total
136
+ dice.result.should == expected_total
137
+ end
138
+ end
139
+
140
+ it "should concisely explain each result" do
141
+ ["3, 6, 2, 4. Keep: 3 + 4 + 6 = 13",
142
+ "5, 6, 3, 6. Keep: 5 + 6 + 6 = 17",
143
+ "2, 5, 6, 1. Keep: 2 + 5 + 6 = 13",
144
+ "5, 5, 2, 1. Keep: 2 + 5 + 5 = 12",
145
+ ].each do |expected_explain|
146
+ dice.roll
147
+ dice.explain_result.should == expected_explain
148
+ end
149
+ end
150
+
151
+ it "should calculate correct min, max = 3,18" do
152
+ dice.min.should == 3
153
+ dice.max.should == 18
154
+ end
155
+
156
+ it "should have a mean value of roughly 12.2446" do
157
+ dice.expected_result.should be_within(1e-9).of 12.244598765
158
+ end
159
+
160
+ it "should calculate probabilities correctly" do
161
+ dice.probabilities[3].should be_within(1e-10).of 1/1296.0
162
+ dice.probabilities[4].should be_within(1e-10).of 4/1296.0
163
+ dice.probabilities[5].should be_within(1e-10).of 10/1296.0
164
+ dice.probabilities[6].should be_within(1e-10).of 21/1296.0
165
+ dice.probabilities[7].should be_within(1e-10).of 38/1296.0
166
+ dice.probabilities[8].should be_within(1e-10).of 62/1296.0
167
+ dice.probabilities[9].should be_within(1e-10).of 91/1296.0
168
+ dice.probabilities[10].should be_within(1e-10).of 122/1296.0
169
+ dice.probabilities[11].should be_within(1e-10).of 148/1296.0
170
+ dice.probabilities[12].should be_within(1e-10).of 167/1296.0
171
+ dice.probabilities[13].should be_within(1e-10).of 172/1296.0
172
+ dice.probabilities[14].should be_within(1e-10).of 160/1296.0
173
+ dice.probabilities[15].should be_within(1e-10).of 131/1296.0
174
+ dice.probabilities[16].should be_within(1e-10).of 94/1296.0
175
+ dice.probabilities[17].should be_within(1e-10).of 54/1296.0
176
+ dice.probabilities[18].should be_within(1e-10).of 21/1296.0
177
+ dice.probabilities.values.inject(:+).should be_within(1e-9).of 1.0
178
+ end
179
+ end
180
+
181
+ describe '10d10 keep worst one' do
182
+ let(:dice) { GamesDice::Bunch.new( :sides => 10, :ndice => 10, :keep_mode => :keep_worst, :keep_number => 1 ) }
183
+
184
+ it "should simulate rolling ten ten-sided dice and keeping the worst value" do
185
+ [2,5,1,2,1,1,2].each do |expected_total|
186
+ dice.roll.should == expected_total
187
+ dice.result.should == expected_total
188
+ end
189
+ end
190
+
191
+ it "should concisely explain each result" do
192
+ ["3, 2, 8, 8, 5, 3, 7, 7, 6, 10. Keep: 2",
193
+ "7, 6, 9, 5, 5, 8, 10, 9, 5, 9. Keep: 5",
194
+ "3, 9, 1, 4, 3, 5, 7, 1, 10, 4. Keep: 1",
195
+ "7, 7, 6, 5, 2, 7, 4, 9, 7, 2. Keep: 2",
196
+ ].each do |expected_explain|
197
+ dice.roll
198
+ dice.explain_result.should == expected_explain
199
+ end
200
+ end
201
+
202
+ it "should calculate correct min, max = 1,10" do
203
+ dice.min.should == 1
204
+ dice.max.should == 10
205
+ end
206
+
207
+ it "should have a mean value of roughly 1.491" do
208
+ dice.expected_result.should be_within(1e-9).of 1.4914341925
209
+ end
210
+
211
+ it "should calculate probabilities correctly" do
212
+ dice.probabilities[1].should be_within(1e-10).of 0.6513215599
213
+ dice.probabilities[2].should be_within(1e-10).of 0.2413042577
214
+ dice.probabilities[3].should be_within(1e-10).of 0.0791266575
215
+ dice.probabilities[4].should be_within(1e-10).of 0.0222009073
216
+ dice.probabilities[5].should be_within(1e-10).of 0.0050700551
217
+ dice.probabilities[6].should be_within(1e-10).of 0.0008717049
218
+ dice.probabilities[7].should be_within(1e-10).of 0.0000989527
219
+ dice.probabilities[8].should be_within(1e-10).of 0.0000058025
220
+ dice.probabilities[9].should be_within(1e-10).of 0.0000001023
221
+ dice.probabilities[10].should be_within(1e-18).of 1e-10
222
+ dice.probabilities.values.inject(:+).should be_within(1e-9).of 1.0
223
+ end
224
+ end
225
+
226
+ describe '5d10, re-roll and add on 10s, keep best 2' do
227
+ let(:dice) {
228
+ GamesDice::Bunch.new(
229
+ :sides => 10, :ndice => 5, :keep_mode => :keep_best, :keep_number => 2,
230
+ :rerolls => [GamesDice::RerollRule.new(10,:==,:reroll_add)]
231
+ ) }
232
+
233
+ it "should simulate rolling five ten-sided 'exploding' dice and adding the best two values" do
234
+ [16,24,17,28,12,21,16].each do |expected_total|
235
+ dice.roll.should == expected_total
236
+ dice.result.should == expected_total
237
+ end
238
+ end
239
+
240
+ it "should concisely explain each result" do
241
+ ["3, 2, 8, 8, 5. Keep: 8 + 8 = 16",
242
+ "3, 7, 7, 6, [10+7] 17. Keep: 7 + 17 = 24",
243
+ "6, 9, 5, 5, 8. Keep: 8 + 9 = 17",
244
+ "[10+9] 19, 5, 9, 3, 9. Keep: 9 + 19 = 28",
245
+ ].each do |expected_explain|
246
+ dice.roll
247
+ dice.explain_result.should == expected_explain
248
+ end
249
+ end
250
+
251
+ it "should calculate correct min, max = 2, > 100" do
252
+ dice.min.should == 2
253
+ dice.max.should > 100
254
+ end
255
+
256
+ it "should have a mean value of roughly 18.986" do
257
+ pending "Too slow"
258
+ dice.expected_result.should be_within(1e-9).of 18.9859925804
259
+ end
260
+
261
+ it "should calculate probabilities correctly" do
262
+ pending "Too slow"
263
+ dice.probabilities[2].should be_within(1e-10).of 0.00001
264
+ dice.probabilities[3].should be_within(1e-10).of 0.00005
265
+ dice.probabilities[4].should be_within(1e-10).of 0.00031
266
+ dice.probabilities[5].should be_within(1e-10).of 0.00080
267
+ dice.probabilities[6].should be_within(1e-10).of 0.00211
268
+ dice.probabilities[7].should be_within(1e-10).of 0.00405
269
+ dice.probabilities[8].should be_within(1e-10).of 0.00781
270
+ dice.probabilities[9].should be_within(1e-10).of 0.01280
271
+ dice.probabilities[10].should be_within(1e-10).of 0.02101
272
+ dice.probabilities[12].should be_within(1e-10).of 0.045715
273
+ dice.probabilities[13].should be_within(1e-10).of 0.060830
274
+ dice.probabilities[14].should be_within(1e-10).of 0.077915
275
+ dice.probabilities[15].should be_within(1e-10).of 0.090080
276
+ dice.probabilities[16].should be_within(1e-10).of 0.097935
277
+ dice.probabilities[17].should be_within(1e-10).of 0.091230
278
+ dice.probabilities[18].should be_within(1e-10).of 0.070015
279
+ dice.probabilities[19].should be_within(1e-10).of 0.020480
280
+ dice.probabilities[20].should be_within(1e-10).of 0.032805
281
+ dice.probabilities[22].should be_within(1e-10).of 0.0334626451
282
+ dice.probabilities[23].should be_within(1e-10).of 0.0338904805
283
+ dice.probabilities[24].should be_within(1e-10).of 0.0338098781
284
+ dice.probabilities[25].should be_within(1e-10).of 0.0328226480
285
+ dice.probabilities[26].should be_within(1e-10).of 0.0304393461
286
+ dice.probabilities[27].should be_within(1e-10).of 0.0260456005
287
+ dice.probabilities[28].should be_within(1e-10).of 0.0189361531
288
+ dice.probabilities[29].should be_within(1e-10).of 0.0082804480
289
+ dice.probabilities[30].should be_within(1e-10).of 0.0103524151
290
+ dice.probabilities.values.inject(:+).should be_within(1e-9).of 1.0
291
+ end
292
+ end
293
+
294
+ describe 'roll 2d20, keep best value' do
295
+ let(:dice) do
296
+ GamesDice::Bunch.new(
297
+ :sides => 20, :ndice => 2, :keep_mode => :keep_best, :keep_number => 1
298
+ )
299
+ end
300
+
301
+ it "should simulate rolling two twenty-sided dice and keeping the best value" do
302
+ [19,18,14,6,13,10,16].each do |expected_total|
303
+ dice.roll.should == expected_total
304
+ dice.result.should == expected_total
305
+ end
306
+ end
307
+
308
+ it "should concisely explain each result" do
309
+ ["19, 14. Keep: 19",
310
+ "18, 16. Keep: 18",
311
+ "5, 14. Keep: 14",
312
+ "3, 6. Keep: 6",
313
+ ].each do |expected_explain|
314
+ dice.roll
315
+ dice.explain_result.should == expected_explain
316
+ end
317
+ end
318
+
319
+ it "should calculate correct min, max = 1,20" do
320
+ dice.min.should == 1
321
+ dice.max.should == 20
322
+ end
323
+
324
+ it "should have a mean value of 13.825" do
325
+ dice.expected_result.should be_within(1e-9).of 13.825
326
+ end
327
+
328
+ it "should calculate probabilities correctly" do
329
+ dice.probabilities[1].should be_within(1e-10).of 1/400.0
330
+ dice.probabilities[2].should be_within(1e-10).of 3/400.0
331
+ dice.probabilities[3].should be_within(1e-10).of 5/400.0
332
+ dice.probabilities[4].should be_within(1e-10).of 7/400.0
333
+ dice.probabilities[5].should be_within(1e-10).of 9/400.0
334
+ dice.probabilities[6].should be_within(1e-10).of 11/400.0
335
+ dice.probabilities[7].should be_within(1e-10).of 13/400.0
336
+ dice.probabilities[8].should be_within(1e-10).of 15/400.0
337
+ dice.probabilities[9].should be_within(1e-10).of 17/400.0
338
+ dice.probabilities[10].should be_within(1e-10).of 19/400.0
339
+ dice.probabilities[11].should be_within(1e-10).of 21/400.0
340
+ dice.probabilities[12].should be_within(1e-10).of 23/400.0
341
+ dice.probabilities[13].should be_within(1e-10).of 25/400.0
342
+ dice.probabilities[14].should be_within(1e-10).of 27/400.0
343
+ dice.probabilities[15].should be_within(1e-10).of 29/400.0
344
+ dice.probabilities[16].should be_within(1e-10).of 31/400.0
345
+ dice.probabilities[17].should be_within(1e-10).of 33/400.0
346
+ dice.probabilities[18].should be_within(1e-10).of 35/400.0
347
+ dice.probabilities[19].should be_within(1e-10).of 37/400.0
348
+ dice.probabilities[20].should be_within(1e-10).of 39/400.0
349
+ dice.probabilities.values.inject(:+).should be_within(1e-9).of 1.0
350
+ end
351
+ end
352
+
353
+ describe 'roll 2d20, keep worst value' do
354
+ let(:dice) do
355
+ GamesDice::Bunch.new(
356
+ :sides => 20, :ndice => 2, :keep_mode => :keep_worst, :keep_number => 1
357
+ )
358
+ end
359
+
360
+ it "should simulate rolling two twenty-sided dice and keeping the best value" do
361
+ [14,16,5,3,7,5,9].each do |expected_total|
362
+ dice.roll.should == expected_total
363
+ dice.result.should == expected_total
364
+ end
365
+ end
366
+
367
+ it "should concisely explain each result" do
368
+ ["19, 14. Keep: 14",
369
+ "18, 16. Keep: 16",
370
+ "5, 14. Keep: 5",
371
+ "3, 6. Keep: 3",
372
+ ].each do |expected_explain|
373
+ dice.roll
374
+ dice.explain_result.should == expected_explain
375
+ end
376
+ end
377
+
378
+ it "should calculate correct min, max = 1,20" do
379
+ dice.min.should == 1
380
+ dice.max.should == 20
381
+ end
382
+
383
+ it "should have a mean value of 7.175" do
384
+ dice.expected_result.should be_within(1e-9).of 7.175
385
+ end
386
+
387
+ it "should calculate probabilities correctly" do
388
+ dice.probabilities[1].should be_within(1e-10).of 39/400.0
389
+ dice.probabilities[2].should be_within(1e-10).of 37/400.0
390
+ dice.probabilities[3].should be_within(1e-10).of 35/400.0
391
+ dice.probabilities[4].should be_within(1e-10).of 33/400.0
392
+ dice.probabilities[5].should be_within(1e-10).of 31/400.0
393
+ dice.probabilities[6].should be_within(1e-10).of 29/400.0
394
+ dice.probabilities[7].should be_within(1e-10).of 27/400.0
395
+ dice.probabilities[8].should be_within(1e-10).of 25/400.0
396
+ dice.probabilities[9].should be_within(1e-10).of 23/400.0
397
+ dice.probabilities[10].should be_within(1e-10).of 21/400.0
398
+ dice.probabilities[11].should be_within(1e-10).of 19/400.0
399
+ dice.probabilities[12].should be_within(1e-10).of 17/400.0
400
+ dice.probabilities[13].should be_within(1e-10).of 15/400.0
401
+ dice.probabilities[14].should be_within(1e-10).of 13/400.0
402
+ dice.probabilities[15].should be_within(1e-10).of 11/400.0
403
+ dice.probabilities[16].should be_within(1e-10).of 9/400.0
404
+ dice.probabilities[17].should be_within(1e-10).of 7/400.0
405
+ dice.probabilities[18].should be_within(1e-10).of 5/400.0
406
+ dice.probabilities[19].should be_within(1e-10).of 3/400.0
407
+ dice.probabilities[20].should be_within(1e-10).of 1/400.0
408
+ dice.probabilities.values.inject(:+).should be_within(1e-9).of 1.0
409
+ end
410
+ end
411
+
412
+ end
413
+
414
+ end