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 CHANGED
@@ -1,3 +1,4 @@
1
1
  Gemfile.lock
2
2
  .DS_Store
3
- pkg/
3
+ pkg/
4
+ *.gem
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 roll dice with it.
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
- ## Usage
13
+ ## Dice
12
14
 
13
- Just `require 'tabletop'` and off you go! The easiest way to create a pool of dice is exactly the way you'd expect.
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
- 3.d6 #=> [3 (d6), 3 (d6), 4 (d6)]
16
- 2.d10 + 1.d8 #=> [2 (d10), 6 (d10), 8 (d8)]
17
- 6.d17 #=> [8 (d17), 3 (d17), 7 (d17), 16 (d17), 11 (d17), 10 (d17)]
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
- Pools are arrays of Dice objects that have a few nice extra functions.
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
- d&d_strength = 3.d6.roll.sum #=> 13
22
- ore_character = 10.d10.sets #=> ["3x2", "2x8", "1x7", "1x6", "1x4", "1x3", "1x1"]
23
- cortex_result = (1.d8 + 2.d6 + 1.d4).highest(2).sum #=> 9
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
- Dice are pretty straightforward.
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 = Die.new
28
- d.sides #=> 6
29
- d.result #=> 4
30
- d.roll #=> "2 (d6)"
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
- ## Note on Patches/Pull Requests
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 rakefile or version.
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, :result
5
- def initialize(sides=6, result=nil)
6
- if sides <= 0
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 result.nil?
14
- result = roll
13
+ if init_value.nil?
14
+ init_value = roll
15
15
  else
16
- raise ArgumentError unless valid_result?(result)
16
+ raise ArgumentError unless valid_value?(init_value)
17
17
  end
18
- @result = result
18
+ @value = init_value
19
19
  end
20
20
  def roll
21
- @result = rand(sides)+1
21
+ @value = rand(sides)+1
22
22
  end
23
- def inspect
24
- "#{@result} (d#{@sides})"
23
+
24
+ def to_s
25
+ "[#{value}]/d#{sides}"
25
26
  end
26
- def result=(new_result)
27
- raise ArgumentError unless valid_result?(new_result)
28
- @result = new_result
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
- @result <=> operand.to_int
33
+ @value <=> operand.to_int
32
34
  end
33
35
  def to_int
34
- @result
36
+ @value
35
37
  end
36
38
 
37
39
  protected
38
- def valid_result?(result)
39
- result > 0 and result <= @sides
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(result = nil)
45
- super(3, result)
46
+ def initialize(init_value = nil)
47
+ super(3, init_value)
46
48
  end
47
49
  def roll
48
- @result = rand(sides)-1
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 valid_result?(result)
56
- [1,0,-1].include?(result)
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 results
39
- map {|die| die.result}
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.result}
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.result] = count {|d| d.result == die.result}
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
- sorted = sort_by {|d| d.result}.reverse
83
- Pool.new(sorted.first(n))
82
+ Pool.new(sort.reverse.first(n))
84
83
  end
85
84
  def lowest(n=1)
86
- sorted = sort_by {|d| d.result}
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.result == drop_value }}
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.result)
105
+ new_pool << FudgeDie.new(die.value)
108
106
  else
109
- new_pool << Die.new(die.sides, die.result)
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
@@ -1,3 +1,3 @@
1
1
  module Tabletop
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/tabletop.rb CHANGED
@@ -1,3 +1,4 @@
1
1
  require_relative 'fixnum'
2
2
  require_relative 'tabletop/die'
3
3
  require_relative 'tabletop/pool'
4
+ require_relative 'tabletop/roll'
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
- d = Die.new(6)
12
- d.sides.should == 6
13
- d = Die.new(20)
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
- d = Die.new
20
- d.sides.should equal(6)
19
+ Die.new.sides.should == 6
21
20
  end
22
- it "cannot be 0 or less" do
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
- describe "#result" do
33
- before :each do
34
- Random.srand(10)
35
- end
34
+
35
+ describe "#value" do
36
36
  it "should be random on instantiation by default" do
37
- d = Die.new
38
- d.result.should equal(2)
39
- d = Die.new(10)
40
- d.result.should equal(5)
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).result.should == 5
46
- Die.new(10, 2).result.should == 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
- describe "#result=" do
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.result = 0 }.should raise_error(ArgumentError)
58
- lambda { d.result = -5 }.should raise_error(ArgumentError)
59
- lambda { d.result = 7 }.should raise_error(ArgumentError)
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.result = 7
62
- lambda { d.result = 22 }.should raise_error(ArgumentError)
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
- it "should return a random result between 1 and @sides" do
71
- d = Die.new
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
- end
89
- context "eleven sides" do
90
- it "should return a random result between 1 and @sides" do
91
- d = Die.new(11)
92
- # d.roll.should == 10 # This result gets swallowed by the init roll
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
- it "should alter the result appropriately" do
98
- d = Die.new(11)
99
- #d.roll # covered by the initial roll
100
- d.result.should == 10
101
- d.roll
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
- describe "#inspect" do
111
- before(:each) do
112
- Random.srand(10)
113
- end
114
- it "should be interesting" do
115
- Die.new.inspect.should == "2 (d6)"
116
- Die.new.inspect.should == "6 (d6)"
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 result" do
101
+ it "returns the value" do
121
102
  d = Die.new
