tabletop 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -1
- data/README.markdown +16 -1
- data/lib/tabletop.rb +2 -1
- data/lib/tabletop/deck.rb +111 -0
- data/lib/tabletop/pool.rb +22 -5
- data/lib/tabletop/version.rb +1 -1
- data/spec/deck_spec.rb +155 -0
- data/spec/fixnum_spec.rb +2 -2
- data/spec/pool_spec.rb +48 -25
- data/spec/spec_helper.rb +3 -14
- data/tabletop.gemspec +1 -0
- metadata +166 -2
data/.gitignore
CHANGED
data/README.markdown
CHANGED
@@ -124,7 +124,22 @@ So, possible results for our cool AW roll:
|
|
124
124
|
open_brain.roll
|
125
125
|
puts open_brain.result #=> 10
|
126
126
|
puts open_brain.effects #=> ["the MC will tell you something new and interesting about the current situation", "...and it's a good detail"]
|
127
|
-
|
127
|
+
|
128
|
+
### Decks
|
129
|
+
|
130
|
+
Decks are essentially weighted hashes with a random #draw method. You can put whatever hashable object you like in a
|
131
|
+
deck (there's no Card class yet) as a key to a value that indicates the number of copies of that object in the deck.
|
132
|
+
|
133
|
+
#draw returns another deck, and reduces the number of cards in the original deck appropriately.
|
134
|
+
|
135
|
+
d = Deck.new
|
136
|
+
d["card A"] = 20
|
137
|
+
d["card B"] = 19
|
138
|
+
d.deck_size #=> 39
|
139
|
+
hand = d.draw(3) #=> {"card A"=>1, "card B" =>2}
|
140
|
+
d #=> {"card A" => 19, "card B"=>17}
|
141
|
+
d << hand #=> {"card A" => 20, "card B"=>19}
|
142
|
+
|
128
143
|
### Coming Soon
|
129
144
|
|
130
145
|
That's already enough functionality to do many different kinds of rolls, but there's a lot more in store.
|
data/lib/tabletop.rb
CHANGED
@@ -0,0 +1,111 @@
|
|
1
|
+
module Tabletop
|
2
|
+
class DrawMoreCardsThanDeckHasError < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
class Deck < Hash
|
6
|
+
def initialize
|
7
|
+
super(0)
|
8
|
+
end
|
9
|
+
|
10
|
+
def << object
|
11
|
+
if object.respond_to? :merge
|
12
|
+
merge(object) {|card,ours,new| ours+new}
|
13
|
+
else
|
14
|
+
self[object] = 1
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def deck_size
|
19
|
+
self.values.inject(:+)
|
20
|
+
end
|
21
|
+
|
22
|
+
def draw(cards=1)
|
23
|
+
raise DrawMoreCardsThanDeckHasError if cards > self.deck_size
|
24
|
+
drawable_cards = self.clone
|
25
|
+
if block_given?
|
26
|
+
drawable_cards = drawable_cards.keep_if {|card,copies| yield(card,copies) }
|
27
|
+
return nil if drawable_cards.empty?
|
28
|
+
# can't use select here, since that returns a Hash instead of a Deck
|
29
|
+
end
|
30
|
+
drawn = Deck.new
|
31
|
+
cards.times do
|
32
|
+
running_weight = 0
|
33
|
+
n = rand*drawable_cards.deck_size
|
34
|
+
drawable_cards.each do |card, weight|
|
35
|
+
if running_weight < n && n <= running_weight + weight
|
36
|
+
self[card] -= 1
|
37
|
+
drawable_cards[card] -= 1
|
38
|
+
drawn << card
|
39
|
+
end
|
40
|
+
running_weight += weight
|
41
|
+
end
|
42
|
+
end
|
43
|
+
drawn
|
44
|
+
end
|
45
|
+
|
46
|
+
def possible_starting_hands(hand_size=7)
|
47
|
+
|
48
|
+
# at any moment, there is some set of cards A that have the highest values, countA
|
49
|
+
# (ie, there's the most of them in the deck)
|
50
|
+
# there may also be some set of cards B that have the next-highest values, countB
|
51
|
+
#
|
52
|
+
# in the case of there only being As
|
53
|
+
# the most likely combinations are equal numbers of each of them, or as close to that as possible.
|
54
|
+
# if A.size is 1, and countA is greater than hand_size
|
55
|
+
# the first and last combination would be {A1=>hand_size}
|
56
|
+
# if A.size is 1, and countA is less than hand_size...
|
57
|
+
# then raise an exception, of course
|
58
|
+
# if A.size is 2, and countA is greater than hand_size
|
59
|
+
# the first combination would be {A1=>hand}
|
60
|
+
# if A.size is 2, and 2*countA is greater than hand_size
|
61
|
+
# if A.size is 2, and 2*countA is less than hand_size, then again, exception
|
62
|
+
#
|
63
|
+
# So the first set of combinations has as it's left term
|
64
|
+
# countA-countB of each card in A
|
65
|
+
# and as it's right term,
|
66
|
+
#
|
67
|
+
# they are likely
|
68
|
+
# n = copies of most popular card - copies of next most popular card
|
69
|
+
#
|
70
|
+
# first_hand = n copies of most popular card, up to seven
|
71
|
+
# now there is some number A>=2 of cards that are equally likely
|
72
|
+
# If A >= 7-n
|
73
|
+
# first_hand << unique (k-n)-combinations of those A cards
|
74
|
+
# if A < 7-n (that is, if )
|
75
|
+
cards_uniq = self.keys
|
76
|
+
Enumerator.new do |hands|
|
77
|
+
|
78
|
+
counts = self.values.uniq.sort
|
79
|
+
|
80
|
+
cards_uniq.repeated_combination(hand_size).each do |a|
|
81
|
+
hands << a if self.possible_hand?(a)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def possible_hand?(array)
|
87
|
+
hand = Hash.new(0)
|
88
|
+
array.each { |e| hand[e] +=1 }
|
89
|
+
hand.each {|card, number| return false if (self[card].nil? or self[card] < number) }
|
90
|
+
true
|
91
|
+
end
|
92
|
+
|
93
|
+
def chance_to_draw(cards)
|
94
|
+
if Array === cards
|
95
|
+
copy = self.clone
|
96
|
+
odds = 1
|
97
|
+
cards.each do |card|
|
98
|
+
odds *= copy.chance_to_draw(card)
|
99
|
+
copy[card] -= 1
|
100
|
+
end
|
101
|
+
odds
|
102
|
+
else
|
103
|
+
if self[cards] and self[cards] != 0
|
104
|
+
Float(self[cards])/self.deck_size
|
105
|
+
else
|
106
|
+
0
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
data/lib/tabletop/pool.rb
CHANGED
@@ -77,7 +77,7 @@ module Tabletop
|
|
77
77
|
end
|
78
78
|
|
79
79
|
# Returns a string of the pool's dice in d-notation
|
80
|
-
def
|
80
|
+
def d_notation
|
81
81
|
fudge = nil
|
82
82
|
result = {}
|
83
83
|
each do |die|
|
@@ -100,9 +100,26 @@ module Tabletop
|
|
100
100
|
end
|
101
101
|
|
102
102
|
# Rolls every die in the pool, and returns the Pool.
|
103
|
-
def roll
|
103
|
+
def roll(params={})
|
104
104
|
each do |die|
|
105
|
-
|
105
|
+
|
106
|
+
meets_all_conditions = true
|
107
|
+
|
108
|
+
params.each do |condition, term|
|
109
|
+
attribute, comparison = condition.to_s.split("_")
|
110
|
+
die_att = die.send(attribute.to_sym)
|
111
|
+
|
112
|
+
case comparison
|
113
|
+
when "under"
|
114
|
+
meets_all_conditions = false unless die_att < term
|
115
|
+
when "over"
|
116
|
+
meets_all_conditions = false unless die_att > term
|
117
|
+
when "equals"
|
118
|
+
meets_all_conditions = false unless die_att == term
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
die.roll if meets_all_conditions
|
106
123
|
end
|
107
124
|
self
|
108
125
|
end
|
@@ -167,13 +184,13 @@ module Tabletop
|
|
167
184
|
# of values) passed.
|
168
185
|
def drop(to_drop)
|
169
186
|
to_drop = [to_drop].flatten #turn it into an array if it isn't one.
|
170
|
-
kept = reject{|die| to_drop.
|
187
|
+
kept = reject{|die| to_drop.include?{die.value}}
|
171
188
|
Pool.new(kept)
|
172
189
|
end
|
173
190
|
|
174
191
|
private
|
175
192
|
def new_union(array)
|
176
|
-
union = [self, array].flatten
|
193
|
+
union = [self, array].flatten # avoid using + in implementation of +
|
177
194
|
new_pool =[]
|
178
195
|
union.each do |die|
|
179
196
|
new_pool << die.class.new(sides:die.sides, value:die.value)
|
data/lib/tabletop/version.rb
CHANGED
data/spec/deck_spec.rb
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
module Tabletop
|
5
|
+
describe Deck do
|
6
|
+
let(:d) do
|
7
|
+
deck = Deck.new
|
8
|
+
deck["Forest"] = 8
|
9
|
+
deck["Mountain"] = 3
|
10
|
+
deck["Island"] = 3
|
11
|
+
deck["Rootbound Crag"] = 4
|
12
|
+
deck["Hinterland Harbor"] = 4
|
13
|
+
deck["Llanowar Elves"] = 3
|
14
|
+
deck["Birds of Paradise"] = 4
|
15
|
+
deck["Phantasmal Image"] = 4
|
16
|
+
deck["Viridian Emissary"] = 4
|
17
|
+
deck["Phyrexian Metamorph"] = 4
|
18
|
+
deck["Acidic Slime"] = 4
|
19
|
+
deck["Inferno Titan"] = 4
|
20
|
+
deck["Wurmcoil Engine"] = 4
|
21
|
+
deck["Rampant Growth"] = 4
|
22
|
+
deck["Lead the Stampede"] = 3
|
23
|
+
deck
|
24
|
+
end
|
25
|
+
it "defaults to having zero of things" do
|
26
|
+
subject["Random Object"].should == 0
|
27
|
+
end
|
28
|
+
describe "#deck_size" do
|
29
|
+
it "counts all the cards" do
|
30
|
+
d.deck_size.should == 60
|
31
|
+
end
|
32
|
+
end
|
33
|
+
describe "<<" do
|
34
|
+
it "merges, summing together the values of collisions" do
|
35
|
+
deck_a = Deck.new()
|
36
|
+
deck_a["card A"] =1
|
37
|
+
deck_a["card B"] = 1
|
38
|
+
deck_b = Deck.new()
|
39
|
+
deck_b["card B"] =2
|
40
|
+
deck_b["card C"] =2
|
41
|
+
merged_deck = deck_a.merge(deck_b) {|k,o,n| o+n}
|
42
|
+
(deck_a << deck_b).should == merged_deck
|
43
|
+
end
|
44
|
+
end
|
45
|
+
describe "#draw" do
|
46
|
+
it "returns a deck containing a random card and decrements that card's copy count in the calling object" do
|
47
|
+
srand(1841922)
|
48
|
+
d.draw.should == {"Acidic Slime"=>1}
|
49
|
+
d["Acidic Slime"].should == 3
|
50
|
+
end
|
51
|
+
context "with one parameter" do
|
52
|
+
it "returns that many cards" do
|
53
|
+
d.draw(3).length.should == 3
|
54
|
+
end
|
55
|
+
it "raises an exception when you try to draw too many" do
|
56
|
+
expect {d.draw(61)}.to raise_error DrawMoreCardsThanDeckHasError
|
57
|
+
end
|
58
|
+
end
|
59
|
+
context "when passed a block " do
|
60
|
+
it "returns a random card for which the block returns true" do
|
61
|
+
srand(1841922)
|
62
|
+
d.draw {|card, copies| true}.should == {"Acidic Slime"=>1}
|
63
|
+
srand(1841922)
|
64
|
+
d.draw do |card, copies|
|
65
|
+
card == "Forest" or card == "Island" or card == "Mountain"
|
66
|
+
end.should == {"Mountain"=> 1}
|
67
|
+
end
|
68
|
+
it "returns nil if the card is not present" do
|
69
|
+
srand(1841922)
|
70
|
+
d.draw {|card, copies| false}.should be_nil
|
71
|
+
d.draw do |card, copies|
|
72
|
+
card == "Sir Not Appearing in this Test"
|
73
|
+
end.should be_nil
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
describe "#chance_to_draw" do
|
78
|
+
context "when passed a card" do
|
79
|
+
it "returns the odds of drawing that card from the deck" do
|
80
|
+
size = d.deck_size
|
81
|
+
d.each do |card,copies|
|
82
|
+
d.chance_to_draw(card).should == Float(copies)/size
|
83
|
+
end
|
84
|
+
d.chance_to_draw("A Card it Doesn't Have").should == 0
|
85
|
+
end
|
86
|
+
end
|
87
|
+
context "when passed an array of cards" do
|
88
|
+
it "returns the odds of drawing all the cards in the array from a draw of {array.length} cards" do
|
89
|
+
d.chance_to_draw(["Acidic Slime"]).should == d.chance_to_draw("Acidic Slime")
|
90
|
+
d.chance_to_draw(["Acidic Slime", "Phyrexian Metamorph"]).should == Float(4*4)/(60*59)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
describe "#possible_starting_hands" do
|
95
|
+
def factorial(number)
|
96
|
+
(1..number).inject(:*)
|
97
|
+
end
|
98
|
+
def combinations(n,k)
|
99
|
+
factorial(n) / (factorial(k) * factorial(n-k))
|
100
|
+
end
|
101
|
+
def check_psh(deck, hand_size)
|
102
|
+
number_of_unique_cards = deck.length
|
103
|
+
guess_hands = combinations(hand_size+number_of_unique_cards-1, hand_size)
|
104
|
+
# Important note: the following only calculates combinations which have too many of any single card
|
105
|
+
# for a hand of size N, there are some combinations of K cards (c1, c2, ... ck) which are impossible
|
106
|
+
# how many integers between 2 and N are there which add to N?
|
107
|
+
# make a recursive function for that, tail case
|
108
|
+
# answer << [self]
|
109
|
+
# if == 2, return 1, 1
|
110
|
+
# then return (1..self-1).each {|v| add_up_to(self-v).each {|w| [v,w]}}
|
111
|
+
unless hand_size == 1
|
112
|
+
deck.each do |card, copies|
|
113
|
+
if copies == hand_size-1
|
114
|
+
guess_hands -= 1 #there is only one impossible hand in that case: a full hand of the card in question
|
115
|
+
elsif copies < hand_size # that is, if more copies of the card than exist might be in a possible hand
|
116
|
+
guess_hands -= combinations(hand_size - (copies+1) + number_of_unique_cards - 1,
|
117
|
+
hand_size - (copies+1))
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
if hand_size == 7
|
123
|
+
deck.possible_starting_hands.to_a.length.should == guess_hands
|
124
|
+
else
|
125
|
+
deck.possible_starting_hands(hand_size).to_a.length.should == guess_hands
|
126
|
+
end
|
127
|
+
end
|
128
|
+
it "enumerates all possible hand of a passed size (default 7)" do
|
129
|
+
7.downto(1).each do |hand|
|
130
|
+
check_psh(d, hand)
|
131
|
+
end
|
132
|
+
deck = Deck.new
|
133
|
+
deck["card a"] = 20
|
134
|
+
deck["card b"] = 20
|
135
|
+
thing = []
|
136
|
+
deck.possible_starting_hands.each do |hand|
|
137
|
+
thing << [-1*deck.chance_to_draw(hand), hand]
|
138
|
+
end
|
139
|
+
p thing.sort
|
140
|
+
end
|
141
|
+
it "enumerates in descending order of likelihood" do
|
142
|
+
pending "discovery of the algorithm"
|
143
|
+
best_odds = 1
|
144
|
+
deck = Deck.new
|
145
|
+
deck["card a"] = 20
|
146
|
+
deck["card b"] = 20
|
147
|
+
deck.possible_starting_hands.each do |hand|
|
148
|
+
chance = deck.chance_to_draw(hand)
|
149
|
+
chance.should <= best_odds
|
150
|
+
best_odds = chance
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
data/spec/fixnum_spec.rb
CHANGED
@@ -5,7 +5,7 @@ module Tabletop
|
|
5
5
|
describe "#dX" do
|
6
6
|
it "generates a pool of the appropriate size and type" do
|
7
7
|
1.d6.should be_instance_of(Pool)
|
8
|
-
4.d7.
|
8
|
+
4.d7.d_notation.should == ["4d7"]
|
9
9
|
10.d100.should be_instance_of(Pool)
|
10
10
|
end
|
11
11
|
|
@@ -23,7 +23,7 @@ module Tabletop
|
|
23
23
|
sotc = 4.dF
|
24
24
|
sotc.should be_instance_of(Pool)
|
25
25
|
sotc.all? { |d| d.instance_of?(FudgeDie) }.should be_true
|
26
|
-
sotc.
|
26
|
+
sotc.d_notation.should == ["4dF"]
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
data/spec/pool_spec.rb
CHANGED
@@ -33,9 +33,9 @@ module Tabletop
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
describe "#
|
36
|
+
describe "#d_notation" do
|
37
37
|
it "should return an array of dice notation" do
|
38
|
-
Pool.new("d20 2dF 2d10").
|
38
|
+
Pool.new("d20 2dF 2d10").d_notation.should == ["2d10","d20", "2dF"]
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -48,42 +48,39 @@ module Tabletop
|
|
48
48
|
end
|
49
49
|
|
50
50
|
describe "+" do
|
51
|
-
before(:each) do
|
52
|
-
@a = 5.d6
|
53
|
-
end
|
54
51
|
context "adding a number" do
|
55
52
|
it "should return the pool's sum plus the number" do
|
56
|
-
(
|
53
|
+
(d6_set + 5).should == d6_set.sum + 5
|
57
54
|
end
|
58
55
|
end
|
59
56
|
context "adding a randomizer" do
|
60
57
|
it "adds to the pool" do
|
61
|
-
|
62
|
-
mixed.length.should == 6
|
58
|
+
(d6_set + Die.new).length.should == 7
|
63
59
|
end
|
64
60
|
it "preserves class" do
|
65
|
-
(
|
66
|
-
(
|
61
|
+
(d6_set + FudgeDie.new(value:-1))[-1].value.should == -1
|
62
|
+
(d6_set + Coin.new)[-1].should respond_to :flip
|
67
63
|
end
|
68
64
|
end
|
69
65
|
context "adding another pool" do
|
70
|
-
|
71
|
-
|
72
|
-
@merge = @a+@b
|
73
|
-
end
|
66
|
+
let(:d4_set) { 4.d4 }
|
67
|
+
let(:merge) { d6_set+d4_set }
|
74
68
|
it "should make a union of the pools" do
|
75
|
-
|
69
|
+
merge.values.should == d6_set.values + d4_set.values
|
76
70
|
end
|
77
71
|
it "should make new die objects" do
|
78
|
-
|
79
|
-
|
72
|
+
a = 1.d6
|
73
|
+
b = 1.d4
|
74
|
+
merge = a+b
|
75
|
+
merge.roll
|
76
|
+
merge.values.should_not == a.values + b.values
|
80
77
|
end
|
81
78
|
it "should persist die types" do
|
82
79
|
(Pool.new("d6")+Pool.new("dF"))[1].should be_instance_of(FudgeDie)
|
83
80
|
(Pool.new("d6")+Pool.new([Coin.new]))[1].should respond_to(:flip)
|
84
81
|
end
|
85
82
|
it "should alter #dice accordingly" do
|
86
|
-
(Pool.new("2d17 d6")+Pool.new("3d17")).
|
83
|
+
(Pool.new("2d17 d6")+Pool.new("3d17")).d_notation.should == ["d6", "5d17"]
|
87
84
|
end
|
88
85
|
end
|
89
86
|
context "adding anything else" do
|
@@ -121,6 +118,13 @@ module Tabletop
|
|
121
118
|
end
|
122
119
|
|
123
120
|
describe "#roll" do
|
121
|
+
before :each do
|
122
|
+
@d1, @d2, @d3= double("a die"), double("a die"), double("a die")
|
123
|
+
@d1.stub(:value).and_return(1)
|
124
|
+
@d2.stub(:value).and_return(2)
|
125
|
+
@d3.stub(:value).and_return(3)
|
126
|
+
@p = Pool.new([@d1, @d2, @d3])
|
127
|
+
end
|
124
128
|
it "should return the Pool itself" do
|
125
129
|
actual = d6_set.roll
|
126
130
|
d6_set.length.times do |i|
|
@@ -128,15 +132,34 @@ module Tabletop
|
|
128
132
|
actual[i].sides.should == d6_set[i].sides
|
129
133
|
end
|
130
134
|
end
|
131
|
-
|
135
|
+
|
132
136
|
it "calls roll on its contents" do
|
133
|
-
|
134
|
-
|
135
|
-
|
137
|
+
@d1.should_receive(:roll)
|
138
|
+
@d2.should_receive(:roll)
|
139
|
+
@d3.should_receive(:roll)
|
140
|
+
@p.roll
|
141
|
+
end
|
142
|
+
it "can roll only dice less than a certain value" do
|
143
|
+
@d1.should_receive(:roll)
|
144
|
+
@d2.should_not_receive(:roll)
|
145
|
+
@d3.should_not_receive(:roll)
|
146
|
+
|
147
|
+
@p.roll(:value_under=>2)
|
148
|
+
end
|
149
|
+
it "can roll only dice above a certain value" do
|
150
|
+
@d1.should_not_receive(:roll)
|
151
|
+
@d2.should_not_receive(:roll)
|
152
|
+
@d3.should_receive(:roll)
|
153
|
+
|
154
|
+
@p.roll(:value_over=>2)
|
155
|
+
end
|
156
|
+
it "can roll only dice equal to a certain value" do
|
157
|
+
@d1.should_not_receive(:roll)
|
158
|
+
@d2.should_receive(:roll)
|
159
|
+
@d3.should_not_receive(:roll)
|
160
|
+
|
161
|
+
@p.roll(:value_equals=>2)
|
136
162
|
end
|
137
|
-
it "can roll only dice below a certain value"
|
138
|
-
it "can roll only dice above a certain value"
|
139
|
-
it "can roll only dice equal to a certain value"
|
140
163
|
end
|
141
164
|
|
142
165
|
describe "#roll_if" do
|
data/spec/spec_helper.rb
CHANGED
@@ -1,15 +1,4 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
Bundler.setup
|
4
|
-
rescue Bundler::BundlerError => e
|
5
|
-
$stderr.puts e.message
|
6
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
7
|
-
exit e.status_code
|
8
|
-
end
|
9
|
-
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start
|
10
3
|
require 'rspec'
|
11
|
-
require 'tabletop'
|
12
|
-
|
13
|
-
# Requires supporting files with custom matchers and macros, etc,
|
14
|
-
# in ./support/ and its subdirectories.
|
15
|
-
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
4
|
+
require 'tabletop'
|
data/tabletop.gemspec
CHANGED
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: tabletop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.4.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Nick Novitski
|
@@ -67,6 +67,17 @@ dependencies:
|
|
67
67
|
type: :development
|
68
68
|
prerelease: false
|
69
69
|
version_requirements: *id005
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: simplecov
|
72
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: "0"
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: *id006
|
70
81
|
description: Tabletop aims to provide a simple way of describing, automating and tracking the tools and tasks involved in "analog" games, determining results from the motions and properties of various dice and chips.
|
71
82
|
email: nicknovitski@gmail.com
|
72
83
|
executables: []
|
@@ -77,6 +88,56 @@ extra_rdoc_files:
|
|
77
88
|
- LICENSE
|
78
89
|
- README.markdown
|
79
90
|
files:
|
91
|
+
- coverage/assets/0.5.3/app.js
|
92
|
+
- coverage/assets/0.5.3/fancybox/blank.gif
|
93
|
+
- coverage/assets/0.5.3/fancybox/fancy_close.png
|
94
|
+
- coverage/assets/0.5.3/fancybox/fancy_loading.png
|
95
|
+
- coverage/assets/0.5.3/fancybox/fancy_nav_left.png
|
96
|
+
- coverage/assets/0.5.3/fancybox/fancy_nav_right.png
|
97
|
+
- coverage/assets/0.5.3/fancybox/fancy_shadow_e.png
|
98
|
+
- coverage/assets/0.5.3/fancybox/fancy_shadow_n.png
|
99
|
+
- coverage/assets/0.5.3/fancybox/fancy_shadow_ne.png
|
100
|
+
- coverage/assets/0.5.3/fancybox/fancy_shadow_nw.png
|
101
|
+
- coverage/assets/0.5.3/fancybox/fancy_shadow_s.png
|
102
|
+
- coverage/assets/0.5.3/fancybox/fancy_shadow_se.png
|
103
|
+
- coverage/assets/0.5.3/fancybox/fancy_shadow_sw.png
|
104
|
+
- coverage/assets/0.5.3/fancybox/fancy_shadow_w.png
|
105
|
+
- coverage/assets/0.5.3/fancybox/fancy_title_left.png
|
106
|
+
- coverage/assets/0.5.3/fancybox/fancy_title_main.png
|
107
|
+
- coverage/assets/0.5.3/fancybox/fancy_title_over.png
|
108
|
+
- coverage/assets/0.5.3/fancybox/fancy_title_right.png
|
109
|
+
- coverage/assets/0.5.3/fancybox/fancybox-x.png
|
110
|
+
- coverage/assets/0.5.3/fancybox/fancybox-y.png
|
111
|
+
- coverage/assets/0.5.3/fancybox/fancybox.png
|
112
|
+
- coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.css
|
113
|
+
- coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.pack.js
|
114
|
+
- coverage/assets/0.5.3/favicon_green.png
|
115
|
+
- coverage/assets/0.5.3/favicon_red.png
|
116
|
+
- coverage/assets/0.5.3/favicon_yellow.png
|
117
|
+
- coverage/assets/0.5.3/highlight.css
|
118
|
+
- coverage/assets/0.5.3/highlight.pack.js
|
119
|
+
- coverage/assets/0.5.3/jquery-1.6.2.min.js
|
120
|
+
- coverage/assets/0.5.3/jquery.dataTables.min.js
|
121
|
+
- coverage/assets/0.5.3/jquery.timeago.js
|
122
|
+
- coverage/assets/0.5.3/jquery.url.js
|
123
|
+
- coverage/assets/0.5.3/loading.gif
|
124
|
+
- coverage/assets/0.5.3/magnify.png
|
125
|
+
- coverage/assets/0.5.3/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
|
126
|
+
- coverage/assets/0.5.3/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
|
127
|
+
- coverage/assets/0.5.3/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
|
128
|
+
- coverage/assets/0.5.3/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
|
129
|
+
- coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_dadada_1x400.png
|
130
|
+
- coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
|
131
|
+
- coverage/assets/0.5.3/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
|
132
|
+
- coverage/assets/0.5.3/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
|
133
|
+
- coverage/assets/0.5.3/smoothness/images/ui-icons_222222_256x240.png
|
134
|
+
- coverage/assets/0.5.3/smoothness/images/ui-icons_2e83ff_256x240.png
|
135
|
+
- coverage/assets/0.5.3/smoothness/images/ui-icons_454545_256x240.png
|
136
|
+
- coverage/assets/0.5.3/smoothness/images/ui-icons_888888_256x240.png
|
137
|
+
- coverage/assets/0.5.3/smoothness/images/ui-icons_cd0a0a_256x240.png
|
138
|
+
- coverage/assets/0.5.3/smoothness/jquery-ui-1.8.4.custom.css
|
139
|
+
- coverage/assets/0.5.3/stylesheet.css
|
140
|
+
- coverage/index.html
|
80
141
|
- doc/created.rid
|
81
142
|
- doc/Fixnum.html
|
82
143
|
- doc/images/brick.png
|
@@ -124,6 +185,7 @@ files:
|
|
124
185
|
- Gemfile
|
125
186
|
- lib/fixnum.rb
|
126
187
|
- lib/tabletop/condition.rb
|
188
|
+
- lib/tabletop/deck.rb
|
127
189
|
- lib/tabletop/pool.rb
|
128
190
|
- lib/tabletop/randomizers.rb
|
129
191
|
- lib/tabletop/roll.rb
|
@@ -134,6 +196,57 @@ files:
|
|
134
196
|
- Rakefile
|
135
197
|
- README.markdown
|
136
198
|
- spec/condition_spec.rb
|
199
|
+
- spec/coverage/assets/0.5.3/app.js
|
200
|
+
- spec/coverage/assets/0.5.3/fancybox/blank.gif
|
201
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_close.png
|
202
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_loading.png
|
203
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_nav_left.png
|
204
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_nav_right.png
|
205
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_shadow_e.png
|
206
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_shadow_n.png
|
207
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_shadow_ne.png
|
208
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_shadow_nw.png
|
209
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_shadow_s.png
|
210
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_shadow_se.png
|
211
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_shadow_sw.png
|
212
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_shadow_w.png
|
213
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_title_left.png
|
214
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_title_main.png
|
215
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_title_over.png
|
216
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_title_right.png
|
217
|
+
- spec/coverage/assets/0.5.3/fancybox/fancybox-x.png
|
218
|
+
- spec/coverage/assets/0.5.3/fancybox/fancybox-y.png
|
219
|
+
- spec/coverage/assets/0.5.3/fancybox/fancybox.png
|
220
|
+
- spec/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.css
|
221
|
+
- spec/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.pack.js
|
222
|
+
- spec/coverage/assets/0.5.3/favicon_green.png
|
223
|
+
- spec/coverage/assets/0.5.3/favicon_red.png
|
224
|
+
- spec/coverage/assets/0.5.3/favicon_yellow.png
|
225
|
+
- spec/coverage/assets/0.5.3/highlight.css
|
226
|
+
- spec/coverage/assets/0.5.3/highlight.pack.js
|
227
|
+
- spec/coverage/assets/0.5.3/jquery-1.6.2.min.js
|
228
|
+
- spec/coverage/assets/0.5.3/jquery.dataTables.min.js
|
229
|
+
- spec/coverage/assets/0.5.3/jquery.timeago.js
|
230
|
+
- spec/coverage/assets/0.5.3/jquery.url.js
|
231
|
+
- spec/coverage/assets/0.5.3/loading.gif
|
232
|
+
- spec/coverage/assets/0.5.3/magnify.png
|
233
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
|
234
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
|
235
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
|
236
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
|
237
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_dadada_1x400.png
|
238
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
|
239
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
|
240
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
|
241
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-icons_222222_256x240.png
|
242
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-icons_2e83ff_256x240.png
|
243
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-icons_454545_256x240.png
|
244
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-icons_888888_256x240.png
|
245
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-icons_cd0a0a_256x240.png
|
246
|
+
- spec/coverage/assets/0.5.3/smoothness/jquery-ui-1.8.4.custom.css
|
247
|
+
- spec/coverage/assets/0.5.3/stylesheet.css
|
248
|
+
- spec/coverage/index.html
|
249
|
+
- spec/deck_spec.rb
|
137
250
|
- spec/fixnum_spec.rb
|
138
251
|
- spec/pool_spec.rb
|
139
252
|
- spec/randomizers_spec.rb
|
@@ -155,7 +268,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
155
268
|
requirements:
|
156
269
|
- - ">="
|
157
270
|
- !ruby/object:Gem::Version
|
158
|
-
hash:
|
271
|
+
hash: -2442987682132944901
|
159
272
|
segments:
|
160
273
|
- 0
|
161
274
|
version: "0"
|
@@ -174,6 +287,57 @@ specification_version: 3
|
|
174
287
|
summary: An RPG and tabletop game library
|
175
288
|
test_files:
|
176
289
|
- spec/condition_spec.rb
|
290
|
+
- spec/coverage/assets/0.5.3/app.js
|
291
|
+
- spec/coverage/assets/0.5.3/fancybox/blank.gif
|
292
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_close.png
|
293
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_loading.png
|
294
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_nav_left.png
|
295
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_nav_right.png
|
296
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_shadow_e.png
|
297
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_shadow_n.png
|
298
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_shadow_ne.png
|
299
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_shadow_nw.png
|
300
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_shadow_s.png
|
301
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_shadow_se.png
|
302
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_shadow_sw.png
|
303
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_shadow_w.png
|
304
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_title_left.png
|
305
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_title_main.png
|
306
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_title_over.png
|
307
|
+
- spec/coverage/assets/0.5.3/fancybox/fancy_title_right.png
|
308
|
+
- spec/coverage/assets/0.5.3/fancybox/fancybox-x.png
|
309
|
+
- spec/coverage/assets/0.5.3/fancybox/fancybox-y.png
|
310
|
+
- spec/coverage/assets/0.5.3/fancybox/fancybox.png
|
311
|
+
- spec/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.css
|
312
|
+
- spec/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.pack.js
|
313
|
+
- spec/coverage/assets/0.5.3/favicon_green.png
|
314
|
+
- spec/coverage/assets/0.5.3/favicon_red.png
|
315
|
+
- spec/coverage/assets/0.5.3/favicon_yellow.png
|
316
|
+
- spec/coverage/assets/0.5.3/highlight.css
|
317
|
+
- spec/coverage/assets/0.5.3/highlight.pack.js
|
318
|
+
- spec/coverage/assets/0.5.3/jquery-1.6.2.min.js
|
319
|
+
- spec/coverage/assets/0.5.3/jquery.dataTables.min.js
|
320
|
+
- spec/coverage/assets/0.5.3/jquery.timeago.js
|
321
|
+
- spec/coverage/assets/0.5.3/jquery.url.js
|
322
|
+
- spec/coverage/assets/0.5.3/loading.gif
|
323
|
+
- spec/coverage/assets/0.5.3/magnify.png
|
324
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
|
325
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
|
326
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
|
327
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
|
328
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_dadada_1x400.png
|
329
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
|
330
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
|
331
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
|
332
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-icons_222222_256x240.png
|
333
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-icons_2e83ff_256x240.png
|
334
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-icons_454545_256x240.png
|
335
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-icons_888888_256x240.png
|
336
|
+
- spec/coverage/assets/0.5.3/smoothness/images/ui-icons_cd0a0a_256x240.png
|
337
|
+
- spec/coverage/assets/0.5.3/smoothness/jquery-ui-1.8.4.custom.css
|
338
|
+
- spec/coverage/assets/0.5.3/stylesheet.css
|
339
|
+
- spec/coverage/index.html
|
340
|
+
- spec/deck_spec.rb
|
177
341
|
- spec/fixnum_spec.rb
|
178
342
|
- spec/pool_spec.rb
|
179
343
|
- spec/randomizers_spec.rb
|