games_dice 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Dependencies are in games_dice.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Neil Slater
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # GamesDice
2
+
3
+ A library for simulating dice, intended for constructing a variety of dice systems as used in
4
+ role-playing and board games.
5
+
6
+ ## Special Note on Versions Prior to 1.0.0
7
+
8
+ The author is using this code as an exercise in gem "best practice". As such, the gem
9
+ will have a deliberately limited set of functionality prior to version 1.0.0, and there should be
10
+ many small release increments before then.
11
+
12
+ The functionality should expand to cover dice systems seen in many role-playing systems, as it
13
+ progresses through 0.x.y versions (in fact much of this code is already written and working, so if
14
+ you have a burning need to simulate dice rolls for a specific game, feel free to get in touch).
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ gem 'games_dice'
21
+
22
+ And then execute:
23
+
24
+ $ bundle
25
+
26
+ Or install it yourself as:
27
+
28
+ $ gem install games_dice
29
+
30
+ ## Usage
31
+
32
+ require 'games_dice'
33
+
34
+ # Simple 6-sided die, more to follow
35
+ d = GamesDice::Die.new( 6 )
36
+ d.roll # => 4
37
+ d.result # => 4
38
+ d.explain_roll # => "4"
39
+
40
+ ## Contributing
41
+
42
+ 1. Fork it
43
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
44
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
45
+ 4. Push to the branch (`git push origin my-new-feature`)
46
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'games_dice/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "games_dice"
8
+ gem.version = GamesDice::VERSION
9
+ gem.authors = ["Neil Slater"]
10
+ gem.email = ["slobo777@gmail.com"]
11
+ gem.description = %q{A simulated-dice library, with flexible rules that allow dice systems from
12
+ many board and roleplay games to be built, run and reported.}
13
+ gem.summary = %q{Simulates and explains dice rolls from a variety of game systems.}
14
+ gem.homepage = ""
15
+
16
+ gem.add_development_dependency "rspec"
17
+
18
+ gem.files = `git ls-files`.split($/)
19
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
20
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
21
+ gem.require_paths = ["lib"]
22
+ end
data/lib/games_dice.rb ADDED
@@ -0,0 +1,6 @@
1
+ require "games_dice/version"
2
+ require "games_dice/die"
3
+
4
+ module GamesDice
5
+ # TODO: Factory methods for various dice schemes
6
+ end
@@ -0,0 +1,92 @@
1
+ module GamesDice
2
+ # basic die that rolls 1..N, typically with equal weighting for each value
3
+ # d = Die.new(6)
4
+ # d.roll # => Integer in range 1..6
5
+ # d.result # => same Integer value as returned by d.roll
6
+ class Die
7
+ # sides is e.g. 6 for traditional cubic die, or 20 for icosahedron.
8
+ # It can take non-traditional values, such as 7, but must be at least 1.
9
+ # prng is an object that has a rand(x) method. If provided, it will be called as
10
+ # prng.rand(sides), and is expected to return an integer in range 0...sides
11
+ def initialize( sides, prng=nil )
12
+ @sides = Integer(sides)
13
+ raise ArgumentError, "sides value #{sides} is too low, it must be 1 or greater" if @sides < 1
14
+ raise ArgumentError, "prng does not support the rand() method" if prng && ! prng.respond_to?(:rand)
15
+ @prng = prng
16
+ @result = nil
17
+ end
18
+
19
+ # number of sides as set by #new
20
+ attr_reader :sides
21
+
22
+ # integer result of last call to #roll, nil if no call made yet
23
+ attr_reader :result
24
+
25
+ # minimum possible value
26
+ def min
27
+ 1
28
+ end
29
+
30
+ # maximum possible value
31
+ def max
32
+ @sides
33
+ end
34
+
35
+ # returns a hash of value (Integer) => probability (Float) pairs
36
+ def probabilities
37
+ return @probabilities if @probabilities
38
+ density = 1.0/@sides
39
+ @probabilities = (1..@sides).inject({}) { |h,x| h[x] = density; h }
40
+ end
41
+
42
+ # returns mean expected value as a Float
43
+ def expected_result
44
+ 0.5 * (1 + @sides)
45
+ end
46
+
47
+ # returns probability than a roll will produce a number greater than target integer
48
+ def probability_gt target
49
+ probability_ge( Integer(target) + 1 )
50
+ end
51
+
52
+ # returns probability than a roll will produce a number greater than or equal to target integer
53
+ def probability_ge target
54
+ target = Integer(target)
55
+ return 1.0 if target <= 1
56
+ return 0.0 if target > @sides
57
+ return 1.0 * (1.0 + @sides - target )/@sides
58
+ end
59
+
60
+ # returns probability than a roll will produce a number less than or equal to target integer
61
+ def probability_le target
62
+ target = Integer(target)
63
+ return 1.0 if target >= @sides
64
+ return 0.0 if target < 1
65
+ return 1.0 * target/@sides
66
+ end
67
+
68
+ # returns probability than a roll will produce a number less than target integer
69
+ def probability_lt target
70
+ probability_le( Integer(target) - 1 )
71
+ end
72
+
73
+ # generates Integer between #min and #max, using rand()
74
+ def roll
75
+ if @prng
76
+ @result = @prng.rand(@sides) + 1
77
+ else
78
+ @result = rand(@sides) + 1
79
+ end
80
+ end
81
+
82
+ # always nil, available for compatibility with ComplexDie
83
+ def rerolls
84
+ nil
85
+ end
86
+
87
+ # always nil, available for compatibility with ComplexDie
88
+ def maps
89
+ nil
90
+ end
91
+ end # class Die
92
+ end # module GamesDice
@@ -0,0 +1,3 @@
1
+ module GamesDice
2
+ VERSION = "0.0.1"
3
+ end
data/spec/die_spec.rb ADDED
@@ -0,0 +1,95 @@
1
+ require 'games_dice/die'
2
+
3
+ # Test helper class, a stub of a PRNG
4
+ class TestPRNG
5
+ def initialize
6
+ # Numbers that I randomly thought up!
7
+ @numbers = [0.123,0.234,0.345,0.999,0.876,0.765,0.543,0.111,0.333,0.777]
8
+ end
9
+ def rand(n)
10
+ Integer( n * @numbers.pop )
11
+ end
12
+ end
13
+
14
+ describe GamesDice::Die do
15
+
16
+ before do
17
+ # Set state of default PRNG
18
+ srand(4567)
19
+ end
20
+
21
+ describe "#new" do
22
+ it "should return an object that represents e.g. a six-sided die" do
23
+ die = GamesDice::Die.new(6)
24
+ die.min.should == 1
25
+ die.max.should == 6
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
+ end
30
+
31
+ it "should accept any object with a rand(Integer) method as the second param" do
32
+ prng = TestPRNG.new()
33
+ die = GamesDice::Die.new(20,prng)
34
+ [16,7,3,11,16,18,20,7].each do |expected|
35
+ die.roll.should == expected
36
+ die.result.should == expected
37
+ end
38
+ end
39
+ end
40
+
41
+ describe "#roll and #result" do
42
+ it "should return results based on Ruby's internal rand() by default" do
43
+ die = GamesDice::Die.new(10)
44
+ [5,4,10,4,7,8,1,9].each do |expected|
45
+ die.roll.should == expected
46
+ die.result.should == expected
47
+ end
48
+ end
49
+ end
50
+
51
+ describe "#min and #max" do
52
+ it "should calculate correct min, max" do
53
+ die = GamesDice::Die.new(20)
54
+ die.min.should == 1
55
+ die.max.should == 20
56
+ end
57
+ end
58
+
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
+ describe "#probabilities" do
67
+ it "should calculate probabilities accurately" do
68
+ 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
76
+
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
80
+
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
84
+
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
88
+
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
92
+ end
93
+ end
94
+
95
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: games_dice
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Neil Slater
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: ! "A simulated-dice library, with flexible rules that allow dice systems
31
+ from\n many board and roleplay games to be built, run and
32
+ reported."
33
+ email:
34
+ - slobo777@gmail.com
35
+ executables: []
36
+ extensions: []
37
+ extra_rdoc_files: []
38
+ files:
39
+ - .gitignore
40
+ - Gemfile
41
+ - LICENSE.txt
42
+ - README.md
43
+ - Rakefile
44
+ - games_dice.gemspec
45
+ - lib/games_dice.rb
46
+ - lib/games_dice/die.rb
47
+ - lib/games_dice/version.rb
48
+ - spec/die_spec.rb
49
+ homepage: ''
50
+ licenses: []
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ requirements: []
68
+ rubyforge_project:
69
+ rubygems_version: 1.8.24
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: Simulates and explains dice rolls from a variety of game systems.
73
+ test_files:
74
+ - spec/die_spec.rb
75
+ has_rdoc: