dicebag 3.2.1 → 3.3.0
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.
- 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 +67 -41
- 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 +58 -47
- data/lib/dicebag.rb +16 -166
- metadata +18 -9
data/lib/dicebag/transform.rb
CHANGED
@@ -1,82 +1,93 @@
|
|
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
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
|
21
|
-
|
22
|
-
rule(keep: simple(:x)) { { keep: Integer(x) } }
|
23
|
-
rule(reroll: simple(:x)) { { reroll: Integer(x) } }
|
24
|
-
rule(target: simple(:x)) { { target: Integer(x) } }
|
25
|
-
|
26
|
-
# Explode is special, in that if it is nil, then it
|
27
|
-
# must remain that way.
|
28
|
-
rule(explode: simple(:x)) { { explode: (x ? Integer(x) : nil) } }
|
29
|
-
|
30
|
-
# Parts {:ops => (:xdx | :number)}
|
31
|
-
# These are first-match, so the simple number will
|
32
|
-
# be matched before the xdx subtree.
|
33
|
-
|
34
|
-
# Match an operator followed by a static number.
|
35
|
-
# TODO: find out why this is not matching simple
|
36
|
-
# op => integers! -- 2016-04-18
|
37
|
-
rule(op: simple(:o), value: simple(:v)) do
|
38
|
-
[String(o), Integer(v)]
|
15
|
+
# Options.
|
16
|
+
#
|
17
|
+
# The full options hash is updated later with these sub-hashes.
|
18
|
+
rule(drop: simple(:x)) do
|
19
|
+
{ drop: Integer(x) }
|
39
20
|
end
|
40
21
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
count = Integer(part[:xdx][:count])
|
45
|
-
sides = Integer(part[:xdx][:sides])
|
46
|
-
options = Transform.hashify_options(part[:options])
|
22
|
+
rule(keep: simple(:x)) do
|
23
|
+
{ keep: Integer(x) }
|
24
|
+
end
|
47
25
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
26
|
+
rule(keeplowest: simple(:x)) do
|
27
|
+
{ keeplowest: Integer(x) }
|
28
|
+
end
|
29
|
+
|
30
|
+
rule(reroll: simple(:x)) do
|
31
|
+
{ reroll: Integer(x) }
|
32
|
+
end
|
52
33
|
|
53
|
-
|
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) }
|
54
46
|
end
|
55
47
|
|
56
48
|
# Match a label by itself.
|
57
|
-
rule(label: simple(:s)) { [:label, String(s)] }
|
49
|
+
rule(label: simple(:s)) { [:label, LabelPart.new(String(s))] }
|
58
50
|
|
59
51
|
# Match a label followed by a :start subtree.
|
60
52
|
rule(label: simple(:s), start: subtree(:part)) do
|
61
|
-
|
62
|
-
|
63
|
-
|
53
|
+
[
|
54
|
+
[:label, LabelPart.new(String(s))],
|
55
|
+
[:start, part]
|
56
|
+
]
|
64
57
|
end
|
65
58
|
|
66
59
|
# Match a :start subtree, with the label not present.
|
67
|
-
# Note that this returns a hash, but the final output
|
68
|
-
# will still be in an array.
|
69
60
|
rule(start: subtree(:part)) do
|
70
61
|
[:start, part]
|
71
62
|
end
|
72
63
|
|
64
|
+
# Match the xdx and options hash.
|
65
|
+
#
|
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.
|
73
69
|
rule(xdx: subtree(:xdx), options: subtree(:opts)) do
|
74
70
|
{ xdx: xdx, options: Transform.hashify_options(opts) }
|
75
71
|
end
|
76
72
|
|
77
73
|
# Convert the count and sides of an :xdx part.
|
78
74
|
rule(count: simple(:c), sides: simple(:s)) do
|
79
|
-
{
|
75
|
+
{
|
76
|
+
count: (c ? Integer(c) : 1),
|
77
|
+
sides: Integer(s)
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
# Match an operator followed by an :xdx subtree.
|
82
|
+
rule(op: simple(:o), value: subtree(:part)) do
|
83
|
+
part[:options] = Transform.hashify_options(part[:options])
|
84
|
+
|
85
|
+
[String(o), part]
|
86
|
+
end
|
87
|
+
|
88
|
+
# Match an operator followed by a immediate value.
|
89
|
+
rule(op: simple(:o), value: simple(:v)) do
|
90
|
+
[String(o), Integer(v)]
|
80
91
|
end
|
81
92
|
end
|
82
93
|
end
|
data/lib/dicebag.rb
CHANGED
@@ -1,183 +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.0
|
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
|
-
else
|
77
|
-
StaticPart.new val
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
# This further massages the xDx hashes.
|
82
|
-
def self.normalize_xdx(hash)
|
83
|
-
count = hash[:xdx][:count]
|
84
|
-
sides = hash[:xdx][:sides]
|
85
|
-
|
86
|
-
# Delete the no longer needed :xdx key.
|
87
|
-
hash.delete(:xdx)
|
88
|
-
|
89
|
-
# Default to at least 1 die.
|
90
|
-
count = 1 if count.zero? || count.nil?
|
91
|
-
|
92
|
-
# Set the :count and :sides keys directly
|
93
|
-
# and set the notes array.
|
94
|
-
hash[:count] = count
|
95
|
-
hash[:sides] = sides
|
96
|
-
hash[:notes] = []
|
97
|
-
|
98
|
-
normalize_options hash
|
99
|
-
end
|
100
|
-
|
101
|
-
def self.normalize_options(hash)
|
102
|
-
if hash[:options].empty?
|
103
|
-
hash.delete(:options)
|
104
|
-
else
|
105
|
-
normalize_explode hash
|
106
|
-
normalize_reroll hash
|
107
|
-
normalize_drop_keep hash
|
108
|
-
normalize_target hash
|
109
|
-
end
|
110
|
-
|
111
|
-
hash
|
112
|
-
end
|
5
|
+
# This is our generic DiceBagError exception subclass.
|
6
|
+
class DiceBagError < StandardError; end
|
113
7
|
|
114
|
-
#
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
if explode.nil? || explode.zero? || explode == 1
|
121
|
-
xdx[:options][:explode] = xdx[:sides]
|
122
|
-
|
123
|
-
xdx[:notes].push("Explode set to #{xdx[:sides]}")
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
# Prevent Reroll abuse.
|
128
|
-
def self.normalize_reroll(xdx)
|
129
|
-
return unless xdx[:options].key? :reroll
|
130
|
-
|
131
|
-
if xdx[:options][:reroll] >= xdx[:sides]
|
132
|
-
xdx[:options][:reroll] = 0
|
133
|
-
|
134
|
-
xdx[: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(xdx)
|
142
|
-
drop = xdx[:options].fetch(:drop, 0)
|
143
|
-
keep = xdx[:options].fetch(:keep, 0)
|
144
|
-
|
145
|
-
if (drop + keep) >= xdx[:count]
|
146
|
-
xdx[:options][:drop] = 0
|
147
|
-
xdx[:options][:keep] = 0
|
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.
|
11
|
+
def self.parse(dstr = '')
|
12
|
+
tree = Parser.new.parse(dstr)
|
13
|
+
ast = Transform.new.apply(tree)
|
148
14
|
|
149
|
-
|
150
|
-
end
|
15
|
+
Normalize.call ast
|
151
16
|
end
|
152
17
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
def self.normalize_target(xdx)
|
157
|
-
return unless xdx[:options].key? :target
|
158
|
-
|
159
|
-
target = xdx[:options][:target]
|
160
|
-
|
161
|
-
return if target >= 0 && target <= xdx[:sides]
|
162
|
-
|
163
|
-
xdx[:options][:target] = 0
|
164
|
-
|
165
|
-
xdx[:notes].push 'Target number too large or is negative; reset to 0.'
|
18
|
+
### Main Syntatic Sugar Interface
|
19
|
+
def self.roll(dstr)
|
20
|
+
DiceBag::Roll.new(dstr).roll
|
166
21
|
end
|
167
22
|
|
168
|
-
#
|
169
|
-
|
170
|
-
|
171
|
-
# array of parsed bits for other purposes.
|
172
|
-
def self.parse(dstr = '')
|
173
|
-
tree = Parser.new.parse(dstr)
|
174
|
-
ast = Transform.new.apply(tree)
|
175
|
-
|
176
|
-
normalize_tree ast
|
23
|
+
# The default roll if one is not given.
|
24
|
+
def self.default_roll
|
25
|
+
'1d6'
|
177
26
|
end
|
178
27
|
end
|
179
28
|
|
180
29
|
# Our sub-modules.
|
30
|
+
require_relative './dicebag/normalize'
|
181
31
|
require_relative './dicebag/roll_string'
|
182
32
|
require_relative './dicebag/roll_part_string'
|
183
33
|
require_relative './dicebag/parser'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
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
|
-
date: 2016-04-
|
11
|
+
date: 2016-04-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parslet
|
@@ -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: []
|