games_dice 0.3.12 → 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.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +38 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +53 -0
  5. data/.yardopts +1 -1
  6. data/CHANGELOG.md +18 -0
  7. data/Gemfile +12 -0
  8. data/README.md +11 -33
  9. data/Rakefile +10 -23
  10. data/ext/games_dice/extconf.rb +4 -22
  11. data/ext/games_dice/games_dice.c +1 -1
  12. data/ext/games_dice/probabilities.c +128 -9
  13. data/ext/games_dice/probabilities.h +1 -1
  14. data/games_dice.gemspec +22 -36
  15. data/lib/games_dice/bunch.rb +203 -247
  16. data/lib/games_dice/bunch_helpers.rb +68 -0
  17. data/lib/games_dice/complex_die.rb +151 -270
  18. data/lib/games_dice/complex_die_helpers.rb +260 -60
  19. data/lib/games_dice/constants.rb +10 -10
  20. data/lib/games_dice/dice.rb +153 -143
  21. data/lib/games_dice/die.rb +101 -97
  22. data/lib/games_dice/die_result.rb +206 -189
  23. data/lib/games_dice/map_rule.rb +72 -70
  24. data/lib/games_dice/marshal.rb +41 -13
  25. data/lib/games_dice/parser.rb +245 -218
  26. data/lib/games_dice/reroll_rule.rb +76 -77
  27. data/lib/games_dice/version.rb +4 -1
  28. data/lib/games_dice.rb +23 -25
  29. data/spec/bunch_spec.rb +399 -420
  30. data/spec/complex_die_spec.rb +314 -305
  31. data/spec/dice_spec.rb +33 -34
  32. data/spec/die_result_spec.rb +174 -181
  33. data/spec/die_spec.rb +81 -81
  34. data/spec/helpers.rb +25 -25
  35. data/spec/map_rule_spec.rb +40 -44
  36. data/spec/parser_spec.rb +106 -82
  37. data/spec/probability_spec.rb +522 -526
  38. data/spec/readme_spec.rb +410 -390
  39. data/spec/reroll_rule_spec.rb +40 -44
  40. metadata +17 -129
  41. data/.travis.yml +0 -14
  42. data/lib/games_dice/prob_helpers.rb +0 -259
  43. data/lib/games_dice/probabilities.rb +0 -244
