tabletop 0.0.1 → 0.1.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 +118 -18
- data/lib/tabletop/die.rb +28 -25
- data/lib/tabletop/pool.rb +9 -11
- data/lib/tabletop/roll.rb +138 -0
- data/lib/tabletop/version.rb +1 -1
- data/lib/tabletop.rb +1 -0
- data/spec/die_spec.rb +85 -102
- data/spec/fixnum_spec.rb +1 -0
- data/spec/pool_spec.rb +74 -43
- data/spec/roll_spec.rb +164 -0
- data/tabletop.gemspec +5 -2
- metadata +18 -34
data/.gitignore
CHANGED
data/README.markdown
CHANGED
@@ -2,41 +2,141 @@
|
|
2
2
|
|
3
3
|
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.
|
4
4
|
|
5
|
-
Currently, you can
|
5
|
+
Currently, you can create pools of dice, and rolls that compare them to different possible results.
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
9
9
|
gem install tabletop
|
10
|
+
|
11
|
+
require 'tabletop'
|
10
12
|
|
11
|
-
##
|
13
|
+
## Dice
|
12
14
|
|
13
|
-
|
15
|
+
Dice are pretty straightforward. They've got a number of sides, set on instantiation (defaulting to 6), and a current value between that number and 1 inclusive, which can be set on instantiation, or directly. They can be rolled, which gives them a new random value.
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
d6 = Die.new
|
18
|
+
d6.sides #=> 6
|
19
|
+
d6.value #=> 4
|
20
|
+
d6.roll
|
21
|
+
d6.value #=> 2
|
22
|
+
|
23
|
+
d8 = Die.new(8, 4)
|
24
|
+
d8.sides #=> 8
|
25
|
+
d8.to_s #=> "[3]/d8"
|
18
26
|
|
19
|
-
|
27
|
+
One fun special kind of die is a "Fudge Die". They are a special kind of three-sided die that have three possible values: -1, 0, or 1. Those are usually expressed as '-', ' ' and '+', though.
|
28
|
+
|
29
|
+
f = FudgeDie.new
|
30
|
+
f.sides #=> 3
|
31
|
+
f.value #=> 0
|
32
|
+
f.to_s #=> "[ ]"
|
33
|
+
|
34
|
+
### Pools
|
35
|
+
|
36
|
+
Pools are essentially arrays of Dice objects with some extra helpful methods.
|
20
37
|
|
21
|
-
|
22
|
-
|
23
|
-
|
38
|
+
The _best_ way to create one is exactly the way you'd expect: the same old d-notation we've been using for decades. You can even combine them with `+`.
|
39
|
+
|
40
|
+
3.d6 #=> [[3]/d6, [3]/d6, [4]/d6]
|
41
|
+
2.d10 + 1.d8 #=> [[2]/d10, [6]/d10, [8]/d8]
|
24
42
|
|
25
|
-
|
43
|
+
You can also create them by passing Pool.new a literal array of dice, or (slightly more interesting) a string in die notation.
|
44
|
+
|
45
|
+
The methods are common operations you might do on a pool of dice: summing, counting sets, dropping the lowest or highest valued dice, dropping all _but_ the lowest or highest valued dice, even dropping any dice a specified list of values.
|
26
46
|
|
27
|
-
d =
|
28
|
-
|
29
|
-
|
30
|
-
|
47
|
+
d&d = 3.d6.sum #=> 13
|
48
|
+
ore = 10.d10.sets #=> ["3x2", "2x8", "1x7", "1x6", "1x4", "1x3", "1x1"]
|
49
|
+
cortex = (1.d8 + 2.d6).drop([1]).highest(2).sum #=> 9
|
50
|
+
tsoy = (4.dF).drop_lowest.sum #=> 2
|
31
51
|
|
32
|
-
|
52
|
+
You can also #roll an entire pool, or you can interact with individual dice in the array using array indices (`[]`).
|
53
|
+
|
54
|
+
When pools are compared to each other or to numbers with <=>, it's assumed you're actually interested in their sum. The same thing happens if you try to add a number to them.
|
55
|
+
|
56
|
+
d&d_alt = 4.d4 + 4 #=> 17
|
57
|
+
1.d20 > 2.d10 #=> false
|
58
|
+
|
59
|
+
### Rolls
|
60
|
+
|
61
|
+
Rolls are very much under construction, but they allow you to automate randomly determining results in a variety of ways.
|
62
|
+
|
63
|
+
Rolls have a lot of options. Let's start by taking an example from one of my favorite games, Apocalypse World.
|
64
|
+
|
65
|
+
>When you open your brain to the world’s psychic maelstrom, roll+weird. On a hit, the MC will tell you something new and interesting about the current situation, and might ask you a question or two; answer them. On a 10+, the MC will give you good detail. On a 7–9, the MC will give you an impression.
|
66
|
+
|
67
|
+
(In the parlance of the game, a "hit" is getting a 7 or higher on 2d6, plus a stat.)
|
68
|
+
|
69
|
+
Here's how I'd write it out in Tabletop.
|
70
|
+
|
71
|
+
cool = [-1, 0, 1, 2, 3].sample #=> get a random stat
|
72
|
+
|
73
|
+
open_brain = Roll.new(2.d6) {
|
74
|
+
modifier cool
|
75
|
+
at_least 7, "the MC will tell you something new and interesting about the current situation"
|
76
|
+
equals (7..9), "...but it's just an impression"
|
77
|
+
at_least 10, "...and it's a good detail"
|
78
|
+
}
|
79
|
+
|
80
|
+
Simple, right? `add` sets a value to be permanently added for the purposes of determining results. `at_least` and `equals` take an integer (or a range, in the case of `equals`) as their first parameter, and then one or more results to trigger if the pools result meets the stated condition.
|
81
|
+
|
82
|
+
Once they've been instantiated, Rolls have two important methods.
|
83
|
+
|
84
|
+
#### #roll
|
33
85
|
|
86
|
+
This method which re-rolls all the dice in the pool, and returns the Roll object. It can take an options hash as a parameter. Notably, one of the options is `:modifier`, which sets a temporary modifier for that roll only; it's cleared the next time `roll` is called.
|
87
|
+
|
88
|
+
bad_luck = -1
|
89
|
+
open_brain.roll(:modifier => bad_luck)
|
90
|
+
|
91
|
+
#### #effects
|
92
|
+
|
93
|
+
This method returns an array, based on the current state of the pool, and any conditions and modifiers. Here's what I can tell you about the Array:
|
94
|
+
|
95
|
+
* Its first element is the "result" of the current pool, which is by default the sum of the values of its dice, plus any static or per-roll modifiers.
|
96
|
+
* The second and subsequent elements are the results of any satisfied conditions.
|
97
|
+
* If no conditions are satisfied, then the second and final element of the array is `nil`
|
98
|
+
|
99
|
+
So, possible results for our cool AW roll:
|
100
|
+
|
101
|
+
open_brain.roll.effects #=> [4, nil]
|
102
|
+
open_brain.roll.effects #=> [8, "the MC will tell you something new and interesting about the current situation", "...but it's just an impression"]
|
103
|
+
roll, *effects = open_brain.roll.effects
|
104
|
+
puts roll #=> 10
|
105
|
+
puts effects #=> ["the MC will tell you something new and interesting about the current situation", "...and it's a good detail"]
|
106
|
+
|
107
|
+
Just these few functions already give enough functionality to do different kinds of rolls, but there's a lot more in store.
|
108
|
+
|
109
|
+
One last thing I'll briefly note is that Rolls can be nested.
|
110
|
+
|
111
|
+
rps = Roll.new(1.d3) {
|
112
|
+
equals 1, "rock"
|
113
|
+
equals 2, "paper"
|
114
|
+
equals 3, "scissors"
|
115
|
+
}
|
116
|
+
jkp = Roll.new(1.d3) {
|
117
|
+
equals 1, "guu"
|
118
|
+
equals 2, "choki"
|
119
|
+
equals 3, "paa"
|
120
|
+
}
|
121
|
+
fist_game = Roll.new(1.d2) {
|
122
|
+
equals 1, "Rock Paper Scissors", rps
|
123
|
+
equals 2, "JanKenPon", jkp
|
124
|
+
}
|
125
|
+
fist_game.roll.effects #=> [2, "JanKenPon", [1, "guu"]]
|
126
|
+
|
127
|
+
This can lead to some surprisingly sophisticated constructions. Remember that "tables" are really just a special case of a roll!
|
128
|
+
|
129
|
+
## How to contribute
|
130
|
+
|
131
|
+
*First and most importantly*, any complaints or suggestions, *regardless of coding knowledge*, are *always welcome* at <nick.novitski@gmail.com>.
|
132
|
+
|
133
|
+
But, if you're feeling up to it, you can always do more. You probably already know the drill by this point.
|
134
|
+
|
34
135
|
* Fork the project.
|
35
136
|
* Create a topic branch
|
36
137
|
* Make tests that describe your feature addition or bug fix.
|
37
138
|
* Write code that passes those tests
|
38
|
-
* Commit, without altering the
|
39
|
-
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
139
|
+
* Commit, without altering the version.
|
40
140
|
* Send me a pull request.
|
41
141
|
|
42
142
|
## Copyright
|
data/lib/tabletop/die.rb
CHANGED
@@ -1,59 +1,62 @@
|
|
1
1
|
module Tabletop
|
2
2
|
class Die
|
3
3
|
include Comparable
|
4
|
-
attr_reader :sides, :
|
5
|
-
def initialize(sides=6,
|
6
|
-
if sides <=
|
4
|
+
attr_reader :sides, :value
|
5
|
+
def initialize(sides=6, init_value=nil)
|
6
|
+
if sides <= 1
|
7
7
|
raise ArgumentError, "Die cannot have #{sides} sides"
|
8
8
|
end
|
9
9
|
unless sides.kind_of? Integer
|
10
10
|
raise ArgumentError, "Parameter must be Integer, not #{sides.class}"
|
11
11
|
end
|
12
12
|
@sides = sides
|
13
|
-
if
|
14
|
-
|
13
|
+
if init_value.nil?
|
14
|
+
init_value = roll
|
15
15
|
else
|
16
|
-
raise ArgumentError unless
|
16
|
+
raise ArgumentError unless valid_value?(init_value)
|
17
17
|
end
|
18
|
-
@
|
18
|
+
@value = init_value
|
19
19
|
end
|
20
20
|
def roll
|
21
|
-
@
|
21
|
+
@value = rand(sides)+1
|
22
22
|
end
|
23
|
-
|
24
|
-
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
"[#{value}]/d#{sides}"
|
25
26
|
end
|
26
|
-
|
27
|
-
|
28
|
-
|
27
|
+
|
28
|
+
def value=(new_value)
|
29
|
+
raise ArgumentError unless valid_value?(new_value)
|
30
|
+
@value = new_value
|
29
31
|
end
|
30
32
|
def <=>(operand)
|
31
|
-
@
|
33
|
+
@value <=> operand.to_int
|
32
34
|
end
|
33
35
|
def to_int
|
34
|
-
@
|
36
|
+
@value
|
35
37
|
end
|
36
38
|
|
37
39
|
protected
|
38
|
-
def
|
39
|
-
|
40
|
+
def valid_value?(val)
|
41
|
+
val > 0 and val <= @sides
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
43
45
|
class FudgeDie < Die
|
44
|
-
def initialize(
|
45
|
-
super(3,
|
46
|
+
def initialize(init_value = nil)
|
47
|
+
super(3, init_value)
|
46
48
|
end
|
47
49
|
def roll
|
48
|
-
@
|
49
|
-
end
|
50
|
-
def inspect
|
51
|
-
"[#{['-', ' ', '+'][@result+1]}] (dF)"
|
50
|
+
@value = rand(sides)-1
|
52
51
|
end
|
53
52
|
|
53
|
+
def to_s
|
54
|
+
"[#{['-', ' ', '+'][@value+1]}]"
|
55
|
+
end
|
56
|
+
|
54
57
|
protected
|
55
|
-
def
|
56
|
-
[1,0,-1].include?(
|
58
|
+
def valid_value?(val)
|
59
|
+
[1,0,-1].include?(val)
|
57
60
|
end
|
58
61
|
end
|
59
62
|
end
|
data/lib/tabletop/pool.rb
CHANGED
@@ -35,8 +35,8 @@ module Tabletop
|
|
35
35
|
sum <=> operand.to_int
|
36
36
|
end
|
37
37
|
|
38
|
-
def
|
39
|
-
map {|die| die.
|
38
|
+
def values
|
39
|
+
map {|die| die.value}
|
40
40
|
end
|
41
41
|
def dice
|
42
42
|
fudge = nil
|
@@ -66,7 +66,7 @@ module Tabletop
|
|
66
66
|
self
|
67
67
|
end
|
68
68
|
def sum
|
69
|
-
inject(0) {|sum, d| sum + d.
|
69
|
+
inject(0) {|sum, d| sum + d.value}
|
70
70
|
end
|
71
71
|
def to_int
|
72
72
|
sum
|
@@ -74,17 +74,15 @@ module Tabletop
|
|
74
74
|
def sets
|
75
75
|
result = {}
|
76
76
|
each do |die|
|
77
|
-
result[die.
|
77
|
+
result[die.value] = count {|d| d.value == die.value}
|
78
78
|
end
|
79
79
|
result.sort_by{|height, width| [width, height] }.collect {|i| i[1].to_s+"x"+i[0].to_s}.reverse
|
80
80
|
end
|
81
81
|
def highest(n=1)
|
82
|
-
|
83
|
-
Pool.new(sorted.first(n))
|
82
|
+
Pool.new(sort.reverse.first(n))
|
84
83
|
end
|
85
84
|
def lowest(n=1)
|
86
|
-
|
87
|
-
Pool.new(sorted.first(n))
|
85
|
+
Pool.new(sort.first(n))
|
88
86
|
end
|
89
87
|
def drop_highest(n=1)
|
90
88
|
Pool.new(self-highest(n))
|
@@ -94,7 +92,7 @@ module Tabletop
|
|
94
92
|
end
|
95
93
|
def drop(to_drop)
|
96
94
|
to_drop = [to_drop].flatten #turn it into an array if it isn't one.
|
97
|
-
kept = reject{|die| to_drop.any?{|drop_value| die.
|
95
|
+
kept = reject{|die| to_drop.any?{|drop_value| die.value == drop_value }}
|
98
96
|
return Pool.new(kept)
|
99
97
|
end
|
100
98
|
|
@@ -104,9 +102,9 @@ module Tabletop
|
|
104
102
|
new_pool =[]
|
105
103
|
union.each do |die|
|
106
104
|
if die.class == FudgeDie
|
107
|
-
new_pool << FudgeDie.new(die.
|
105
|
+
new_pool << FudgeDie.new(die.value)
|
108
106
|
else
|
109
|
-
new_pool << Die.new(die.sides, die.
|
107
|
+
new_pool << Die.new(die.sides, die.value)
|
110
108
|
end
|
111
109
|
end
|
112
110
|
Pool.new(new_pool)
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require_relative 'pool'
|
2
|
+
|
3
|
+
module Tabletop
|
4
|
+
|
5
|
+
class Possibility
|
6
|
+
attr_reader :outcomes, :conditions
|
7
|
+
|
8
|
+
def initialize(outcomes, conditions)
|
9
|
+
@outcomes = outcomes
|
10
|
+
@conditions = conditions
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Roll
|
15
|
+
attr_reader :pool, :possibilities
|
16
|
+
|
17
|
+
def initialize(pool=nil, &block)
|
18
|
+
if pool
|
19
|
+
raise ArgumentError if pool.class != Tabletop::Pool
|
20
|
+
end
|
21
|
+
@pool = pool
|
22
|
+
@possibilities = []
|
23
|
+
@die_sides = nil
|
24
|
+
@static_modifier = 0
|
25
|
+
@roll_modifier = 0
|
26
|
+
@result_set = false
|
27
|
+
instance_eval(&block)
|
28
|
+
unless @result_set
|
29
|
+
set_result(:sum)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def effects
|
34
|
+
results = []
|
35
|
+
|
36
|
+
if @difficulty
|
37
|
+
results << "Success" if result >= @difficulty
|
38
|
+
end
|
39
|
+
|
40
|
+
@possibilities.each do |poss|
|
41
|
+
if meets?(poss)
|
42
|
+
poss.outcomes.each do |outcome|
|
43
|
+
if Roll === outcome
|
44
|
+
results << outcome.roll.effects
|
45
|
+
else
|
46
|
+
results << outcome
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
if results.empty?
|
54
|
+
results << nil
|
55
|
+
end
|
56
|
+
|
57
|
+
results.unshift(result)
|
58
|
+
end
|
59
|
+
|
60
|
+
def roll(opts={})
|
61
|
+
@roll_modifier = opts[:modifier] ? opts[:modifier] : 0
|
62
|
+
if @die_sides
|
63
|
+
if opts[:pool]
|
64
|
+
@pool = opts[:pool].dX(@die_sides)
|
65
|
+
else
|
66
|
+
raise ArgumentError
|
67
|
+
end
|
68
|
+
end
|
69
|
+
if opts[:difficulty]
|
70
|
+
@difficulty = opts[:difficulty]
|
71
|
+
end
|
72
|
+
@pool.roll
|
73
|
+
self
|
74
|
+
end
|
75
|
+
|
76
|
+
def meets?(p)
|
77
|
+
answer = true
|
78
|
+
if p.conditions[:>=]
|
79
|
+
if p.conditions[:>=] > sum
|
80
|
+
answer = false
|
81
|
+
end
|
82
|
+
end
|
83
|
+
if p.conditions[:==]
|
84
|
+
answer = false if p.conditions[:==] != sum
|
85
|
+
end
|
86
|
+
answer
|
87
|
+
end
|
88
|
+
|
89
|
+
def sum
|
90
|
+
@pool.sum + @static_modifier + @roll_modifier
|
91
|
+
end
|
92
|
+
|
93
|
+
# instance_eval methods
|
94
|
+
|
95
|
+
## Possibility-creating methods
|
96
|
+
def at_least(value, *outcomes)
|
97
|
+
@possibilities << Possibility.new(outcomes, :>= => value)
|
98
|
+
end
|
99
|
+
|
100
|
+
def equals(values, *outcomes)
|
101
|
+
if values.class == Range
|
102
|
+
values.each do |val|
|
103
|
+
@possibilities << Possibility.new(outcomes, :== => val)
|
104
|
+
end
|
105
|
+
else
|
106
|
+
@possibilities << Possibility.new(outcomes, :== => values)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def set_result(symbol, args={})
|
111
|
+
if symbol == :count
|
112
|
+
@count_at_least = args[:at_least]
|
113
|
+
@count_doubles = args[:doubles]
|
114
|
+
def result
|
115
|
+
normal = @pool.count {|die| die.value >= @count_at_least}
|
116
|
+
extra = @count_doubles ? @pool.count {|die| die.value == @count_doubles} : 0
|
117
|
+
normal + extra
|
118
|
+
end
|
119
|
+
else
|
120
|
+
def result
|
121
|
+
sum
|
122
|
+
end
|
123
|
+
end
|
124
|
+
@result_set = true
|
125
|
+
end
|
126
|
+
|
127
|
+
# instance-variable-setting methods
|
128
|
+
def add(mod)
|
129
|
+
@static_modifier = mod
|
130
|
+
end
|
131
|
+
|
132
|
+
def sides(num_sides)
|
133
|
+
@die_sides = num_sides
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
data/lib/tabletop/version.rb
CHANGED
data/lib/tabletop.rb
CHANGED
data/spec/die_spec.rb
CHANGED
@@ -2,187 +2,170 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module Tabletop
|
4
4
|
describe Die do
|
5
|
+
|
5
6
|
before :each do
|
6
7
|
@d6_2 = Die.new(6, 2)
|
7
8
|
@d6_3 = Die.new(6, 3)
|
8
9
|
end
|
10
|
+
|
9
11
|
describe "#sides" do
|
10
12
|
it "can be accessed" do
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
d.sides.should == 20
|
15
|
-
d = Die.new(7)
|
16
|
-
d.sides.should equal(7)
|
13
|
+
(2..10).each do |i|
|
14
|
+
Die.new(i).sides.should == i
|
15
|
+
end
|
17
16
|
end
|
17
|
+
|
18
18
|
it "is 6 by default" do
|
19
|
-
|
20
|
-
d.sides.should equal(6)
|
19
|
+
Die.new.sides.should == 6
|
21
20
|
end
|
22
|
-
|
21
|
+
|
22
|
+
it "cannot be 1 or less" do
|
23
23
|
lambda { Die.new(0) }.should raise_error(ArgumentError)
|
24
|
+
lambda { Die.new(1) }.should raise_error(ArgumentError)
|
24
25
|
lambda { Die.new(-5) }.should raise_error(ArgumentError)
|
25
26
|
end
|
27
|
+
|
26
28
|
it "cannot be a non-integer" do
|
27
29
|
lambda { Die.new(0.1) }.should raise_error(ArgumentError)
|
28
30
|
lambda { Die.new(5.7694) }.should raise_error(ArgumentError)
|
29
31
|
lambda { Die.new("foof") }.should raise_error(ArgumentError)
|
30
32
|
end
|
31
33
|
end
|
32
|
-
|
33
|
-
|
34
|
-
Random.srand(10)
|
35
|
-
end
|
34
|
+
|
35
|
+
describe "#value" do
|
36
36
|
it "should be random on instantiation by default" do
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
d = Die.new(50)
|
42
|
-
d.result.should equal(16)
|
37
|
+
Random.srand(10)
|
38
|
+
Die.new.value.should == 2
|
39
|
+
Die.new(10).value.should == 5
|
40
|
+
Die.new(50).value.should == 16
|
43
41
|
end
|
42
|
+
|
44
43
|
it "can be set to a given value on instantiation" do
|
45
|
-
Die.new(6, 5).
|
46
|
-
Die.new(10, 2).
|
44
|
+
Die.new(6, 5).value.should == 5
|
45
|
+
Die.new(10, 2).value.should == 2
|
47
46
|
end
|
47
|
+
|
48
48
|
it "cannot be a non-integer" do
|
49
49
|
lambda { Die.new(0.1) }.should raise_error(ArgumentError)
|
50
50
|
lambda { Die.new(5.7694) }.should raise_error(ArgumentError)
|
51
51
|
lambda { Die.new("foof") }.should raise_error(ArgumentError)
|
52
52
|
end
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
|
+
describe "#value=" do
|
55
56
|
it "can only be set to an integer i, where 0 < i <= sides" do
|
56
57
|
d = Die.new
|
57
|
-
lambda { d.
|
58
|
-
lambda { d.
|
59
|
-
lambda { d.
|
58
|
+
lambda { d.value = 0 }.should raise_error(ArgumentError)
|
59
|
+
lambda { d.value = -5 }.should raise_error(ArgumentError)
|
60
|
+
lambda { d.value = 7 }.should raise_error(ArgumentError)
|
60
61
|
d = Die.new(10)
|
61
|
-
d.
|
62
|
-
lambda { d.
|
62
|
+
d.value = 7
|
63
|
+
lambda { d.value = 22 }.should raise_error(ArgumentError)
|
63
64
|
end
|
64
65
|
end
|
66
|
+
|
65
67
|
describe "#roll" do
|
66
68
|
before(:each) do
|
67
69
|
Random.srand(10)
|
68
70
|
end
|
71
|
+
|
69
72
|
context "six sides" do
|
70
|
-
|
71
|
-
|
72
|
-
#d.roll.should == 2 # This result gets swallowed by the init roll
|
73
|
-
d.roll.should == 6
|
74
|
-
d.roll.should == 5
|
75
|
-
d.roll.should == 1
|
76
|
-
end
|
77
|
-
it "should alter the result appropriately" do
|
78
|
-
d = Die.new
|
79
|
-
#d.roll # Covered by the initial roll
|
80
|
-
d.result.should == 2
|
81
|
-
d.roll
|
82
|
-
d.result.should == 6
|
83
|
-
d.roll
|
84
|
-
d.result.should == 5
|
85
|
-
d.roll
|
86
|
-
d.result.should == 1
|
73
|
+
before(:each) do
|
74
|
+
@d6 = Die.new #=> 2
|
87
75
|
end
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
d.roll.should == 5
|
94
|
-
d.roll.should == 1
|
95
|
-
d.roll.should == 2
|
76
|
+
|
77
|
+
it "should return a random result between 1 and @sides" do
|
78
|
+
@d6.roll.should == 6
|
79
|
+
@d6.roll.should == 5
|
80
|
+
@d6.roll.should == 1
|
96
81
|
end
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
d.result.should == 5
|
103
|
-
d.roll
|
104
|
-
d.result.should == 1
|
105
|
-
d.roll
|
106
|
-
d.result.should == 2
|
82
|
+
|
83
|
+
it "should alter the value appropriately" do
|
84
|
+
10.times do
|
85
|
+
@d6.roll.should == @d6.value
|
86
|
+
end
|
107
87
|
end
|
108
88
|
end
|
109
89
|
end
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
90
|
+
|
91
|
+
describe "#to_str" do
|
92
|
+
it "should tell you the die's value" do
|
93
|
+
5.times do
|
94
|
+
d = Die.new(rand(10)+3)
|
95
|
+
"#{d}".should == "[#{d.value}]/d#{d.sides}"
|
96
|
+
end
|
117
97
|
end
|
118
98
|
end
|
99
|
+
|
119
100
|
describe "#to_int" do
|
120
|
-
it "returns the
|
101
|
+
it "returns the value" do
|
121
102
|
d = Die.new
|
122
|
-
d.to_int.should == d.
|
103
|
+
d.to_int.should == d.value
|
123
104
|
end
|
124
105
|
end
|
106
|
+
|
125
107
|
describe "<=>" do
|
126
108
|
it "compares numeric objects with the die's value" do
|
127
|
-
(
|
128
|
-
|
129
|
-
|
130
|
-
(@d6_3 > 4).should be_false
|
131
|
-
(@d6_3 >= 3).should be_true
|
132
|
-
(@d6_3 >= 10).should be_false
|
133
|
-
(@d6_3 <= 3).should be_true
|
134
|
-
(@d6_3 <= 2).should be_false
|
135
|
-
(@d6_3 == 3).should be_true
|
136
|
-
(@d6_3 == 6).should be_false
|
109
|
+
(1..10).each do |i|
|
110
|
+
(@d6_3 <=> i) == (3 <=> i)
|
111
|
+
end
|
137
112
|
end
|
113
|
+
|
138
114
|
it "compares dice with each other by value" do
|
139
|
-
(@d6_3
|
140
|
-
(@d6_3 < @d6_2).should be_false
|
141
|
-
(@d6_2 < @d6_3).should be_true
|
142
|
-
(@d6_2 > @d6_3).should be_false
|
143
|
-
(@d6_3 == @d6_2).should be_false
|
115
|
+
(@d6_3 <=> @d6_2) == (3 <=> 2)
|
144
116
|
end
|
145
117
|
end
|
146
118
|
end
|
119
|
+
|
147
120
|
describe FudgeDie do
|
148
121
|
before(:each) do
|
149
122
|
Random.srand(10)
|
150
123
|
@fudge = FudgeDie.new
|
151
124
|
end
|
125
|
+
|
152
126
|
describe "#sides" do
|
153
127
|
it "is always 3" do
|
154
128
|
@fudge.sides.should == 3
|
155
129
|
end
|
156
130
|
end
|
157
|
-
|
131
|
+
|
132
|
+
describe "#value" do
|
158
133
|
it "can be set on instantiation" do
|
159
|
-
FudgeDie.new(1).
|
160
|
-
FudgeDie.new(0).
|
161
|
-
FudgeDie.new(-1).
|
134
|
+
FudgeDie.new(1).value.should == 1
|
135
|
+
FudgeDie.new(0).value.should == 0
|
136
|
+
FudgeDie.new(-1).value.should == -1
|
162
137
|
end
|
138
|
+
|
163
139
|
it "is randomly rolled if not set" do
|
164
|
-
@fudge.
|
140
|
+
@fudge.value.should == 0
|
165
141
|
end
|
142
|
+
|
166
143
|
it "can only be one of either -1, 0, or 1" do
|
144
|
+
[-1, 0, 1].each do |v|
|
145
|
+
FudgeDie.new(v)
|
146
|
+
end
|
167
147
|
lambda {FudgeDie.new(2)}.should raise_error(ArgumentError)
|
168
148
|
lambda {FudgeDie.new(0.6)}.should raise_error(ArgumentError)
|
169
149
|
lambda {FudgeDie.new("5")}.should raise_error(ArgumentError)
|
170
150
|
end
|
171
151
|
end
|
172
|
-
|
152
|
+
|
153
|
+
describe "#value=" do
|
173
154
|
it "cannot be set to anything but -1, 0, or 1" do
|
174
|
-
lambda {@fudge.
|
175
|
-
lambda {@fudge.
|
176
|
-
lambda {@fudge.
|
177
|
-
|
178
|
-
|
155
|
+
lambda {@fudge.value = 2}.should raise_error(ArgumentError)
|
156
|
+
lambda {@fudge.value = 0.6}.should raise_error(ArgumentError)
|
157
|
+
lambda {@fudge.value = "5"}.should raise_error(ArgumentError)
|
158
|
+
[-1, 0, 1].each do |v|
|
159
|
+
@fudge.value = v
|
160
|
+
end
|
179
161
|
end
|
180
162
|
end
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
FudgeDie.new(
|
185
|
-
FudgeDie.new(
|
163
|
+
|
164
|
+
describe "#to_s" do
|
165
|
+
it "should return cute little dice with symbols" do
|
166
|
+
FudgeDie.new(1).to_s.should == "[+]"
|
167
|
+
FudgeDie.new(0).to_s.should == "[ ]"
|
168
|
+
FudgeDie.new(-1).to_s.should == "[-]"
|
186
169
|
end
|
187
170
|
end
|
188
171
|
end
|
data/spec/fixnum_spec.rb
CHANGED
data/spec/pool_spec.rb
CHANGED
@@ -9,6 +9,7 @@ module Tabletop
|
|
9
9
|
@mixed = Pool.new("2d10 d20")
|
10
10
|
@fudge = Pool.new("3dF")
|
11
11
|
end
|
12
|
+
|
12
13
|
describe "#dice" do
|
13
14
|
it "should return an array of dice notation" do
|
14
15
|
@mixed.dice.should == ["2d10","d20"]
|
@@ -18,31 +19,36 @@ module Tabletop
|
|
18
19
|
Pool.new("d20 2dF 2d10").dice.should == ["2d10","d20", "2dF"]
|
19
20
|
end
|
20
21
|
end
|
22
|
+
|
21
23
|
describe "[]" do
|
22
24
|
it "should access Die objects" do
|
23
25
|
@d6[0].class.should == Die
|
24
26
|
@fudge[0].class.should == FudgeDie
|
25
27
|
end
|
26
28
|
end
|
29
|
+
|
27
30
|
describe "+" do
|
28
31
|
it "should join Pools into new Pools" do
|
29
32
|
(@mixed + @d17s).class == Pool
|
30
33
|
(@d6 + @fudge).class == Pool
|
31
34
|
end
|
35
|
+
|
32
36
|
it "should persist die types" do
|
33
37
|
(@d6 + @fudge)[1].class.should == FudgeDie
|
34
38
|
end
|
39
|
+
|
35
40
|
it "should join pools without rolling them" do
|
36
41
|
merge = @d6 + @d17s
|
37
|
-
merge.
|
42
|
+
merge.values.should == [2, 5, 16, 1, 17, 9]
|
38
43
|
merge.roll
|
39
|
-
merge.
|
44
|
+
merge.values.should == [4, 17, 5, 16, 12, 12]
|
40
45
|
end
|
46
|
+
|
41
47
|
it "creates genuinely new pools" do
|
42
48
|
merge = @d6 + @d17s
|
43
49
|
merge.roll
|
44
|
-
@d6.
|
45
|
-
@d17s.
|
50
|
+
@d6.values.should == [2]
|
51
|
+
@d17s.values.should == [5, 16, 1, 17, 9]
|
46
52
|
end
|
47
53
|
|
48
54
|
it "should alter #dice accordingly" do
|
@@ -54,69 +60,83 @@ module Tabletop
|
|
54
60
|
(@d17s + @mixed).dice.should == ["2d10","5d17","d20"]
|
55
61
|
(@mixed + @fudge).dice.should == ["2d10", "d20", "3dF"]
|
56
62
|
end
|
63
|
+
|
57
64
|
it "should understand adding a number as looking for a sum result" do
|
58
65
|
(@d17s + 5).should == 53
|
59
66
|
(@mixed + @d6 + 10).should == 34
|
60
67
|
(@fudge + 3).should == 2
|
61
68
|
end
|
69
|
+
|
62
70
|
it "should add literal dice arrays as if they were pools" do
|
63
71
|
g = @d6 + [Die.new(6,3), Die.new(10, 4)]
|
64
|
-
g.
|
72
|
+
g.values.should == [2, 3, 4]
|
65
73
|
g.dice.should == ["2d6", "d10"]
|
66
74
|
g.roll
|
67
|
-
@d6.
|
75
|
+
@d6.values.should == [2]
|
68
76
|
end
|
77
|
+
|
69
78
|
it "should reject adding anything else" do
|
70
79
|
lambda {@d6 + "foof"}.should raise_error(ArgumentError)
|
71
80
|
lambda {@d6 + [Die.new, Object.new]}.should raise_error(ArgumentError)
|
72
81
|
end
|
73
82
|
end
|
74
|
-
|
83
|
+
|
84
|
+
describe "#values" do
|
75
85
|
it "should be an array of random numbers" do
|
76
|
-
@d6.
|
77
|
-
@d17s.
|
78
|
-
@mixed.
|
86
|
+
@d6.values.should == [2]
|
87
|
+
@d17s.values.should == [5, 16, 1, 17, 9]
|
88
|
+
@mixed.values.should == [10, 1, 11]
|
79
89
|
end
|
80
90
|
end
|
91
|
+
|
81
92
|
describe "#roll" do
|
82
93
|
it "should return the Pool itself" do
|
83
94
|
@d6.roll.length.should == @d6.length
|
84
95
|
@d6.roll.class.should == @d6.class
|
85
96
|
end
|
97
|
+
|
86
98
|
it "should store the new values" do
|
87
99
|
@d6.roll
|
88
|
-
@d6.
|
100
|
+
@d6.values.should == [4]
|
89
101
|
@d17s.roll
|
90
|
-
@d17s.
|
102
|
+
@d17s.values.should == [17, 5, 16, 12, 12]
|
91
103
|
@mixed.roll
|
92
|
-
@mixed.
|
104
|
+
@mixed.values.should == [2, 9, 5]
|
93
105
|
end
|
106
|
+
it "can roll only dice below a certain value"
|
107
|
+
it "can roll only dice above a certain value"
|
108
|
+
it "can roll only dice equal to a certain value"
|
94
109
|
end
|
110
|
+
|
95
111
|
describe "#sum" do
|
96
112
|
it "should sum the dice values" do
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
113
|
+
5.times do
|
114
|
+
p = 10.d6
|
115
|
+
p.sum.should == p.values.inject(:+)
|
116
|
+
end
|
101
117
|
end
|
118
|
+
|
102
119
|
it "should be aliased to #to_int" do
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
120
|
+
5.times do
|
121
|
+
p = 10.d6
|
122
|
+
p.to_int.should == p.sum
|
123
|
+
end
|
107
124
|
end
|
108
125
|
end
|
126
|
+
|
109
127
|
describe "<=>" do
|
110
128
|
it "should compare the sums of different pools" do
|
111
129
|
@d17s.should >= @d6
|
112
130
|
@d6.should < Pool.new([Die.new(4, 4)])
|
113
131
|
end
|
132
|
+
|
114
133
|
it "should compare pools to numbers" do
|
115
134
|
@d6.should < 10
|
116
135
|
@d6.should == 2
|
117
136
|
@d17s.should <= 49
|
118
137
|
end
|
119
138
|
end
|
139
|
+
|
120
140
|
describe "#sets" do
|
121
141
|
it "should list the sets, in order by height and width" do
|
122
142
|
ore = Pool.new("10d10")
|
@@ -127,67 +147,78 @@ module Tabletop
|
|
127
147
|
ore.sets.should == ["3x9", "2x8", "2x7", "1x10", "1x3", "1x1"]
|
128
148
|
end
|
129
149
|
end
|
150
|
+
|
130
151
|
describe "#highest" do
|
131
152
|
it "should return a pool of the highest-value die" do
|
132
153
|
@d6.highest.class.should == Pool
|
133
|
-
@d6.highest.
|
134
|
-
@d17s.highest.
|
135
|
-
@mixed.highest.
|
154
|
+
@d6.highest.values.should == [2]
|
155
|
+
@d17s.highest.values.should == [17]
|
156
|
+
@mixed.highest.values.should == [11]
|
136
157
|
end
|
158
|
+
|
137
159
|
it "should return as many items as are specified" do
|
138
|
-
@d6.highest(5).
|
139
|
-
@d17s.highest(3).
|
140
|
-
@mixed.highest(2).
|
160
|
+
@d6.highest(5).values.should == [2]
|
161
|
+
@d17s.highest(3).values.should == [17, 16, 9]
|
162
|
+
@mixed.highest(2).values.should == [11, 10]
|
141
163
|
end
|
142
164
|
end
|
165
|
+
|
143
166
|
describe "#lowest" do
|
144
167
|
it "should return a pool of the lowest-value die." do
|
145
|
-
@d6.lowest.
|
168
|
+
@d6.lowest.values.should == [2]
|
146
169
|
@d17s.lowest.class.should == Pool
|
147
|
-
@d17s.lowest.
|
148
|
-
@mixed.lowest.
|
170
|
+
@d17s.lowest.values.should == [1]
|
171
|
+
@mixed.lowest.values.should == [1]
|
149
172
|
end
|
173
|
+
|
150
174
|
it "should return as many items as are specified" do
|
151
|
-
@d6.lowest(5).
|
152
|
-
@d17s.lowest(3).
|
153
|
-
@mixed.lowest(2).
|
175
|
+
@d6.lowest(5).values.should == [2]
|
176
|
+
@d17s.lowest(3).values.should == [1, 5, 9]
|
177
|
+
@mixed.lowest(2).values.should == [1, 10]
|
154
178
|
end
|
155
179
|
end
|
180
|
+
|
156
181
|
describe "#drop_highest" do
|
157
182
|
it "should return a new pool missing the highest result" do
|
158
183
|
p = @d17s.drop_highest
|
159
|
-
p.
|
160
|
-
@d17s.
|
184
|
+
p.values.should == [5, 16, 1, 9]
|
185
|
+
@d17s.values.should == [5, 16, 1, 17, 9]
|
161
186
|
end
|
187
|
+
|
162
188
|
it "should drop as many items as are specified and are possible" do
|
163
189
|
p = @d17s.drop_highest(2)
|
164
|
-
p.
|
190
|
+
p.values.should == [5, 1, 9]
|
165
191
|
p = @d6.drop_highest(10)
|
166
|
-
p.
|
192
|
+
p.values.should == []
|
167
193
|
end
|
168
194
|
end
|
195
|
+
|
169
196
|
describe "#drop_lowest" do
|
170
197
|
it "should return a pool missing the lowest result" do
|
171
198
|
p = @d17s.drop_lowest
|
172
|
-
p.
|
173
|
-
@d17s.
|
199
|
+
p.values.should == [5, 16, 17, 9]
|
200
|
+
@d17s.values.should == [5, 16, 1, 17, 9]
|
174
201
|
end
|
202
|
+
|
175
203
|
it "should drop as many items as are specified" do
|
176
204
|
p = @d17s.drop_lowest(2)
|
177
|
-
p.
|
205
|
+
p.values.should == [16, 17, 9]
|
178
206
|
end
|
179
207
|
end
|
208
|
+
|
180
209
|
describe "#drop" do
|
181
210
|
it "should drop any dice of the specified value" do
|
182
211
|
ore = Pool.new("10d10")
|
183
|
-
ore.
|
212
|
+
ore.values.should == [4, 1, 5, 7, 9, 2, 9, 5, 2, 4]
|
184
213
|
at_least_two = ore.drop(1)
|
185
|
-
at_least_two.
|
214
|
+
at_least_two.values.should == [4, 5, 7, 9, 2, 9, 5, 2, 4]
|
186
215
|
at_least_three = ore.drop([1,2])
|
187
|
-
at_least_three.
|
216
|
+
at_least_three.values.should == [4, 5, 7, 9, 9, 5, 4]
|
188
217
|
end
|
189
218
|
end
|
219
|
+
|
190
220
|
context "pool has been emptied" do
|
191
221
|
end
|
222
|
+
|
192
223
|
end
|
193
224
|
end
|
data/spec/roll_spec.rb
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Tabletop
|
4
|
+
describe Roll do
|
5
|
+
|
6
|
+
describe "#pool" do
|
7
|
+
it "accesses the roll's pool" do
|
8
|
+
d20 = Roll.new(1.d20) do
|
9
|
+
end
|
10
|
+
d20.pool.class.should == Pool
|
11
|
+
d20.pool.length.should == 1
|
12
|
+
d20.pool[0].sides.should == 20
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when used as an attribute or skill roll" do
|
17
|
+
|
18
|
+
context "for Apocalypse World" do
|
19
|
+
|
20
|
+
it "can be used with a static difficulty and dice pool, and both static and dynamic modifiers" do
|
21
|
+
cool = 1
|
22
|
+
under_fire = Roll.new(2.d6) do
|
23
|
+
add cool
|
24
|
+
at_least 10, "You do it"
|
25
|
+
equals (7..9), "You flinch, hesitate, or stall"
|
26
|
+
end
|
27
|
+
20.times do
|
28
|
+
mod = [1, 0, -1].sample
|
29
|
+
if mod != 0
|
30
|
+
under_fire.roll(:modifier => mod)
|
31
|
+
else
|
32
|
+
under_fire.roll
|
33
|
+
end
|
34
|
+
if under_fire.pool.sum + cool + mod >= 10
|
35
|
+
effect = "You do it"
|
36
|
+
elsif under_fire.pool.sum + cool + mod >= 7
|
37
|
+
effect = "You flinch, hesitate, or stall"
|
38
|
+
end
|
39
|
+
under_fire.effects.should == [under_fire.pool.sum + cool + mod, effect]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "in Exalted" do
|
45
|
+
before :each do
|
46
|
+
@exalted = Roll.new do
|
47
|
+
set_result :count, :at_least=>7, :doubles=>10
|
48
|
+
sides 10
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def count_successes(pool)
|
53
|
+
pool.count {|die| die.value >= 7 } + pool.count {|die| die.value == 10 }
|
54
|
+
end
|
55
|
+
|
56
|
+
it "can be instantiated without a complete pool" do
|
57
|
+
@exalted.roll(:pool=>6)
|
58
|
+
@exalted.pool.length.should == 6
|
59
|
+
@exalted.pool.each do |die|
|
60
|
+
die.sides.should == 10
|
61
|
+
end
|
62
|
+
@exalted.roll(:pool=>10)
|
63
|
+
@exalted.pool.length.should == 10
|
64
|
+
lambda {@exalted.roll}.should raise_error(ArgumentError)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "can count successes" do
|
68
|
+
@exalted.roll(:pool=>10)
|
69
|
+
10.times do
|
70
|
+
@exalted.effects.should == [count_successes(@exalted.pool), nil]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "can determine success" do
|
75
|
+
(1..10).each do |i|
|
76
|
+
@exalted.roll(:pool=>6, :difficulty=>i)
|
77
|
+
effect = (count_successes(@exalted.pool) >= i) ? "Success" : nil
|
78
|
+
@exalted.effects.should == [count_successes(@exalted.pool), effect]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
context "when used like a table" do
|
87
|
+
it "can have nested results" do
|
88
|
+
rps = Roll.new(1.d3) {
|
89
|
+
equals 1, "rock"
|
90
|
+
equals 2, "paper"
|
91
|
+
equals 3, "scissors"
|
92
|
+
}
|
93
|
+
jkp = Roll.new(1.d3) {
|
94
|
+
equals 1, "guu"
|
95
|
+
equals 2, "choki"
|
96
|
+
equals 3, "paa"
|
97
|
+
}
|
98
|
+
fist_game = Roll.new(1.d2) {
|
99
|
+
equals 1, "Rock Paper Scissors", rps
|
100
|
+
equals 2, "JanKenPon", jkp
|
101
|
+
}
|
102
|
+
a, b, c = fist_game.roll.effects
|
103
|
+
|
104
|
+
[1,2].include?(a).should be_true
|
105
|
+
|
106
|
+
if a == 1
|
107
|
+
b.should == "Rock Paper Scissors"
|
108
|
+
else
|
109
|
+
b.should == "JanKenPon"
|
110
|
+
end
|
111
|
+
|
112
|
+
[1,2,3].include?(c[0]).should be_true
|
113
|
+
|
114
|
+
b[1].class.should == String
|
115
|
+
|
116
|
+
end
|
117
|
+
before :each do
|
118
|
+
ill_fortune = Roll.new(1.d10) do
|
119
|
+
equals 1, "Accident"
|
120
|
+
equals 2, "Maltreatment"
|
121
|
+
equals 3, "Disease"
|
122
|
+
equals 4, "Dropped"
|
123
|
+
equals 5, "Parental Loss"
|
124
|
+
equals 6, "Family Loss"
|
125
|
+
equals 7, "Torment"
|
126
|
+
equals 8, "Homeless"
|
127
|
+
equals 9, "Ghost"
|
128
|
+
equals 10, "Prying Eyes"
|
129
|
+
end
|
130
|
+
good_fortune = Roll.new(1.d10) do
|
131
|
+
equals 1, "Dreamer"
|
132
|
+
equals 2, "Childhood Patron"
|
133
|
+
equals 3, "Active Youth"
|
134
|
+
equals 4, "Apt Pupil"
|
135
|
+
equals 5, "Save a Life"
|
136
|
+
equals 6, "First Love"
|
137
|
+
equals 7, "Childhood Friend"
|
138
|
+
equals 8, "Heirloom"
|
139
|
+
equals 9, "Spirit Blessing"
|
140
|
+
equals 10, "Temple Assistant"
|
141
|
+
end
|
142
|
+
@childhood_event = Roll.new(1.d10) do
|
143
|
+
equals (1..4), "Roll on ill fortune table", ill_fortune
|
144
|
+
equals (5..8), "Roll on good fortune table", good_fortune
|
145
|
+
equals (9..10), "Roll on both ill and good fortune tables", ill_fortune, good_fortune
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
it "can compose multiple nested results" do
|
150
|
+
20.times do
|
151
|
+
@childhood_event.roll
|
152
|
+
if @childhood_event.effects[0] >= 9
|
153
|
+
@childhood_event.effects.length.should == 4
|
154
|
+
else
|
155
|
+
@childhood_event.effects.length.should == 3
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
end
|
data/tabletop.gemspec
CHANGED
@@ -20,8 +20,11 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.rubygems_version = '1.3.7'
|
21
21
|
s.specification_version = 3
|
22
22
|
|
23
|
-
|
24
|
-
|
23
|
+
ignores = File.readlines(".gitignore").grep(/\S+/).map {|s| s.chomp }
|
24
|
+
dotfiles = [".gitignore"]
|
25
|
+
|
26
|
+
s.files = Dir["**/*"].reject {|f| File.directory?(f) || ignores.any? {|i| File.fnmatch(i, f) } } + dotfiles
|
27
|
+
s.test_files = s.files.grep(/^spec\//)
|
25
28
|
s.require_paths = ['lib']
|
26
29
|
|
27
30
|
s.add_development_dependency 'rspec'
|
metadata
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tabletop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
version: 0.0.1
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.0
|
10
6
|
platform: ruby
|
11
7
|
authors:
|
12
8
|
- Nick Novitski
|
@@ -14,73 +10,62 @@ autorequire:
|
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
12
|
|
17
|
-
date: 2011-08-10 00:00:00
|
18
|
-
default_executable:
|
13
|
+
date: 2011-08-10 00:00:00 Z
|
19
14
|
dependencies:
|
20
15
|
- !ruby/object:Gem::Dependency
|
21
16
|
name: rspec
|
22
|
-
prerelease: false
|
23
17
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
18
|
none: false
|
25
19
|
requirements:
|
26
20
|
- - ">="
|
27
21
|
- !ruby/object:Gem::Version
|
28
|
-
segments:
|
29
|
-
- 0
|
30
22
|
version: "0"
|
31
23
|
type: :development
|
24
|
+
prerelease: false
|
32
25
|
version_requirements: *id001
|
33
26
|
- !ruby/object:Gem::Dependency
|
34
27
|
name: bundler
|
35
|
-
prerelease: false
|
36
28
|
requirement: &id002 !ruby/object:Gem::Requirement
|
37
29
|
none: false
|
38
30
|
requirements:
|
39
31
|
- - ">="
|
40
32
|
- !ruby/object:Gem::Version
|
41
|
-
segments:
|
42
|
-
- 0
|
43
33
|
version: "0"
|
44
34
|
type: :development
|
35
|
+
prerelease: false
|
45
36
|
version_requirements: *id002
|
46
37
|
- !ruby/object:Gem::Dependency
|
47
38
|
name: bueller
|
48
|
-
prerelease: false
|
49
39
|
requirement: &id003 !ruby/object:Gem::Requirement
|
50
40
|
none: false
|
51
41
|
requirements:
|
52
42
|
- - ">="
|
53
43
|
- !ruby/object:Gem::Version
|
54
|
-
segments:
|
55
|
-
- 0
|
56
44
|
version: "0"
|
57
45
|
type: :development
|
46
|
+
prerelease: false
|
58
47
|
version_requirements: *id003
|
59
48
|
- !ruby/object:Gem::Dependency
|
60
49
|
name: rake
|
61
|
-
prerelease: false
|
62
50
|
requirement: &id004 !ruby/object:Gem::Requirement
|
63
51
|
none: false
|
64
52
|
requirements:
|
65
53
|
- - ">="
|
66
54
|
- !ruby/object:Gem::Version
|
67
|
-
segments:
|
68
|
-
- 0
|
69
55
|
version: "0"
|
70
56
|
type: :development
|
57
|
+
prerelease: false
|
71
58
|
version_requirements: *id004
|
72
59
|
- !ruby/object:Gem::Dependency
|
73
60
|
name: rdoc
|
74
|
-
prerelease: false
|
75
61
|
requirement: &id005 !ruby/object:Gem::Requirement
|
76
62
|
none: false
|
77
63
|
requirements:
|
78
64
|
- - ">="
|
79
65
|
- !ruby/object:Gem::Version
|
80
|
-
segments:
|
81
|
-
- 0
|
82
66
|
version: "0"
|
83
67
|
type: :development
|
68
|
+
prerelease: false
|
84
69
|
version_requirements: *id005
|
85
70
|
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.
|
86
71
|
email: nicknovitski@gmail.com
|
@@ -92,22 +77,23 @@ extra_rdoc_files:
|
|
92
77
|
- LICENSE
|
93
78
|
- README.markdown
|
94
79
|
files:
|
95
|
-
- .gitignore
|
96
80
|
- Gemfile
|
97
|
-
- LICENSE
|
98
|
-
- README.markdown
|
99
|
-
- Rakefile
|
100
81
|
- lib/fixnum.rb
|
101
|
-
- lib/tabletop.rb
|
102
82
|
- lib/tabletop/die.rb
|
103
83
|
- lib/tabletop/pool.rb
|
84
|
+
- lib/tabletop/roll.rb
|
104
85
|
- lib/tabletop/version.rb
|
86
|
+
- lib/tabletop.rb
|
87
|
+
- LICENSE
|
88
|
+
- Rakefile
|
89
|
+
- README.markdown
|
105
90
|
- spec/die_spec.rb
|
106
91
|
- spec/fixnum_spec.rb
|
107
92
|
- spec/pool_spec.rb
|
93
|
+
- spec/roll_spec.rb
|
108
94
|
- spec/spec_helper.rb
|
109
95
|
- tabletop.gemspec
|
110
|
-
|
96
|
+
- .gitignore
|
111
97
|
homepage: http://github.com/njay/tabletop
|
112
98
|
licenses: []
|
113
99
|
|
@@ -121,6 +107,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
121
107
|
requirements:
|
122
108
|
- - ">="
|
123
109
|
- !ruby/object:Gem::Version
|
110
|
+
hash: -2668007910377914487
|
124
111
|
segments:
|
125
112
|
- 0
|
126
113
|
version: "0"
|
@@ -129,15 +116,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
129
116
|
requirements:
|
130
117
|
- - ">="
|
131
118
|
- !ruby/object:Gem::Version
|
132
|
-
segments:
|
133
|
-
- 1
|
134
|
-
- 3
|
135
|
-
- 7
|
136
119
|
version: 1.3.7
|
137
120
|
requirements: []
|
138
121
|
|
139
122
|
rubyforge_project:
|
140
|
-
rubygems_version: 1.
|
123
|
+
rubygems_version: 1.8.7
|
141
124
|
signing_key:
|
142
125
|
specification_version: 3
|
143
126
|
summary: A Ruby DSL for role-playing games
|
@@ -145,4 +128,5 @@ test_files:
|
|
145
128
|
- spec/die_spec.rb
|
146
129
|
- spec/fixnum_spec.rb
|
147
130
|
- spec/pool_spec.rb
|
131
|
+
- spec/roll_spec.rb
|
148
132
|
- spec/spec_helper.rb
|