tabletop 0.0.1 → 0.1.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.
- 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
|