tabletop 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -2,4 +2,5 @@ Gemfile.lock
2
2
  .DS_Store
3
3
  pkg/
4
4
  doc/
5
- *.gem
5
+ *.gem
6
+ .idea/
data/README.markdown CHANGED
@@ -2,17 +2,19 @@
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 create pools of dice, and rolls that compare them to different possible results.
6
-
7
5
  ## Installation
8
6
 
9
7
  gem install tabletop
10
8
 
11
9
  require 'tabletop'
12
10
 
13
- ## Dice
11
+ ## Usage
12
+
13
+ For detailed information, I recommend the [full documentation](http://rubydoc.info/gems/tabletop/), but I want this file to give you a good primer, so let's get started.
14
14
 
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.
15
+ ### Dice
16
+
17
+ 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 set directly. Finally, they can be rolled, which gives them a new random value.
16
18
 
17
19
  d6 = Die.new
18
20
  d6.sides #=> 6
@@ -22,7 +24,7 @@ Dice are pretty straightforward. They've got a number of sides, set on instanti
22
24
 
23
25
  d8 = Die.new(8, 4)
24
26
  d8.sides #=> 8
25
- d8.to_s #=> "[3]/d8"
27
+ d8.to_s #=> "[4]/d8"
26
28
 
27
29
  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
30
 
@@ -30,19 +32,27 @@ One fun special kind of die is a "Fudge Die". They are a special kind of three-
30
32
  f.sides #=> 3
31
33
  f.value #=> 0
32
34
  f.to_s #=> "[ ]"
35
+
36
+ You may not believe this, but coins are also a special case of die. Coins have two sides, and have a value of either 1 or 0, aka heads or tails, aka "+" or " ". They can be rolled if you really want, but you'd normally call that "flipping," right?
37
+
38
+ c = Coin.new
39
+ c.sides #=> 2
40
+ c.value #=> 1
41
+ c.to_s #=> "(+)"
42
+ c.flip.to_s #=> "( )"
33
43
 
34
44
  ### Pools
35
45
 
36
- Pools are essentially arrays of Dice objects with some extra helpful methods.
46
+ Pools are arrays of Dice objects with some extra helpful methods.
37
47
 
38
48
  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
49
 
40
50
  3.d6 #=> [[3]/d6, [3]/d6, [4]/d6]
41
51
  2.d10 + 1.d8 #=> [[2]/d10, [6]/d10, [8]/d8]
42
-
52
+
43
53
  You can also create them by passing Pool.new a literal array of dice, or (slightly more interesting) a string in die notation.
44
54
 
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.
55
+ Pool's instance 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.
46
56
 
47
57
  d&d = 3.d6.sum #=> 13
48
58
  ore = 10.d10.sets #=> ["3x2", "2x8", "1x7", "1x6", "1x4", "1x3", "1x1"]
@@ -53,33 +63,33 @@ You can also #roll an entire pool, or you can interact with individual dice in t
53
63
 
54
64
  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
65
 
56
- d&d_alt = 4.d4 + 4 #=> 17
57
- 1.d20 > 2.d10 #=> false
66
+ 4.d4 + 4 #=> 17
67
+ 1.d20 > 2.d10 #=> false
58
68
 
59
69
  ### Rolls
60
70
 
61
- Rolls are very much under construction, but they allow you to automate randomly determining results in a variety of ways.
71
+ Rolls are very much under construction and their API is in flux, but they allow you to automate randomly determining results in a variety of ways.
62
72
 
63
- Rolls have a lot of options. Let's start by taking an example from one of my favorite games, Apocalypse World.
73
+ Rolls have a lot of options, described in detail in the documentation. But let's take a simple example from one of my favorite games, Apocalypse World.
64
74
 
65
75
  >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
76
 
67
- (In the parlance of the game, a "hit" is getting a 7 or higher on 2d6, plus a stat.)
77
+ (In the parlance of the game, a "hit" is getting a 7 or higher. "Roll+weird" means to roll 2d6 and add the character's "weird" stat, which is an integer from -1 to 3.)
68
78
 
69
- Here's how I'd write it out in Tabletop.
79
+ Here's how I'd write that out in Tabletop:
70
80
 
71
- cool = [-1, 0, 1, 2, 3].sample #=> get a random stat
81
+ weird = [-1, 0, 1, 2, 3].sample #=> get a random stat
72
82
 
73
83
  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"
84
+ add weird
85
+ at_least 7, "the MC will tell you something new and interesting about the current situation..."
76
86
  equals (7..9), "...but it's just an impression"
77
87
  at_least 10, "...and it's a good detail"
78
88
  }
79
89
 
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.
90
+ 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 values to return if the pool's result meets the stated condition.
81
91
 
82
- Once they've been instantiated, Rolls have two important methods.
92
+ Once they've been instantiated, Rolls have three important methods.
83
93
 
84
94
  #### #roll
85
95
 
@@ -88,25 +98,38 @@ This method which re-rolls all the dice in the pool, and returns the Roll object
88
98
  bad_luck = -1
89
99
  open_brain.roll(:modifier => bad_luck)
90
100
 
91
- #### #effects
101
+ #### #result
92
102
 
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:
103
+ This method, by default, returns the sum of the values of the Roll's dice, plus any static modifiers from `add` or per-roll modifiers from `roll(:modifier)`.
94
104
 
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`
105
+ But! When instantiating a roll, you can call `set_result` with an appropriate symbol to make `result` mean something else.
106
+
107
+ For example, in Exalted, you principally care about how many dice in your pool came up 7 or higher, counting 10s twice:
108
+
109
+ exalted = Roll.new(8.d10) do
110
+ set_result :count, :at_least=>7, :doubles=>10
111
+ end
112
+
113
+ exalted.result #=> 2
114
+ exalted.sum #=> 30
115
+
116
+ #### #effects
117
+
118
+ This method returns either an array containing the results passed to any `at_least` and `equals` calls whose conditions were met, or nil if no such conditions were met.
98
119
 
99
120
  So, possible results for our cool AW roll:
100
121
 
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"]
122
+ open_brain.roll.effects #=> nil
123
+ open_brain.roll.effects #=> ["the MC will tell you something new and interesting about the current situation", "...but it's just an impression"]
124
+ open_brain.roll
125
+ puts open_brain.result #=> 10
126
+ puts open_brain.effects #=> ["the MC will tell you something new and interesting about the current situation", "...and it's a good detail"]
106
127
 
107
- Just these few functions already give enough functionality to do different kinds of rolls, but there's a lot more in store.
128
+ ### Coming Soon
129
+
130
+ That's already enough functionality to do many different kinds of rolls, but there's a lot more in store.
108
131
 
109
- One last thing I'll briefly note is that Rolls can be nested.
132
+ One bonus thing I'll briefly note is that Rolls can be nested, and `effects` returns them as such.
110
133
 
111
134
  rps = Roll.new(1.d3) {
112
135
  equals 1, "rock"
@@ -122,21 +145,20 @@ One last thing I'll briefly note is that Rolls can be nested.
122
145
  equals 1, "Rock Paper Scissors", rps
123
146
  equals 2, "JanKenPon", jkp
124
147
  }
125
- fist_game.roll.effects #=> [2, "JanKenPon", [1, "guu"]]
148
+ fist_game.roll.effects #=> ["JanKenPon", ["guu"]]
126
149
 
127
150
  This can lead to some surprisingly sophisticated constructions. Remember that "tables" are really just a special case of a roll!
128
151
 
129
152
  ## How to contribute
130
153
 
131
- *First and most importantly*, any complaints or suggestions, *regardless of coding knowledge*, are *always welcome* at <nick.novitski@gmail.com>.
154
+ *First and most importantly*, if you're reading this and you make games, please tell me about them! Second, any complaints or suggestions are always welcome, _regardless of coding knowledge_. Feel free to communicate your opinions by [creating an issue on github](https://github.com/njay/tabletop/issues), or just dropping me a line at <nick.novitski@gmail.com>.
132
155
 
133
- But, if you're feeling up to it, you can always do more. You probably already know the drill by this point.
156
+ If you have clear ideas about what more the project should do, and you think you can do something about it, then make it so! Don't even bother asking me about it, you know the drill:
134
157
 
135
158
  * Fork the project.
136
- * Create a topic branch
159
+ * Create a topic branch.
137
160
  * Make tests that describe your feature addition or bug fix.
138
- * Write code that passes those tests
139
- * Commit, without altering the version.
161
+ * Write code that passes those tests.
140
162
  * Send me a pull request.
141
163
 
142
164
  ## Copyright
data/Rakefile CHANGED
@@ -55,8 +55,12 @@ task :clean do
55
55
  FileUtils.rm_rf "pkg"
56
56
  end
57
57
 
58
+ desc "Update master and develop branches on github"
59
+ task :github do
60
+ system "git push origin : --tags"
61
+ end
62
+
58
63
  desc "Push changes to github and rubygems"
59
- task :publish do
60
- system "git push origin master --tags"
64
+ task :publish => :github do
61
65
  system "gem push pkg/#{gemspec.name}-#{gemspec.version}.gem"
62
66
  end
data/lib/fixnum.rb CHANGED
@@ -4,21 +4,17 @@ class Fixnum
4
4
 
5
5
  # Returns a pool of dice of the given sides and size self
6
6
  def dX(sides)
7
- dice = []
8
- times { dice << Tabletop::Die.new(sides) }
9
- Tabletop::Pool.new(dice)
7
+ Tabletop::Pool.new("#{self}d#{sides}")
10
8
  end
11
9
 
12
10
  # Returns a pool of fudge dice of size self
13
11
  def dF
14
- dice = []
15
- times {dice << Tabletop::FudgeDie.new}
16
- Tabletop::Pool.new(dice)
12
+ Tabletop::Pool.new("#{self}dF")
17
13
  end
18
14
 
19
- # Matches any methods of the form d(.*), and calls #dX($1.to_i)
15
+ # Matches any methods of the form dN, where N > 0, and calls #dX(N)
20
16
  def method_missing(symbol, *args, &block)
21
- if symbol =~ /^d(.*)$/
17
+ if symbol =~ /^d(.*)$/ and $1.to_i > 0
22
18
  dX($1.to_i)
23
19
  else
24
20
  super
@@ -0,0 +1,20 @@
1
+ module Tabletop
2
+
3
+ # Stores a block to evaluate against a Pool
4
+ class Condition
5
+ def initialize(&block)
6
+ @test = block
7
+ end
8
+
9
+ # returns false if the stored block evaluates to false or nil,
10
+ # otherwise returns true
11
+ def met_by?(pool)
12
+ if @test.call(pool)
13
+ true
14
+ else
15
+ false
16
+ end
17
+ end
18
+ end
19
+
20
+ end
data/lib/tabletop/pool.rb CHANGED
@@ -1,42 +1,59 @@
1
1
  require_relative 'randomizers'
2
- require 'delegate'
3
2
 
4
3
  module Tabletop
5
- class Pool < DelegateClass(Array)
4
+ class Pool < Array
6
5
  include Comparable
7
6
 
8
- # requires one parameter, which can be either of
7
+ # Requires one parameter, which can be either of
9
8
  # - an array of Die objects
10
- # - a string of d-notation
9
+ # - a string of elements separated by spaces which can be in two different formats:
10
+ # + d-notation (ie, "d20", "3dF", etc) denoting dice that will be given random values
11
+ # + a value, a slash, then a number of sides (ie, "2/6", "47/100", etc)
11
12
  def initialize(init_dice)
12
- return super(init_dice) if init_dice.instance_of?(Array)
13
+ return super(init_dice) if init_dice.kind_of?(Array)
13
14
  d_groups = init_dice.split
14
15
  dice = []
15
- d_groups.each do |d_notation|
16
- number, sides = d_notation.split('d')
17
- number = number.to_i
18
- number += 1 if number == 0
19
- if sides.to_i > 0
20
- number.times { dice << Die.new(sides.to_i)}
21
- elsif sides == "F"
22
- number.times {dice << FudgeDie.new}
16
+ d_groups.each do |d|
17
+ if d =~ /d/ # d_notation
18
+ number, sides = d.split('d')
19
+ number = number.to_i
20
+ number += 1 if number == 0
21
+ if sides.to_i > 0
22
+ number.times { dice << Die.new(sides: sides.to_i)}
23
+ elsif sides == "F"
24
+ number.times {dice << FudgeDie.new}
25
+ end
26
+ else
27
+ dice << Die.new_from_string(d)
23
28
  end
24
29
  end
25
30
  super(dice)
26
31
  end
27
32
 
28
- # Behavior depends on the class of what is passed to it.
29
- # Numeric:: returns the sum of the operand and the values of all dice in the receiving pool
30
- # Pool:: returns a new pool with copies of all the dice in both operands
31
- # AnythingElse:: raises an ArgumentError
33
+ # If adding a pool or array of dice objects, returns the the union of these pools.
34
+ #
35
+ # If adding a number, returns the sum of that number and all die values in the pool.
36
+ #
37
+ # Otherwise, raises an ArgumentError.
32
38
  def +(operand)
33
- # if the operator is a pool, or an array only of Die objects...
34
- if operand.instance_of?(Pool) or (operand.instance_of?(Array) and !(operand.detect{|obj| !(obj.instance_of?(Die))}))
39
+ # if the parameter seems to be an array of dice (this includes pools)
40
+ if operand.respond_to?(:all?) and operand.all?{|obj| obj.respond_to?(:roll)}
35
41
  new_union(operand)
36
- elsif operand.kind_of? Numeric
42
+ # if the parameter seems to be a randomizer
43
+ elsif operand.respond_to?(:sides)
44
+ new_union([operand])
45
+ elsif operand.respond_to?(:to_int)
37
46
  sum + operand
38
47
  else
39
- raise ArgumentError, "Cannot add operand of class #{operand.class}"
48
+ raise ArgumentError, "Only numbers and other pools can be added to pools"
49
+ end
50
+ end
51
+
52
+ def -(operand)
53
+ if operand.respond_to?(:to_a)
54
+ super
55
+ else
56
+ sum - operand
40
57
  end
41
58
  end
42
59
 
@@ -89,6 +106,12 @@ module Tabletop
89
106
  end
90
107
  self
91
108
  end
109
+
110
+ def roll_if(&block)
111
+ each do |die|
112
+ die.roll if block.call(die)
113
+ end
114
+ end
92
115
 
93
116
  # Returns the sum of all values of dice in the pool
94
117
  def sum
@@ -109,12 +132,24 @@ module Tabletop
109
132
 
110
133
  # Returns a Pool containing copies of the n highest dice
111
134
  def highest(n=1)
112
- Pool.new(sort.reverse.first(n))
135
+ if n < length
136
+ drop_lowest(length-n)
137
+ else
138
+ self
139
+ end
113
140
  end
114
141
 
115
142
  # Returns a Pool containing copies of the n lowest dice
116
143
  def lowest(n=1)
117
- Pool.new(sort.first(n))
144
+ sorted = sort.first(n)
145
+ in_order = []
146
+ each do |d|
147
+ if sorted.include?(d)
148
+ in_order << d
149
+ sorted -= [d]
150
+ end
151
+ end
152
+ Pool.new(in_order)
118
153
  end
119
154
 
120
155
  # Returns a copy of the Pool, minus the n highest-value dice
@@ -133,19 +168,15 @@ module Tabletop
133
168
  def drop(to_drop)
134
169
  to_drop = [to_drop].flatten #turn it into an array if it isn't one.
135
170
  kept = reject{|die| to_drop.any?{|drop_value| die.value == drop_value }}
136
- return Pool.new(kept)
171
+ Pool.new(kept)
137
172
  end
138
173
 
139
174
  private
140
175
  def new_union(array)
141
176
  union = [self, array].flatten
142
177
  new_pool =[]
143
- union.each do |die|
144
- if die.instance_of?(FudgeDie)
145
- new_pool << FudgeDie.new(die.value)
146
- else
147
- new_pool << Die.new(die.sides, die.value)
148
- end
178
+ union.each do |die|
179
+ new_pool << die.class.new(sides:die.sides, value:die.value)
149
180
  end
150
181
  Pool.new(new_pool)
151
182
  end
@@ -3,23 +3,29 @@ module Tabletop
3
3
  include Comparable
4
4
 
5
5
  attr_reader :sides, :value
6
-
7
- # Sides must be greater then or equal to 1.
8
- # If init_value is nil, then #roll is called.
9
- def initialize(sides=6, init_value=nil)
10
- if sides <= 1
11
- raise ArgumentError, "Die cannot have #{sides} sides"
12
- end
13
- unless sides.kind_of? Integer
14
- raise ArgumentError, "Parameter must be Integer, not #{sides.class}"
6
+
7
+ # :sides must be greater then or equal to 1. By default it is 6.
8
+ # If :value is nil, then #roll is called.
9
+ def initialize(params={})
10
+
11
+ if params[:sides].nil?
12
+ @sides = 6
13
+ else
14
+ @sides = Integer(params[:sides])
15
+ raise ArgumentError if @sides < 2
15
16
  end
16
- @sides = sides
17
- if init_value.nil?
18
- init_value = roll
17
+
18
+ if params[:value].nil?
19
+ roll
19
20
  else
20
- raise ArgumentError unless valid_value?(init_value)
21
+ self.value = params[:value]
21
22
  end
22
- @value = init_value
23
+ end
24
+
25
+ def self.new_from_string(string)
26
+ raise ArgumentError unless string.respond_to?(:split)
27
+ v, s = string.split('/')
28
+ Die.new(sides: s.to_i, value: v.to_i)
23
29
  end
24
30
 
25
31
  # Sets @value to a random number n, where 1 <= n <= @sides
@@ -34,8 +40,9 @@ module Tabletop
34
40
 
35
41
  # Raises ArgumentError if new_value isn't between 1 and @sides inclusive
36
42
  def value=(new_value)
37
- raise ArgumentError unless valid_value?(new_value)
38
- @value = new_value
43
+ integer_value = Integer(new_value)
44
+ raise ArgumentError unless valid_value?(integer_value)
45
+ @value = integer_value
39
46
  end
40
47
 
41
48
  # Compares based on value of the die
@@ -50,7 +57,7 @@ module Tabletop
50
57
 
51
58
  protected
52
59
  def valid_value?(val)
53
- val > 0 and val <= @sides
60
+ 0 < val and @sides >= val
54
61
  end
55
62
  end
56
63
 
@@ -58,8 +65,8 @@ module Tabletop
58
65
  # A FudgeDie is a kind of three-sided Die that has a value
59
66
  # of either 0, 1, or -1.
60
67
  class FudgeDie < Die
61
- def initialize(init_value = nil)
62
- super(3, init_value)
68
+ def initialize(params = {})
69
+ super(sides: 3, value: params[:value])
63
70
  end
64
71
  def roll
65
72
  @value = rand(sides)-1
@@ -80,8 +87,8 @@ module Tabletop
80
87
  # A coin is a kind of two-sided Die that has a value of
81
88
  # either 0 or 1
82
89
  class Coin < Die
83
- def initialize(value=nil)
84
- super(2, value)
90
+ def initialize(params={})
91
+ super(sides: 2, value: params[:value])
85
92
  end
86
93
 
87
94
  def roll #:nodoc:
@@ -93,7 +100,15 @@ module Tabletop
93
100
  roll
94
101
  self
95
102
  end
96
-
103
+
104
+ def heads?
105
+ @value == 1
106
+ end
107
+
108
+ def tails?
109
+ @value == 0
110
+ end
111
+
97
112
  # Returns either "( )" or "(+)" depending on @value
98
113
  def to_s
99
114
  "(#{[' ', '+'][value]})"
data/lib/tabletop/roll.rb CHANGED
@@ -10,6 +10,7 @@ module Tabletop
10
10
  def initialize(outcomes, conditions)
11
11
  @outcomes, @conditions = outcomes, conditions
12
12
  end
13
+
13
14
  end
14
15
 
15
16
  class Roll
@@ -38,11 +39,10 @@ module Tabletop
38
39
  end
39
40
 
40
41
 
41
- # Returns an array.
42
- # + The first value in the array is #result
43
- # + If a "difficulty" was set in the most call of #roll, and #result meets or exceeds it, then the second element will be "Success".
44
- # + if the conditions of any of the roll's @possibilities are met (see #meets?), then their outcomes will be all following elements.
45
- # + if none of the above conditions are met, the second and final element is nil.
42
+ # Returns either an array or nil.
43
+ # + If a "difficulty" was set in the most recent call of #roll, and #result meets or exceeds it, then the first element will be "Success".
44
+ # + If the conditions of any of the roll's @possibilities are met (see #meets?), then their outcomes will be all following elements.
45
+ # + If none of these conditions are met, returns nil
46
46
  def effects
47
47
  results = []
48
48
 
@@ -51,22 +51,15 @@ module Tabletop
51
51
  end
52
52
 
53
53
  @possibilities.each do |poss|
54
- if meets?(poss)
55
- poss.outcomes.each do |outcome|
56
- if outcome.instance_of?(Roll)
57
- results << outcome.roll.effects
58
- else
59
- results << outcome
60
- end
61
- end
62
- end
54
+ results.concat(check(poss))
63
55
  end
64
-
56
+
57
+ results.compact!
58
+
65
59
  if results.empty?
66
- results << nil
60
+ results = nil
67
61
  end
68
-
69
- results.unshift(result)
62
+ results
70
63
  end
71
64
 
72
65
  # Without any options passed, calls Pool#roll on the roll's pool. Returns the Roll.
@@ -94,21 +87,36 @@ module Tabletop
94
87
  self
95
88
  end
96
89
 
97
- # Takes an object, returns false if anything set in the object's conditions hash
98
- # are not met by #sum, otherwise returns true
90
+ # Takes a Possibility, returns an Array containing nil if any of it's conditions
91
+ # aren't met. Otherwise, returns an Array containing all the Possibility's
92
+ # outcomes. If any of those outcomes are Roll objects, they are rolled and their
93
+ # #effects are returned as an outcome.
99
94
  #--
100
95
  # TODO: checks #result, not #sum
101
- def meets?(p)
102
- answer = true
103
- if p.conditions[:>=]
104
- if p.conditions[:>=] > sum
105
- answer = false
106
- end
96
+ def check(p) #:nodoc:
97
+ conditions_met = true
98
+
99
+ if p.conditions[:>=] and sum < p.conditions[:>=]
100
+ conditions_met = false
101
+ end
102
+
103
+ if p.conditions[:==] and p.conditions[:==] != sum
104
+ conditions_met = false
107
105
  end
108
- if p.conditions[:==]
109
- answer = false if p.conditions[:==] != sum
106
+
107
+ if conditions_met
108
+ results = []
109
+ p.outcomes.each do |outcome|
110
+ if outcome.instance_of?(Roll)
111
+ results << outcome.roll.effects
112
+ else
113
+ results << outcome
114
+ end
115
+ end
116
+ results
117
+ else
118
+ [nil]
110
119
  end
111
- answer
112
120
  end
113
121
 
114
122
  # The sum of the values of dice in the pool, and any modifier set in