games_dice 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +39 -9
- data/lib/games_dice/parser.rb +59 -12
- data/lib/games_dice/version.rb +1 -1
- data/spec/readme_spec.rb +71 -0
- metadata +4 -4
data/README.md
CHANGED
@@ -54,11 +54,10 @@ Or install it yourself as:
|
|
54
54
|
## Library API
|
55
55
|
|
56
56
|
Although you can refer to the documentation for the contained classes, and use it if needed to
|
57
|
-
build some exotic dice systems,
|
58
|
-
|
59
|
-
dice rolls, explain the results or calculate probabilties as required.
|
57
|
+
build some exotic dice systems, all you need to know to access the core features is described
|
58
|
+
here.
|
60
59
|
|
61
|
-
### GamesDice factory
|
60
|
+
### GamesDice factory method
|
62
61
|
|
63
62
|
#### GamesDice.create
|
64
63
|
|
@@ -217,23 +216,54 @@ A die modifier can also be a single letter plus an integer value, e.g.
|
|
217
216
|
|
218
217
|
1d6r1
|
219
218
|
|
220
|
-
|
221
|
-
|
219
|
+
You can add comma-seperated parameters to a modifier by using a ":" (colon) character after the
|
220
|
+
modifier letter, and a "." (full stop) to signify the end of the parameters. What parameters are
|
221
|
+
accepted, and what they mean, depends on the modifier:
|
222
222
|
|
223
|
-
5d10r
|
223
|
+
5d10r:>8,add.
|
224
|
+
|
225
|
+
You can use more than one modifier. Modifiers should be separated by a "." (full stop) character, although
|
226
|
+
this is optional if you use modifiers without parameters:
|
227
|
+
|
228
|
+
5d10r:10,add.k2
|
229
|
+
5d10xk2
|
230
|
+
5d10x.k2
|
231
|
+
|
232
|
+
are all equivalent.
|
224
233
|
|
225
234
|
#### Rerolls
|
226
235
|
|
227
236
|
You can specify that dice rolling certain values should be re-rolled, and how that re-roll should be
|
228
237
|
interpretted.
|
229
238
|
|
230
|
-
The simple form specifies a low value that will automatically trigger a
|
239
|
+
The simple form specifies a low value that will automatically trigger a re-roll and replace:
|
231
240
|
|
232
241
|
1d6r1
|
233
242
|
|
234
243
|
When rolled, this die will score from 1 to 6. If it rolls a 1, it will roll again automatically
|
235
244
|
and use that result instead.
|
236
245
|
|
246
|
+
The full version of this modifier, allows you to specify from 1 to 3 parameters:
|
247
|
+
|
248
|
+
1d10r:[VALUE_COMPARISON],[REROLL_TYPE],[LIMIT].
|
249
|
+
|
250
|
+
Where:
|
251
|
+
|
252
|
+
* VALUE_COMPARISON is one of >, >=, == (default), <= < plus an integer to set conditions on when the reroll should occur
|
253
|
+
* REROLL_TYPE is one of
|
254
|
+
* replace (default) - use the new value in place of existing value for the die
|
255
|
+
* add - add result of reroll to running total, and ignore any subtract rules
|
256
|
+
* subtract - subtract result of reroll from running total, and reverse sense of any further add results
|
257
|
+
* use_best - use the new value if it is higher than the existing value
|
258
|
+
* use_worst - use the new value if it is higher than the existing value
|
259
|
+
* LIMIT is an integer that sets the maximum number of times that the rule can be triggered, the default is 1000
|
260
|
+
|
261
|
+
Examples:
|
262
|
+
|
263
|
+
1d6r:1. # Same as "1d6r1"
|
264
|
+
1d10r:10,replace,1. #
|
265
|
+
1d20r:<=10,use_best,1. # Roll a 20-sided die, re-roll a result if 10 or lower, and use best result
|
266
|
+
|
237
267
|
#### Maps
|
238
268
|
|
239
269
|
You can specify that the value shown on each die is converted to some other set of values. If
|
@@ -264,7 +294,7 @@ short codes.
|
|
264
294
|
|
265
295
|
This is an alias for "exploding" dice:
|
266
296
|
|
267
|
-
5d10x
|
297
|
+
5d10x # Same as '5d10r:10,add.'
|
268
298
|
|
269
299
|
When rolled, this will score from 5 to theoretically any number, as results of 10 on any die mean that
|
270
300
|
die rolls again and the result is added on.
|
data/lib/games_dice/parser.rb
CHANGED
@@ -3,16 +3,17 @@ require 'parslet'
|
|
3
3
|
# converts string dice descriptions to data usable for the GamesDice::Dice constructor
|
4
4
|
class GamesDice::Parser < Parslet::Parser
|
5
5
|
|
6
|
-
#
|
7
|
-
#
|
8
|
-
# NdXr[Z,add] - a roll of N dice, sides X, re-roll and add on a result of Z
|
9
|
-
# NdXr[Y..Z,add] - a roll of N dice, sides X, re-roll and add on a result of Y..Z
|
10
|
-
# NdXm[>=Z,A] - mapped dice, values greater than or equal to Z score A (unmapped values score 0 by default)
|
6
|
+
# These are the Parslet rules that define the dice grammar. It's an inefficient and over-complex
|
7
|
+
# use of Parslet, and could do with logical a clean-up.
|
11
8
|
|
12
|
-
# These are the Parslet rules that define the dice grammar
|
13
9
|
rule(:integer) { match('[0-9]').repeat(1) }
|
14
10
|
rule(:range) { integer.as(:range_start) >> str('..') >> integer.as(:range_end) }
|
15
11
|
rule(:dlabel) { match('[d]') }
|
12
|
+
rule(:space) { match('\s').repeat(1) }
|
13
|
+
rule(:space?) { space.maybe }
|
14
|
+
rule(:underscore) { str('_').repeat(1) }
|
15
|
+
rule(:underscore?) { space.maybe }
|
16
|
+
|
16
17
|
rule(:bunch_start) { integer.as(:ndice) >> dlabel >> integer.as(:sides) }
|
17
18
|
|
18
19
|
rule(:reroll_label) { match(['r']).as(:reroll) }
|
@@ -23,12 +24,33 @@ class GamesDice::Parser < Parslet::Parser
|
|
23
24
|
rule(:single_modifier) { alias_label }
|
24
25
|
rule(:modifier_label) { reroll_label | keep_label | map_label }
|
25
26
|
rule(:simple_modifier) { modifier_label >> integer.as(:simple_value) }
|
26
|
-
rule(:
|
27
|
+
rule(:comparison_op) { str('>=') | str('<=') | str('==') | str('>') | str('<') }
|
28
|
+
rule(:ctl_string) { match('[a-z_]').repeat(1) }
|
29
|
+
rule(:output_string) { match('[A-Za-z0-9_]').repeat(1) }
|
30
|
+
|
31
|
+
rule(:opint_or_int) { (comparison_op.as(:comparison) >> integer.as(:compare_num)) | integer.as(:compare_num) }
|
32
|
+
rule(:comma) { str(',') }
|
33
|
+
rule(:stop) { str('.') }
|
34
|
+
|
35
|
+
rule(:condition_only) { opint_or_int.as(:condition) }
|
36
|
+
|
37
|
+
rule(:condition_and_type) { opint_or_int.as(:condition) >> comma >> ctl_string.as(:type) }
|
38
|
+
rule(:condition_and_num) { opint_or_int.as(:condition) >> comma >> integer.as(:num) }
|
39
|
+
|
40
|
+
rule(:condition_type_and_num) { opint_or_int.as(:condition) >> comma >> ctl_string.as(:type) >> comma >> integer.as(:num) }
|
41
|
+
rule(:condition_num_and_output) { opint_or_int.as(:condition) >> comma >> integer.as(:num) >> comma >> ctl_string.as(:output) }
|
42
|
+
|
43
|
+
rule(:reroll_params) { condition_type_and_num | condition_and_type | condition_only }
|
44
|
+
rule(:map_params) { condition_num_and_output | condition_and_num | condition_only }
|
45
|
+
|
46
|
+
rule(:full_reroll) { reroll_label >> str(':') >> reroll_params >> stop }
|
47
|
+
rule(:full_map) { map_label >> str(':') >> map_params >> stop }
|
48
|
+
|
49
|
+
rule(:complex_modifier) { full_reroll | full_map }
|
27
50
|
|
28
|
-
rule(:bunch_modifier) { single_modifier | simple_modifier }
|
51
|
+
rule(:bunch_modifier) { complex_modifier | ( single_modifier >> stop.maybe ) | ( simple_modifier >> stop.maybe ) }
|
29
52
|
rule(:bunch) { bunch_start >> bunch_modifier.repeat.as(:mods) }
|
30
|
-
|
31
|
-
rule(:space?) { space.maybe }
|
53
|
+
|
32
54
|
rule(:operator) { match('[+-]').as(:op) >> space? }
|
33
55
|
rule(:add_bunch) { operator >> bunch >> space? }
|
34
56
|
rule(:add_constant) { operator >> integer.as(:constant) >> space? }
|
@@ -116,8 +138,18 @@ class GamesDice::Parser < Parslet::Parser
|
|
116
138
|
out_hash[:rerolls] ||= []
|
117
139
|
if reroll_mod[:simple_value]
|
118
140
|
out_hash[:rerolls] << [ reroll_mod[:simple_value].to_i, :>=, :reroll_replace, 1 ]
|
141
|
+
return
|
142
|
+
end
|
143
|
+
# Typical reroll_mod: {:reroll=>"r"@5, :condition=>{:compare_num=>"10"@7}, :type=>"add"@10}
|
144
|
+
op = get_op_symbol( reroll_mod[:condition][:comparison] || '==' )
|
145
|
+
v = reroll_mod[:condition][:compare_num].to_i
|
146
|
+
type = ( 'reroll_' + ( reroll_mod[:type] || 'replace' ) ).to_sym
|
147
|
+
|
148
|
+
if reroll_mod[:num]
|
149
|
+
out_hash[:rerolls] << [ v, op, type, reroll_mod[:num].to_i ]
|
150
|
+
else
|
151
|
+
out_hash[:rerolls] << [ v, op, type ]
|
119
152
|
end
|
120
|
-
# TODO: Handle complex descriptions
|
121
153
|
end
|
122
154
|
|
123
155
|
# Called for any parsed keeper mode
|
@@ -137,7 +169,22 @@ class GamesDice::Parser < Parslet::Parser
|
|
137
169
|
out_hash[:maps] << [ map_mod[:simple_value].to_i, :<=, 1 ]
|
138
170
|
return
|
139
171
|
end
|
140
|
-
|
172
|
+
|
173
|
+
# Typical
|
174
|
+
end
|
175
|
+
|
176
|
+
# The dice description language uses (r).op.x, whilst GamesDice::RerollRule uses x.op.(r), so
|
177
|
+
# as well as converting to a symbol, we must reverse sense of input to constructor
|
178
|
+
OP_CONVERSION = {
|
179
|
+
'==' => :==,
|
180
|
+
'>=' => :<=,
|
181
|
+
'>' => :<,
|
182
|
+
'<' => :>,
|
183
|
+
'<=' => :>=,
|
184
|
+
}
|
185
|
+
|
186
|
+
def get_op_symbol parsed_op_string
|
187
|
+
OP_CONVERSION[ parsed_op_string.to_s ]
|
141
188
|
end
|
142
189
|
|
143
190
|
end # class Parser
|
data/lib/games_dice/version.rb
CHANGED
data/spec/readme_spec.rb
CHANGED
@@ -146,3 +146,74 @@ describe GamesDice::Probabilities do
|
|
146
146
|
end
|
147
147
|
|
148
148
|
end # describe GamesDice::Probabilities
|
149
|
+
|
150
|
+
describe 'String Dice Description' do
|
151
|
+
|
152
|
+
before :each do
|
153
|
+
srand(35241)
|
154
|
+
end
|
155
|
+
|
156
|
+
describe "'1d6'" do
|
157
|
+
it "returns expected results from rolling" do
|
158
|
+
d = GamesDice.create '1d6'
|
159
|
+
(1..20).map { |n| d.roll }.should == [6, 3, 2, 3, 4, 6, 4, 2, 6, 3, 3, 5, 6, 6, 3, 6, 5, 2, 1, 4]
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "'2d6 + 1d4'" do
|
164
|
+
it "returns expected results from rolling" do
|
165
|
+
d = GamesDice.create '2d6 + 1d4'
|
166
|
+
(1..5).map { |n| d.roll }.should == [11, 10, 12, 12, 14]
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
describe "'1d100 + 1d20 - 5'" do
|
171
|
+
it "returns expected results from rolling" do
|
172
|
+
d = GamesDice.create '1d100 + 1d20 - 5'
|
173
|
+
(1..5).map { |n| d.roll }.should == [75, 78, 24, 102, 32]
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe "'1d10x'" do
|
178
|
+
it "returns expected results from rolling" do
|
179
|
+
d = GamesDice.create '1d10x'
|
180
|
+
(1..20).map { |n| d.roll }.should == [2, 3, 4, 7, 6, 7, 4, 2, 6, 3, 7, 5, 6, 7, 6, 6, 5, 19, 4, 19]
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "'1d6r1'" do
|
185
|
+
it "returns expected results from rolling" do
|
186
|
+
d = GamesDice.create '1d6r1'
|
187
|
+
(1..20).map { |n| d.roll }.should == [6, 3, 2, 3, 4, 6, 4, 2, 6, 3, 3, 5, 6, 6, 3, 6, 5, 2, 4, 2]
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
describe "'5d10r:10,add.k2'" do
|
192
|
+
it "returns expected results from rolling" do
|
193
|
+
d = GamesDice.create '5d10r:10,add.k2'
|
194
|
+
(1..5).map { |n| d.roll }.should == [13, 13, 14, 38, 15]
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
describe "'3d10m6'" do
|
199
|
+
it "returns expected results from rolling" do
|
200
|
+
d = GamesDice.create '3d10m6'
|
201
|
+
(1..6).map { |n| d.roll }.should == [0, 3, 1, 1, 3, 2]
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe "'5d10k2'" do
|
206
|
+
it "returns expected results from rolling" do
|
207
|
+
d = GamesDice.create '5d10k2'
|
208
|
+
(1..5).map { |n| d.roll }.should == [13, 13, 14, 19, 19]
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
describe "'5d10x'" do
|
213
|
+
it "returns expected results from rolling" do
|
214
|
+
d = GamesDice.create '5d10x'
|
215
|
+
(1..5).map { |n| d.roll }.should == [22, 22, 31, 53, 25]
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: games_dice
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-05-
|
12
|
+
date: 2013-05-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -112,7 +112,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
112
112
|
version: '0'
|
113
113
|
segments:
|
114
114
|
- 0
|
115
|
-
hash: -
|
115
|
+
hash: -4383036419295474875
|
116
116
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
117
|
none: false
|
118
118
|
requirements:
|
@@ -121,7 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
121
121
|
version: '0'
|
122
122
|
segments:
|
123
123
|
- 0
|
124
|
-
hash: -
|
124
|
+
hash: -4383036419295474875
|
125
125
|
requirements: []
|
126
126
|
rubyforge_project:
|
127
127
|
rubygems_version: 1.8.24
|