games_dice 0.4.0 → 0.4.2
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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +38 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +41 -3
- data/.yardopts +1 -1
- data/CHANGELOG.md +12 -0
- data/Gemfile +10 -0
- data/README.md +11 -33
- data/Rakefile +2 -18
- data/ext/games_dice/games_dice.c +1 -1
- data/ext/games_dice/probabilities.c +127 -8
- data/ext/games_dice/probabilities.h +1 -1
- data/games_dice.gemspec +11 -19
- data/lib/games_dice/bunch.rb +27 -65
- data/lib/games_dice/bunch_helpers.rb +68 -0
- data/lib/games_dice/complex_die.rb +10 -146
- data/lib/games_dice/complex_die_helpers.rb +238 -46
- data/lib/games_dice/dice.rb +17 -10
- data/lib/games_dice/die.rb +2 -2
- data/lib/games_dice/die_result.rb +84 -71
- data/lib/games_dice/marshal.rb +26 -3
- data/lib/games_dice/parser.rb +128 -102
- data/lib/games_dice/version.rb +2 -1
- data/lib/games_dice.rb +7 -9
- data/spec/bunch_spec.rb +72 -72
- data/spec/complex_die_spec.rb +158 -158
- data/spec/dice_spec.rb +5 -5
- data/spec/die_result_spec.rb +98 -98
- data/spec/die_spec.rb +19 -19
- data/spec/helpers.rb +2 -4
- data/spec/map_rule_spec.rb +17 -17
- data/spec/parser_spec.rb +7 -7
- data/spec/probability_spec.rb +188 -196
- data/spec/readme_spec.rb +28 -22
- data/spec/reroll_rule_spec.rb +15 -15
- metadata +16 -139
- data/.travis.yml +0 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8e1494acd8aaa52a4d11f10bc8507c872be7eff6e77e6ad3d628d58d900a7e45
|
|
4
|
+
data.tar.gz: fb92f1c294ec39199c7a98f52ffae82620f25dce69ee92afe08e630bcc273692
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3cf986407235b5bf5017695d61d2ae6dcde5287233d94f07b1c716763913bfb88c7e99c21bab98a684c1939e17cc2a827d5225b35808a241bf3c83c71730d351
|
|
7
|
+
data.tar.gz: 5b5ec53e5140dfa03fd56b5e5c4115a25547f591305c9993ed1a1ebfb747d84e3441c0cd4a9eda394e1b76998230274441d3e9b20c39d115722008ede3637928
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
contents: read
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
rspec:
|
|
11
|
+
name: RSpec (Ruby ${{ matrix.ruby }})
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
ruby: ['3.3', '3.4']
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
- uses: ruby/setup-ruby@v1
|
|
20
|
+
with:
|
|
21
|
+
ruby-version: ${{ matrix.ruby }}
|
|
22
|
+
bundler-cache: true
|
|
23
|
+
- run: bundle exec rake compile spec
|
|
24
|
+
|
|
25
|
+
rubocop:
|
|
26
|
+
name: RuboCop (Ruby ${{ matrix.ruby }})
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
strategy:
|
|
29
|
+
fail-fast: false
|
|
30
|
+
matrix:
|
|
31
|
+
ruby: ['3.3', '3.4']
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@v4
|
|
34
|
+
- uses: ruby/setup-ruby@v1
|
|
35
|
+
with:
|
|
36
|
+
ruby-version: ${{ matrix.ruby }}
|
|
37
|
+
bundler-cache: true
|
|
38
|
+
- run: bundle exec rubocop
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
|
@@ -1,15 +1,53 @@
|
|
|
1
|
+
plugins:
|
|
2
|
+
- rubocop-performance
|
|
3
|
+
- rubocop-rake
|
|
4
|
+
- rubocop-rspec
|
|
5
|
+
|
|
1
6
|
AllCops:
|
|
2
|
-
TargetRubyVersion:
|
|
7
|
+
TargetRubyVersion: 3.3
|
|
3
8
|
NewCops: enable
|
|
9
|
+
SuggestExtensions: false
|
|
4
10
|
|
|
5
11
|
Layout/LineLength:
|
|
6
12
|
Max: 120
|
|
7
13
|
|
|
8
14
|
Metrics/BlockLength:
|
|
9
|
-
|
|
15
|
+
AllowedMethods:
|
|
10
16
|
- context
|
|
11
17
|
- describe
|
|
12
18
|
- shared_examples
|
|
13
19
|
- define
|
|
14
|
-
|
|
15
20
|
|
|
21
|
+
RSpec/ExampleLength:
|
|
22
|
+
Max: 25
|
|
23
|
+
|
|
24
|
+
RSpec/MultipleExpectations:
|
|
25
|
+
Max: 21
|
|
26
|
+
|
|
27
|
+
RSpec/NestedGroups:
|
|
28
|
+
Max: 4
|
|
29
|
+
|
|
30
|
+
# This project keeps specs flat so they are easy to run individually.
|
|
31
|
+
RSpec/SpecFilePathFormat:
|
|
32
|
+
Enabled: false
|
|
33
|
+
|
|
34
|
+
RSpec/IndexedLet:
|
|
35
|
+
Enabled: false
|
|
36
|
+
|
|
37
|
+
RSpec/InstanceVariable:
|
|
38
|
+
Exclude:
|
|
39
|
+
- spec/complex_die_spec.rb
|
|
40
|
+
|
|
41
|
+
RSpec/MultipleDescribes:
|
|
42
|
+
Exclude:
|
|
43
|
+
- spec/readme_spec.rb
|
|
44
|
+
|
|
45
|
+
RSpec/DescribeClass:
|
|
46
|
+
Exclude:
|
|
47
|
+
- spec/readme_spec.rb
|
|
48
|
+
|
|
49
|
+
# Probabilities implements #each without mixing in Enumerable; these specs
|
|
50
|
+
# intentionally collect yielded pairs manually.
|
|
51
|
+
Style/MapIntoArray:
|
|
52
|
+
Exclude:
|
|
53
|
+
- spec/probability_spec.rb
|
data/.yardopts
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# GamesDice Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.2 ( 19 July 2026 )
|
|
4
|
+
|
|
5
|
+
* Require MRI Ruby 3.3 or later and test against Ruby 3.3 and 3.4.
|
|
6
|
+
* Update development and runtime dependencies.
|
|
7
|
+
* Replace Travis CI with GitHub Actions.
|
|
8
|
+
* Modernise the RSpec suite and RuboCop configuration.
|
|
9
|
+
* Correct and clarify README documentation.
|
|
10
|
+
|
|
11
|
+
## 0.4.1
|
|
12
|
+
|
|
13
|
+
* Tidy up documentation and address some Rubocop offences.
|
|
14
|
+
|
|
3
15
|
## 0.4.0 ( 19 September 2021 )
|
|
4
16
|
|
|
5
17
|
* Dropping support for older Ruby versions (< 2.6)
|
data/Gemfile
CHANGED
|
@@ -4,3 +4,13 @@ source 'https://rubygems.org'
|
|
|
4
4
|
|
|
5
5
|
# Dependencies are in games_dice.gemspec
|
|
6
6
|
gemspec
|
|
7
|
+
|
|
8
|
+
gem 'rake', '~> 13.2'
|
|
9
|
+
gem 'rake-compiler', '~> 1.2'
|
|
10
|
+
gem 'redcarpet', '~> 3.6'
|
|
11
|
+
gem 'rspec', '~> 3.13'
|
|
12
|
+
gem 'rubocop', '~> 1.75', require: false
|
|
13
|
+
gem 'rubocop-performance', '~> 1.25', require: false
|
|
14
|
+
gem 'rubocop-rake', '~> 0.7', require: false
|
|
15
|
+
gem 'rubocop-rspec', '~> 3.6', require: false
|
|
16
|
+
gem 'yard', '~> 0.9'
|
data/README.md
CHANGED
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
# GamesDice
|
|
2
|
-
[](http://badge.fury.io/rb/games_dice)
|
|
3
|
-
[](http://travis-ci.org/neilslater/games_dice)
|
|
4
|
-
[](https://coveralls.io/r/neilslater/games_dice?branch=master)
|
|
5
|
-
[](http://inch-ci.org/github/neilslater/games_dice)
|
|
6
|
-
[](https://codeclimate.com/github/neilslater/games_dice)
|
|
7
|
-
[](https://gemnasium.com/neilslater/games_dice)
|
|
8
2
|
|
|
9
3
|
A library for simulating dice. Use it to construct dice-rolling systems used in role-playing and board games.
|
|
10
4
|
|
|
@@ -30,11 +24,10 @@ gem as-is, and add them as features within your project code.
|
|
|
30
24
|
|
|
31
25
|
## Supported Ruby Versions
|
|
32
26
|
|
|
33
|
-
GamesDice
|
|
34
|
-
"build passing" badge is based on those tests.
|
|
27
|
+
GamesDice 0.4.2 supports MRI Ruby 3.3 and 3.4. It uses a native extension and does not support JRuby.
|
|
35
28
|
|
|
36
|
-
|
|
37
|
-
|
|
29
|
+
GamesDice 0.4.0 and 0.4.1 support MRI Ruby 2.6 and later. Versions before 0.4.0 also provide a
|
|
30
|
+
pure-Ruby implementation of the probability calculations and can be used with JRuby.
|
|
38
31
|
|
|
39
32
|
## Installation
|
|
40
33
|
|
|
@@ -50,21 +43,6 @@ Or install it yourself as:
|
|
|
50
43
|
|
|
51
44
|
$ gem install games_dice
|
|
52
45
|
|
|
53
|
-
When installed, GamesDice will attempt to install Ruby native extensions in C, for speeding up probabilities
|
|
54
|
-
calculations. However, all the features are available in pure Ruby, and the gem should fall back to that
|
|
55
|
-
automatically on installation if your system does not support C native extensions. You can verify which
|
|
56
|
-
is being installed by installing the gem in verbose mode:
|
|
57
|
-
|
|
58
|
-
$ gem install games_dice --verbose
|
|
59
|
-
|
|
60
|
-
You can also verify which version you are using in Ruby by calling the class method:
|
|
61
|
-
|
|
62
|
-
GamesDice::Probabilities.implemented_in
|
|
63
|
-
|
|
64
|
-
which will return either *:ruby* or *:c*. Other than this method, and a speed difference between
|
|
65
|
-
implementations, there should be no other difference. If you find one, then it will be considered
|
|
66
|
-
as a bug.
|
|
67
|
-
|
|
68
46
|
## Usage
|
|
69
47
|
|
|
70
48
|
require 'games_dice'
|
|
@@ -88,8 +66,8 @@ Converts a string such as '3d6+6' into a GamesDice::Dice object
|
|
|
88
66
|
|
|
89
67
|
Parameters:
|
|
90
68
|
|
|
91
|
-
* dice_description is a string such as
|
|
92
|
-
* prng is optional
|
|
69
|
+
* `dice_description` is a string such as `3d6` or `2d4-1`. See String Dice Descriptions below for possibilities.
|
|
70
|
+
* `prng` is optional. If provided, it must respond to `rand(integer)` in the same way as Ruby's built-in `rand` method.
|
|
93
71
|
|
|
94
72
|
Returns a GamesDice::Dice object.
|
|
95
73
|
|
|
@@ -215,12 +193,12 @@ Returns the probability of a result less than or equal to the integer n.
|
|
|
215
193
|
|
|
216
194
|
Returns the probability of a result less than the integer n.
|
|
217
195
|
|
|
218
|
-
probabilities.p_lt( 17 ) # => 0.
|
|
196
|
+
probabilities.p_lt( 17 ) # => 0.9814814814814
|
|
219
197
|
probabilities.p_lt( 3 ) # => 0.0
|
|
220
198
|
|
|
221
199
|
#### probabilities.expected
|
|
222
200
|
|
|
223
|
-
Returns the mean result, weighted by
|
|
201
|
+
Returns the mean result, weighted by the probability of each value.
|
|
224
202
|
|
|
225
203
|
probabilities.expected # => 10.5 (rounded to nearest 1e-9)
|
|
226
204
|
|
|
@@ -254,7 +232,7 @@ A die modifier can also be a single letter plus an integer value, e.g.
|
|
|
254
232
|
|
|
255
233
|
1d6r1
|
|
256
234
|
|
|
257
|
-
You can add comma-
|
|
235
|
+
You can add comma-separated parameters to a modifier by using a ":" (colon) character after the
|
|
258
236
|
modifier letter, and a "." (full stop) to signify the end of the parameters. What parameters are
|
|
259
237
|
accepted, and what they mean, depends on the modifier:
|
|
260
238
|
|
|
@@ -272,7 +250,7 @@ are all equivalent.
|
|
|
272
250
|
#### Rerolls
|
|
273
251
|
|
|
274
252
|
You can specify that dice rolling certain values should be re-rolled, and how that re-roll should be
|
|
275
|
-
|
|
253
|
+
interpreted.
|
|
276
254
|
|
|
277
255
|
The simple form specifies a low value that will automatically trigger a re-roll and replace:
|
|
278
256
|
|
|
@@ -287,7 +265,7 @@ The full version of this modifier, allows you to specify from 1 to 3 parameters:
|
|
|
287
265
|
|
|
288
266
|
Where:
|
|
289
267
|
|
|
290
|
-
* VALUE_COMPARISON is one of
|
|
268
|
+
* VALUE_COMPARISON is one of `>`, `>=`, `==` (default), `<=`, or `<`, plus an integer that determines when the reroll occurs
|
|
291
269
|
* REROLL_TYPE is one of
|
|
292
270
|
* replace (default) - use the new value in place of existing value for the die
|
|
293
271
|
* add - add result of reroll to running total, and ignore any subtract rules
|
|
@@ -319,7 +297,7 @@ The full version of this modifier, allows you to specify from 1 to 3 parameters:
|
|
|
319
297
|
|
|
320
298
|
Where:
|
|
321
299
|
|
|
322
|
-
* VALUE_COMPARISON is one of
|
|
300
|
+
* VALUE_COMPARISON is one of `>`, `>=` (default), `==`, `<=`, or `<`, plus an integer that determines when the map occurs
|
|
323
301
|
* MAP_VALUE is an integer that will be used in place of a result from a die, default value is 1
|
|
324
302
|
* maps are tested in order that they are declared, and first one that matches is applied
|
|
325
303
|
* when at least one map has been defined, all unmapped values default to 0
|
data/Rakefile
CHANGED
|
@@ -5,14 +5,8 @@ require 'rspec/core/rake_task'
|
|
|
5
5
|
require 'rake/extensiontask'
|
|
6
6
|
require 'yard'
|
|
7
7
|
|
|
8
|
-
def can_compile_extensions
|
|
9
|
-
return false if RUBY_DESCRIPTION =~ /jruby/
|
|
10
|
-
|
|
11
|
-
true
|
|
12
|
-
end
|
|
13
|
-
|
|
14
8
|
desc 'GamesDice unit tests'
|
|
15
|
-
RSpec::Core::RakeTask.new(:
|
|
9
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
|
16
10
|
t.pattern = 'spec/*_spec.rb'
|
|
17
11
|
t.verbose = false
|
|
18
12
|
end
|
|
@@ -30,14 +24,4 @@ Rake::ExtensionTask.new do |ext|
|
|
|
30
24
|
ext.gem_spec = gemspec
|
|
31
25
|
end
|
|
32
26
|
|
|
33
|
-
task :
|
|
34
|
-
`rm lib/games_dice/games_dice.*`
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
task pure_test: %i[delete_compiled_ext test]
|
|
38
|
-
|
|
39
|
-
if can_compile_extensions
|
|
40
|
-
task default: %i[compile test]
|
|
41
|
-
else
|
|
42
|
-
task default: [:test]
|
|
43
|
-
end
|
|
27
|
+
task default: %i[compile spec]
|
data/ext/games_dice/games_dice.c
CHANGED
|
@@ -574,6 +574,13 @@ int copy_key_value( VALUE key, VALUE val, VALUE obj ) {
|
|
|
574
574
|
// Ruby class and instance methods for Probabilities
|
|
575
575
|
//
|
|
576
576
|
|
|
577
|
+
/*
|
|
578
|
+
* @overload initialize(probs, offset)
|
|
579
|
+
* Creates new instance of GamesDice::Probabilities.
|
|
580
|
+
* @param [Array<Float>] probs Each entry in the array is the probability of getting a result
|
|
581
|
+
* @param [Integer] offset The result associated with index of 0 in the array
|
|
582
|
+
* @return [GamesDice::Probabilities]
|
|
583
|
+
*/
|
|
577
584
|
VALUE probabilities_initialize( VALUE self, VALUE arr, VALUE offset ) {
|
|
578
585
|
int i, o, s;
|
|
579
586
|
double error, p_item;
|
|
@@ -604,7 +611,11 @@ VALUE probabilities_initialize( VALUE self, VALUE arr, VALUE offset ) {
|
|
|
604
611
|
return self;
|
|
605
612
|
}
|
|
606
613
|
|
|
607
|
-
|
|
614
|
+
/*
|
|
615
|
+
* @overload clone
|
|
616
|
+
* Cloning an object of this class creates a deep copy of the probabilities hash.
|
|
617
|
+
* @return [GamesDice::Probabilities]
|
|
618
|
+
*/
|
|
608
619
|
VALUE probabilities_initialize_copy( VALUE copy, VALUE orig ) {
|
|
609
620
|
ProbabilityList *pl_copy;
|
|
610
621
|
ProbabilityList *pl_orig;
|
|
@@ -622,6 +633,12 @@ VALUE probabilities_initialize_copy( VALUE copy, VALUE orig ) {
|
|
|
622
633
|
return copy;
|
|
623
634
|
}
|
|
624
635
|
|
|
636
|
+
/*
|
|
637
|
+
* A hash representation of the distribution. Each key is an integer result,
|
|
638
|
+
* and the matching value is probability of getting that result. A new hash is generated on each
|
|
639
|
+
* call to this method.
|
|
640
|
+
* @return [Hash]
|
|
641
|
+
*/
|
|
625
642
|
VALUE probabilities_to_h( VALUE self ) {
|
|
626
643
|
ProbabilityList *pl = get_probability_list( self );
|
|
627
644
|
VALUE h = rb_hash_new();
|
|
@@ -637,56 +654,126 @@ VALUE probabilities_to_h( VALUE self ) {
|
|
|
637
654
|
return h;
|
|
638
655
|
}
|
|
639
656
|
|
|
657
|
+
/*
|
|
658
|
+
* @overload min
|
|
659
|
+
* @!attribute [r] min
|
|
660
|
+
* Minimum result in the distribution
|
|
661
|
+
* @return [Integer]
|
|
662
|
+
*/
|
|
640
663
|
VALUE probabilities_min( VALUE self ) {
|
|
641
664
|
return INT2NUM( pl_min( get_probability_list( self ) ) );
|
|
642
665
|
}
|
|
643
666
|
|
|
667
|
+
/*
|
|
668
|
+
* @overload max
|
|
669
|
+
* @!attribute [r] max
|
|
670
|
+
* Maximum result in the distribution
|
|
671
|
+
* @return [Integer]
|
|
672
|
+
*/
|
|
644
673
|
VALUE probabilities_max( VALUE self ) {
|
|
645
674
|
return INT2NUM( pl_max( get_probability_list( self ) ) );
|
|
646
675
|
}
|
|
647
676
|
|
|
677
|
+
/*
|
|
678
|
+
* Probability of result equalling specific target
|
|
679
|
+
* @param [Integer] target
|
|
680
|
+
* @return [Float] in range (0.0..1.0)
|
|
681
|
+
*/
|
|
648
682
|
VALUE probabilites_p_eql( VALUE self, VALUE target ) {
|
|
649
683
|
return DBL2NUM( pl_p_eql( get_probability_list( self ), NUM2INT(target) ) );
|
|
650
684
|
}
|
|
651
685
|
|
|
686
|
+
/*
|
|
687
|
+
* Probability of result being greater than specific target
|
|
688
|
+
* @param [Integer] target
|
|
689
|
+
* @return [Float] in range (0.0..1.0)
|
|
690
|
+
*/
|
|
652
691
|
VALUE probabilites_p_gt( VALUE self, VALUE target ) {
|
|
653
692
|
return DBL2NUM( pl_p_gt( get_probability_list( self ), NUM2INT(target) ) );
|
|
654
693
|
}
|
|
655
694
|
|
|
695
|
+
/*
|
|
696
|
+
* Probability of result being equal to or greater than specific target
|
|
697
|
+
* @param [Integer] target
|
|
698
|
+
* @return [Float] in range (0.0..1.0)
|
|
699
|
+
*/
|
|
656
700
|
VALUE probabilites_p_ge( VALUE self, VALUE target ) {
|
|
657
701
|
return DBL2NUM( pl_p_ge( get_probability_list( self ), NUM2INT(target) ) );
|
|
658
702
|
}
|
|
659
703
|
|
|
704
|
+
/*
|
|
705
|
+
* Probability of result being equal to or less than specific target
|
|
706
|
+
* @param [Integer] target
|
|
707
|
+
* @return [Float] in range (0.0..1.0)
|
|
708
|
+
*/
|
|
660
709
|
VALUE probabilites_p_le( VALUE self, VALUE target ) {
|
|
661
710
|
return DBL2NUM( pl_p_le( get_probability_list( self ), NUM2INT(target) ) );
|
|
662
711
|
}
|
|
663
712
|
|
|
713
|
+
/*
|
|
714
|
+
* Probability of result being less than specific target
|
|
715
|
+
* @param [Integer] target
|
|
716
|
+
* @return [Float] in range (0.0..1.0)
|
|
717
|
+
*/
|
|
664
718
|
VALUE probabilites_p_lt( VALUE self, VALUE target ) {
|
|
665
719
|
return DBL2NUM( pl_p_lt( get_probability_list( self ), NUM2INT(target) ) );
|
|
666
720
|
}
|
|
667
721
|
|
|
722
|
+
/*
|
|
723
|
+
* @overload expected
|
|
724
|
+
* @!attribute [r] expected
|
|
725
|
+
* Expected value of distribution.
|
|
726
|
+
* @return [Float]
|
|
727
|
+
*/
|
|
668
728
|
VALUE probabilites_expected( VALUE self ) {
|
|
669
729
|
return DBL2NUM( pl_expected( get_probability_list( self ) ) );
|
|
670
730
|
}
|
|
671
731
|
|
|
732
|
+
/*
|
|
733
|
+
* Probability distribution derived from this one, where we know (or are only interested in
|
|
734
|
+
* situations where) the result is greater than or equal to target.
|
|
735
|
+
* @param [Integer] target
|
|
736
|
+
* @return [GamesDice::Probabilities] new distribution.
|
|
737
|
+
*/
|
|
672
738
|
VALUE probabilities_given_ge( VALUE self, VALUE target ) {
|
|
673
739
|
int t = NUM2INT(target);
|
|
674
740
|
ProbabilityList *pl = get_probability_list( self );
|
|
675
741
|
return pl_as_ruby_class( pl_given_ge( pl, t ), Probabilities );
|
|
676
742
|
}
|
|
677
743
|
|
|
744
|
+
/*
|
|
745
|
+
* Probability distribution derived from this one, where we know (or are only interested in
|
|
746
|
+
* situations where) the result is less than or equal to target.
|
|
747
|
+
* @param [Integer] target
|
|
748
|
+
* @return [GamesDice::Probabilities] new distribution.
|
|
749
|
+
*/
|
|
678
750
|
VALUE probabilities_given_le( VALUE self, VALUE target ) {
|
|
679
751
|
int t = NUM2INT(target);
|
|
680
752
|
ProbabilityList *pl = get_probability_list( self );
|
|
681
753
|
return pl_as_ruby_class( pl_given_le( pl, t ), Probabilities );
|
|
682
754
|
}
|
|
683
755
|
|
|
756
|
+
/*
|
|
757
|
+
* @overload repeat_sum(n)
|
|
758
|
+
* Adds a distribution to itself repeatedly, to simulate a number of dice
|
|
759
|
+
* results being summed.
|
|
760
|
+
* @param [Integer] n Number of repetitions, must be at least 1
|
|
761
|
+
* @return [GamesDice::Probabilities] new distribution
|
|
762
|
+
*/
|
|
684
763
|
VALUE probabilities_repeat_sum( VALUE self, VALUE nsum ) {
|
|
685
764
|
int n = NUM2INT(nsum);
|
|
686
765
|
ProbabilityList *pl = get_probability_list( self );
|
|
687
766
|
return pl_as_ruby_class( pl_repeat_sum( pl, n ), Probabilities );
|
|
688
767
|
}
|
|
689
768
|
|
|
769
|
+
/*
|
|
770
|
+
* @overload repeat_n_sum_k(n, k, kmode = :keep_best)
|
|
771
|
+
* Calculates distribution generated by summing best k results of n iterations
|
|
772
|
+
* of the distribution.
|
|
773
|
+
* @param [Integer] n Number of repetitions, must be at least 1
|
|
774
|
+
* @param [Integer] k Number of best results to keep and sum
|
|
775
|
+
* @return [GamesDice::Probabilities] new distribution
|
|
776
|
+
*/
|
|
690
777
|
VALUE probabilities_repeat_n_sum_k( int argc, VALUE* argv, VALUE self ) {
|
|
691
778
|
VALUE nsum, nkeepers, kmode;
|
|
692
779
|
int keep_best, n, k;
|
|
@@ -709,6 +796,12 @@ VALUE probabilities_repeat_n_sum_k( int argc, VALUE* argv, VALUE self ) {
|
|
|
709
796
|
return pl_as_ruby_class( pl_repeat_n_sum_k( pl, n, k, keep_best ), Probabilities );
|
|
710
797
|
}
|
|
711
798
|
|
|
799
|
+
/*
|
|
800
|
+
* Iterates through value, probability pairs
|
|
801
|
+
* @yieldparam [Integer] result A result that may be possible in the dice scheme
|
|
802
|
+
* @yieldparam [Float] probability Probability of result, in range 0.0..1.0
|
|
803
|
+
* @return [GamesDice::Probabilities] this object
|
|
804
|
+
*/
|
|
712
805
|
VALUE probabilities_each( VALUE self ) {
|
|
713
806
|
ProbabilityList *pl = get_probability_list( self );
|
|
714
807
|
int i;
|
|
@@ -725,6 +818,11 @@ VALUE probabilities_each( VALUE self ) {
|
|
|
725
818
|
return self;
|
|
726
819
|
}
|
|
727
820
|
|
|
821
|
+
/*
|
|
822
|
+
* Distribution for a die with equal chance of rolling 1..N
|
|
823
|
+
* @param [Integer] sides Number of sides on die
|
|
824
|
+
* @return [GamesDice::Probabilities]
|
|
825
|
+
*/
|
|
728
826
|
VALUE probabilities_for_fair_die( VALUE self, VALUE sides ) {
|
|
729
827
|
int s = NUM2INT( sides );
|
|
730
828
|
VALUE obj;
|
|
@@ -743,6 +841,13 @@ VALUE probabilities_for_fair_die( VALUE self, VALUE sides ) {
|
|
|
743
841
|
return obj;
|
|
744
842
|
}
|
|
745
843
|
|
|
844
|
+
/*
|
|
845
|
+
* @overload from_h(prob_hash)
|
|
846
|
+
* Creates new instance of GamesDice::Probabilities.
|
|
847
|
+
* @param [Hash] prob_hash A hash representation of the distribution, each key is an integer result,
|
|
848
|
+
* and the matching value is probability of getting that result
|
|
849
|
+
* @return [GamesDice::Probabilities]
|
|
850
|
+
*/
|
|
746
851
|
VALUE probabilities_from_h( VALUE self, VALUE hash ) {
|
|
747
852
|
VALUE obj;
|
|
748
853
|
ProbabilityList *pl;
|
|
@@ -773,6 +878,14 @@ VALUE probabilities_from_h( VALUE self, VALUE hash ) {
|
|
|
773
878
|
return obj;
|
|
774
879
|
}
|
|
775
880
|
|
|
881
|
+
/*
|
|
882
|
+
* @overload add_distributions(pd_a, pd_b)
|
|
883
|
+
* Combines two distributions to create a third, that represents the distribution created when adding
|
|
884
|
+
* results together.
|
|
885
|
+
* @param [GamesDice::Probabilities] pd_a First distribution
|
|
886
|
+
* @param [GamesDice::Probabilities] pd_b Second distribution
|
|
887
|
+
* @return [GamesDice::Probabilities]
|
|
888
|
+
*/
|
|
776
889
|
VALUE probabilities_add_distributions( VALUE self, VALUE gdpa, VALUE gdpb ) {
|
|
777
890
|
ProbabilityList *pl_a = get_probability_list( gdpa );
|
|
778
891
|
ProbabilityList *pl_b = get_probability_list( gdpb );
|
|
@@ -783,6 +896,16 @@ VALUE probabilities_add_distributions( VALUE self, VALUE gdpa, VALUE gdpb ) {
|
|
|
783
896
|
return pl_as_ruby_class( pl_add_distributions( pl_a, pl_b ), Probabilities );
|
|
784
897
|
}
|
|
785
898
|
|
|
899
|
+
/*
|
|
900
|
+
* @overload add_distributions_mult(m_a, pd_a, m_b, pd_b)
|
|
901
|
+
* Combines two distributions with multipliers to create a third, that represents the distribution
|
|
902
|
+
* created when adding weighted results together.
|
|
903
|
+
* @param [Integer] m_a Weighting for first distribution
|
|
904
|
+
* @param [GamesDice::Probabilities] pd_a First distribution
|
|
905
|
+
* @param [Integer] m_b Weighting for second distribution
|
|
906
|
+
* @param [GamesDice::Probabilities] pd_b Second distribution
|
|
907
|
+
* @return [GamesDice::Probabilities]
|
|
908
|
+
*/
|
|
786
909
|
VALUE probabilities_add_distributions_mult( VALUE self, VALUE m_a, VALUE gdpa, VALUE m_b, VALUE gdpb ) {
|
|
787
910
|
int mul_a, mul_b;
|
|
788
911
|
ProbabilityList *pl_a;
|
|
@@ -797,17 +920,14 @@ VALUE probabilities_add_distributions_mult( VALUE self, VALUE m_a, VALUE gdpa, V
|
|
|
797
920
|
return pl_as_ruby_class( pl_add_distributions_mult( mul_a, pl_a, mul_b, pl_b ), Probabilities );
|
|
798
921
|
}
|
|
799
922
|
|
|
800
|
-
VALUE probabilities_implemented_in( VALUE self ) {
|
|
801
|
-
return ID2SYM( rb_intern("c") );
|
|
802
|
-
}
|
|
803
|
-
|
|
804
923
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
805
924
|
//
|
|
806
925
|
// Setup Probabilities class for Ruby interpretter
|
|
807
926
|
//
|
|
808
927
|
|
|
809
|
-
void init_probabilities_class(
|
|
810
|
-
|
|
928
|
+
void init_probabilities_class() {
|
|
929
|
+
VALUE GamesDice = rb_define_module("GamesDice");
|
|
930
|
+
Probabilities = rb_define_class_under( GamesDice, "Probabilities", rb_cObject );
|
|
811
931
|
rb_define_alloc_func( Probabilities, pl_alloc );
|
|
812
932
|
rb_define_method( Probabilities, "initialize", probabilities_initialize, 2 );
|
|
813
933
|
rb_define_method( Probabilities, "initialize_copy", probabilities_initialize_copy, 1 );
|
|
@@ -828,7 +948,6 @@ void init_probabilities_class( VALUE ParentModule ) {
|
|
|
828
948
|
rb_define_singleton_method( Probabilities, "for_fair_die", probabilities_for_fair_die, 1 );
|
|
829
949
|
rb_define_singleton_method( Probabilities, "add_distributions", probabilities_add_distributions, 2 );
|
|
830
950
|
rb_define_singleton_method( Probabilities, "add_distributions_mult", probabilities_add_distributions_mult, 4 );
|
|
831
|
-
rb_define_singleton_method( Probabilities, "implemented_in", probabilities_implemented_in, 0 );
|
|
832
951
|
rb_define_singleton_method( Probabilities, "from_h", probabilities_from_h, 1 );
|
|
833
952
|
return;
|
|
834
953
|
}
|
data/games_dice.gemspec
CHANGED
|
@@ -10,31 +10,23 @@ Gem::Specification.new do |gem|
|
|
|
10
10
|
gem.version = GamesDice::VERSION
|
|
11
11
|
gem.authors = ['Neil Slater']
|
|
12
12
|
gem.email = ['slobo777@gmail.com']
|
|
13
|
-
gem.description =
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
gem.description = <<~GEMDESC
|
|
14
|
+
A library for simulating dice. Use it to construct dice-rolling systems used in role-playing and board games.
|
|
15
|
+
GEMDESC
|
|
16
|
+
gem.summary = <<~GEMSUMM
|
|
17
|
+
Simulates and explains dice rolls from simple "1d6" to complex "roll 7 ten-sided dice, take best 3,
|
|
18
|
+
results of 10 roll again and add on".
|
|
19
|
+
GEMSUMM
|
|
16
20
|
gem.homepage = 'https://github.com/neilslater/games_dice'
|
|
17
21
|
gem.license = 'MIT'
|
|
18
22
|
|
|
19
|
-
gem.required_ruby_version = '>=
|
|
20
|
-
gem.add_development_dependency 'coveralls', '>= 0.6.7'
|
|
21
|
-
gem.add_development_dependency 'json', '>= 1.7.7'
|
|
22
|
-
gem.add_development_dependency 'rake', '>= 1.9.1'
|
|
23
|
-
gem.add_development_dependency 'rake-compiler', '>= 0.8.3'
|
|
24
|
-
gem.add_development_dependency 'rspec', '>= 2.13.0'
|
|
25
|
-
gem.add_development_dependency 'rubocop', '>= 1.2.1'
|
|
26
|
-
gem.add_development_dependency 'yard', '>= 0.8.6'
|
|
23
|
+
gem.required_ruby_version = '>= 3.3.0'
|
|
27
24
|
|
|
28
|
-
|
|
29
|
-
# However, it has a C extension, which will not work in JRuby. This only affects the gem build process, so
|
|
30
|
-
# is only really used in environments like Travis, and is safe to wrap like this in the gemspec.
|
|
31
|
-
gem.add_development_dependency 'redcarpet', '>=3.5.1' if RUBY_DESCRIPTION !~ /jruby/
|
|
25
|
+
gem.add_dependency 'parslet', '~> 2.0'
|
|
32
26
|
|
|
33
|
-
gem.
|
|
34
|
-
|
|
35
|
-
gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
|
27
|
+
gem.files = `git ls-files -z`.split("\0").select { |file| File.file?(file) }
|
|
36
28
|
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
|
37
29
|
gem.extensions = gem.files.grep(%r{/extconf\.rb$})
|
|
38
|
-
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
|
39
30
|
gem.require_paths = ['lib']
|
|
31
|
+
gem.metadata['rubygems_mfa_required'] = 'true'
|
|
40
32
|
end
|