nerd_dice 0.3.0 → 0.4.0
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
- checksums.yaml.gz.sig +0 -0
- data/.rubocop.yml +19 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile +2 -2
- data/Gemfile.lock +17 -18
- data/README.md +181 -34
- data/bin/nerd_dice_benchmark +126 -8
- data/checksum/nerd_dice-0.3.0.gem.sha256 +1 -0
- data/checksum/nerd_dice-0.3.0.gem.sha512 +1 -0
- data/lib/nerd_dice/class_methods/harvest_totals.rb +9 -4
- data/lib/nerd_dice/convenience_methods.rb +279 -0
- data/lib/nerd_dice/version.rb +1 -1
- data/lib/nerd_dice.rb +3 -0
- data/nerd_dice.gemspec +4 -4
- data.tar.gz.sig +0 -0
- metadata +17 -14
- metadata.gz.sig +2 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8f64389429514a7d0c2a8410b2e27575e5c11b316b50cee41b37c58d8f8af953
|
|
4
|
+
data.tar.gz: 4d2365e3ce8139d4675695dfe47edf9ef5d52b9cc873beb5c7c314b8955aaa33
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d8bf0ea2c85e3aedf952d82d0f511463accedcad5122b14a7d6769a94100902887ca0e52cf85a6d8b69a75a6cd750858852ad71e34980e61624d39666bedff5b
|
|
7
|
+
data.tar.gz: ee2e8117b3071872a3d07353dabd4685c4a20e188591e80cbcb93609ba9f134ab22082ae01bee152c34c9cdd1a81a6a40aec2b1521d3e2a106d10f0c8fa313ae
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/.rubocop.yml
CHANGED
|
@@ -400,3 +400,22 @@ Lint/AmbiguousRange: # new in 1.19
|
|
|
400
400
|
Enabled: true
|
|
401
401
|
Style/RedundantSelfAssignmentBranch: # new in 1.19
|
|
402
402
|
Enabled: true
|
|
403
|
+
|
|
404
|
+
Lint/AmbiguousOperatorPrecedence: # new in 1.21
|
|
405
|
+
Enabled: true
|
|
406
|
+
Lint/IncompatibleIoSelectWithFiberScheduler: # new in 1.21
|
|
407
|
+
Enabled: true
|
|
408
|
+
Lint/RequireRelativeSelfPath: # new in 1.22
|
|
409
|
+
Enabled: true
|
|
410
|
+
Security/IoMethods: # new in 1.22
|
|
411
|
+
Enabled: true
|
|
412
|
+
Style/NumberedParameters: # new in 1.22
|
|
413
|
+
Enabled: true
|
|
414
|
+
Style/NumberedParametersLimit: # new in 1.22
|
|
415
|
+
Enabled: true
|
|
416
|
+
Style/SelectByRegexp: # new in 1.22
|
|
417
|
+
Enabled: true
|
|
418
|
+
RSpec/ExcessiveDocstringSpacing: # new in 2.5
|
|
419
|
+
Enabled: true
|
|
420
|
+
RSpec/SubjectDeclaration: # new in 2.5
|
|
421
|
+
Enabled: true
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@
|
|
|
5
5
|
### Changed
|
|
6
6
|
### Fixed
|
|
7
7
|
|
|
8
|
+
## 0.4.0 \(2021-10-23\)
|
|
9
|
+
### Added
|
|
10
|
+
* Add `NerdDice::ConvenienceMethods` method_missing mixin module that allows for dynamic invocation of patterns in the method name that get converted into calls to `NerdDice.roll_dice` or `NerdDice.total_dice` along with allowing the advantage/disadvantage mechanic or bonuses to be parsed from the method name. Full documentation of the module can be found in the [Convenience Methods Mixin](README.md#convenience-methods-mixin) section of the README.
|
|
11
|
+
* Add exensive specs to support the ConvenienceMethods module
|
|
12
|
+
### Changed
|
|
13
|
+
* Replace `Benchmark.bmbm` with `Benchmark.bm` in the nerd_dice_benchmark
|
|
14
|
+
* Add convenience_methods to nerd_dice_benchmark
|
|
15
|
+
* Extend `NerdDice::ConvenienceMethods` into top-level module as class methods
|
|
16
|
+
### Fixed
|
|
17
|
+
* Fix typos and horizontal scrolling in README
|
|
18
|
+
* Fix CodeClimate Code Smell on harvest_totals
|
|
19
|
+
|
|
8
20
|
## 0.3.0 \(2021-09-11\)
|
|
9
21
|
### Added
|
|
10
22
|
* Add new options to `NerdDice::Configuration`
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
nerd_dice (0.
|
|
5
|
-
securerandom (~> 0.1, >= 0.1.
|
|
4
|
+
nerd_dice (0.4.0)
|
|
5
|
+
securerandom (~> 0.1, >= 0.1.1)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: https://rubygems.org/
|
|
9
9
|
specs:
|
|
10
10
|
ast (2.4.2)
|
|
11
|
-
coveralls_reborn (0.
|
|
11
|
+
coveralls_reborn (0.23.0)
|
|
12
12
|
simplecov (>= 0.18.1, < 0.22.0)
|
|
13
13
|
term-ansicolor (~> 1.6)
|
|
14
14
|
thor (>= 0.20.3, < 2.0)
|
|
15
15
|
tins (~> 1.16)
|
|
16
16
|
diff-lcs (1.4.4)
|
|
17
17
|
docile (1.4.0)
|
|
18
|
-
parallel (1.
|
|
18
|
+
parallel (1.21.0)
|
|
19
19
|
parser (3.0.2.0)
|
|
20
20
|
ast (~> 2.4.1)
|
|
21
21
|
rainbow (3.0.0)
|
|
22
|
-
rake (
|
|
22
|
+
rake (13.0.6)
|
|
23
23
|
regexp_parser (2.1.1)
|
|
24
24
|
rexml (3.2.5)
|
|
25
25
|
rspec (3.10.0)
|
|
@@ -35,27 +35,26 @@ GEM
|
|
|
35
35
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
36
36
|
rspec-support (~> 3.10.0)
|
|
37
37
|
rspec-support (3.10.2)
|
|
38
|
-
rubocop (1.
|
|
38
|
+
rubocop (1.22.2)
|
|
39
39
|
parallel (~> 1.10)
|
|
40
40
|
parser (>= 3.0.0.0)
|
|
41
41
|
rainbow (>= 2.2.2, < 4.0)
|
|
42
42
|
regexp_parser (>= 1.8, < 3.0)
|
|
43
43
|
rexml
|
|
44
|
-
rubocop-ast (>= 1.
|
|
44
|
+
rubocop-ast (>= 1.12.0, < 2.0)
|
|
45
45
|
ruby-progressbar (~> 1.7)
|
|
46
46
|
unicode-display_width (>= 1.4.0, < 3.0)
|
|
47
|
-
rubocop-ast (1.
|
|
47
|
+
rubocop-ast (1.12.0)
|
|
48
48
|
parser (>= 3.0.1.1)
|
|
49
49
|
rubocop-performance (1.11.5)
|
|
50
50
|
rubocop (>= 1.7.0, < 2.0)
|
|
51
51
|
rubocop-ast (>= 0.4.0)
|
|
52
52
|
rubocop-rake (0.6.0)
|
|
53
53
|
rubocop (~> 1.0)
|
|
54
|
-
rubocop-rspec (2.
|
|
55
|
-
rubocop (~> 1.
|
|
56
|
-
rubocop-ast (>= 1.1.0)
|
|
54
|
+
rubocop-rspec (2.5.0)
|
|
55
|
+
rubocop (~> 1.19)
|
|
57
56
|
ruby-progressbar (1.11.0)
|
|
58
|
-
securerandom (0.1.
|
|
57
|
+
securerandom (0.1.1)
|
|
59
58
|
simplecov (0.21.2)
|
|
60
59
|
docile (~> 1.1)
|
|
61
60
|
simplecov-html (~> 0.11)
|
|
@@ -69,20 +68,20 @@ GEM
|
|
|
69
68
|
thor (1.1.0)
|
|
70
69
|
tins (1.29.1)
|
|
71
70
|
sync
|
|
72
|
-
unicode-display_width (2.
|
|
71
|
+
unicode-display_width (2.1.0)
|
|
73
72
|
|
|
74
73
|
PLATFORMS
|
|
75
74
|
ruby
|
|
76
75
|
|
|
77
76
|
DEPENDENCIES
|
|
78
|
-
coveralls_reborn (~> 0.
|
|
77
|
+
coveralls_reborn (~> 0.23.0)
|
|
79
78
|
nerd_dice!
|
|
80
|
-
rake (~>
|
|
81
|
-
rspec (~> 3.
|
|
82
|
-
rubocop (~> 1.
|
|
79
|
+
rake (~> 13.0)
|
|
80
|
+
rspec (~> 3.10)
|
|
81
|
+
rubocop (~> 1.22, >= 1.22.2)
|
|
83
82
|
rubocop-performance (~> 1.11, >= 1.11.5)
|
|
84
83
|
rubocop-rake (~> 0.6, >= 0.6.0)
|
|
85
|
-
rubocop-rspec (~> 2.
|
|
84
|
+
rubocop-rspec (~> 2.5, >= 2.5.0)
|
|
86
85
|
simplecov-lcov (~> 0.8.0)
|
|
87
86
|
|
|
88
87
|
BUNDLED WITH
|
data/README.md
CHANGED
|
@@ -24,6 +24,15 @@ Or install it yourself as:
|
|
|
24
24
|
$ gem install nerd_dice
|
|
25
25
|
|
|
26
26
|
## Usage
|
|
27
|
+
After the gem is installed, you can require it as you would any other gem.
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
require 'nerd_dice'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Module methods or a dynamic method_missing DSL
|
|
34
|
+
There are two main patterns for using NerdDice in your project. You can invoke the module-level methods like `NerdDice.total_dice` or you can include the `NerdDice::ConvenienceMethods` module to your class \(or IRB \). Once mixed in, you can dynamically invoke methods like `roll_d20_with_advantage` or `total_3d8_plus5`. See the [Convenience Methods Mixin](#convenience-methods-mixin) section for usage details.
|
|
35
|
+
|
|
27
36
|
### Configuration
|
|
28
37
|
You can customize the behavior of NerdDice via a configuration block as below or by assigning an individual property via the ```NerdDice.configuration.property = value``` syntax \(where ```property``` is the config property and ```value``` is the value you want to assign\)\. The available configuration options as well as their defaults, if applicable, are listed in the example configuration block below:
|
|
29
38
|
|
|
@@ -39,7 +48,9 @@ NerdDice.configure do | config|
|
|
|
39
48
|
# total number of dice rolled for each ability score
|
|
40
49
|
config.ability_score_dice_rolled = 4 # must duck-type to positive Integer
|
|
41
50
|
|
|
42
|
-
# highest(n) dice from the total number of dice rolled
|
|
51
|
+
# highest(n) dice from the total number of dice rolled
|
|
52
|
+
# that are included in the ability scoretotal
|
|
53
|
+
#
|
|
43
54
|
# CANNOT EXCEED ability_score_dice_rolled see Note below
|
|
44
55
|
config.ability_score_dice_kept = 3 # must duck-type to positive Integer
|
|
45
56
|
|
|
@@ -49,14 +60,16 @@ NerdDice.configure do | config|
|
|
|
49
60
|
# (Seed is shared with other processes. Too predictable)
|
|
50
61
|
# :random_object => Uses Random.new() and calls rand()
|
|
51
62
|
# Medium entropy, fastest speed. (Performs the best under speed benchmark)
|
|
52
|
-
# :randomized =>
|
|
63
|
+
# :randomized =>
|
|
64
|
+
# Uses a random choice of the :securerandom, :rand, and :random_new_interval options above
|
|
53
65
|
config.randomization_technique = :random_object # fast with independent seed
|
|
54
66
|
|
|
55
67
|
# Number of iterations to use on a generator before refreshing the seed
|
|
56
68
|
# 1 very slow and heavy pressure on processor and memory but very high entropy
|
|
57
69
|
# 1000 would refresh the object every 1000 times you call rand()
|
|
58
70
|
config.refresh_seed_interval = nil # don't refresh the seed
|
|
59
|
-
# Background and foreground die colors are string values.
|
|
71
|
+
# Background and foreground die colors are string values.
|
|
72
|
+
# By default these correspond to the constants in the class
|
|
60
73
|
# Defaults: DEFAULT_BACKGROUND_COLOR = "#0000DD" DEFAULT_FOREGROUND_COLOR = "#DDDDDD"
|
|
61
74
|
# It is recommended but not enforced that these should be valid CSS color property attributes
|
|
62
75
|
config.die_background_color = "red"
|
|
@@ -70,25 +83,26 @@ You can use two different methods to roll dice. The `total_dice` method returns
|
|
|
70
83
|
|
|
71
84
|
```ruby
|
|
72
85
|
# roll a single d4
|
|
73
|
-
NerdDice.total_dice(4) # =>
|
|
74
|
-
NerdDice.roll_dice(4) # =>
|
|
75
|
-
NerdDice.roll_dice(4).total # =>
|
|
86
|
+
NerdDice.total_dice(4) # => Integer: between 1-4
|
|
87
|
+
NerdDice.roll_dice(4) # => DiceSet: with one 4-sided Die with a value between 1-4
|
|
88
|
+
NerdDice.roll_dice(4).total # => Integer: between 1-4
|
|
76
89
|
|
|
77
90
|
# roll 3d6
|
|
78
|
-
NerdDice.total_dice(6, 3) # =>
|
|
79
|
-
NerdDice.roll_dice(6, 3) # =>
|
|
80
|
-
NerdDice.roll_dice(6, 3).total # =>
|
|
91
|
+
NerdDice.total_dice(6, 3) # => Integer: total of three 6-sided dice
|
|
92
|
+
NerdDice.roll_dice(6, 3) # => DiceSet: three 6-sided Die objects, each with values between 1-6
|
|
93
|
+
NerdDice.roll_dice(6, 3).total # => Integer: total of three 6-sided dice
|
|
81
94
|
|
|
82
95
|
# roll a d20 and add 5 to the value
|
|
83
|
-
NerdDice.total_dice(20, bonus: 5) #
|
|
84
|
-
NerdDice.roll_dice(20, bonus: 5) #
|
|
85
|
-
NerdDice.roll_dice(20, bonus: 5).total #
|
|
96
|
+
NerdDice.total_dice(20, bonus: 5) # => Integer: roll a d20 and add the bonus to the total
|
|
97
|
+
NerdDice.roll_dice(20, bonus: 5) # => DiceSet: one 20-sided Die and bonus of 5
|
|
98
|
+
NerdDice.roll_dice(20, bonus: 5).total # => Integer: roll a d20 and add the bonus to the total
|
|
86
99
|
|
|
87
100
|
# without changing the config at the module level
|
|
88
101
|
# roll a d20 and overide the configured randomization_technique one time
|
|
89
102
|
NerdDice.total_dice(20, randomization_technique: :randomized) # => Integer
|
|
90
|
-
# roll a d20 and overide the configured randomization_technique for the DiceSet
|
|
91
|
-
|
|
103
|
+
# roll a d20 and overide the configured randomization_technique for the DiceSet
|
|
104
|
+
# object will persist on the DiceSet object for subsequent rerolls
|
|
105
|
+
NerdDice.roll_dice(20, randomization_technique: :randomized) # => DiceSet with :randomized
|
|
92
106
|
```
|
|
93
107
|
__NOTE:__ If provided, the bonus must respond to `:to_i` or an `ArgumentError` will be raised
|
|
94
108
|
|
|
@@ -96,26 +110,29 @@ __NOTE:__ If provided, the bonus must respond to `:to_i` or an `ArgumentError` w
|
|
|
96
110
|
The `NerdDice.roll_dice` method or the `NerdDice::DiceSet.new` methods return a collection object with an array of one or more `Die` objects. There are properties on both the `DiceSet` object and the `Die` object. Applicable properties are cascaded from the `DiceSet` to the `Die` objects in the collection by default.
|
|
97
111
|
|
|
98
112
|
```ruby
|
|
99
|
-
# These are equivalent
|
|
100
|
-
dice_set = NerdDice.roll_dice(6, 3, bonus: 2, randomization_technique: :randomized,
|
|
101
|
-
#
|
|
102
|
-
|
|
103
|
-
|
|
113
|
+
# These are equivalent. Both return a NerdDice::DiceSet
|
|
114
|
+
dice_set = NerdDice.roll_dice(6, 3, bonus: 2, randomization_technique: :randomized,
|
|
115
|
+
damage_type: 'psychic', foreground_color: '#FFF', background_color: '#0FF')
|
|
116
|
+
|
|
117
|
+
dice_set = NerdDice::DiceSet.new(6, 3, bonus: 2, randomization_technique: :randomized,
|
|
118
|
+
damage_type: 'psychic', foreground_color: '#FFF', background_color: '#0FF')
|
|
119
|
+
|
|
104
120
|
```
|
|
105
121
|
#### Available options for NerdDice::DiceSet objects
|
|
106
122
|
There are a number of options that can be provided when initializing a `NerdDice::DiceSet` object after specifying the mandatory number of sides and the optional number of dice \(default: 1\). The list below provides the options and indicates whether they are cascaded to the Die objects in the collection.
|
|
107
123
|
* `bonus` \(Duck-type Integer, _default: 0_\): Bonus or penalty to apply to the total after all dice are rolled. _**Not applied** to Die objects_
|
|
108
|
-
* `randomization_technique` \(Symbol, _default: nil_\): Randomization technique override to use for the `DiceSet`. If `nil` it will use the value in `NerdDice.configuration`. _**Applied** to Die objects by default with ability modify_
|
|
109
|
-
* `damage_type` \(String, _default: nil_\): Optional string indicating the damage type associated with the dice for systems where it is relevant. _**Applied** to Die objects by default with ability modify_
|
|
110
|
-
* `foreground_color` \(String, _default: `NerdDice.configuration.die_foreground_color`_\): Intended foreground color to apply to the dice in the `DiceSet`. Should be a valid CSS color but is not validated or enforced and doesn\'t currently have any real functionality associated with it. _**Applied** to Die objects by default with ability modify_
|
|
111
|
-
* `background_color` \(String, _default: `NerdDice.configuration.die_background_color`_\): Intended background color to apply to the dice in the `DiceSet`. Should be a valid CSS color but is not validated or enforced and doesn\'t currently have any real functionality associated with it. _**Applied** to Die objects by default with ability modify_
|
|
124
|
+
* `randomization_technique` \(Symbol, _default: nil_\): Randomization technique override to use for the `DiceSet`. If `nil` it will use the value in `NerdDice.configuration`. _**Applied** to Die objects by default with ability to modify_
|
|
125
|
+
* `damage_type` \(String, _default: nil_\): Optional string indicating the damage type associated with the dice for systems where it is relevant. _**Applied** to Die objects by default with ability to modify_
|
|
126
|
+
* `foreground_color` \(String, _default: `NerdDice.configuration.die_foreground_color`_\): Intended foreground color to apply to the dice in the `DiceSet`. Should be a valid CSS color but is not validated or enforced and doesn\'t currently have any real functionality associated with it. _**Applied** to Die objects by default with ability to modify_
|
|
127
|
+
* `background_color` \(String, _default: `NerdDice.configuration.die_background_color`_\): Intended background color to apply to the dice in the `DiceSet`. Should be a valid CSS color but is not validated or enforced and doesn\'t currently have any real functionality associated with it. _**Applied** to Die objects by default with ability to modify_
|
|
112
128
|
|
|
113
129
|
#### Properties of individual Die objects
|
|
114
130
|
When initialized from a `DiceSet` object most of the properties of the `Die` object are inherited from the `DiceSet` object. In addition, there is an `is_included_in_total` public attribute that can be set to indicate whether the value of that particular die should be included in the total for its parent `DiceSet`. This property always starts out as true when the `Die` is initialized, but can be set to false.
|
|
115
131
|
|
|
116
132
|
```ruby
|
|
117
133
|
# six sided die
|
|
118
|
-
die = NerdDice::Die.new(6, randomization_technique: :randomized, damage_type: 'psychic',
|
|
134
|
+
die = NerdDice::Die.new(6, randomization_technique: :randomized, damage_type: 'psychic',
|
|
135
|
+
foreground_color: '#FFF', background_color: '#0FF')
|
|
119
136
|
die.is_included_in_total # => true
|
|
120
137
|
die.included_in_total? # => true
|
|
121
138
|
die.is_included_in_total = false
|
|
@@ -123,9 +140,11 @@ die.included_in_total? # => false
|
|
|
123
140
|
|
|
124
141
|
# value property
|
|
125
142
|
die.value # => Integer between 1 and number_of_sides
|
|
126
|
-
|
|
143
|
+
|
|
144
|
+
# Rolls/rerolls the Die, sets value to the result of the roll, and returns the new value
|
|
145
|
+
die.roll # => Integer.
|
|
127
146
|
```
|
|
128
|
-
#### Iterating through
|
|
147
|
+
#### Iterating through dice in a DiceSet
|
|
129
148
|
The `DiceSet` class mixes in the `Enumerable` module and the `Die` object mixes in the `Comparable` module. This allows you to iterate over the dice in the collection. The `sort` method on the dice will return the die objects in ascending value from lowest to highest.
|
|
130
149
|
|
|
131
150
|
```ruby
|
|
@@ -155,23 +174,31 @@ Since the DiceSet is an object, you can call methods that operate on the result
|
|
|
155
174
|
# assuming 4d6 with values of [1, 3, 4, 6]
|
|
156
175
|
##############################################
|
|
157
176
|
dice_set = NerdDice.roll_dice(6, 4)
|
|
177
|
+
|
|
158
178
|
# the 6, 4, and 3 will have is_included_in_total true while the 1 has it false
|
|
159
|
-
|
|
160
|
-
dice_set.
|
|
179
|
+
# Returns the existing DiceSet object with the changes made to dice inclusion
|
|
180
|
+
dice_set.highest(3) # => DiceSet
|
|
181
|
+
dice_set.with_advantage(3) # => DiceSet (Alias of highest method)
|
|
182
|
+
|
|
161
183
|
# calling total after highest/with_advantage for this DiceSet
|
|
162
184
|
dice_set.total # => 13
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
185
|
+
|
|
186
|
+
# same DiceSet using lowest.
|
|
187
|
+
# The 1, 3, and 4 will have is_included_in_total true while the 6 has it false
|
|
188
|
+
dice_set.lowest(3) # => DiceSet
|
|
189
|
+
dice_set.with_disadvantage(3) # => DiceSet (Alias of lowest method)
|
|
190
|
+
|
|
166
191
|
# calling total after lowest/with_disadvantage for this DiceSet
|
|
167
192
|
dice_set.total # => 8
|
|
193
|
+
|
|
168
194
|
# you can chain these methods (assumes the same seed as the above examples)
|
|
169
195
|
NerdDice.roll_dice(6, 4).with_advantage(3).total # => 13
|
|
170
196
|
NerdDice.roll_dice(6, 4).lowest(3).total # => 8
|
|
171
197
|
|
|
172
198
|
# reroll_all! method
|
|
173
199
|
dice_set = NerdDice.roll_dice(6, 4)
|
|
174
|
-
|
|
200
|
+
# rerolls each of the Die objects in the collection and re-includes them in the total
|
|
201
|
+
dice_set.reroll_all!
|
|
175
202
|
|
|
176
203
|
# include_all_dice! method
|
|
177
204
|
dice_set.include_all_dice! # resets is_included_in_total to true for all Die objects
|
|
@@ -232,7 +259,7 @@ NerdDice.refresh_seed!(randomization_technique: :randomized,
|
|
|
232
259
|
random_rand_seed: 1337,
|
|
233
260
|
random_object_seed: 24601)
|
|
234
261
|
```
|
|
235
|
-
__NOTE:__ Ability to specify a seed
|
|
262
|
+
__NOTE:__ Ability to specify a seed is primarily provided for testing purposes. This makes all random numbers generated _transparently deterministic_ and should not be used if you want behavior approximating randomness.
|
|
236
263
|
|
|
237
264
|
### Utility Methods
|
|
238
265
|
|
|
@@ -250,6 +277,126 @@ totals_array = NerdDice.harvest_totals(totals_array)
|
|
|
250
277
|
# => [15, 14, 13, 12, 10, 8]
|
|
251
278
|
# yes, it just happened to be the standard array by amazing coincidence
|
|
252
279
|
```
|
|
280
|
+
<a name="convenience-methods-mixin"></a>
|
|
281
|
+
### Convenience Methods Mixin
|
|
282
|
+
NerdDice provides an optional mixin `NerdDice::ConvenienceMethods` that uses Ruby\'s `method_missing` metaprogramming pattern to allow you to roll any number of dice with bonuses and/or the advantage/disadvantage mechanic by dynamically responding to methods that you type that match the `roll_` or `total_` pattern.
|
|
283
|
+
|
|
284
|
+
#### Considerations for ConvenienceMethods
|
|
285
|
+
Before mixing in this method with a class, be aware of other `method_missing` gems that you are also mixing into your project and be sure to write robust tests. We have sought to use `method_missing` in a responsible manner that delegates back to the default implementation using `super` if the method does not match the `ConvenienceMethods` pattern, but there is no guarantee that other gems included in your project are doing the same. If you run into problems with the `ConvenienceMethods` module interacting with other `method_missing` gems, everything that the `ConvenienceMethods` module does can be replicated using the module\-level methods described above or by calling the convenience method on `NerdDice`.
|
|
286
|
+
|
|
287
|
+
Once a particular method has been called, it will define that method so that the next time it will invoke the method directly instead of traversing up the call stack for `method_missing`, which improves performance. The method will remain defined for the duration of the Ruby interpreter process.
|
|
288
|
+
|
|
289
|
+
#### Calling ConvenienceMethods as NerdDice class methods
|
|
290
|
+
NerdDice extends the `ConvenienceMethods` module into the top-level module as class methods, so you can call the methods on the NerdDice module without needing to worry about the implications of extending it into your own class.
|
|
291
|
+
```ruby
|
|
292
|
+
require 'nerd_dice'
|
|
293
|
+
# works with all the examples and patterns below
|
|
294
|
+
NerdDice.roll_3d6_lowest2_minus1
|
|
295
|
+
NerdDice.total_d20_with_advantage_p6
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
#### Mixing in the ConvenienceMethods module
|
|
299
|
+
To mix the NerdDice DSL into your class, make sure the gem is required if not already and then use `include NerdDice::ConvenienceMethods` as shown below:
|
|
300
|
+
```ruby
|
|
301
|
+
# example of a class that mixes in NerdDice::ConvenienceMethods
|
|
302
|
+
require 'nerd_dice'
|
|
303
|
+
class Monster
|
|
304
|
+
include NerdDice::ConvenienceMethods
|
|
305
|
+
|
|
306
|
+
# hard-coding probably not the best solution
|
|
307
|
+
# but gives you an idea how to mix in to a simple class
|
|
308
|
+
def hits_the_monster
|
|
309
|
+
# using the ConvenienceMethods version
|
|
310
|
+
total_d20_plus5 >= @armor_class ? "hit" : "miss"
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
def initialize(armor_class=16)
|
|
314
|
+
@armor_class = armor_class
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
```
|
|
318
|
+
To mix in the module as class methods, you can use `extend NerdDice::ConvenienceMethods`
|
|
319
|
+
```ruby
|
|
320
|
+
# example of a class that mixes in NerdDice::ConvenienceMethods
|
|
321
|
+
require 'nerd_dice'
|
|
322
|
+
class OtherClass
|
|
323
|
+
extend NerdDice::ConvenienceMethods
|
|
324
|
+
end
|
|
325
|
+
OtherClass.roll_3d6_lowest2_minus1 # returns NerdDice::DiceSet
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
#### ConvenienceMethods usage examples
|
|
329
|
+
Any invocation of `NerdDice.roll_dice` and `NerdDice.total_dice` can be duplicated using the `NerdDice::ConvenienceMethods` mixin. Here are some examples of what you can do with the return types and equivalent methods in the comments:
|
|
330
|
+
|
|
331
|
+
* `roll_dNN` and `total_dNN` roll one die
|
|
332
|
+
```ruby
|
|
333
|
+
roll_d20 # => DiceSet: NerdDice.roll_dice(20)
|
|
334
|
+
roll_d8 # => DiceSet: NerdDice.roll_dice(8)
|
|
335
|
+
roll_d1000 # => DiceSet: NerdDice.roll_dice(1000)
|
|
336
|
+
total_d20 # => Integer NerdDice.total_dice(20)
|
|
337
|
+
total_d8 # => Integer NerdDice.total_dice(8)
|
|
338
|
+
total_d1000 # => Integer NerdDice.total_dice(1000)
|
|
339
|
+
```
|
|
340
|
+
* `roll_NNdNN` and `total_NNdNN` roll specified quantity of dice
|
|
341
|
+
```ruby
|
|
342
|
+
roll_2d20 # => DiceSet: NerdDice.roll_dice(20, 2)
|
|
343
|
+
roll_3d8 # => DiceSet: NerdDice.roll_dice(8, 3)
|
|
344
|
+
roll_22d1000 # => DiceSet: NerdDice.roll_dice(1000, 22)
|
|
345
|
+
total_2d20 # => Integer NerdDice.total_dice(20, 2)
|
|
346
|
+
total_3d8 # => Integer NerdDice.total_dice(8, 3)
|
|
347
|
+
total_22d1000 # => Integer NerdDice.total_dice(1000, 22)
|
|
348
|
+
```
|
|
349
|
+
* Keyword arguments are passed on to `roll_dice`/`total_dice` method
|
|
350
|
+
```ruby
|
|
351
|
+
roll_2d20 foreground_color: "blue" # => DiceSet: NerdDice.roll_dice(20, 2, foreground_color: "blue")
|
|
352
|
+
|
|
353
|
+
total_d12 randomization_technique: :randomized
|
|
354
|
+
# => Integer NerdDice.total_dice(12, randomization_technique: :randomized)
|
|
355
|
+
total_22d1000 randomization_technique: :random_rand
|
|
356
|
+
# => Integer NerdDice.total_dice(1000, 22, randomization_technique: :random_rand)
|
|
357
|
+
|
|
358
|
+
roll_4d6_with_advantage3 background_color: 'blue'
|
|
359
|
+
# => DiceSet: NerdDice.roll_dice(4, 3, background_color: 'blue').highest(3)
|
|
360
|
+
total_4d6_with_advantage3 randomization_technique: :random_rand
|
|
361
|
+
# => Integer: NerdDice.roll_dice(4, 3, randomization_technique: :random_rand).highest(3).total
|
|
362
|
+
```
|
|
363
|
+
* Positive and negative bonuses can be used with `plus` (alias `p`) or `minus` (alias `m`)
|
|
364
|
+
```ruby
|
|
365
|
+
roll_d20_plus6 # => DiceSet: NerdDice.roll_dice(20, bonus: 6)
|
|
366
|
+
total_3d8_p2 # => Integer: NerdDice.total_dice(8, 3, bonus: 2)
|
|
367
|
+
total_d20_minus5 # => Integer: NerdDice.total_dice(20, bonus: -6)
|
|
368
|
+
roll_3d8_m3 # => DiceSet: NerdDice.roll_dice(8, 3, bonus: -3)
|
|
369
|
+
```
|
|
370
|
+
* `_with_advantageN` or `highestN` roll with advantage
|
|
371
|
+
* `_with_disadvantageN` or `lowestN` roll with disadvantage
|
|
372
|
+
* Calling `roll_dNN_with_advantage` \(and variants\) rolls 2 dice and keeps one
|
|
373
|
+
```ruby
|
|
374
|
+
# equivalent
|
|
375
|
+
roll_3d8_with_advantage1
|
|
376
|
+
roll_3d8_highest1
|
|
377
|
+
# => DiceSet: NerdDice.roll_dice(8, 3).with_advantage(1)
|
|
378
|
+
|
|
379
|
+
# calls roll_dice and total to return an integer
|
|
380
|
+
total_3d8_with_advantage1
|
|
381
|
+
total_3d8_highest1
|
|
382
|
+
# => Integer: NerdDice.roll_dice(8, 3).with_advantage(1).total
|
|
383
|
+
|
|
384
|
+
# rolls two dice in this case
|
|
385
|
+
# equal to roll_2d20_with_advantage but more natural
|
|
386
|
+
roll_d20_with_advantage # => DiceSet: NerdDice.roll_dice(20, 2).with_advantage(1)
|
|
387
|
+
# equal to total_2d20_with_advantage but more natural
|
|
388
|
+
total_d20_with_advantage # => Integer: NerdDice.roll_dice(20, 2).with_advantage(1).total
|
|
389
|
+
```
|
|
390
|
+
#### ConvenienceMethods error handling
|
|
391
|
+
* If you try to call with a plus and a minus, an Exception is raised
|
|
392
|
+
* If you call with a bonus and a keyword argument and they don't match, an Exception is raised
|
|
393
|
+
* Any combination not expressly allowed or matched will call `super` on `method_missing`
|
|
394
|
+
```ruby
|
|
395
|
+
roll_3d8_plus3_m2 # will raise NameError using super method_missing
|
|
396
|
+
roll_3d8_plus3 bonus: 1 # will raise NerdDice::Error with message about "Bonus integrity failure"
|
|
397
|
+
roll_d20_with_advantage_lowest # will raise NameError using super method_missing
|
|
398
|
+
total_4d6_lowest3_highest2 # will raise NameError using super method_missing
|
|
399
|
+
```
|
|
253
400
|
|
|
254
401
|
## Development
|
|
255
402
|
|
|
@@ -264,4 +411,4 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/statel
|
|
|
264
411
|
|
|
265
412
|
## Unlicense, License, and Copyright
|
|
266
413
|
|
|
267
|
-
The
|
|
414
|
+
The project is dual-licensed under the [MIT](https://opensource.org/licenses/MIT) license and the [UNLICENSE](https://unlicense.org/) \(with strong preference toward the UNLICENSE\)\. The content is released under [CC0](https://creativecommons.org/share-your-work/public-domain/cc0/) \(no rights reserved\). You are free to include it in its original form or modified with or without additional modification in your own project\.
|
data/bin/nerd_dice_benchmark
CHANGED
|
@@ -16,16 +16,28 @@ RATIOS = {
|
|
|
16
16
|
total_dice_random_rand_3d6: 30.0,
|
|
17
17
|
total_dice_random_object_3d6: 25.5,
|
|
18
18
|
total_dice_randomized_3d6: 15.5,
|
|
19
|
+
total_magic_securerandom: 6.04,
|
|
20
|
+
total_magic_random_rand: 85.9,
|
|
21
|
+
total_magic_random_object: 89.42,
|
|
22
|
+
total_magic_randomized: 20.27,
|
|
19
23
|
roll_dice_securerandom: 4.0,
|
|
20
24
|
roll_dice_random_rand: 42.0,
|
|
21
25
|
roll_dice_random_object: 44.0,
|
|
22
26
|
roll_dice_randomized: 14.5,
|
|
27
|
+
roll_magic_securerandom: 6.04,
|
|
28
|
+
roll_magic_random_rand: 85.9,
|
|
29
|
+
roll_magic_random_object: 89.42,
|
|
30
|
+
roll_magic_randomized: 20.27,
|
|
23
31
|
roll_dice_securerandom_3d6: 13.0,
|
|
24
32
|
roll_dice_random_rand_3d6: 79.0,
|
|
25
33
|
roll_dice_random_object_3d6: 86.0,
|
|
26
34
|
roll_dice_randomized_3d6: 26.5,
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
roll_magic_securerandom_3d6: 18.38,
|
|
36
|
+
roll_magic_random_rand_3d6: 108.54,
|
|
37
|
+
roll_magic_random_object_3d6: 118.36,
|
|
38
|
+
roll_magic_randomized_3d6: 44.39,
|
|
39
|
+
roll_ability_scores_randomized: 30.5,
|
|
40
|
+
total_ability_scores_randomized: 30.5
|
|
29
41
|
}.freeze
|
|
30
42
|
|
|
31
43
|
def check_against_baseline!(baseline_value, test_value)
|
|
@@ -36,7 +48,7 @@ def check_against_baseline!(baseline_value, test_value)
|
|
|
36
48
|
end
|
|
37
49
|
|
|
38
50
|
puts "Set baseline"
|
|
39
|
-
baselines = Benchmark.
|
|
51
|
+
baselines = Benchmark.bm do |x|
|
|
40
52
|
# Random.rand()
|
|
41
53
|
x.report("Random.rand") do # standard rand()
|
|
42
54
|
n.times { Random.rand(1000) }
|
|
@@ -52,7 +64,9 @@ random_rand_baseline = baselines[0].real
|
|
|
52
64
|
securerandom_baseline = baselines[1].real
|
|
53
65
|
|
|
54
66
|
puts "Roll d1000s"
|
|
55
|
-
|
|
67
|
+
|
|
68
|
+
puts "total_dice"
|
|
69
|
+
total_dice_d1000_results = Benchmark.bm do |x|
|
|
56
70
|
# NerdDice.total_dice securerandom
|
|
57
71
|
x.report("total_dice_securerandom") do
|
|
58
72
|
NerdDice.configuration.randomization_technique = :securerandom
|
|
@@ -84,7 +98,43 @@ check_against_baseline! random_rand_baseline, total_dice_random_object
|
|
|
84
98
|
total_dice_randomized = total_dice_d1000_results[3]
|
|
85
99
|
check_against_baseline! ((random_rand_baseline * 0.75) + (securerandom_baseline * 0.25)), total_dice_randomized
|
|
86
100
|
|
|
87
|
-
|
|
101
|
+
puts "total_ d1000s ConvenienceMethods"
|
|
102
|
+
|
|
103
|
+
# NOTE: Due to method_missing overhead, using roll_ ratios for ConvenienceMethods total_dice
|
|
104
|
+
total_d1000_results = Benchmark.bm do |x|
|
|
105
|
+
# NerdDice.total_dice securerandom
|
|
106
|
+
x.report("total_magic_securerandom") do
|
|
107
|
+
NerdDice.configuration.randomization_technique = :securerandom
|
|
108
|
+
n.times { NerdDice.total_d1000 }
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
x.report("total_magic_random_rand") do
|
|
112
|
+
NerdDice.configuration.randomization_technique = :random_rand
|
|
113
|
+
n.times { NerdDice.total_d1000 }
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
x.report("total_magic_random_object") do
|
|
117
|
+
NerdDice.configuration.randomization_technique = :random_object
|
|
118
|
+
n.times { NerdDice.total_d1000 }
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
x.report("total_magic_randomized") do
|
|
122
|
+
NerdDice.configuration.randomization_technique = :randomized
|
|
123
|
+
n.times { NerdDice.total_d1000 }
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
total_magic_securerandom = total_d1000_results[0]
|
|
128
|
+
check_against_baseline! securerandom_baseline, total_magic_securerandom
|
|
129
|
+
total_magic_random_rand = total_d1000_results[1]
|
|
130
|
+
check_against_baseline! random_rand_baseline, total_magic_random_rand
|
|
131
|
+
total_magic_random_object = total_d1000_results[2]
|
|
132
|
+
check_against_baseline! random_rand_baseline, total_magic_random_object
|
|
133
|
+
total_magic_randomized = total_d1000_results[3]
|
|
134
|
+
check_against_baseline! ((random_rand_baseline * 0.75) + (securerandom_baseline * 0.25)), total_magic_randomized
|
|
135
|
+
|
|
136
|
+
puts "roll_dice"
|
|
137
|
+
roll_dice_d1000_results = Benchmark.bm do |x|
|
|
88
138
|
# NerdDice.roll_dice securerandom
|
|
89
139
|
x.report("roll_dice_securerandom") do
|
|
90
140
|
NerdDice.configuration.randomization_technique = :securerandom
|
|
@@ -116,8 +166,42 @@ check_against_baseline! random_rand_baseline, roll_dice_random_object
|
|
|
116
166
|
roll_dice_randomized = roll_dice_d1000_results[3]
|
|
117
167
|
check_against_baseline! ((random_rand_baseline * 0.75) + (securerandom_baseline * 0.25)), roll_dice_randomized
|
|
118
168
|
|
|
169
|
+
puts "roll_ d1000s ConvenienceMethods"
|
|
170
|
+
roll_d1000_results = Benchmark.bm do |x|
|
|
171
|
+
# NerdDice.roll_dice securerandom
|
|
172
|
+
x.report("roll_magic_securerandom") do
|
|
173
|
+
NerdDice.configuration.randomization_technique = :securerandom
|
|
174
|
+
n.times { NerdDice.roll_d1000 }
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
x.report("roll_magic_random_rand") do
|
|
178
|
+
NerdDice.configuration.randomization_technique = :random_rand
|
|
179
|
+
n.times { NerdDice.roll_d1000 }
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
x.report("roll_magic_random_object") do
|
|
183
|
+
NerdDice.configuration.randomization_technique = :random_object
|
|
184
|
+
n.times { NerdDice.roll_d1000 }
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
x.report("roll_magic_randomized") do
|
|
188
|
+
NerdDice.configuration.randomization_technique = :randomized
|
|
189
|
+
n.times { NerdDice.roll_d1000 }
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
roll_magic_securerandom = roll_d1000_results[0]
|
|
194
|
+
check_against_baseline! securerandom_baseline, roll_magic_securerandom
|
|
195
|
+
roll_magic_random_rand = roll_d1000_results[1]
|
|
196
|
+
check_against_baseline! random_rand_baseline, roll_magic_random_rand
|
|
197
|
+
roll_magic_random_object = roll_d1000_results[2]
|
|
198
|
+
check_against_baseline! random_rand_baseline, roll_magic_random_object
|
|
199
|
+
roll_magic_randomized = roll_d1000_results[3]
|
|
200
|
+
check_against_baseline! ((random_rand_baseline * 0.75) + (securerandom_baseline * 0.25)), roll_magic_randomized
|
|
201
|
+
|
|
119
202
|
puts "Roll 3d6"
|
|
120
|
-
|
|
203
|
+
puts "total_dice 3d6"
|
|
204
|
+
total_dice_3d6_results = Benchmark.bm do |x|
|
|
121
205
|
# NerdDice.total_dice securerandom
|
|
122
206
|
x.report("total_dice_securerandom_3d6") do
|
|
123
207
|
NerdDice.configuration.randomization_technique = :securerandom
|
|
@@ -149,7 +233,8 @@ check_against_baseline! random_rand_baseline, total_dice_3d6_random_object
|
|
|
149
233
|
total_dice_3d6_randomized = total_dice_3d6_results[3]
|
|
150
234
|
check_against_baseline! ((random_rand_baseline * 0.75) + (securerandom_baseline * 0.25)), total_dice_3d6_randomized
|
|
151
235
|
|
|
152
|
-
|
|
236
|
+
puts "roll_dice 3d6"
|
|
237
|
+
roll_dice_3d6_results = Benchmark.bm do |x|
|
|
153
238
|
# NerdDice.roll_dice securerandom
|
|
154
239
|
x.report("roll_dice_securerandom_3d6") do
|
|
155
240
|
NerdDice.configuration.randomization_technique = :securerandom
|
|
@@ -181,11 +266,44 @@ check_against_baseline! random_rand_baseline, roll_dice_3d6_random_object
|
|
|
181
266
|
roll_dice_3d6_randomized = roll_dice_3d6_results[3]
|
|
182
267
|
check_against_baseline! ((random_rand_baseline * 0.75) + (securerandom_baseline * 0.25)), roll_dice_3d6_randomized
|
|
183
268
|
|
|
269
|
+
puts "roll_3d6 ConvenienceMethods"
|
|
270
|
+
roll_magic_3d6_results = Benchmark.bm do |x|
|
|
271
|
+
# NerdDice.roll_magic securerandom
|
|
272
|
+
x.report("roll_magic_securerandom_3d6") do
|
|
273
|
+
NerdDice.configuration.randomization_technique = :securerandom
|
|
274
|
+
n.times { NerdDice.roll_3d6 }
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
x.report("roll_magic_random_rand_3d6") do
|
|
278
|
+
NerdDice.configuration.randomization_technique = :random_rand
|
|
279
|
+
n.times { NerdDice.roll_3d6 }
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
x.report("roll_magic_random_object_3d6") do
|
|
283
|
+
NerdDice.configuration.randomization_technique = :random_object
|
|
284
|
+
n.times { NerdDice.roll_3d6 }
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
x.report("roll_magic_randomized_3d6") do
|
|
288
|
+
NerdDice.configuration.randomization_technique = :randomized
|
|
289
|
+
n.times { NerdDice.roll_3d6 }
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
roll_magic_3d6_securerandom = roll_magic_3d6_results[0]
|
|
294
|
+
check_against_baseline! securerandom_baseline, roll_magic_3d6_securerandom
|
|
295
|
+
roll_magic_3d6_random_rand = roll_magic_3d6_results[1]
|
|
296
|
+
check_against_baseline! random_rand_baseline, roll_magic_3d6_random_rand
|
|
297
|
+
roll_magic_3d6_random_object = roll_magic_3d6_results[2]
|
|
298
|
+
check_against_baseline! random_rand_baseline, roll_magic_3d6_random_object
|
|
299
|
+
roll_magic_3d6_randomized = roll_magic_3d6_results[3]
|
|
300
|
+
check_against_baseline! ((random_rand_baseline * 0.75) + (securerandom_baseline * 0.25)), roll_magic_3d6_randomized
|
|
301
|
+
|
|
184
302
|
puts "Setting n down to 5,000 due to more intensive methods"
|
|
185
303
|
n = 5_000
|
|
186
304
|
|
|
187
305
|
puts "Roll and total ability scores"
|
|
188
|
-
roll_ability_scores_results = Benchmark.
|
|
306
|
+
roll_ability_scores_results = Benchmark.bm do |x|
|
|
189
307
|
x.report("roll_ability_scores_randomized") do
|
|
190
308
|
NerdDice.configuration.randomization_technique = :randomized
|
|
191
309
|
n.times { NerdDice.roll_ability_scores }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
30f9d3809362099e81e414bf987b711c8dad59703c68579809bb36ce9b199d58
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1a8913b8f2878c1471f32dadaddf9965fd61c7ef2e9a255961babdb9586f2c18b7eca1cd0f1021061fb69c96a330151a97df9a102b2871e1e1c5e5675f34a511
|
|
@@ -24,12 +24,17 @@ module NerdDice
|
|
|
24
24
|
def harvest_totals(collection)
|
|
25
25
|
collection.map(&:total)
|
|
26
26
|
rescue NoMethodError => e
|
|
27
|
-
specific_message =
|
|
28
|
-
|
|
27
|
+
specific_message = get_harvest_totals_error_message(e)
|
|
28
|
+
specific_message ? raise(ArgumentError, "You must provide a valid collection. #{specific_message}") : raise
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def get_harvest_totals_error_message(rescued_error)
|
|
34
|
+
case rescued_error.message
|
|
29
35
|
when /`total'/ then "Each element must respond to :total."
|
|
30
36
|
when /`map'/ then "Argument must respond to :map."
|
|
31
37
|
end
|
|
32
|
-
|
|
33
|
-
end
|
|
38
|
+
end
|
|
34
39
|
end
|
|
35
40
|
end
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NerdDice
|
|
4
|
+
# The NerdDice::ConvenienceMethods module overrides the default behavior of method_missing to
|
|
5
|
+
# provide the ability to dynamically roll dice with methods names that match specific patterns.
|
|
6
|
+
#
|
|
7
|
+
# Examples:
|
|
8
|
+
# `roll_dNN` and `total_dNN` roll one die
|
|
9
|
+
# <tt>
|
|
10
|
+
# roll_d20 # => DiceSet: NerdDice.roll_dice(20)
|
|
11
|
+
# roll_d8 # => DiceSet: NerdDice.roll_dice(8)
|
|
12
|
+
# roll_d1000 # => DiceSet: NerdDice.roll_dice(1000)
|
|
13
|
+
# total_d20 # => Integer NerdDice.total_dice(20)
|
|
14
|
+
# total_d8 # => Integer NerdDice.total_dice(8)
|
|
15
|
+
# total_d1000 # => Integer NerdDice.total_dice(1000)
|
|
16
|
+
# </tt>
|
|
17
|
+
#
|
|
18
|
+
# `roll_NNdNN` and `total_NNdNN` roll specified quantity of dice
|
|
19
|
+
# <tt>
|
|
20
|
+
# roll_2d20 # => DiceSet: NerdDice.roll_dice(20, 2)
|
|
21
|
+
# roll_3d8 # => DiceSet: NerdDice.roll_dice(8, 3)
|
|
22
|
+
# roll_22d1000 # => DiceSet: NerdDice.roll_dice(1000, 22)
|
|
23
|
+
# total_2d20 # => Integer NerdDice.total_dice(20, 2)
|
|
24
|
+
# total_3d8 # => Integer NerdDice.total_dice(8, 3)
|
|
25
|
+
# total_22d1000 # => Integer NerdDice.total_dice(1000, 22)
|
|
26
|
+
# </tt>
|
|
27
|
+
#
|
|
28
|
+
# Keyword arguments are passed on to `roll_dice`/`total_dice` method
|
|
29
|
+
# <tt>
|
|
30
|
+
# roll_2d20 foreground_color: 'blue' # => DiceSet: NerdDice.roll_dice(20, 2, foreground_color: 'blue')
|
|
31
|
+
# roll_2d20 foreground_color: 'blue' # => DiceSet: NerdDice.roll_dice(20, 2, foreground_color: 'blue')
|
|
32
|
+
# total_d12 randomization_technique: :randomized
|
|
33
|
+
# # => Integer NerdDice.total_dice(12, randomization_technique: :randomized)
|
|
34
|
+
# total_22d1000 randomization_technique: :random_rand
|
|
35
|
+
# # => Integer NerdDice.total_dice(1000, 22, randomization_technique: :random_rand)
|
|
36
|
+
# roll_4d6_with_advantage3 foreground_color: 'blue'
|
|
37
|
+
# # => DiceSet: NerdDice.roll_dice(4, 3, foreground_color: 'blue').highest(3)
|
|
38
|
+
# total_4d6_with_advantage3 randomization_technique: :random_rand
|
|
39
|
+
# # => Integer: NerdDice.roll_dice(4, 3, randomization_technique: :random_rand).highest(3).total
|
|
40
|
+
# </tt>
|
|
41
|
+
#
|
|
42
|
+
# Positive and negative bonuses can be used with `plus` (alias `p`) or `minus` (alias `m`) in DSL
|
|
43
|
+
# <tt>
|
|
44
|
+
# roll_d20_plus6 # => DiceSet: NerdDice.roll_dice(20, bonus: 6)
|
|
45
|
+
# total_3d8_p2 # => Integer: NerdDice.total_dice(8, 3, bonus: 2)
|
|
46
|
+
# total_d20_minus5 # => Integer: NerdDice.total_dice(20, bonus: -6)
|
|
47
|
+
# roll_3d8_m3 # => DiceSet: NerdDice.roll_dice(8, 3, bonus: -3)
|
|
48
|
+
# </tt>
|
|
49
|
+
#
|
|
50
|
+
# Advantage and disadvantage
|
|
51
|
+
# * `_with_advantageN` or `highestN` roll with advantage
|
|
52
|
+
# * `_with_disadvantageN` or `lowestN` roll with disadvantage
|
|
53
|
+
# * Calling `roll_dNN_with_advantage` \(and variants\) rolls 2 dice and keeps one
|
|
54
|
+
# <tt>
|
|
55
|
+
# # equivalent
|
|
56
|
+
# roll_3d8_with_advantage1
|
|
57
|
+
# roll_3d8_highest1
|
|
58
|
+
# # => DiceSet: NerdDice.roll_dice(8, 3).with_advantage(1)
|
|
59
|
+
# # calls roll_dice and total to return an integer
|
|
60
|
+
# total_3d8_with_advantage1
|
|
61
|
+
# total_3d8_highest1
|
|
62
|
+
# # => Integer: NerdDice.roll_dice(8, 3).with_advantage(1).total
|
|
63
|
+
# # rolls two dice in this case
|
|
64
|
+
# # equal to roll_2d20_with_advantage but more natural
|
|
65
|
+
# roll_d20_with_advantage # => DiceSet: NerdDice.roll_dice(20, 2).with_advantage(1)
|
|
66
|
+
# # equal to total_2d20_with_advantage but more natural
|
|
67
|
+
# total_d20_with_advantage # => Integer: NerdDice.roll_dice(20, 2).with_advantage(1).total
|
|
68
|
+
# </tt>
|
|
69
|
+
#
|
|
70
|
+
# Error Handling
|
|
71
|
+
# * If you try to call with a plus and a minus, an Exception is raised
|
|
72
|
+
# * If you call with a bonus and a keyword argument and they don't match, an Exception is raised
|
|
73
|
+
# * Any combination not expressly allowed or matched will call `super`
|
|
74
|
+
# <tt>
|
|
75
|
+
# roll_3d8_plus3_m2 # raise NerdDice::Error
|
|
76
|
+
# roll_3d8_plus3 bonus: 1 # raise NerdDice::Error
|
|
77
|
+
# roll_d20_with_advantage_lowest # will raise NameError using super method_missing
|
|
78
|
+
# total_4d6_lowest3_highest2 # will raise NameError using super method_missing
|
|
79
|
+
module ConvenienceMethods
|
|
80
|
+
DIS = /_(with_disadvantage|lowest)/.freeze
|
|
81
|
+
ADV = /_(with_advantage|highest)/.freeze
|
|
82
|
+
MOD = /(_p(lus)?\d+|_m(inus)?\d+)/.freeze
|
|
83
|
+
OVERALL_REGEXP = /\A(roll|total)_\d*d\d+((#{ADV}|#{DIS})\d*)?#{MOD}?\z/.freeze
|
|
84
|
+
|
|
85
|
+
# Override of method_missing
|
|
86
|
+
# * Attempts to match pattern to the regular expression matching the methods
|
|
87
|
+
# we want to intercept
|
|
88
|
+
# * If the method matches the pattern, it is defined and executed with send
|
|
89
|
+
# * Subsequent calls to the same method name will not hit method_missing
|
|
90
|
+
# * If the method name does not match the regular expression pattern, the default
|
|
91
|
+
# implementation of method_missing is called by invoking super
|
|
92
|
+
def method_missing(method_name, *args, **kwargs, &block)
|
|
93
|
+
# returns false if no match
|
|
94
|
+
if match_pattern_and_delegate(method_name, *args, **kwargs, &block)
|
|
95
|
+
# send the method after defining it
|
|
96
|
+
send(method_name, *args, **kwargs, &block)
|
|
97
|
+
else
|
|
98
|
+
super
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Override :respond_to_missing? so that :respond_to? works as expected when the
|
|
103
|
+
# module is included.
|
|
104
|
+
def respond_to_missing?(symbol, include_all)
|
|
105
|
+
symbol.to_s.match?(OVERALL_REGEXP) || super
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
private
|
|
109
|
+
|
|
110
|
+
# Compares the method name to the regular expression patterns for the module
|
|
111
|
+
# * If the pattern matches the convenience method is defined and a truthy value is returned
|
|
112
|
+
# * If the pattern does not match then the method returns false and method_missing invokes `super`
|
|
113
|
+
def match_pattern_and_delegate(method_name, *args, **kwargs, &block)
|
|
114
|
+
case method_name.to_s
|
|
115
|
+
when /\Aroll_\d*d\d+((#{ADV}|#{DIS})\d*)?#{MOD}?\z/o then define_roll_nndnn(method_name, *args, **kwargs,
|
|
116
|
+
&block)
|
|
117
|
+
when /\Atotal_\d*d\d+((#{ADV}|#{DIS})\d*)?#{MOD}?\z/o then define_total_nndnn(method_name, *args, **kwargs,
|
|
118
|
+
&block)
|
|
119
|
+
else
|
|
120
|
+
false
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# * Evaluates the method name and then uses class_eval and define_method to define the method
|
|
125
|
+
# * Subsequent calls to the method will bypass method_missing
|
|
126
|
+
#
|
|
127
|
+
# Defined method will return a NerdDice::DiceSet
|
|
128
|
+
def define_roll_nndnn(method_name, *_args, **_kwargs)
|
|
129
|
+
sides, number_of_dice, number_to_keep = parse_from_method_name(method_name)
|
|
130
|
+
# defines the method on the class mixing in the module
|
|
131
|
+
(class << self; self; end).class_eval do
|
|
132
|
+
define_method method_name do |*_args, **kwargs|
|
|
133
|
+
modifier = get_modifier_from_method_name!(method_name, kwargs)
|
|
134
|
+
kwargs[:bonus] = modifier if modifier
|
|
135
|
+
# NerdDice::DiceSet object
|
|
136
|
+
dice = NerdDice.roll_dice(sides, number_of_dice, **kwargs)
|
|
137
|
+
# invoke highest or lowest on the DiceSet if applicable
|
|
138
|
+
parse_number_to_keep(dice, method_name, number_to_keep)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# The implementation of this is different than the roll_ version because NerdDice.total_dice
|
|
144
|
+
# cannot deal with highest/lowest calls
|
|
145
|
+
# * Evaluates the method name and then uses class_eval and define_method to define the method
|
|
146
|
+
# * Calls :determine_total_method to allow for handling of highest/lowest mechanic
|
|
147
|
+
# * Subsequent calls to the method will bypass method_missing
|
|
148
|
+
#
|
|
149
|
+
# Defined method will return an Integer
|
|
150
|
+
def define_total_nndnn(method_name, *_args, **_kwargs)
|
|
151
|
+
(class << self; self; end).class_eval do
|
|
152
|
+
define_method method_name do |*_args, **kwargs|
|
|
153
|
+
# parse out bonus before calling determine_total_method
|
|
154
|
+
modifier = get_modifier_from_method_name!(method_name, kwargs)
|
|
155
|
+
kwargs[:bonus] = modifier if modifier
|
|
156
|
+
# parse the method and take different actions based on method_name pattern
|
|
157
|
+
determine_total_method(method_name, kwargs)
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Determines whether to call NerdDice.total_dice or NerdDice.roll_dice.total based on RegEx pattern
|
|
163
|
+
# * If the method matches the ADV or DIS regular expressions, the method will call :roll_dice and :total
|
|
164
|
+
# * If the method does not match ADV or DIS, the method will call :total_dice (which is faster)
|
|
165
|
+
#
|
|
166
|
+
# Returns Integer irrespective of which methodology is used
|
|
167
|
+
def determine_total_method(method_name, kwargs)
|
|
168
|
+
sides, number_of_dice, number_to_keep = parse_from_method_name(method_name)
|
|
169
|
+
if number_to_keep
|
|
170
|
+
# NerdDice::DiceSet
|
|
171
|
+
dice = NerdDice.roll_dice(sides, number_of_dice, **kwargs)
|
|
172
|
+
# invoke the highest or lowest method to define dice included and then return the total
|
|
173
|
+
parse_number_to_keep(dice, method_name, number_to_keep).total
|
|
174
|
+
else
|
|
175
|
+
NerdDice.total_dice(sides, number_of_dice, **kwargs)
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# calls a series of parse methods and then returns them as an array so the define_ methods above can
|
|
180
|
+
# use a one-liner to assign the variables
|
|
181
|
+
def parse_from_method_name(method_name)
|
|
182
|
+
sides = get_sides_from_method_name(method_name)
|
|
183
|
+
number_of_dice = get_number_of_dice_from_method_name(method_name)
|
|
184
|
+
number_to_keep = get_number_to_keep_from_method_name(method_name, number_of_dice)
|
|
185
|
+
[sides, number_of_dice, number_to_keep]
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# parses out the Integer value of number of sides from the method name
|
|
189
|
+
# will only ever get called if the pattern matches so no need for guard against nil
|
|
190
|
+
def get_sides_from_method_name(method_name)
|
|
191
|
+
method_name.to_s.match(/d\d+/).to_s[1..].to_i
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# parses the number of dice from the method name and returns the applicable Integer value
|
|
195
|
+
# * If number of dice are specified in the method name, that value is used
|
|
196
|
+
# * If number of dice are not specified and ADV or DIS match, the number is set to 2
|
|
197
|
+
# * If number of dice are not specified and no ADV or DIS match, the number is set to 1
|
|
198
|
+
def get_number_of_dice_from_method_name(method_name)
|
|
199
|
+
match_data = method_name.to_s.match(/_\d+d/)
|
|
200
|
+
default = method_name.to_s.match?(/_d\d+((#{ADV}|#{DIS})\d*)/o) ? 2 : 1
|
|
201
|
+
match_data ? match_data.to_s[1...-1].to_i : default
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# parses out the modifier from the method name
|
|
205
|
+
# * Input must be a valid MatchData object matching the MOD regular expression
|
|
206
|
+
# * Does not handle nil
|
|
207
|
+
# * Only called from get_modifier_from_method_name!
|
|
208
|
+
def get_modifier_from_match_data(match_data)
|
|
209
|
+
if match_data.to_s.match?(/_p(lus)?\d+/)
|
|
210
|
+
match_data.to_s.match(/_p(lus)?\d+/).to_s.match(/\d+/).to_s.to_i
|
|
211
|
+
else
|
|
212
|
+
match_data.to_s.match(/_m(inus)?\d+/).to_s.match(/\d+/).to_s.to_i * -1
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Parses the method name to determine if the modifier pattern is present
|
|
217
|
+
# * Returns nil if method name does not match pattern
|
|
218
|
+
# * Calls get_modifier_from_match_data to get the Integer value of the modifier
|
|
219
|
+
# * Calls check_bonus_integrity! to ensure that the parsed modifier matches the
|
|
220
|
+
# keyword argument if present (which will raise an error if they don't match)
|
|
221
|
+
# * Returns the Integer value of the modifier
|
|
222
|
+
def get_modifier_from_method_name!(method_name, kwargs)
|
|
223
|
+
match_data = method_name.to_s.match(MOD)
|
|
224
|
+
|
|
225
|
+
return nil unless match_data
|
|
226
|
+
|
|
227
|
+
modifier = get_modifier_from_match_data(match_data)
|
|
228
|
+
|
|
229
|
+
# will raise error if mismatch
|
|
230
|
+
check_bonus_integrity!(kwargs, modifier)
|
|
231
|
+
modifier
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# Determines whether the highest/lowest/with_advantage/with_disadvantage pattern is present in the
|
|
235
|
+
# method name and takes appropriate action
|
|
236
|
+
# * Returns nil if no match
|
|
237
|
+
# * Returns Integer value of number to keep otherwise (irrespective of highest/lowest)
|
|
238
|
+
# * Takes the number to keep from the method name if specified
|
|
239
|
+
# * Returns 1 if number to keep not specified and number of dice equals 1
|
|
240
|
+
# * Returns number_of_dice -1 if number to keep not specified and more than one die
|
|
241
|
+
def get_number_to_keep_from_method_name(method_name, number_of_dice)
|
|
242
|
+
return nil unless method_name.to_s.match?(/(#{ADV}|#{DIS})/o)
|
|
243
|
+
|
|
244
|
+
specified_number = method_name.to_s.match(/(#{ADV}|#{DIS})\d+/o)
|
|
245
|
+
|
|
246
|
+
# set the default to 1 if only one die or number minus 1 if multiple
|
|
247
|
+
default = number_of_dice == 1 ? 1 : number_of_dice - 1
|
|
248
|
+
|
|
249
|
+
# return pattern match if one exists or number of dice -1 if no pattern match
|
|
250
|
+
specified_number ? specified_number.to_s.match(/\d+/).to_s.to_i : default
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Checks that there is not a mismatch between the modifier specified in the method name and the
|
|
254
|
+
# modifier specified in the keyword arguments if one is specified
|
|
255
|
+
# * Raises a NerdDice::Error if there is a mismatch
|
|
256
|
+
# * Returns true if no keyword argument bonus
|
|
257
|
+
# * Returns true if keyword argument bonus and method name modifier are consistent
|
|
258
|
+
def check_bonus_integrity!(kwargs, bonus)
|
|
259
|
+
bonus_error_message = "Bonus integrity failure: "
|
|
260
|
+
bonus_error_message += "Modifier specified in keyword arguments was #{kwargs[:bonus]}. "
|
|
261
|
+
bonus_error_message += "Modifier specified in method_name was #{bonus}. "
|
|
262
|
+
raise NerdDice::Error, bonus_error_message if kwargs && kwargs[:bonus] && kwargs[:bonus].to_i != bonus
|
|
263
|
+
|
|
264
|
+
true
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
# Parses number to keep on a NerdDice::DiceSet
|
|
268
|
+
# * If number_to_keep falsey, just return the DiceSet object
|
|
269
|
+
# * If number_to_keep matches ADV pattern return DiceSet with highest called
|
|
270
|
+
# * If number_to_keep matches DIS pattern return DiceSet with lowest called
|
|
271
|
+
def parse_number_to_keep(dice, method_name, number_to_keep)
|
|
272
|
+
return dice unless number_to_keep
|
|
273
|
+
|
|
274
|
+
# use match against ADV to determine truth value of ternary expression
|
|
275
|
+
match_data = method_name.to_s.match(ADV)
|
|
276
|
+
match_data ? dice.highest(number_to_keep) : dice.lowest(number_to_keep)
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|
data/lib/nerd_dice/version.rb
CHANGED
data/lib/nerd_dice.rb
CHANGED
|
@@ -7,6 +7,7 @@ require "nerd_dice/die"
|
|
|
7
7
|
require "nerd_dice/dice_set"
|
|
8
8
|
require "nerd_dice/class_methods"
|
|
9
9
|
require "securerandom"
|
|
10
|
+
require "nerd_dice/convenience_methods"
|
|
10
11
|
# Nerd dice allows you to roll polyhedral dice and add bonuses as you would in
|
|
11
12
|
# a tabletop roleplaying game. You can choose to roll multiple dice and keep a
|
|
12
13
|
# specified number of dice such as rolling 4d6 and dropping the lowest for
|
|
@@ -23,4 +24,6 @@ module NerdDice
|
|
|
23
24
|
RANDOMIZATION_TECHNIQUES = %i[securerandom random_rand random_object randomized].freeze
|
|
24
25
|
ABILITY_SCORE_KEYS = %i[ability_score_array_size ability_score_number_of_sides ability_score_dice_rolled
|
|
25
26
|
ability_score_dice_kept].freeze
|
|
27
|
+
|
|
28
|
+
extend ConvenienceMethods
|
|
26
29
|
end
|
data/nerd_dice.gemspec
CHANGED
|
@@ -43,13 +43,13 @@ Gem::Specification.new do |spec|
|
|
|
43
43
|
spec.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $PROGRAM_NAME.end_with?("gem")
|
|
44
44
|
|
|
45
45
|
# Dependencies
|
|
46
|
-
spec.add_dependency "securerandom", "~> 0.1", ">= 0.1.
|
|
46
|
+
spec.add_dependency "securerandom", "~> 0.1", ">= 0.1.1"
|
|
47
47
|
|
|
48
48
|
# Development Dependencies
|
|
49
|
-
spec.add_development_dependency "coveralls_reborn", "~> 0.
|
|
50
|
-
spec.add_development_dependency "rubocop", "~> 1.
|
|
49
|
+
spec.add_development_dependency "coveralls_reborn", "~> 0.23.0"
|
|
50
|
+
spec.add_development_dependency "rubocop", "~> 1.22", ">= 1.22.2"
|
|
51
51
|
spec.add_development_dependency "rubocop-performance", "~> 1.11", ">= 1.11.5"
|
|
52
52
|
spec.add_development_dependency "rubocop-rake", "~> 0.6", ">= 0.6.0"
|
|
53
|
-
spec.add_development_dependency "rubocop-rspec", "~> 2.
|
|
53
|
+
spec.add_development_dependency "rubocop-rspec", "~> 2.5", ">= 2.5.0"
|
|
54
54
|
spec.add_development_dependency "simplecov-lcov", "~> 0.8.0"
|
|
55
55
|
end
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: nerd_dice
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Michael Duchemin
|
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
|
35
35
|
WQ4faXJSevxT+x9TgyUNJINPkz/KqreClzdL83cwxPzFFQto7zF6zMCsj0slqJjW
|
|
36
36
|
EQ==
|
|
37
37
|
-----END CERTIFICATE-----
|
|
38
|
-
date: 2021-
|
|
38
|
+
date: 2021-10-23 00:00:00.000000000 Z
|
|
39
39
|
dependencies:
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: securerandom
|
|
@@ -46,7 +46,7 @@ dependencies:
|
|
|
46
46
|
version: '0.1'
|
|
47
47
|
- - ">="
|
|
48
48
|
- !ruby/object:Gem::Version
|
|
49
|
-
version: 0.1.
|
|
49
|
+
version: 0.1.1
|
|
50
50
|
type: :runtime
|
|
51
51
|
prerelease: false
|
|
52
52
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -56,41 +56,41 @@ dependencies:
|
|
|
56
56
|
version: '0.1'
|
|
57
57
|
- - ">="
|
|
58
58
|
- !ruby/object:Gem::Version
|
|
59
|
-
version: 0.1.
|
|
59
|
+
version: 0.1.1
|
|
60
60
|
- !ruby/object:Gem::Dependency
|
|
61
61
|
name: coveralls_reborn
|
|
62
62
|
requirement: !ruby/object:Gem::Requirement
|
|
63
63
|
requirements:
|
|
64
64
|
- - "~>"
|
|
65
65
|
- !ruby/object:Gem::Version
|
|
66
|
-
version: 0.
|
|
66
|
+
version: 0.23.0
|
|
67
67
|
type: :development
|
|
68
68
|
prerelease: false
|
|
69
69
|
version_requirements: !ruby/object:Gem::Requirement
|
|
70
70
|
requirements:
|
|
71
71
|
- - "~>"
|
|
72
72
|
- !ruby/object:Gem::Version
|
|
73
|
-
version: 0.
|
|
73
|
+
version: 0.23.0
|
|
74
74
|
- !ruby/object:Gem::Dependency
|
|
75
75
|
name: rubocop
|
|
76
76
|
requirement: !ruby/object:Gem::Requirement
|
|
77
77
|
requirements:
|
|
78
78
|
- - "~>"
|
|
79
79
|
- !ruby/object:Gem::Version
|
|
80
|
-
version: '1.
|
|
80
|
+
version: '1.22'
|
|
81
81
|
- - ">="
|
|
82
82
|
- !ruby/object:Gem::Version
|
|
83
|
-
version: 1.
|
|
83
|
+
version: 1.22.2
|
|
84
84
|
type: :development
|
|
85
85
|
prerelease: false
|
|
86
86
|
version_requirements: !ruby/object:Gem::Requirement
|
|
87
87
|
requirements:
|
|
88
88
|
- - "~>"
|
|
89
89
|
- !ruby/object:Gem::Version
|
|
90
|
-
version: '1.
|
|
90
|
+
version: '1.22'
|
|
91
91
|
- - ">="
|
|
92
92
|
- !ruby/object:Gem::Version
|
|
93
|
-
version: 1.
|
|
93
|
+
version: 1.22.2
|
|
94
94
|
- !ruby/object:Gem::Dependency
|
|
95
95
|
name: rubocop-performance
|
|
96
96
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -137,20 +137,20 @@ dependencies:
|
|
|
137
137
|
requirements:
|
|
138
138
|
- - "~>"
|
|
139
139
|
- !ruby/object:Gem::Version
|
|
140
|
-
version: '2.
|
|
140
|
+
version: '2.5'
|
|
141
141
|
- - ">="
|
|
142
142
|
- !ruby/object:Gem::Version
|
|
143
|
-
version: 2.
|
|
143
|
+
version: 2.5.0
|
|
144
144
|
type: :development
|
|
145
145
|
prerelease: false
|
|
146
146
|
version_requirements: !ruby/object:Gem::Requirement
|
|
147
147
|
requirements:
|
|
148
148
|
- - "~>"
|
|
149
149
|
- !ruby/object:Gem::Version
|
|
150
|
-
version: '2.
|
|
150
|
+
version: '2.5'
|
|
151
151
|
- - ">="
|
|
152
152
|
- !ruby/object:Gem::Version
|
|
153
|
-
version: 2.
|
|
153
|
+
version: 2.5.0
|
|
154
154
|
- !ruby/object:Gem::Dependency
|
|
155
155
|
name: simplecov-lcov
|
|
156
156
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -204,6 +204,8 @@ files:
|
|
|
204
204
|
- checksum/nerd_dice-0.1.1.gem.sha512
|
|
205
205
|
- checksum/nerd_dice-0.2.0.gem.sha256
|
|
206
206
|
- checksum/nerd_dice-0.2.0.gem.sha512
|
|
207
|
+
- checksum/nerd_dice-0.3.0.gem.sha256
|
|
208
|
+
- checksum/nerd_dice-0.3.0.gem.sha512
|
|
207
209
|
- lib/nerd_dice.rb
|
|
208
210
|
- lib/nerd_dice/class_methods.rb
|
|
209
211
|
- lib/nerd_dice/class_methods/configure.rb
|
|
@@ -215,6 +217,7 @@ files:
|
|
|
215
217
|
- lib/nerd_dice/class_methods/total_ability_scores.rb
|
|
216
218
|
- lib/nerd_dice/class_methods/total_dice.rb
|
|
217
219
|
- lib/nerd_dice/configuration.rb
|
|
220
|
+
- lib/nerd_dice/convenience_methods.rb
|
|
218
221
|
- lib/nerd_dice/dice_set.rb
|
|
219
222
|
- lib/nerd_dice/die.rb
|
|
220
223
|
- lib/nerd_dice/sets_randomization_technique.rb
|
metadata.gz.sig
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
�-�w�r���[�5�7��,�4���_��}�SJ:
|
|
1
|
+
����vܕu&��rXsϴ����j]4_�|F���k��Ū�eQl��?n�WC.,E(��;�B�/�(%َWۊ��#sՉ� �~ګj0U6H����M9��b/�ơ�H���|
|
|
2
|
+
N&Y{�2p�M��4Mյ��V��M!a�Ӛ��9($���!y^bTq�ה��GZ�;������c-�a)����e4��.������a�gr=0�a�͖=�
|