dicebag 3.2.2 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/bin/dicebag +47 -0
- data/lib/dicebag/label_part.rb +4 -2
- data/lib/dicebag/normalize.rb +165 -0
- data/lib/dicebag/parser.rb +65 -40
- data/lib/dicebag/result.rb +14 -7
- data/lib/dicebag/roll.rb +18 -14
- data/lib/dicebag/roll_part.rb +111 -41
- data/lib/dicebag/roll_part_string.rb +25 -10
- data/lib/dicebag/roll_string.rb +11 -10
- data/lib/dicebag/simple_part.rb +7 -4
- data/lib/dicebag/static_part.rb +9 -4
- data/lib/dicebag/systems/dnd.rb +65 -0
- data/lib/dicebag/systems/fudge.rb +80 -0
- data/lib/dicebag/systems/gurps.rb +52 -0
- data/lib/dicebag/systems/savage_worlds.rb +31 -0
- data/lib/dicebag/systems/standard.rb +19 -0
- data/lib/dicebag/systems/storyteller.rb +45 -0
- data/lib/dicebag/transform.rb +43 -20
- data/lib/dicebag.rb +15 -171
- metadata +17 -8
data/lib/dicebag/transform.rb
CHANGED
@@ -1,30 +1,49 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# This continues definining the DiceBag module.
|
1
|
+
# DiceBag module.
|
4
2
|
module DiceBag
|
5
|
-
# This is the Transform subclass that takes the
|
6
|
-
#
|
7
|
-
#
|
3
|
+
# This is the Transform subclass that takes the parsed tree and
|
4
|
+
# transforms it into its (almost) final form. (It gets a normalization
|
5
|
+
# pass later.)
|
8
6
|
class Transform < Parslet::Transform
|
9
7
|
def self.hashify_options(options)
|
10
8
|
opts = {}
|
11
9
|
|
12
|
-
options.each { |val| opts.update val } if options.respond_to?
|
10
|
+
options.each { |val| opts.update val } if options.respond_to?(:each)
|
13
11
|
|
14
12
|
opts
|
15
13
|
end
|
16
14
|
|
17
15
|
# Options.
|
18
|
-
#
|
19
|
-
# sub-hashes.
|
20
|
-
rule(drop:
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
#
|
17
|
+
# The full options hash is updated later with these sub-hashes.
|
18
|
+
rule(drop: simple(:x)) do
|
19
|
+
{ drop: Integer(x) }
|
20
|
+
end
|
21
|
+
|
22
|
+
rule(keep: simple(:x)) do
|
23
|
+
{ keep: Integer(x) }
|
24
|
+
end
|
25
|
+
|
26
|
+
rule(keeplowest: simple(:x)) do
|
27
|
+
{ keeplowest: Integer(x) }
|
28
|
+
end
|
24
29
|
|
25
|
-
|
26
|
-
|
27
|
-
|
30
|
+
rule(reroll: simple(:x)) do
|
31
|
+
{ reroll: Integer(x) }
|
32
|
+
end
|
33
|
+
|
34
|
+
rule(target: simple(:x)) do
|
35
|
+
{ target: Integer(x) }
|
36
|
+
end
|
37
|
+
|
38
|
+
rule(failure: simple(:x)) do
|
39
|
+
{ failure: Integer(x) }
|
40
|
+
end
|
41
|
+
|
42
|
+
# Explode is special, in that if it is nil, then we set it to -1 to
|
43
|
+
# reflect that.
|
44
|
+
rule(explode: simple(:x)) do
|
45
|
+
{ explode: (x ? Integer(x) : nil) }
|
46
|
+
end
|
28
47
|
|
29
48
|
# Match a label by itself.
|
30
49
|
rule(label: simple(:s)) { [:label, LabelPart.new(String(s))] }
|
@@ -44,16 +63,19 @@ module DiceBag
|
|
44
63
|
|
45
64
|
# Match the xdx and options hash.
|
46
65
|
#
|
47
|
-
# TODO: Remove the .as(:xdx) in the Parser sub-class
|
48
|
-
#
|
49
|
-
#
|
66
|
+
# TODO: Remove the .as(:xdx) in the Parser sub-class and then update
|
67
|
+
# this class to account for it. It'll make the resulting data much
|
68
|
+
# cleaner.
|
50
69
|
rule(xdx: subtree(:xdx), options: subtree(:opts)) do
|
51
70
|
{ xdx: xdx, options: Transform.hashify_options(opts) }
|
52
71
|
end
|
53
72
|
|
54
73
|
# Convert the count and sides of an :xdx part.
|
55
74
|
rule(count: simple(:c), sides: simple(:s)) do
|
56
|
-
{
|
75
|
+
{
|
76
|
+
count: (c ? Integer(c) : 1),
|
77
|
+
sides: Integer(s)
|
78
|
+
}
|
57
79
|
end
|
58
80
|
|
59
81
|
# Match an operator followed by an :xdx subtree.
|
@@ -63,6 +85,7 @@ module DiceBag
|
|
63
85
|
[String(o), part]
|
64
86
|
end
|
65
87
|
|
88
|
+
# Match an operator followed by a immediate value.
|
66
89
|
rule(op: simple(:o), value: simple(:v)) do
|
67
90
|
[String(o), Integer(v)]
|
68
91
|
end
|
data/lib/dicebag.rb
CHANGED
@@ -1,189 +1,33 @@
|
|
1
|
-
# Copyright (c) 2012 Randy Carnahan <syn at dragonsbait dot com>
|
2
|
-
#
|
3
|
-
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
-
# a copy of this software and associated documentation files (the "Software"),
|
5
|
-
# to deal in the Software without restriction, including without limitation
|
6
|
-
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
7
|
-
# and/or sell copies of the Software, and to permit persons to whom the
|
8
|
-
# Software is furnished to do so, subject to the following conditions:
|
9
|
-
#
|
10
|
-
# The above copyright notice and this permission notice shall be included
|
11
|
-
# in all copies or substantial portions of the Software.
|
12
|
-
#
|
13
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
14
|
-
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
15
|
-
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
16
|
-
# NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
17
|
-
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
18
|
-
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
19
|
-
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
-
#
|
21
|
-
# dicelib.rb -- version: 3.2.2
|
22
|
-
|
23
1
|
require 'parslet'
|
24
2
|
|
25
3
|
# This defined the main DiceBag module.
|
26
4
|
module DiceBag
|
27
|
-
|
28
|
-
|
29
|
-
# This is our generic DiceBagError
|
30
|
-
# exception subclass.
|
31
|
-
class DiceBagError < Exception; end
|
32
|
-
|
33
|
-
###
|
34
|
-
# Module Methods
|
35
|
-
###
|
36
|
-
|
37
|
-
# This takes the parsed tree, AFTER it has
|
38
|
-
# been through the Transform class, and massages
|
39
|
-
# the data a bit more, to ease the iteration that
|
40
|
-
# happens in the Roll class. It will convert all
|
41
|
-
# values into the correct *Part class.
|
42
|
-
def self.normalize_tree(tree)
|
43
|
-
tree = [tree] unless tree.first.is_a? Array
|
44
|
-
|
45
|
-
tree.map { |part| normalize part }
|
46
|
-
end
|
47
|
-
|
48
|
-
def self.normalize(part)
|
49
|
-
[
|
50
|
-
normalize_op(part.first),
|
51
|
-
normalize_value(part.last)
|
52
|
-
]
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.normalize_op(op)
|
56
|
-
# We swap out the strings for symbols.
|
57
|
-
# If the op is not one of the arithimetic
|
58
|
-
# operators, then the op itself is returned.
|
59
|
-
# (This should only happen on :start arrays.)
|
60
|
-
case op
|
61
|
-
when '+' then :add
|
62
|
-
when '-' then :sub
|
63
|
-
when '*' then :mul
|
64
|
-
when '/' then :div
|
65
|
-
else
|
66
|
-
op
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def self.normalize_value(val)
|
71
|
-
case val
|
72
|
-
when String
|
73
|
-
LabelPart.new val
|
74
|
-
when Hash
|
75
|
-
RollPart.new normalize_xdx(val)
|
76
|
-
when Integer
|
77
|
-
StaticPart.new val
|
78
|
-
else
|
79
|
-
val
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
# This further massages the xDx hashes.
|
84
|
-
def self.normalize_xdx(hash)
|
85
|
-
count = hash[:xdx][:count]
|
86
|
-
sides = hash[:xdx][:sides]
|
87
|
-
|
88
|
-
# Delete the no longer needed :xdx key.
|
89
|
-
hash.delete(:xdx)
|
90
|
-
|
91
|
-
# Default to at least 1 die.
|
92
|
-
count = 1 if count.zero? || count.nil?
|
93
|
-
|
94
|
-
# Set the :count and :sides keys directly
|
95
|
-
# and set the notes array.
|
96
|
-
hash[:count] = count
|
97
|
-
hash[:sides] = sides
|
98
|
-
hash[:notes] = []
|
99
|
-
|
100
|
-
normalize_options hash
|
101
|
-
end
|
102
|
-
|
103
|
-
def self.normalize_options(hash)
|
104
|
-
if hash[:options].empty?
|
105
|
-
hash.delete(:options)
|
106
|
-
else
|
107
|
-
normalize_explode hash
|
108
|
-
normalize_reroll hash
|
109
|
-
normalize_drop_keep hash
|
110
|
-
normalize_target hash
|
111
|
-
end
|
112
|
-
|
113
|
-
hash
|
114
|
-
end
|
5
|
+
# This is our generic DiceBagError exception subclass.
|
6
|
+
class DiceBagError < StandardError; end
|
115
7
|
|
116
|
-
#
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
if hash[:options][:explode] == 1
|
121
|
-
hash[:options][:explode] = hash[:sides]
|
122
|
-
|
123
|
-
hash[:notes].push("Explode set to #{hash[:sides]}")
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
# Prevent Reroll abuse.
|
128
|
-
def self.normalize_reroll(hash)
|
129
|
-
return unless hash[:options].key? :reroll
|
130
|
-
|
131
|
-
if hash[:options][:reroll] >= hash[:sides]
|
132
|
-
hash[:options][:reroll] = 0
|
133
|
-
|
134
|
-
hash[:notes].push 'Reroll reset to 0.'
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
# Make sure there are enough dice to
|
139
|
-
# handle both Drop and Keep values.
|
140
|
-
# If not, both are reset to 0. Harsh.
|
141
|
-
def self.normalize_drop_keep(hash)
|
142
|
-
drop = hash[:options].fetch(:drop, 0)
|
143
|
-
keep = hash[:options].fetch(:keep, 0)
|
144
|
-
|
145
|
-
if (drop + keep) >= hash[:count]
|
146
|
-
hash[:options][:drop] = 0
|
147
|
-
hash[:options][:keep] = 0
|
148
|
-
|
149
|
-
hash[:notes].push 'Drop and Keep Conflict. Both reset to 0.'
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
# Finally, if we have a target number,
|
154
|
-
# make sure it is equal to or less than
|
155
|
-
# the dice sides and greater than 0,
|
156
|
-
# otherwise, set it to 0 (aka no target
|
157
|
-
# number) and add a note.
|
158
|
-
def self.normalize_target(hash)
|
159
|
-
return unless hash[:options].key? :target
|
160
|
-
|
161
|
-
target = hash[:options][:target]
|
162
|
-
|
163
|
-
return if target >= 0 && target <= hash[:sides]
|
164
|
-
|
165
|
-
hash[:options][:target] = 0
|
166
|
-
|
167
|
-
hash[:notes].push 'Target number too large or is negative; reset to 0.'
|
168
|
-
end
|
169
|
-
|
170
|
-
# This is the wrapper for the parse, transform,
|
171
|
-
# and normalize calls. This is called by the Roll
|
172
|
-
# class, but may be called to get the raw returned
|
173
|
-
# array of parsed bits for other purposes.
|
8
|
+
# This is the wrapper for the parse, transform, and normalize calls.
|
9
|
+
# This is called by the Roll class, but may be called to get the raw
|
10
|
+
# returned array of parsed parts for other purposes.
|
174
11
|
def self.parse(dstr = '')
|
175
12
|
tree = Parser.new.parse(dstr)
|
176
13
|
ast = Transform.new.apply(tree)
|
177
14
|
|
178
|
-
|
15
|
+
Normalize.call ast
|
16
|
+
end
|
17
|
+
|
18
|
+
### Main Syntatic Sugar Interface
|
19
|
+
def self.roll(dstr)
|
20
|
+
DiceBag::Roll.new(dstr).roll
|
179
21
|
end
|
180
22
|
|
181
|
-
|
182
|
-
|
23
|
+
# The default roll if one is not given.
|
24
|
+
def self.default_roll
|
25
|
+
'1d6'
|
183
26
|
end
|
184
27
|
end
|
185
28
|
|
186
29
|
# Our sub-modules.
|
30
|
+
require_relative './dicebag/normalize'
|
187
31
|
require_relative './dicebag/roll_string'
|
188
32
|
require_relative './dicebag/roll_part_string'
|
189
33
|
require_relative './dicebag/parser'
|
metadata
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dicebag
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- SynTruth
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
date: 2016-04-25 00:00:00.000000000 Z
|
@@ -32,12 +32,15 @@ dependencies:
|
|
32
32
|
version: 1.4.0
|
33
33
|
description: A very flexible dice rolling library for Ruby.
|
34
34
|
email: syntruth@gmail.com
|
35
|
-
executables:
|
35
|
+
executables:
|
36
|
+
- dicebag
|
36
37
|
extensions: []
|
37
38
|
extra_rdoc_files: []
|
38
39
|
files:
|
40
|
+
- bin/dicebag
|
39
41
|
- lib/dicebag.rb
|
40
42
|
- lib/dicebag/label_part.rb
|
43
|
+
- lib/dicebag/normalize.rb
|
41
44
|
- lib/dicebag/parser.rb
|
42
45
|
- lib/dicebag/result.rb
|
43
46
|
- lib/dicebag/roll.rb
|
@@ -46,29 +49,35 @@ files:
|
|
46
49
|
- lib/dicebag/roll_string.rb
|
47
50
|
- lib/dicebag/simple_part.rb
|
48
51
|
- lib/dicebag/static_part.rb
|
52
|
+
- lib/dicebag/systems/dnd.rb
|
53
|
+
- lib/dicebag/systems/fudge.rb
|
54
|
+
- lib/dicebag/systems/gurps.rb
|
55
|
+
- lib/dicebag/systems/savage_worlds.rb
|
56
|
+
- lib/dicebag/systems/standard.rb
|
57
|
+
- lib/dicebag/systems/storyteller.rb
|
49
58
|
- lib/dicebag/transform.rb
|
50
59
|
homepage: https://github.com/syntruth/Dice-Bag
|
51
60
|
licenses:
|
52
61
|
- MIT
|
53
62
|
metadata: {}
|
54
|
-
post_install_message:
|
63
|
+
post_install_message:
|
55
64
|
rdoc_options: []
|
56
65
|
require_paths:
|
57
66
|
- lib
|
67
|
+
- lib/systems
|
58
68
|
required_ruby_version: !ruby/object:Gem::Requirement
|
59
69
|
requirements:
|
60
70
|
- - ">="
|
61
71
|
- !ruby/object:Gem::Version
|
62
|
-
version:
|
72
|
+
version: 2.7.1
|
63
73
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
74
|
requirements:
|
65
75
|
- - ">="
|
66
76
|
- !ruby/object:Gem::Version
|
67
77
|
version: '0'
|
68
78
|
requirements: []
|
69
|
-
|
70
|
-
|
71
|
-
signing_key:
|
79
|
+
rubygems_version: 3.1.2
|
80
|
+
signing_key:
|
72
81
|
specification_version: 4
|
73
82
|
summary: 'Dice Bag: Ruby Dice Rolling Library'
|
74
83
|
test_files: []
|