122
- d.to_int.should == d.result
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
- (@d6_3 < 4).should be_true
128
- (@d6_3 < 2).should be_false
129
- (@d6_3 > 2).should be_true
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 > @d6_2).should be_true
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
- describe "#result" do
131
+
132
+ describe "#value" do
158
133
  it "can be set on instantiation" do
159
- FudgeDie.new(1).result.should == 1
160
- FudgeDie.new(0).result.should == 0
161
- FudgeDie.new(-1).result.should == -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.result.should == 0
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
- describe "#result=" do
152
+
153
+ describe "#value=" do
173
154
  it "cannot be set to anything but -1, 0, or 1" do
174
- lambda {@fudge.result = 2}.should raise_error(ArgumentError)
175
- lambda {@fudge.result = 0.6}.should raise_error(ArgumentError)
176
- lambda {@fudge.result = "5"}.should raise_error(ArgumentError)
177
- @fudge.result = 1
178
- @fudge.result.should == 1
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
- describe "#inspect" do
182
- it "should look like plusses, minuses and spaces" do
183
- FudgeDie.new(1).inspect.should == "[+] (dF)"
184
- FudgeDie.new(0).inspect.should == "[ ] (dF)"
185
- FudgeDie.new(-1).inspect.should == "[-] (dF)"
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
@@ -8,6 +8,7 @@ module Tabletop
8
8
  4.d7.dice.should == ["4d7"]
9
9
  10.d100.class.should == Pool
10
10
  end
11
+
11
12
  it "shows up in respond_to?(:dN)" do
12
13
  1.respond_to?(:d50).should be_true
13
14
  end
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.results.should == [2, 5, 16, 1, 17, 9]
42
+ merge.values.should == [2, 5, 16, 1, 17, 9]
38
43
  merge.roll
39
- merge.results.should == [4, 17, 5, 16, 12, 12]
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.results.should == [2]
45
- @d17s.results.should == [5, 16, 1, 17, 9]
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.results.should == [2, 3, 4]
72
+ g.values.should == [2, 3, 4]
65
73
  g.dice.should == ["2d6", "d10"]
66
74
  g.roll
67
- @d6.results.should == [2]
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
- describe "#results" do
83
+
84
+ describe "#values" do
75
85
  it "should be an array of random numbers" do
76
- @d6.results.should == [2]
77
- @d17s.results.should == [5, 16, 1, 17, 9]
78
- @mixed.results.should == [10, 1, 11]
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.results.should == [4]
100
+ @d6.values.should == [4]
89
101
  @d17s.roll
90
- @d17s.results.should == [17, 5, 16, 12, 12]
102
+ @d17s.values.should == [17, 5, 16, 12, 12]
91
103
  @mixed.roll
92
- @mixed.results.should == [2, 9, 5]
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
- @d6.sum.should == 2
98
- @d17s.sum.should == 48
99
- @mixed.sum.should == 22
100
- @fudge.sum.should == -1
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
- @d6.to_int.should == @d6.sum
104
- @d17s.to_int.should == @d17s.sum
105
- @mixed.to_int.should == @mixed.sum
106
- @fudge.to_int.should == @fudge.sum
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.results.should == [2]
134
- @d17s.highest.results.should == [17]
135
- @mixed.highest.results.should == [11]
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).results.should == [2]
139
- @d17s.highest(3).results.should == [17, 16, 9]
140
- @mixed.highest(2).results.should == [11, 10]
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.results.should == [2]
168
+ @d6.lowest.values.should == [2]
146
169
  @d17s.lowest.class.should == Pool
147
- @d17s.lowest.results.should == [1]
148
- @mixed.lowest.results.should == [1]
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).results.should == [2]
152
- @d17s.lowest(3).results.should == [1, 5, 9]
153
- @mixed.lowest(2).results.should == [1, 10]
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.results.should == [5, 16, 1, 9]
160
- @d17s.results.should == [5, 16, 1, 17, 9]
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.results.should == [5, 1, 9]
190
+ p.values.should == [5, 1, 9]
165
191
  p = @d6.drop_highest(10)
166
- p.results.should == []
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.results.should == [5, 16, 17, 9]
173
- @d17s.results.should == [5, 16, 1, 17, 9]
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.results.should == [16, 17, 9]
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.results.should == [4, 1, 5, 7, 9, 2, 9, 5, 2, 4]
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.results.should == [4, 5, 7, 9, 2, 9, 5, 2, 4]
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.results.should == [4, 5, 7, 9, 9, 5, 4]
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
- s.files = `git ls-files`.split("\n")
24
- s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
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: false
5
- segments:
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 -07: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
- has_rdoc: true
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.3.7
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