diceguru 0.1.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.
- checksums.yaml +7 -0
- data/lib/dicebag.rb +194 -0
- metadata +44 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0bfa1a9bc2621613e65150ba835eb73fd688f347
|
4
|
+
data.tar.gz: 13f43f46fc9fa9d6242e2dd342cce5caaaa3e620
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a2760cdf0ec8860af51bde4caf8b28cb81080c24bac874162abbe3462cadb5bf472332309e79ffb48ac6a0d9a5ff0656a63f7cd58fa721c2881643650559f5a9
|
7
|
+
data.tar.gz: 36cf0336b2753f5b19c1da6abf9ce1178ba5c877ab48d9258196b5d2988fc76d083c0f338fb58718cdbfcc7f3aba9b482313a9a5388e78663a008baf707b5e6b
|
data/lib/dicebag.rb
ADDED
@@ -0,0 +1,194 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Kernel
|
5
|
+
def d
|
6
|
+
DiceBag.instance
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class DiceDSL
|
11
|
+
|
12
|
+
class << self
|
13
|
+
|
14
|
+
def parse(dices)
|
15
|
+
%r{^(?<top_or_bottom>t|b)?(?<tb_number>\d)?\[(?<dice>.*)\](?<explode>\*)?(?<plus>\+\d+)?\=?(?<target>.*)?$} =~ dices
|
16
|
+
die_set = eval "[" + string_to_dice_array(dice) + "]"
|
17
|
+
dice_pool({set: die_set, top: tb_number.to_i, plus: plus.to_i})
|
18
|
+
end
|
19
|
+
|
20
|
+
def dice_pool(*args)
|
21
|
+
DicePool.new(*args)
|
22
|
+
end
|
23
|
+
|
24
|
+
def string_to_dice_array(dice)
|
25
|
+
dice.gsub(/\s+/, '').
|
26
|
+
split("+").
|
27
|
+
map{|ds| ds.split('d') }.
|
28
|
+
collect {|how_many, dice_face| (["d^#{dice_face}"]*how_many.to_i ).join(",") }.
|
29
|
+
join(",")
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
class DiceBag
|
37
|
+
|
38
|
+
include Singleton
|
39
|
+
|
40
|
+
def ^(max)
|
41
|
+
@max = max
|
42
|
+
Die.new(sides: max)
|
43
|
+
end
|
44
|
+
|
45
|
+
def roll(what: self, plus: 0, keep: nil, how_many: nil)
|
46
|
+
raise "Must include :how_many if you pass an individual Die" unless how_many
|
47
|
+
keep = how_many if keep.nil?
|
48
|
+
DicePool.new set: how_many.times.collect{ what.clone.reroll }, top: keep, plus: plus
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
class Die
|
54
|
+
|
55
|
+
def initialize(sides: 6, plus: 0)
|
56
|
+
@plus = plus
|
57
|
+
@sides = sides
|
58
|
+
roll
|
59
|
+
end
|
60
|
+
|
61
|
+
def +(x)
|
62
|
+
@plus = x
|
63
|
+
reroll
|
64
|
+
end
|
65
|
+
|
66
|
+
def inspect; "d#{@sides}#{"+#{@plus}" unless @plus.zero?}=>#{value}"; end
|
67
|
+
|
68
|
+
def to_h
|
69
|
+
{sides: @sides, plus: @plus, value: value}
|
70
|
+
end
|
71
|
+
|
72
|
+
def value; @value; end
|
73
|
+
|
74
|
+
def roll; @value = rand(1..@sides)+@plus; self end
|
75
|
+
|
76
|
+
def reroll; roll; end
|
77
|
+
|
78
|
+
def to_s; value; end
|
79
|
+
|
80
|
+
def to_i; value; end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
class DicePool
|
85
|
+
|
86
|
+
attr_reader :how_many, :top_number_of_dice, :results, :plus, :set
|
87
|
+
attr_writer :how_many, :top_number_of_dice, :results, :plus
|
88
|
+
|
89
|
+
def initialize(set: nil, plus: 0, top: 2)
|
90
|
+
@set = set.is_a?(Die) ? [set] : set
|
91
|
+
raise 'Dice passed to DicePool must be instances of Die.' unless @set.any?{|s| s.is_a?(Die) }
|
92
|
+
@plus = plus
|
93
|
+
@how_many = 100_000
|
94
|
+
@top_number_of_dice = top
|
95
|
+
end
|
96
|
+
|
97
|
+
def highest(top: top_number_of_dice, re_roll: false)
|
98
|
+
reroll if re_roll
|
99
|
+
highest_results = set.sort_by{|d| d.value }.reverse[0..top-1]
|
100
|
+
return highest_results.map(&:to_i).inject(0){|sum,i| sum += i } + plus
|
101
|
+
end
|
102
|
+
alias :result :highest
|
103
|
+
|
104
|
+
def reroll
|
105
|
+
set.map(&:reroll)
|
106
|
+
self
|
107
|
+
end
|
108
|
+
|
109
|
+
def roll; reroll; end
|
110
|
+
|
111
|
+
def generate_results
|
112
|
+
@results = Hash.new(0)
|
113
|
+
how_many.times { @results[highest(top: top_number_of_dice, re_roll: true)] += 1 }
|
114
|
+
self
|
115
|
+
end
|
116
|
+
|
117
|
+
def graph(r=@results)
|
118
|
+
DiceGraph.new(r, how_many, top_number_of_dice).graph
|
119
|
+
end
|
120
|
+
|
121
|
+
def roll_results
|
122
|
+
set.inspect
|
123
|
+
end
|
124
|
+
|
125
|
+
def results
|
126
|
+
"results: #{(@results.sort_by {|k,v| k }).to_h.inspect}"
|
127
|
+
end
|
128
|
+
|
129
|
+
def total
|
130
|
+
highest(top: top_number_of_dice)
|
131
|
+
end
|
132
|
+
|
133
|
+
def inspect
|
134
|
+
puts "<DicePool:\n @set: #{@set.inspect}, @plus: #{plus}, @total: #{total}, @top: #{top_number_of_dice}>"
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.inspect
|
138
|
+
puts "<DicePool:\n @set: #{@set.inspect}, @plus: #{plus}, @total: #{total}, @top: #{top_number_of_dice}>"
|
139
|
+
end
|
140
|
+
|
141
|
+
def to_h
|
142
|
+
{
|
143
|
+
top: top_number_of_dice,
|
144
|
+
total: total,
|
145
|
+
plus: plus,
|
146
|
+
set: @set.map(&:to_h)
|
147
|
+
}
|
148
|
+
end
|
149
|
+
|
150
|
+
def to_json
|
151
|
+
to_h.to_json
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
class DiceGraph
|
157
|
+
|
158
|
+
def initialize(r, how_many, top_number_of_dice)
|
159
|
+
@data = generate_text_graph(r, how_many, top_number_of_dice)
|
160
|
+
end
|
161
|
+
|
162
|
+
def graph
|
163
|
+
@data
|
164
|
+
end
|
165
|
+
|
166
|
+
def generate_text_graph(r, how_many, top_number_of_dice)
|
167
|
+
raise "There are no statistical results to graph. Run :generate_results" unless r
|
168
|
+
data = "Running #{how_many} times, taking the top #{top_number_of_dice}, the breakdown of results by value rolled are:"
|
169
|
+
data << "\n" + ("◘" * 30) + "\n"
|
170
|
+
r.sort.each do |total, count|
|
171
|
+
percentage = (count.to_f/how_many.to_f)
|
172
|
+
data << sprintf("%3d ", total)
|
173
|
+
data << '('
|
174
|
+
data << sprintf("%5.2f", percentage * 100)
|
175
|
+
data << "%) "
|
176
|
+
dots = (percentage*500).to_i
|
177
|
+
if dots > 100
|
178
|
+
data << '▃' * 80
|
179
|
+
data << "*(#{dots})"
|
180
|
+
else
|
181
|
+
data << '▃' * (percentage*500).to_i
|
182
|
+
end
|
183
|
+
data << "\n"
|
184
|
+
end
|
185
|
+
data
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
Dice = DiceBag.instance
|
191
|
+
|
192
|
+
|
193
|
+
# ds=DiceDSL.parse("3[4d6]"); [ds.reroll.total, ds.reroll.total, ds.reroll.total, ds.reroll.total, ds.reroll.total, ds.reroll.total]
|
194
|
+
# h=[]; (2..7).each {|e| (2..7).each {|i| (0..12).each {|plus| 1_000.times {|x| if e > i; e = i; end; h << DiceDSL.parse("#{e}[#{i}d6]+#{plus}").to_h } } } }
|
metadata
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: diceguru
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matt Petty
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-11-28 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Roll sets of dice and generate statistical information
|
14
|
+
email: matt@kizmeta.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/dicebag.rb
|
20
|
+
homepage: http://rubygems.org/gems/diceguru
|
21
|
+
licenses:
|
22
|
+
- MIT
|
23
|
+
metadata: {}
|
24
|
+
post_install_message:
|
25
|
+
rdoc_options: []
|
26
|
+
require_paths:
|
27
|
+
- lib
|
28
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
34
|
+
requirements:
|
35
|
+
- - ">="
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
requirements: []
|
39
|
+
rubyforge_project:
|
40
|
+
rubygems_version: 2.2.2
|
41
|
+
signing_key:
|
42
|
+
specification_version: 4
|
43
|
+
summary: Dice roller and statistic generation
|
44
|
+
test_files: []
|