@@ -1,70 +1,72 @@
1
- # This class models rules that convert numbers shown on a die to values used in a game. A
2
- # common use for this is to count "successes" - dice that score a certain number or higher.
3
- #
4
- # An object of the class represents a single rule, such as "count a die result of 5 or more as 1
5
- # _success_".
6
- #
7
- # @example A rule for counting successes
8
- # rule = GamesDice::MapRule.new( 6, :<=, 1, 'Success' )
9
- # # Test how the rule applies . . .
10
- # rule.map_from 4 # => nil
11
- # rule.map_from 6 # => 1
12
- #
13
- # @example A rule for counting "fumbles" which reduce total successes
14
- # rule = GamesDice::MapRule.new( 1, :==, -1, 'Fumble' )
15
- # # Test how the rule applies . . .
16
- # rule.map_from 7 # => nil
17
- # rule.map_from 1 # => -1
18
- #
19
-
20
- class GamesDice::MapRule
21
-
22
- # Creates new instance of GamesDice::MapRule. The rule will be assessed as
23
- # trigger_value.send( trigger_op, x )
24
- # where x is the Integer value shown on a die.
25
- # @param [Integer,Range<Integer>,Object] trigger_value Any object is allowed, but typically an Integer
26
- # @param [Symbol] trigger_op A method of trigger_value that takes an Integer param and returns Boolean
27
- # @param [Integer] mapped_value The value to use in place of the trigger value
28
- # @param [String] mapped_name Name of mapped value, for use in descriptions
29
- # @return [GamesDice::MapRule]
30
- def initialize trigger_value, trigger_op, mapped_value=0, mapped_name=''
31
-
32
- if ! trigger_value.respond_to?( trigger_op )
33
- raise ArgumentError, "trigger_value #{trigger_value.inspect} cannot respond to trigger_op #{trigger_value.inspect}"
34
- end
35
-
36
- @trigger_value = trigger_value
37
- @trigger_op = trigger_op
38
- raise TypeError if ! mapped_value.is_a? Numeric
39
- @mapped_value = Integer(mapped_value)
40
- @mapped_name = mapped_name.to_s
41
- end
42
-
43
- # Trigger operation. How the rule is assessed against #trigger_value.
44
- # @return [Symbol] Method name to be sent to #trigger_value
45
- attr_reader :trigger_op
46
-
47
- # Trigger value. An object that will use #trigger_op to assess a die result for a reroll.
48
- # @return [Integer,Range,Object] Object that receives (#trigger_op, die_result)
49
- attr_reader :trigger_value
50
-
51
- # Value that a die will use after the value has been mapped.
52
- # @return [Integer]
53
- attr_reader :mapped_value
54
-
55
- # Name for mapped value, used in explanations.
56
- # @return [String]
57
- attr_reader :mapped_name
58
-
59
- # Assesses the rule against a die result value.
60
- # @param [Integer] test_value Value that is result of rolling a single die.
61
- # @return [Integer,nil] Replacement value, or nil if this rule doesn't apply
62
- def map_from test_value
63
- op_result = @trigger_value.send( @trigger_op, test_value )
64
- return nil unless op_result
65
- if op_result == true
66
- return @mapped_value
67
- end
68
- return op_result
69
- end
70
- end # class MapRule
1
+ # frozen_string_literal: true
2
+
3
+ module GamesDice
4
+ # This class models rules that convert numbers shown on a die to values used in a game. A
5
+ # common use for this is to count "successes" - dice that score a certain number or higher.
6
+ #
7
+ # An object of the class represents a single rule, such as "count a die result of 5 or more as 1
8
+ # _success_".
9
+ #
10
+ # @example A rule for counting successes
11
+ # rule = GamesDice::MapRule.new( 6, :<=, 1, 'Success' )
12
+ # # Test how the rule applies . . .
13
+ # rule.map_from 4 # => nil
14
+ # rule.map_from 6 # => 1
15
+ #
16
+ # @example A rule for counting "fumbles" which reduce total successes
17
+ # rule = GamesDice::MapRule.new( 1, :==, -1, 'Fumble' )
18
+ # # Test how the rule applies . . .
19
+ # rule.map_from 7 # => nil
20
+ # rule.map_from 1 # => -1
21
+ #
22
+ class MapRule
23
+ # Creates new instance of GamesDice::MapRule. The rule will be assessed as
24
+ # trigger_value.send( trigger_op, x )
25
+ # where x is the Integer value shown on a die.
26
+ # @param [Integer,Range<Integer>,Object] trigger_value Any object is allowed, but typically an Integer
27
+ # @param [Symbol] trigger_op A method of trigger_value that takes an Integer param and returns Boolean
28
+ # @param [Integer] mapped_value The value to use in place of the trigger value
29
+ # @param [String] mapped_name Name of mapped value, for use in descriptions
30
+ # @return [GamesDice::MapRule]
31
+ def initialize(trigger_value, trigger_op, mapped_value = 0, mapped_name = '')
32
+ unless trigger_value.respond_to?(trigger_op)
33
+ raise ArgumentError,
34
+ "trigger_value #{trigger_value.inspect} cannot respond to trigger_op #{trigger_value.inspect}"
35
+ end
36
+
37
+ @trigger_value = trigger_value
38
+ @trigger_op = trigger_op
39
+ raise TypeError unless mapped_value.is_a? Numeric
40
+
41
+ @mapped_value = Integer(mapped_value)
42
+ @mapped_name = mapped_name.to_s
43
+ end
44
+
45
+ # Trigger operation. How the rule is assessed against #trigger_value.
46
+ # @return [Symbol] Method name to be sent to #trigger_value
47
+ attr_reader :trigger_op
48
+
49
+ # Trigger value. An object that will use #trigger_op to assess a die result for a reroll.
50
+ # @return [Integer,Range,Object] Object that receives (#trigger_op, die_result)
51
+ attr_reader :trigger_value
52
+
53
+ # Value that a die will use after the value has been mapped.
54
+ # @return [Integer]
55
+ attr_reader :mapped_value
56
+
57
+ # Name for mapped value, used in explanations.
58
+ # @return [String]
59
+ attr_reader :mapped_name
60
+
61
+ # Assesses the rule against a die result value.
62
+ # @param [Integer] test_value Value that is result of rolling a single die.
63
+ # @return [Integer,nil] Replacement value, or nil if this rule doesn't apply
64
+ def map_from(test_value)
65
+ op_result = @trigger_value.send(@trigger_op, test_value)
66
+ return nil unless op_result
67
+ return @mapped_value if op_result == true
68
+
69
+ op_result
70
+ end
71
+ end
72
+ end
@@ -1,13 +1,41 @@
1
- class GamesDice::Probabilities
2
- # @!visibility private
3
- # Adds support for Marshal, via to_h and from_h methods
4
- def _dump *ignored
5
- Marshal.dump to_h
6
- end
7
-
8
- # @!visibility private
9
- def self._load buf
10
- h = Marshal.load buf
11
- from_h h
12
- end
13
- end
1
+ # frozen_string_literal: true
2
+
3
+ module GamesDice
4
+ # This class models probability distributions for dice systems.
5
+ #
6
+ # An object of this class represents a single distribution, which might be the result of a complex
7
+ # combination of dice.
8
+ #
9
+ # @example Distribution for a six-sided die
10
+ # probs = GamesDice::Probabilities.for_fair_die( 6 )
11
+ # probs.min # => 1
12
+ # probs.max # => 6
13
+ # probs.expected # => 3.5
14
+ # probs.p_ge( 4 ) # => 0.5
15
+ #
16
+ # @example Adding two distributions
17
+ # pd6 = GamesDice::Probabilities.for_fair_die( 6 )
18
+ # probs = GamesDice::Probabilities.add_distributions( pd6, pd6 )
19
+ # probs.min # => 2
20
+ # probs.max # => 12
21
+ # probs.expected # => 7.0
22
+ # probs.p_ge( 10 ) # => 0.16666666666666669
23
+ #
24
+ class Probabilities
25
+ # @!visibility private
26
+ # Adds support for Marshal, via to_h and from_h methods
27
+ def marshal_dump
28
+ to_h
29
+ end
30
+
31
+ # @!visibility private
32
+ def self._load(buf)
33
+ # Use of Marshal for general-purpose object serialisation is discouraged. However, this class does support
34
+ # it for backwards-compatibility.
35
+ # rubocop:disable Security/MarshalLoad
36
+ h = Marshal.load buf
37
+ # rubocop:enable Security/MarshalLoad
38
+ from_h h
39
+ end
40
+ end
41
+ end