nerd_dice 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a931b4532dcafcb4ce3aeddf3ac30399bb9334d25bf78671a0811366670d719
4
- data.tar.gz: 970d96a32b68dc1fc75618376bf059707c5c711441d30edd6302dcd37e831c8b
3
+ metadata.gz: fa0fb8eebb2386727cce81ce7a3c301599322a3531db13f01329aa26225c88b3
4
+ data.tar.gz: 205640e5b275ae107e0c2ee0ff1c10b777782f21c7a3c0ae7a5aac98e27f4841
5
5
  SHA512:
6
- metadata.gz: 5cdbd36e786d2c4e6f8950f4486119548bb1a62babdbf3c9ae4fadba095170b9300461411926d19ca50e5e8d277804c3f8cb61e28d96605fd5fad8b7e9c9b700
7
- data.tar.gz: 21b2b92dbf7ad4060a888d267383e9c87b3e310dff4931bb1853f401fb417f480a2bea7cca859ad75d3eac83608a4631541a36afc7449955a68ea8ff84c319c7
6
+ metadata.gz: 0d275950feb1506a5a7602450690dab697c0ccd35b8d85a0869c4675c2dd714c85d2c744854ac7f69c7f204b1e55ecbf7e80f9209eb672ef4705d15fdbd10fd7
7
+ data.tar.gz: fb8d5aa2297ecbf722b9242caf2680272a502d801dbd94fd53c6bd359a21a50e6e0e1096a5c5518a25a9ef842609c6db0af7c6b5273f4a1fd2e4f2f6089d393e
checksums.yaml.gz.sig CHANGED
Binary file
@@ -0,0 +1,67 @@
1
+ # This is a basic workflow to help you get started with Actions
2
+
3
+ name: Nerd Dice CI
4
+
5
+ # Controls when the action will run.
6
+ on: [push, pull_request]
7
+
8
+ # Allows you to run this workflow manually from the Actions tab
9
+ # workflow_dispatch:
10
+
11
+ jobs:
12
+ test_rspec:
13
+
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ matrix:
17
+ ruby-version: ['2.7', '3.0']
18
+
19
+ steps:
20
+ - uses: actions/checkout@v2
21
+ - name: Set up Ruby
22
+ uses: ruby/setup-ruby@v1
23
+ with:
24
+ ruby-version: ${{ matrix.ruby-version }}
25
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
26
+ - name: Run tests
27
+ run: bundle exec rake
28
+ - name: Coveralls Parallel
29
+ uses: coverallsapp/github-action@master
30
+ with:
31
+ github-token: ${{ secrets.github_token }}
32
+ flag-name: run-${{ matrix.test_number }}
33
+ parallel: true
34
+
35
+ rubocop:
36
+ runs-on: ubuntu-latest
37
+ steps:
38
+ - uses: actions/checkout@v2
39
+ - name: Set up Ruby
40
+ uses: ruby/setup-ruby@v1
41
+ with:
42
+ ruby-version: '3.0'
43
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
44
+ - name: Run rubocop
45
+ run: bundle exec rubocop --parallel
46
+
47
+ benchmark:
48
+ runs-on: ubuntu-latest
49
+ steps:
50
+ - uses: actions/checkout@v2
51
+ - name: Set up Ruby
52
+ uses: ruby/setup-ruby@v1
53
+ with:
54
+ ruby-version: '3.0'
55
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
56
+ - name: Run benchmark script
57
+ run: bin/nerd_dice_benchmark
58
+
59
+ finish:
60
+ needs: test_rspec
61
+ runs-on: ubuntu-latest
62
+ steps:
63
+ - name: Coveralls Finished
64
+ uses: coverallsapp/github-action@master
65
+ with:
66
+ github-token: ${{ secrets.github_token }}
67
+ parallel-finished: true
data/.rubocop.yml CHANGED
@@ -334,3 +334,69 @@ Style/EndlessMethod: # (new in 1.8)
334
334
 
335
335
  Style/HashExcept: # (new in 1.7)
