games_dice 0.3.12 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rubocop.yml +15 -0
- data/.travis.yml +7 -10
- data/CHANGELOG.md +6 -0
- data/Gemfile +2 -0
- data/Rakefile +14 -11
- data/ext/games_dice/extconf.rb +4 -22
- data/ext/games_dice/probabilities.c +1 -1
- data/games_dice.gemspec +26 -32
- data/lib/games_dice/bunch.rb +241 -247
- data/lib/games_dice/complex_die.rb +287 -270
- data/lib/games_dice/complex_die_helpers.rb +68 -60
- data/lib/games_dice/constants.rb +10 -10
- data/lib/games_dice/dice.rb +146 -143
- data/lib/games_dice/die.rb +101 -97
- data/lib/games_dice/die_result.rb +193 -189
- data/lib/games_dice/map_rule.rb +72 -70
- data/lib/games_dice/marshal.rb +18 -13
- data/lib/games_dice/parser.rb +219 -218
- data/lib/games_dice/reroll_rule.rb +76 -77
- data/lib/games_dice/version.rb +3 -1
- data/lib/games_dice.rb +19 -19
- data/spec/bunch_spec.rb +399 -420
- data/spec/complex_die_spec.rb +314 -305
- data/spec/dice_spec.rb +33 -34
- data/spec/die_result_spec.rb +162 -169
- data/spec/die_spec.rb +81 -81
- data/spec/helpers.rb +23 -21
- data/spec/map_rule_spec.rb +40 -44
- data/spec/parser_spec.rb +106 -82
- data/spec/probability_spec.rb +530 -526
- data/spec/readme_spec.rb +404 -390
- data/spec/reroll_rule_spec.rb +40 -44
- metadata +39 -28
- data/lib/games_dice/prob_helpers.rb +0 -259
- data/lib/games_dice/probabilities.rb +0 -244
@@ -1,77 +1,76 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
|
9
|
-
#
|
10
|
-
# rule.
|
11
|
-
# rule.
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# rule
|
15
|
-
|
16
|
-
#
|
17
|
-
# rule.
|
18
|
-
# rule.
|
19
|
-
#
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
raise ArgumentError, "Unrecognised reason for a re-roll #{type}"
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
end
|
76
|
-
|
77
|
-
end # class RerollRule
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GamesDice
|
4
|
+
# This class models a variety of game rules that cause dice to be re-rolled.
|
5
|
+
#
|
6
|
+
# An object of the class represents a single rule, such as "re-roll a result of 1
|
7
|
+
# and use the new value".
|
8
|
+
#
|
9
|
+
# @example A rule for "exploding" dice
|
10
|
+
# rule = GamesDice::RerollRule.new( 6, :<=, :reroll_add )
|
11
|
+
# # Test whether the rule applies . . .
|
12
|
+
# rule.applies? 4 # => false
|
13
|
+
# rule.applies? 6 # => true
|
14
|
+
# rule.type # => :reroll_add
|
15
|
+
#
|
16
|
+
# @example A rule for re-rolling and taking best value if first attempt is lower than a threshold
|
17
|
+
# rule = GamesDice::RerollRule.new( 11, :>, :reroll_use_best, 1 )
|
18
|
+
# # Test whether the rule applies . . .
|
19
|
+
# rule.applies? 4 # => true
|
20
|
+
# rule.applies? 14 # => false
|
21
|
+
# rule.type # => :reroll_use_best
|
22
|
+
#
|
23
|
+
class RerollRule
|
24
|
+
# Creates new instance of GamesDice::RerollRule. The rule will be assessed as
|
25
|
+
# trigger_value.send( trigger_op, x )
|
26
|
+
# where x is the Integer value shown on a die.
|
27
|
+
# @param [Integer,Range<Integer>,Object] trigger_value Any object is allowed, but typically an Integer
|
28
|
+
# @param [Symbol] trigger_op A method of trigger_value that takes an Integer param and returns Boolean
|
29
|
+
# @param [Symbol] type The type of reroll
|
30
|
+
# @param [Integer] limit Maximum number of times this rule can be applied to a single die
|
31
|
+
# @return [GamesDice::RerollRule]
|
32
|
+
def initialize(trigger_value, trigger_op, type, limit = 1000)
|
33
|
+
unless trigger_value.respond_to?(trigger_op)
|
34
|
+
raise ArgumentError,
|
35
|
+
"trigger_value #{trigger_value.inspect} cannot respond to trigger_op #{trigger_value.inspect}"
|
36
|
+
end
|
37
|
+
|
38
|
+
raise ArgumentError, "Unrecognised reason for a re-roll #{type}" unless GamesDice::REROLL_TYPES.key?(type)
|
39
|
+
|
40
|
+
@trigger_value = trigger_value
|
41
|
+
@trigger_op = trigger_op
|
42
|
+
@type = type
|
43
|
+
@limit = limit ? Integer(limit) : 1000
|
44
|
+
@limit = 1 if @type == :reroll_subtract
|
45
|
+
end
|
46
|
+
|
47
|
+
# Trigger operation. How the rule is assessed against #trigger_value.
|
48
|
+
# @return [Symbol] Method name to be sent to #trigger_value
|
49
|
+
attr_reader :trigger_op
|
50
|
+
|
51
|
+
# Trigger value. An object that will use #trigger_op to assess a die result for a reroll.
|
52
|
+
# @return [Integer,Range,Object] Object that receives (#trigger_op, die_result)
|
53
|
+
attr_reader :trigger_value
|
54
|
+
|
55
|
+
# The reroll behaviour that this rule triggers.
|
56
|
+
# @return [Symbol] A category for the re-roll, declares how it should be processed
|
57
|
+
# The following values are supported:
|
58
|
+
# +:reroll_add+:: add result of reroll to running total, and ignore :reroll_subtract for this die
|
59
|
+
# +reroll_subtract+:: subtract result of reroll from running total, reverse sense of any further :reroll_add results
|
60
|
+
# +:reroll_replace+:: use the new value in place of existing value for the die
|
61
|
+
# +:reroll_use_best+:: use the new value if it is higher than the existing value
|
62
|
+
# +:reroll_use_worst+:: use the new value if it is higher than the existing value
|
63
|
+
attr_reader :type
|
64
|
+
|
65
|
+
# Maximum to number of times that this rule can be applied to a single die.
|
66
|
+
# @return [Integer] A number of rolls.
|
67
|
+
attr_reader :limit
|
68
|
+
|
69
|
+
# Assesses the rule against a die result value.
|
70
|
+
# @param [Integer] test_value Value that is result of rolling a single die.
|
71
|
+
# @return [Boolean] Whether the rule applies.
|
72
|
+
def applies?(test_value)
|
73
|
+
@trigger_value.send(@trigger_op, test_value) ? true : false
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/games_dice/version.rb
CHANGED
data/lib/games_dice.rb
CHANGED
@@ -1,19 +1,21 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'games_dice/version'
|
2
4
|
begin
|
3
|
-
require
|
5
|
+
require 'games_dice/games_dice'
|
4
6
|
rescue LoadError
|
5
|
-
require
|
7
|
+
require 'games_dice/probabilities'
|
6
8
|
end
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require
|
16
|
-
require
|
9
|
+
require 'games_dice/constants'
|
10
|
+
require 'games_dice/die'
|
11
|
+
require 'games_dice/die_result'
|
12
|
+
require 'games_dice/reroll_rule'
|
13
|
+
require 'games_dice/map_rule'
|
14
|
+
require 'games_dice/complex_die'
|
15
|
+
require 'games_dice/bunch'
|
16
|
+
require 'games_dice/dice'
|
17
|
+
require 'games_dice/parser'
|
18
|
+
require 'games_dice/marshal'
|
17
19
|
|
18
20
|
module GamesDice
|
19
21
|
# @!visibility private
|
@@ -24,11 +26,9 @@ module GamesDice
|
|
24
26
|
# @param [#rand] prng Optional random number generator, default is to use Ruby's built-in #rand()
|
25
27
|
# @return [GamesDice::Dice] A new dice object.
|
26
28
|
#
|
27
|
-
def self.create
|
28
|
-
parsed = @@parser.parse(
|
29
|
-
if prng
|
30
|
-
|
31
|
-
end
|
32
|
-
GamesDice::Dice.new( parsed[:bunches], parsed[:offset] )
|
29
|
+
def self.create(dice_description, prng = nil)
|
30
|
+
parsed = @@parser.parse(dice_description)
|
31
|
+
parsed[:bunches].each { |bunch| bunch.merge!(prng: prng) } if prng
|
32
|
+
GamesDice::Dice.new(parsed[:bunches], parsed[:offset])
|
33
33
|
end
|
34
34
|
end
|