336
336
  Enabled: true
337
+
338
+ # Added 2021-08-14
339
+ Gemspec/DateAssignment: # (new in 1.10)
340
+ Enabled: true
341
+
342
+ Layout/LineEndStringConcatenationIndentation: # (new in 1.18)
343
+ Enabled: true
344
+
345
+ Lint/EmptyInPattern: # (new in 1.16)
346
+ Enabled: true
347
+
348
+ Lint/NumberedParameterAssignment: # (new in 1.9)
349
+ Enabled: true
350
+
351
+ Lint/OrAssignmentToConstant: # (new in 1.9)
352
+ Enabled: true
353
+
354
+ Lint/SymbolConversion: # (new in 1.9)
355
+ Enabled: true
356
+
357
+ Lint/TripleQuotes: # (new in 1.9)
358
+ Enabled: true
359
+
360
+ Naming/InclusiveLanguage: # (new in 1.18)
361
+ Enabled: false
362
+
363
+ Style/HashConversion: # (new in 1.10)
364
+ Enabled: true
365
+
366
+ Style/IfWithBooleanLiteralBranches: # (new in 1.9)
367
+ Enabled: true
368
+
369
+ Style/InPatternThen: # (new in 1.16)
370
+ Enabled: true
371
+
372
+ Style/MultilineInPatternThen: # (new in 1.16)
373
+ Enabled: true
374
+
375
+ Style/QuotedSymbols: # (new in 1.16)
376
+ Enabled: true
377
+
378
+ Style/StringChars: # (new in 1.12)
379
+ Enabled: true
380
+
381
+ Performance/MapCompact: # (new in 1.11)
382
+ Enabled: true
383
+
384
+ Performance/RedundantEqualityComparisonBlock: # (new in 1.10)
385
+ Enabled: true
386
+
387
+ Performance/RedundantSplitRegexpArgument: # (new in 1.10)
388
+ Enabled: true
389
+
390
+ RSpec/IdenticalEqualityAssertion: # (new in 2.4)
391
+ Enabled: true
392
+
393
+ RSpec/Rails/AvoidSetupHook: # (new in 2.4)
394
+ Enabled: true
395
+
396
+ RSpec/MessageSpies:
397
+ EnforcedStyle: receive
398
+
399
+ Lint/AmbiguousRange: # new in 1.19
400
+ Enabled: true
401
+ Style/RedundantSelfAssignmentBranch: # new in 1.19
402
+ Enabled: true
data/CHANGELOG.md CHANGED
@@ -5,7 +5,35 @@
5
5
  ### Changed
6
6
  ### Fixed
7
7
 
8
- ## 0.2.0 \(2020-12-12\)
8
+ ## 0.3.0 \(2021-09-11\)
9
+ ### Added
10
+ * Add new options to `NerdDice::Configuration`
11
+ - `ability_score_number_of_sides`
12
+ - `ability_score_dice_rolled`
13
+ - `ability_score_dice_kept`
14
+ * Add `NerdDice.harvest_totals` method that takes in a collection and returns the results of calling `total` on each element
15
+ * Add `NerdDice.roll_ability_scores` convenience method that returns an array of `DiceSet` objects based on options and/or configuration
16
+ * Add `NerdDice.total_ability_scores` convenience method that returns an array of integers based on options and/or configuration
17
+ * Add `NerdDice::Die` class that represents a single die object and mixes in the `Comparable` module
18
+ * Add `NerdDice::DiceSet` class that represents a collection of `Die` objects and mixes in the `Enumerable` module
19
+ * Add `NerdDice::SetsRandomizationTechnique` mixin module and include in the `DiceSet` and `Die` classes
20
+ * Add `die_background_color` and `die_foreground_color` to `Configuration` class with defaults defined as constants
21
+ * Add `NerdDice.roll_dice` method that behaves in a similar fashion to `total_dice` but returns a `DiceSet` object instead of an `Integer` and has additional optional arguments relating to the non-numeric attributes of the dice
22
+ * Add `coveralls_reborn` to RSpec and GitHub actions
23
+ * Add build badge to README
24
+ * Add Code Climate maintainability integration and badge to README
25
+ * Add `nerd_dice_benchmark` script to bin directory
26
+ * Add GitHub Action CI build
27
+ - Run RSpec test suite, fail if specs fail, report coverage via Coveralls
28
+ - Run RuboCop and fail if violations
29
+ - Run benchmark suite and fail if outside of allowed ratios
30
+ ### Changed
31
+ * Update RuboCop version and configuration
32
+ * Break up the NerdDice source code file into several smaller files that are included by the module
33
+ * Enforce that `NerdDice.configuration.ability_score_array_size` must be a positive duck-type integer
34
+ ### Fixed
35
+
36
+ ## 0.2.0 \(2021-01-28\)
9
37
  ### Added
10
38
  * Add ability to configure with `NerdDice.configure` block or `NerdDice.configuration`
11
39
  - Configure `randomization_technique` as `:random_rand`, `:securerandom`, `:random_object`, or `randomized`
data/Gemfile.lock CHANGED
@@ -1,21 +1,27 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nerd_dice (0.2.0)
4
+ nerd_dice (0.3.0)
5
5
  securerandom (~> 0.1, >= 0.1.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
10
  ast (2.4.2)
11
+ coveralls_reborn (0.22.0)
12
+ simplecov (>= 0.18.1, < 0.22.0)
13
+ term-ansicolor (~> 1.6)
14
+ thor (>= 0.20.3, < 2.0)
15
+ tins (~> 1.16)
11
16
  diff-lcs (1.4.4)
17
+ docile (1.4.0)
12
18
  parallel (1.20.1)
13
- parser (3.0.0.0)
19
+ parser (3.0.2.0)
14
20
  ast (~> 2.4.1)
15
21
  rainbow (3.0.0)
16
22
  rake (12.3.3)
17
- regexp_parser (2.0.3)
18
- rexml (3.2.4)
23
+ regexp_parser (2.1.1)
24
+ rexml (3.2.5)
19
25
  rspec (3.10.0)
20
26
  rspec-core (~> 3.10.0)
21
27
  rspec-expectations (~> 3.10.0)
@@ -25,44 +31,59 @@ GEM
25
31
  rspec-expectations (3.10.1)
26
32
  diff-lcs (>= 1.2.0, < 2.0)
27
33
  rspec-support (~> 3.10.0)
28
- rspec-mocks (3.10.1)
34
+ rspec-mocks (3.10.2)
29
35
  diff-lcs (>= 1.2.0, < 2.0)
30
36
  rspec-support (~> 3.10.0)
31
- rspec-support (3.10.1)
32
- rubocop (1.8.1)
37
+ rspec-support (3.10.2)
38
+ rubocop (1.20.0)
33
39
  parallel (~> 1.10)
34
40
  parser (>= 3.0.0.0)
35
41
  rainbow (>= 2.2.2, < 4.0)
36
42
  regexp_parser (>= 1.8, < 3.0)
37
43
  rexml
38
- rubocop-ast (>= 1.2.0, < 2.0)
44
+ rubocop-ast (>= 1.9.1, < 2.0)
39
45
  ruby-progressbar (~> 1.7)
40
46
  unicode-display_width (>= 1.4.0, < 3.0)
41
- rubocop-ast (1.4.1)
42
- parser (>= 2.7.1.5)
43
- rubocop-performance (1.9.2)
44
- rubocop (>= 0.90.0, < 2.0)
47
+ rubocop-ast (1.11.0)
48
+ parser (>= 3.0.1.1)
49
+ rubocop-performance (1.11.5)
50
+ rubocop (>= 1.7.0, < 2.0)
45
51
  rubocop-ast (>= 0.4.0)
46
- rubocop-rake (0.5.1)
47
- rubocop
48
- rubocop-rspec (2.1.0)
52
+ rubocop-rake (0.6.0)
53
+ rubocop (~> 1.0)
54
+ rubocop-rspec (2.4.0)
49
55
  rubocop (~> 1.0)
50
56
  rubocop-ast (>= 1.1.0)
51
57
  ruby-progressbar (1.11.0)
52
58
  securerandom (0.1.0)
59
+ simplecov (0.21.2)
60
+ docile (~> 1.1)
61
+ simplecov-html (~> 0.11)
62
+ simplecov_json_formatter (~> 0.1)
63
+ simplecov-html (0.12.3)
64
+ simplecov-lcov (0.8.0)
65
+ simplecov_json_formatter (0.1.3)
66
+ sync (0.5.0)
67
+ term-ansicolor (1.7.1)
68
+ tins (~> 1.0)
69
+ thor (1.1.0)
70
+ tins (1.29.1)
71
+ sync
53
72
  unicode-display_width (2.0.0)
54
73
 
55
74
  PLATFORMS
56
75
  ruby
57
76
 
58
77
  DEPENDENCIES
78
+ coveralls_reborn (~> 0.22.0)
59
79
  nerd_dice!
60
80
  rake (~> 12.0)
61
81
  rspec (~> 3.0)
62
- rubocop (~> 1.8, >= 1.8.1)
63
- rubocop-performance (~> 1.9, >= 1.9.1)
64
- rubocop-rake (~> 0.5, >= 0.5.1)
65
- rubocop-rspec (~> 2.1, >= 2.1.0)
82
+ rubocop (~> 1.20, >= 1.20.0)
83
+ rubocop-performance (~> 1.11, >= 1.11.5)
84
+ rubocop-rake (~> 0.6, >= 0.6.0)
85
+ rubocop-rspec (~> 2.4, >= 2.4.0)
86
+ simplecov-lcov (~> 0.8.0)
66
87
 
67
88
  BUNDLED WITH
68
- 2.2.3
89
+ 2.2.22
data/README.md CHANGED
@@ -1,6 +1,12 @@
1
+ [![Coverage Status](https://coveralls.io/repos/github/statelesscode/nerd_dice/badge.svg?branch=master)](https://coveralls.io/github/statelesscode/nerd_dice?branch=master)
2
+ ![Build](https://github.com/statelesscode/nerd_dice/actions/workflows/main.yml/badge.svg)
3
+ [![Maintainability](https://api.codeclimate.com/v1/badges/721f587b792d583065be/maintainability)](https://codeclimate.com/github/statelesscode/nerd_dice/maintainability)
1
4
  # NerdDice
2
5
  Nerd dice allows you to roll polyhedral dice and add bonuses as you would in a tabletop roleplaying game. You can choose to roll multiple dice and keep a specified number of dice such as rolling 4d6 and dropping the lowest for ability scores or rolling with advantage and disadvantage if those mechanics exist in your game.
3
6
 
7
+ ## Educational Videos By Stateless Code
8
+ The end-to-end process of developing this gem has been captured as [instructional videos](https://www.youtube.com/playlist?list=PL9kkbu1kLUeOnUtMpAnJOCtHdThx1Efkt). The videos are in a one-take style so that the mistakes along the way have troubleshooting and the concepts used to develop the gem are explained as they are covered.
9
+
4
10
  ## Installation
5
11
 
6
12
  Add this line to your application's Gemfile:
@@ -25,7 +31,17 @@ You can customize the behavior of NerdDice via a configuration block as below or
25
31
  NerdDice.configure do | config|
26
32
 
27
33
  # number of ability scores to place in an ability score array
28
- config.ability_score_array_size = 6
34
+ config.ability_score_array_size = 6 # must duck-type to positive Integer
35
+
36
+ # number of sides for each ability score Die
37
+ config.ability_score_number_of_sides = 6 # must duck-type to positive Integer
38
+
39
+ # total number of dice rolled for each ability score
40
+ config.ability_score_dice_rolled = 4 # must duck-type to positive Integer
41
+
42
+ # highest(n) dice from the total number of dice rolled that are included in the ability score total
43
+ # CANNOT EXCEED ability_score_dice_rolled see Note below
44
+ config.ability_score_dice_kept = 3 # must duck-type to positive Integer
29
45
 
30
46
  # randomization technique options are:
31
47
  # :securerandom => Uses SecureRandom.rand(). Good entropy, medium speed.
@@ -40,26 +56,167 @@ NerdDice.configure do | config|
40
56
  # 1 very slow and heavy pressure on processor and memory but very high entropy
41
57
  # 1000 would refresh the object every 1000 times you call rand()
42
58
  config.refresh_seed_interval = nil # don't refresh the seed
59
+ # Background and foreground die colors are string values. By default these correspond to the constants in the class
60
+ # Defaults: DEFAULT_BACKGROUND_COLOR = "#0000DD" DEFAULT_FOREGROUND_COLOR = "#DDDDDD"
61
+ # It is recommended but not enforced that these should be valid CSS color property attributes
62
+ config.die_background_color = "red"
63
+ config.die_foreground_color = "#000"
43
64
  end
44
65
  ```
66
+ **Note:** You cannot set `ability_score_dice_kept` greater than `ability_score_dice_rolled`. If you try to set `ability_score_dice_kept` higher than `ability_score_dice_rolled`, an error will be raised. If you set `ability_score_dice_rolled` _lower_ than the existing value of `ability_score_dice_kept`, no error will be thrown, but `ability_score_dice_kept` will be _**modified**_ to match `ability_score_dice_rolled` and a warning will be printed.
45
67
 
46
68
  ### Rolling a number of dice and adding a bonus
69
+ You can use two different methods to roll dice. The `total_dice` method returns an `Integer` representing the total of the dice plus any applicable bonuses. The `total_dice` method does not support chaining additional methods like `highest`, `lowest`, `with_advantage`, `with_disadvantage`. The `roll_dice` method returns a `DiceSet` collection object, and allows for chaining the methods mentioned above and iterating over the individual `Die` objects. `NerdDice.roll_dice.total` and `NerdDice.total_dice` are roughly equivalent.
70
+
47
71
  ```ruby
48
72
  # roll a single d4
49
73
  NerdDice.total_dice(4) # => return random Integer between 1-4
74
+ NerdDice.roll_dice(4) # => return a DiceSet with one 4-sided Die with a value between 1-4
75
+ NerdDice.roll_dice(4).total # => return random Integer between 1-4
50
76
 
51
77
  # roll 3d6
52
78
  NerdDice.total_dice(6, 3) # => return Integer total of three 6-sided dice
79
+ NerdDice.roll_dice(6, 3) # => return a DiceSet with three 6-sided Die objects, each with values between 1-6
80
+ NerdDice.roll_dice(6, 3).total # => return Integer total of three 6-sided dice
53
81
 
54
82
  # roll a d20 and add 5 to the value
55
- NerdDice.total_dice(20, bonus: 5)
83
+ NerdDice.total_dice(20, bonus: 5) # rolls a d20 and adds the bonus to the total => Integer
84
+ NerdDice.roll_dice(20, bonus: 5) # return a DiceSet with one 20-sided Die with a value between 1-20 and a bonus attribute of 5
85
+ NerdDice.roll_dice(20, bonus: 5).total # rolls a d20 and adds the bonus to the total => Integer
56
86
 
87
+ # without changing the config at the module level
57
88
  # roll a d20 and overide the configured randomization_technique one time
58
- # without changing the config
59
- NerdDice.total_dice(20, randomization_technique: :randomized)
89
+ NerdDice.total_dice(20, randomization_technique: :randomized) # => Integer
90
+ # roll a d20 and overide the configured randomization_technique for the DiceSet object will persist on the DiceSet object for subsequent rerolls
91
+ NerdDice.roll_dice(20, randomization_technique: :randomized) # => DiceSet with randomization_technique: :randomized
60
92
  ```
61
93
  __NOTE:__ If provided, the bonus must respond to `:to_i` or an `ArgumentError` will be raised
62
94
 
95
+ ### Taking actions on the dice as objects using the DiceSet object
96
+ 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
+
98
+ ```ruby
99
+ # These are equivalent
100
+ dice_set = NerdDice.roll_dice(6, 3, bonus: 2, randomization_technique: :randomized, damage_type: 'psychic', foreground_color: '#FFF', background_color: '#0FF')
101
+ # => NerdDice::DiceSet
102
+ dice_set = NerdDice::DiceSet.new(6, 3, bonus: 2, randomization_technique: :randomized, damage_type: 'psychic', foreground_color: '#FFF', background_color: '#0FF')
103
+ # => NerdDice::DiceSet
104
+ ```
105
+ #### Available options for NerdDice::DiceSet objects
106
+ 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
+ * `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_
112
+
113
+ #### Properties of individual Die objects
114
+ 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
+
116
+ ```ruby
117
+ # six sided die
118
+ die = NerdDice::Die.new(6, randomization_technique: :randomized, damage_type: 'psychic', foreground_color: '#FFF', background_color: '#0FF')
119
+ die.is_included_in_total # => true
120
+ die.included_in_total? # => true
121
+ die.is_included_in_total = false
122
+ die.included_in_total? # => false
123
+
124
+ # value property
125
+ die.value # => Integer between 1 and number_of_sides
126
+ die.roll # => Integer. Rolls/rerolls the Die and sets value to the result of the roll. Returns the new value
127
+ ```
128
+ #### Iterating through dices in a DiceSet
129
+ 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
+
131
+ ```ruby
132
+ dice_set = NerdDice.roll_dice(6, 3) # => NerdDice::DiceSet
133
+ dice_set.dice => Array of Die objects
134
+ dice_set.length # => 3. (dice_set.dice.length)
135
+ dice_set[0] # => NerdDice::Die (first element of dice array)
136
+ # take actions on each die
137
+ dice_set.each do |die|
138
+ # print the current value
139
+ puts "Die value before reroll is #{die.value}"
140
+ # set the foreground_color of the die
141
+ die.foreground_color = ["gray", "#FF0000#", "#d9d9d9", "green"].shuffle.first
142
+ # reroll the die
143
+ die.roll
144
+ # print the new value
145
+ puts "Die value after reroll is #{die.value}"
146
+ # do other things
147
+ end
148
+ ```
149
+ #### Methods and method chaining on the DiceSet
150
+ Since the DiceSet is an object, you can call methods that operate on the result returned and allow for things like the 5e advantage/disadvantage mechanic, the ability to re-roll all of the dice in the `DiceSet`, or to mark them all as included in the total.
151
+
152
+ ```ruby
153
+ ##############################################
154
+ # highest/with_advantage and lowest/with_disadvantage methods
155
+ # assuming 4d6 with values of [1, 3, 4, 6]
156
+ ##############################################
157
+ dice_set = NerdDice.roll_dice(6, 4)
158
+ # the 6, 4, and 3 will have is_included_in_total true while the 1 has it false
159
+ dice_set.highest(3) # => Returns the existing DiceSet object with the changes made to dice inclusion
160
+ dice_set.with_advantage(3) # => Alias of highest method
161
+ # calling total after highest/with_advantage for this DiceSet
162
+ dice_set.total # => 13
163
+ # same DiceSet using lowest. The 1, 3, and 4 will have is_included_in_total true while the 6 has it false
164
+ dice_set.lowest(3) # => Returns the existing DiceSet object with the changes made to dice inclusion
165
+ dice_set.with_disadvantage(3) # => Alias of lowest method
166
+ # calling total after lowest/with_disadvantage for this DiceSet
167
+ dice_set.total # => 8
168
+ # you can chain these methods (assumes the same seed as the above examples)
169
+ NerdDice.roll_dice(6, 4).with_advantage(3).total # => 13
170
+ NerdDice.roll_dice(6, 4).lowest(3).total # => 8
171
+
172
+ # reroll_all! method
173
+ dice_set = NerdDice.roll_dice(6, 4)
174
+ dice_set.reroll_all! # rerolls each of the Die objects in the collection and re-includes them in the total
175
+
176
+ # include_all_dice! method
177
+ dice_set.include_all_dice! # resets is_included_in_total to true for all Die objects
178
+ ```
179
+
180
+ ### Rolling Ability Scores
181
+ You can call `roll_ability_scores` or `total_ability_scores` to get back an array of `DiceSet` objects or `Integer` objects, respectively. The `total_ability_scores` method calls `total` on each `DiceSet` and returns those numbers with one value per ability score. The `Configuration` object defaults to 6 ability scores using a methodology of __4d6 drop the lowest__ by default.
182
+
183
+ ```ruby
184
+ # return an array of DiceSet objects including info about the discarded dice
185
+ #
186
+ NerdDice.roll_ability_scores
187
+ #=> [DiceSet0, DiceSet1, ...]
188
+ # => DiceSet0 hash representation { total: 12, dice: [
189
+ # {value: 2, is_included_in_total: true},
190
+ # {value: 6, is_included_in_total: true},
191
+ # {value: 4, is_included_in_total: true},
192
+ # {value: 1, is_included_in_total: false}
193
+ # ]}
194
+ # if you want to get back DiceSet objects that you can interact with
195
+
196
+ # just return an array of totaled ability scores
197
+ NerdDice.total_ability_scores
198
+ #=> [12, 14, 13, 15, 10, 8]
199
+ ```
200
+
201
+ Both methods can be called without arguments to use the values specified in `NerdDice.configuration` or passed a set of options.
202
+ ```ruby
203
+
204
+ # total_dice and roll_dice take the same set of options
205
+ NerdDice.roll_ability_scores(
206
+ ability_score_array_size: 7,
207
+ ability_score_number_of_sides: 8,
208
+ ability_score_dice_rolled: 5,
209
+ ability_score_dice_kept: 4,
210
+ randomization_technique: :randomized,
211
+ foreground_color: "#FF0000",
212
+ background_color: "#FFFFFF"
213
+ )
214
+ # => [DiceSet0, DiceSet1, ...] with 7 ability scores that each roll 5d8 dropping the lowest
215
+ # or if called with total_ability_scores
216
+ # => [27, 17, 21, 17, 23, 13, 27]
217
+ ```
218
+ **Note:** If you try to call this method with `ability_score_dice_kept` greater than `ability_score_dice_rolled` an error will be raised.
219
+
63
220
  ### Manually setting or refreshing the random generator seed
64
221
  For randomization techniques other than `:securerandom` you can manually set or refresh the generator's seed by calling the `refresh_seed!` method. This is automatically called at the interval specified in `NerdDice.configuration.refresh_seed_interval` if it is not nil.
65
222
 
@@ -77,6 +234,23 @@ NerdDice.refresh_seed!(randomization_technique: :randomized,
77
234
  ```
78
235
  __NOTE:__ Ability to specify a seed it primarily provided for testing purposes. This makes all random numbers generated _transparently deterministic_ and should not be used if you want behavior approximating randomness.
79
236
 
237
+ ### Utility Methods
238
+
239
+ #### Harvesting Totals from DiceSets
240
+ The `harvest_totals` method take any collection of objects where each element responds to `total` and return an array of the results of the total method.
241
+ ```ruby
242
+ ability_score_array = NerdDice.roll_ability_scores
243
+ # => Array of 6 DiceSet objects
244
+
245
+ # Arguments:
246
+ # collection (Enumerable) a collection where each element responds to total
247
+ #
248
+ # Return (Array) => Data type of each element will be whatever is returned by total method
249
+ totals_array = NerdDice.harvest_totals(totals_array)
250
+ # => [15, 14, 13, 12, 10, 8]
251
+ # yes, it just happened to be the standard array by amazing coincidence
252
+ ```
253
+
80
254
  ## Development
81
255
 
82
256
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -90,4 +264,4 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/statel
90
264
 
91
265
  ## Unlicense, License, and Copyright
92
266
 
93
- The document 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 modification in your own project\.
267
+ The document 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\.